从.so文件访问全局静态变量,而无需修改库

时间:2019-01-11 10:47:35

标签: c compiler-construction

我在库(.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进行编译。

2 个答案:

答案 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);

按要求使用骇客的方式;)

相关问题