ret2shellcode与沙箱
这一块的题难度上升的有点快,已经涉及到基本的汇编知识了,并且明显看出来在为接下来的ret2syscall做铺垫,exp也是不好理解,接下来进行详细的讲解
沙箱
seccomp函数,它会阻止进程的一部分系统调用,比如我们的execve,这种情况下我们无法直接拿到shell,只能去通过orw,即open-read-write去读出flag文件
seccomp-tools dump ./pwn
我们可以通过上述指令查看允许的系统调用
pwntools的前置语法基础
我们需要一些pwntools的语法,不过这并不算难
asm(code, vma=0, extract=True, arch=None, os=None)
后面三个不用管,我们重点看前两个
code是必填的,它包含汇编指令的字符串
vms是虚拟内存地址,是指定代码被编译时所处的起始地址
asm(shellcraft.你要调用的函数)
shellcraft不仅可以帮助我们生成shellcode的汇编,还可以帮我们生成某个函数的汇编代码,这样就不需要我们自己生成了
如果我们需要写连续的汇编指令,可以用分分号连接
eg:ctfshow pwn69
1 | __int64 __fastcall main(int a1, char **a2, char **a3) |
1 | __int64 sub_400949() |
1 | void sub_400906() |
1 | int sub_400A16() |
第一个函数里存在沙箱,第三个函数里给了我们栈溢出的地方
一般来说遇到read函数我们就要注意了,因为它通常会限制我们溢出的长度,本题就是只给了我们0x38的余地,这显然是不够的,但是我们注意到main函数里存在mmap函数,可以放到0x123000处

沙箱只允许我们进行orw这三个函数的系统调用
我一开始的思路和ret2syscall一样,打算先找寄存器的gadget,但是用ROPgadget尝试找了gadget发现是找不到的,所以这个题主要利用的不全是ROP技术,我们是直接在mmap分配的内存里直接写入汇编指令的,不需要费劲一个个跳转了

我们不要用pop rsp,要用jmp rsp
0x0000000000400a01 : jmp rsp
1 | from pwn import * |
在栈迁移里,我们学到在返回地址处,程序调用ret指令,等价于pop rip,会把返回地址弹到rip寄存器里
我们把read(0,mmap_addr,0x100),mov rax,0x123000,jmp rax写到缓冲区开始,然后把返回地址改成jmp_rsp,也就是把jmp_rsp的地址弹到rip里,然后rsp随后指向sub rsp,0x30; jmp rsp,也就是把rsp往下减0x30个字节到缓冲区开始,然后再jmp rsp跳转过去。接下来我们执行read(0,mmap_addr,0x100)这个时候程序挂起等待我们输入,并且把输入的内容存到mmap里,然后mov rax,0x123000,jmp rax,跳转到mmap处,开始执行shellcode
总结
这种ret2ORW的题目本质上还是ret2shellcode,只不过需要我们自己套模板,这里的jmp rsp是精妙之处,要重点理解







