Toddler's Bottle의 마지막 문제다.. 한~~참 과거에 glibc2.3.2 버전 이하에서 힙을 free() 해줄때 내부의 unlink취약점을 문제에 나타냈다.
업데이트되고 지금은 활용할 수 없는 버그이다.
소스코드를 먼저 보겠다. 구조체와 system함수, unlink함수, gets함수 등... 으로 구성 되어 있다.
OBJ구조체가 선언 되있다. 그 내용을 보면 구조체의 포인터 fd와 bk가 있고 8바이트 크기의 버퍼로 구성 되어있다.
malloc(동적할당)함수를 이용하여 힙공간을 할당하면 구조체의 사이즈보다 더 넓은 메모리 공간이 생성된다. 그이유는
size(4바이트)와 pre_size(4바이트) 정보를 담아야하기 때문이다.
size : 현재 chunk의 크기정보
prev_size : 이전의 chunk가 free되었을 때 그 chunk의 크기정보
OBJ구조체는 총 24바이트의 공간으로 힙에 할당 될 것이다.
간단히 오버플로우가 일어나는 것을 확인해준다.(이유는 문자열 길이를 체크하지 않는 gets함수의 사용때문)
프로그램을 실행한뒤 'AAAA'를 입력해주고 힙내부를 봤다.
구조체의 FD BK가 A <=> B <=> C를 가르키고 있는 구조다.
size는 24바이트로 16진수로 표현하면 0x18이여야 하지만 왜 0x19일까? 이유는 하위 3비트가 플래그 용도로 사용되기 때문이다.
1. PREV_INUSE : 이전 chunk가 사용중일때 설정되는 플래그
2. IS_MMAPPED : mmap()함수로 할당된 chunk일 때 설정되는 플래그
3.NON_MAIN_ARENA : 멀티쓰레드 환경에서 main이 아닌 쓰레드에서 생성된 메모리 일 때 설정되는 플래그
하지만, 다음 아래는 unlink(B)함수 실행 뒤의 힙 구조이다. C의 BK가 B대신 A를 가르킨다.
system("/bin/sh");를 주어준 것을 보아 ret을 bof로 덮어 shell을 실행 하라는 의도 같다. 어떻게 할 수 있을까?
gets(A->buf);로 덮을 수 있는 값을 구조체 B, C의 메모리 공간들이다.
malloc된 A, B, C는 어떤 과정을 거쳐 double linked list 구조를 가지는지,
fd의 값과 bk값이 어떻게 담기게 되는지 어셈으로 알아본다. 아래와 같은 과정을 거치는 것을 알 수 있다.
C code to asm ------->>>>>>
다음으로 unlink함수의 과정이다.
C code to asm--------->>
1번부터 차례대로 BK=P -> bk; , FD=P -> fd; .... 라고 볼 수 있다.
1번 과정에 ebp-0x4는 BK공간이고 2번 과정에 ebp-0x8은 FD공간이라고 할 수 있다.
3번은 FD->bk=BK; 과정인데 fd+4(ebp-0x8)에 bk를 넣고
4번 BK->fd=FD; 과정에서는 bk(ebp-0x4)에 fd를 저장하는 것을 알 수 있다.
AAAA(4) | shell()함수주소| dummy(8) | {heapleak주소+12바이트(A의 fd로부터 shell()함수주소까지 거리)+4바이트(lea esp,[ecx-4]이기 때문에)}(4) | 스택의 leak 주소+16바이트(ebp-0x4와의 거리차이)(4)(즉, C의구조체의 bk공간의 주소 = 스택의 ebp-0x4의 주소를 넣는다.) <- 이 공간엔 unlink취약점에 의해 shell함수의 주소값이 들어갈 것
[ebp-0x4]= shell()주소가 담긴 heap의 위치+4 왜+4? ecx-0x4때문에
ebp-0x4 = leak stack주소 + 거리차이(0x10)
'System Hacking > pwable.kr' 카테고리의 다른 글
18.pwnable asm (0) | 2018.02.28 |
---|---|
17.pwnable memcpy (0) | 2018.02.28 |
16.pwnable uaf (0) | 2018.02.26 |
15.pwnable cmd2 (0) | 2018.02.23 |
14.pwnable cmd1 (0) | 2018.02.23 |