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

如何在无法修改a.cpp时获取命名空间内静态变量mysecret的地址?

如何在无法修改a.cpp的情况下获取secret命名空间的静态变量mysecret?

首先明确你的场景:我们有两个文件,a.cpp里的secret命名空间包含一个静态变量mysecret,_main函数先通过cin读取这个变量的值,再调用hack(),要求hack()返回的值必须和mysecret一致,且完全不能修改a.cpp。初始的b.cpp里hack()只是固定返回31,显然没法适配任意输入的mysecret,所以核心目标是拿到这个静态变量的实际值。

先贴出你的代码方便参考:

原文件代码

a.cpp

#include <iostream>
#include <cassert>
using namespace std;
int hack();
typedef int (*hackFunction)();
namespace secret {
static int mysecret;
int _main(hackFunction hack) {
cin >> mysecret;
assert(hack() == mysecret);
return 0;
}
}
int main() {
return secret::_main(hack);
}

初始b.cpp

int hack() {
return 31;
}

你提到反汇编后发现mysecret通过0x0(%%rip)寻址,这说明在x86-64架构下,这个静态变量的地址是用RIP相对偏移计算的——核心思路就是在hack()里拿到合适的RIP值,结合偏移算出mysecret的地址,最后取值返回即可。下面是几个可行的方案:


方案1:用GCC内置函数获取返回地址计算

GCC提供了内置函数__builtin_return_address(0),它能获取当前函数的返回地址——也就是调用hack()的那条指令的下一条指令的RIP值。你只需要根据反汇编结果,算出mysecret相对于这个返回地址的偏移,就能直接计算出变量地址。

举个例子,假设反汇编后发现mysecret的地址相对于hack()返回地址的偏移是-0x10(实际值需要你根据自己的反汇编结果调整),代码可以这么写:

#include <cstdint>

int hack() {
    // 获取hack()的返回地址,即secret::_main中调用hack后的下一条指令地址
    uintptr_t return_rip = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    // 根据实际偏移计算mysecret的地址
    uintptr_t mysecret_addr = return_rip - 0x10;
    // 取值并返回
    return *reinterpret_cast<int*>(mysecret_addr);
}

方案2:直接用汇编获取当前RIP计算

x86-64架构中,可以通过lea rax, [rip]直接获取当前指令的RIP值,结合已知的偏移就能算出mysecret的地址。这种方法更直接,不依赖编译器内置函数,在x86-64的GCC/clang环境下都能使用。

代码示例如下,记得替换成你实际反汇编得到的偏移值:

int hack() {
    int* mysecret_ptr;
    __asm__ volatile (
        "lea rax, [rip + %1]\n"  // 用当前RIP加上偏移得到mysecret的地址
        "mov %0, rax\n"
        : "=r"(mysecret_ptr)  // 输出变量,将计算好的地址存入mysecret_ptr
        : "i"(-0x10)  // 填入实际偏移值,需根据反汇编结果调整
        : "rax"  // 告知编译器rax寄存器会被修改,避免优化冲突
    );
    return *mysecret_ptr;
}

方案3:静态编译时利用ELF符号偏移(适合固定环境)

如果程序是静态编译的,mysecret作为静态变量会在ELF文件的.data或.bss段有固定偏移地址。你可以先用readelf或objdump工具分析编译后的可执行文件,找到secret::mysecret的偏移,再在运行时计算程序基地址加上该偏移,就能拿到变量地址。

不过这个方法的局限性是,一旦编译环境(如编译器版本、优化选项)改变,偏移值可能会变化,更适合固定环境下使用。


关键注意事项

  • 偏移值必须匹配实际反汇编结果:你提到mysecret在0x0(%%rip),这应该是指访问mysecret的那条汇编指令中,RIP加上0就是变量地址。你需要找到这条指令的地址与hack()调用点地址的差值,才能算出正确的偏移。
  • 注意编译器优化级别:不同的优化选项(如-O0和-O2)会改变指令布局,偏移值也会随之变化,一定要在实际使用的编译环境下反汇编获取偏移。

内容的提问来源于stack exchange,提问作者Alexander Morozov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:39:51