一般来说,静态全局变量不能被访问是正确的。在某些情况下,它甚至可能被优化掉,因此根本不存在固定的内存位置。
但如果它没有被优化掉,那么当然总会有“hackish”的方式来访问它。然而,爬取符号表不是一种选择,因为符号通常不在那里列出。您必须更深入地研究汇编代码。此示例适用于具有 gcc 和 x86_64 cpu 的 linux。它假定源可用,以识别汇编代码中的变量访问。
想象以下共享对象源文件:
static int bar = 31337;
int foo (void) {
bar = getpid();
}
bar 是你的静态变量。现在,您可以通过检查反汇编的源代码,从函数 foo 中找出 bar 的偏移量 - 尽管整个库已重新定位,但它始终保持不变:
objdump -x shared.so
00000000000006a0 <foo>:
6a0: 48 83 ec 08 sub $0x8,%rsp
6a4: 31 c0 xor %eax,%eax
6a6: e8 c5 fe ff ff callq 570 <getpid@plt>
6ab: 89 05 c7 02 20 00 mov %eax,0x2002c7(%rip) # 200978 <_fini+0x2002c0>
6b1: 48 83 c4 08 add $0x8,%rsp
6b5: c3 retq
在这里,您看到函数foo 的地址为6a0(稍后会重新定位),静态全局变量bar 在地址200978 上被访问,这使得总偏移量为200978-6a0 = 2002D8。所以如果你打开共享库
void *h = dlopen("shared.so", RTLD_LAZY);
并查找符号foo
void *foo = dlsym(h, "foo");
你可以通过添加计算出的偏移量来计算bar的地址:
int *a = foo + 0x2002D8;
printf("%d\n", *a);
根据要求,一种骇人听闻的方式;)