ret2syscall 即通过系统调用控制程序获得shell
Linux系统调用
过程(32位):
1.把系统调用的编号存放在寄存器EAX中
2.传入函数参数到相应的寄存器
3.触发int 80号中断
64位:
1.调用编号存放到rax中
2.传参数到寄存器,前六个参数对应的寄存器: rdi rsi rdx r10 r8 r9
注意:系统调用第四个参数放在r10中,平时的函数第四个参数放在rcx
3.触发syscall命令中断
各个函数的系统调用号:Linux X86架构 32 64系统调用表_32位 syscall-CSDN博客
excve函数
system函数实际上是调用excve函数,ret2syscall基本上是让程序执行execve函数
函数原型
excve("/bin/sh",NULL,NULL)
得到shell
excve在32位下系统调用号为11,在16进制下为0xb,所以eax中应该存放0xb
在传上参数,因此相应寄存器参数如下(32位)
1 | eax = 0xb |
在栈和寄存器上分布如下
实例分析
来源:[CISCN 2023 初赛]烧烤摊儿 | NSSCTF
分析
开启了nx保护和canary保护(canary最后没检查,跟没开一样)
题目情景是到烧烤摊买东西,直到在gaiming()
这个函数中才存在溢出
承包摊位后可以改名调用函数,因此想办法赚钱承包即可。
发现买东西时输入没有检查,因此买负数的东西即可赚钱(卖东西(bushi )
输入v5后v5内的东西拷贝到name中去,因此binsh直接写在v5中就行,binsh最后要加\x00以防止系统一直往下读
之后按照ret2syscall思路向寄存器传参
1 | ROPgadget --binary shaokao --only 'syscall' //找syscall命令 |
64位中excve调用号位59,因此rax中传入59
注:程序内没有单独的pop rdx ; ret
因此利用pop rdx ; pop rbx ; ret
来传参,只不过要多一个参数
或者直接利用pop rax;pop rdx;pop rbx;ret
在给rax传参数时就给rbx传好参数
exp
1 | from pwn import* |
得到flag