[W05] Challenge 03 - Heap Buffer Overflow

silver ·2일 전

크래프톤 정글

목록 보기
17/18

- 문제

- 시나리오

자동 성장하는 정수 동적 배열 IntList (init/ensure/push/sum).
용량이 부족하면 list_ensure() 가 용량을 2배로 늘리고 realloc 한다.
이 리스트로 큰 수열을 만들어 합을 구한다.

- 문제 풀이

1)

친절한 주석 선생님 덕분에 어디서 터질지 약간 알수잇었지만..^.^ 그래도 내 눈으로 확인하기 위해 gdb를 통해 추적을 해보았다

pwndbg> bt
#0  __pthread_kill_implementation (no_tid=0x0, signo=0x6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=0x6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=0x6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff7dec27e in __GI_raise (sig=sig@entry=0x6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff7dcf8ff in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff7dd07b6 in __libc_message_impl (fmt=fmt@entry=0x7ffff7f768f0 "%s\n") at ../sysdeps/posix/libc_fatal.c:134

//
#6  0x00007ffff7e500d5 in malloc_printerr (str=str@entry=0x7ffff7f74759 "realloc(): invalid next size") at ./malloc/malloc.c:5775
#7  0x00007ffff7e5421c in _int_realloc (av=av@entry=0x7ffff7fabac0 <main_arena>, oldp=oldp@entry=0x555555559290, oldsize=oldsize@entry=0x30, 
    nb=nb@entry=0x50) at ./malloc/malloc.c:4939
#8  0x00007ffff7e553f5 in __GI___libc_realloc (oldmem=0x5555555592a0, bytes=0x40) at ./malloc/malloc.c:3508
#9  0x00005555555552f2 in list_ensure (l=0x7fffffffdde0, need=0x11) at challenges/03_heap_buffer_overflow/bug.c:68
#10 0x0000555555555384 in list_push (l=0x7fffffffdde0, x=0x10) at challenges/03_heap_buffer_overflow/bug.c:76
#11 0x00005555555554b0 in main () at challenges/03_heap_buffer_overflow/bug.c:98
//

#12 0x00007ffff7dd11ca in __libc_start_call_main (main=main@entry=0x555555555449 <main>, argc=argc@entry=0x1, argv=argv@entry=0x7fffffffdf28)
    at ../sysdeps/nptl/libc_start_call_main.h:58
#13 0x00007ffff7dd128b in __libc_start_main_impl (main=0x555555555449 <main>, argc=0x1, argv=0x7fffffffdf28, init=<optimized out>, 
    fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdf18) at ../csu/libc-start.c:360
#14 0x0000555555555145 in _start ()

main() -> list_push -> list_ensure 하다가 터짐 확인

2)

더 깊이 파보기위해 list_push 근처로 들어가봄

→ newcap * sizeof(int)과 l -> cap * sizeof(int) 크기 다른 문제 확인

3)

l -> cap 이 newcap의 사이즈를 가지도록 고쳐줌

4)


코어타임 때 팀원분들의 코드를 봤는데 다들 이렇게 쓰셨더라고?

5) 그래서 찾아본 두 방식의 차이점

내 방식대로 하면
realloc이 성공하기도 전에 cap을 먼저 변경함
→ realloc 실패 시 cap(변경 완)과 실제버퍼(아직 변경 전)가 불일치 상태가 됨
이 코드는 실패하면 exit(1)로 끝내니 문제가 안 되지만, 실패해도 프로그램이 계속 도는 코드에서는 이 불일치가 이번 버그와 똑같은 문제를 다시 일으킴.

cap 줄을 위로 옮겼기 때문에 realloc이 맞게 동작한다 줄 순서에 숨은 의존성
나중에 줄 순서를 바꾸면 다시 버그가 살아남.
∴ 실제 할당이 확정된 뒤에만 cap을 변경하도록 해줘야함.

0개의 댓글