You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现上下文切换时替代混淆jmp_buf的可行方案问询

针对Linux jmp_buf指针混淆的替代实现方案

你给出的i64_ptr_mangle是x86_64架构下glibc用于混淆jmp_buf中敏感指针的标准实现,逻辑固定为「指针异或TLS段中的canary值(fs:0x30)+ 循环左移17位」,针对你的基础线程库开发需求,有3种可行替代方案:


方案1:实现配对的解混淆/重混淆函数

不需要替换现有逻辑,直接根据加密逻辑反向实现解密函数,修改完指针后再重新加密写回jmp_buf即可,代码如下:

// 原有加密函数,用于修改后重新混淆指针
static long int i64_ptr_mangle(long int p) {
    long int ret;
    asm(" mov %1, %%rax;\n"
        " xor %%fs:0x30, %%rax;"
        " rol $0x11, %%rax;"
        " mov %%rax, %0;"
        : "=r"(ret)
        : "r"(p)
        : "%rax"
    );
    return ret;
}

// 新增解密函数,用于读取jmp_buf中的原始指针
static long int i64_ptr_demangle(long int p) {
    long int ret;
    asm(" mov %1, %%rax;\n"
        " ror $0x11, %%rax;" // 反向操作:先循环右移17位
        " xor %%fs:0x30, %%rax;" // 再异或canary值
        " mov %%rax, %0;"
        : "=r"(ret)
        : "r"(p)
        : "%rax"
    );
    return ret;
}

操作逻辑:

  • 调用系统setjmp保存上下文后,用i64_ptr_demangle把jmp_buf中存储的rsp、rbp、rip字段解密得到原始值
  • 修改对应指针为你线程的自定义栈地址、入口地址后,用i64_ptr_mangle重新混淆后写回jmp_buf对应位置
  • 后续调用longjmp即可正常跳转到自定义上下文执行

方案2:完全自定义轻量上下文保存逻辑,绕开系统jmp_buf

如果你不想依赖glibc的setjmp实现逻辑,避免不同版本glibc混淆规则变动的问题,可以直接用汇编实现极简的上下文保存/恢复逻辑,只保存你需要的寄存器,完全不需要处理混淆:

# 自定义my_setjmp实现,x86_64架构
.global my_setjmp
my_setjmp:
    mov %rbx, (%rdi)
    mov %rbp, 8(%rdi)
    mov %r12, 16(%rdi)
    mov %r13, 24(%rdi)
    mov %r14, 32(%rdi)
    mov %r15, 40(%rdi)
    mov %rsp, 48(%rdi)
    # 保存返回地址作为rip
    mov (%rsp), %rax
    mov %rax, 56(%rdi)
    xor %rax, %rax
    ret

# 自定义my_longjmp实现
.global my_longjmp
my_longjmp:
    mov (%rdi), %rbx
    mov 8(%rdi), %rbp
    mov 16(%rdi), %r12
    mov 24(%rdi), %r13
    mov 32(%rdi), %r14
    mov 40(%rdi), %r15
    mov 48(%rdi), %rsp
    mov 56(%rdi), %rax
    mov %rax, (%rsp)
    mov %rsi, %rax
    ret

对应的C头文件定义:

// 自定义上下文结构,无混淆,直接访问字段修改即可
typedef struct {
    long rbx;
    long rbp;
    long r12;
    long r13;
    long r14;
    long r15;
    long rsp;
    long rip;
} my_jmp_buf;

int my_setjmp(my_jmp_buf *env);
void my_longjmp(my_jmp_buf *env, int val);

这个方案完全不依赖系统的setjmp.h和ucontext.h,你可以直接修改结构体里的rsp、rbp、rip字段,不需要任何加解密操作,适合线程库底层开发。


方案3:编译期关闭指针混淆(仅调试用)

如果是开发阶段临时调试用,可以在编译glibc的时候关闭PTR_MANGLE配置选项,或者给你的程序编译时加上-fno-stack-protector参数(部分发行版会同时关闭指针混淆逻辑),但这个方案不推荐生产环境使用,会降低安全性。


内容的提问来源于stack exchange,提问作者Gaurav Chaudhari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 09:15:02