我在库(.so
文件)中定义了一个全局静态变量,该变量要从我的应用程序访问。应用程序在运行时加载.so
库。
是否可以在不修改库代码的情况下访问静态变量?我知道这并不简单,因为我看到一旦完成编译,可变符号本身就会从符号表中消失。我仍然认为可能会有一些骇人听闻的方法(通过抓取符号表等)来访问此变量。有帮助吗?
lib.c -> static struct Abc abc --> compiled to a.so
app.c ->loads a.so and need to access abc variable?
更新:a.so使用gcc -O2 option
进行编译。
答案 0 :(得分:6)
这是不可能的,因为static
全局变量的概念是使它对除当前编译单元以外的任何内容都不可见
如果库开发人员将对象静态化,则可能是出于某种原因,并且他不希望在库代码之外访问该对象
答案 1 :(得分:3)
通常,不能访问静态全局变量是正确的。在某些情况下甚至可以对其进行优化,以使根本不存在固定的内存位置。
但是,如果没有对其进行优化,则当然总会有“骇人听闻”的方式来访问它。但是,爬网符号表不是一种选择,因为符号通常不在此处列出。您必须更深入地研究汇编代码。此示例适用于具有gcc和x86_64 cpu的linux。它假定源可用,以标识汇编代码中的变量访问。
想象以下共享对象源文件:
static int bar = 31337;
int foo (void) {
bar = getpid();
}
bar
是您的静态变量。现在,您可以通过检查反汇编源,从函数bar
中找出foo
的偏移量-尽管整个库都已重定位,该偏移量始终是恒定的。
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);
按要求使用骇客的方式;)