4

I have a global static variable defined in a library (.so file) which I want to access from my application. Application loads the .so library at run time.

Is there a way to access the static variable without modifying the library code? I know it is not straightforward as I see that variable symbol itself will be gone from symbol table once compilation is done. I still think that there could be some hacky way (by crawling symbol table etc) to access this variable. Any help?

lib.c -> static struct Abc abc --> compiled to a.so
app.c ->loads a.so and need to access abc variable?

update: a.so is compiled using gcc -O2 option.

roschach
  • 8,390
  • 14
  • 74
  • 124
deadbeef
  • 621
  • 6
  • 20

2 Answers2

6

In general, it is correct that a static global variable cannot be accessed. It even might be optimized away under some circumstances, so that there doesn't exist a fixed memory location at all.

But if it is not optimized away, then of course there are always "hackish" ways to access it anyway. Crawling the symbol table is however not an option, since the symbol usually is not listed there. You have to dig deeper into the assembly code. This example is for linux with gcc and x86_64 cpu. It assumes, that the source is available, to identify the variable access in the assembly code.

Imagine the following shared object source file:

static int bar = 31337;

int foo (void) {
    bar = getpid();
}

bar is your static variable. You can now find out the offset of bar from the function foo - which is always constant despite relocation of the whole library - by examining the disassembled source:

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  

Here, you see that the function foo has address 6a0 (subject to relocation later) and the static global variable bar is accessed at address 200978, which makes a total offset of 200978-6a0 = 2002D8. So if you open the shared library

void *h = dlopen("shared.so", RTLD_LAZY);

and lookup the symbol foo

void *foo = dlsym(h, "foo");

you can calculate the address of bar by adding the calculated offset:

int *a = foo + 0x2002D8;
printf("%d\n", *a);

A hackish way, as requested ;)

Ctx
  • 18,090
  • 24
  • 36
  • 51
  • but it requires modification of the library source code which OP wants to avoid – 0___________ Jan 11 '19 at 11:40
  • If OP can modify the source code not hacks are needed `static int bar; int getbar(void) { return bar; } void setbar(int b) { bar = b; }` – 0___________ Jan 11 '19 at 11:43
  • 1
    @P__J__ No, this method does not require alteration of the library source code. Which step should that be? – Ctx Jan 11 '19 at 12:19
  • You assume that there is a function which we now how and where it is accessing the variable etc. Very unlikely situation – 0___________ Jan 11 '19 at 13:12
  • 1
    @P__J__ C'mon, give me a library and a static variable to find, I will do it in minutes for you – Ctx Jan 11 '19 at 13:16
  • No prob when I come back home I will – 0___________ Jan 11 '19 at 13:23
  • 1
    Two steps omitted from this answer are (a) Identify an access to the variable in the source code and (b) identify the corresponding object code. The question does not say the source code is available, so (a) may not be possible. – Eric Postpischil Jan 11 '19 at 13:34
  • 1
    @EricPostpischil The question implies, that the source is available, since the existance of a static variable and its relevance/semantic wouldn't be known at all otherwise. – Ctx Jan 11 '19 at 14:19
  • @Ctx: I can tell you a static variable exists without giving you my source. We do not know the source of OP’s knowledge. – Eric Postpischil Jan 11 '19 at 14:22
  • @EricPostpischil I personally think, that the question implies the source is available and I assume that in this answer. If this is untrue, then it is harder, if not impossible, depending on other circumstances. Why do you strive to construct circumstances, where this method fails? Just to see me fail? To tell me, that this answer is unnecessary and I shouldn't have given it in the first place? What is your intention? – Ctx Jan 11 '19 at 14:26
  • @Ctx: I point out the answer omits steps and requires source code that the question does not say is available because the answer omits steps and requires source code that the question does not say is available. Characterizing the circumstances in which a solution will or will not work, and explicitly stating what it requires in order to work, are useful for informing readers whether an answer is useful in their circumstances. However, if you prefer, I can retract my vote up. – Eric Postpischil Jan 11 '19 at 14:36
  • @EricPostpischil As I said, I had the impression you wanted to convey that this is utterly useless, since there is no source available. If your sole intention was to emphasize, that the source code is needed for this method: I admit that (and already admitted it in the comment above and now also in the answer). – Ctx Jan 11 '19 at 14:43
5

It is not possible as the idea of the static global variable is to make it invisible to anything except the current compilation unit

If the library developer made the object static probably it was done for a reason and he did not want this object to accessed outside the library code

0___________
  • 60,014
  • 4
  • 34
  • 74
  • 4
    This answer erroneous concludes that because the semantics of C preclude a solution inside the C semantics that no solution is possible. However, the question requested a “hacky way,” meaning a solution outside C semantics is acceptable, and this answer fails to consider that. – Eric Postpischil Jan 11 '19 at 13:02