Even Pardides
Even Pardides

Reputation: 35

Link an ELF binary with a c program

Given only access to a standalone ELF program I want to be able to call a function within the program from my own program. Let's say the below code is main.c

#include <stdio.h>

extern int mystery(int a,int b);

int main() {
        int a = 0;
        int b = 1;
        printf("mystery(a,b) = %d\n",mystery(a,b));
        return 0;
}

The function mystery exists in some elf file not_my_program. What I'm trying to do is something along the lines of

gcc main.c not_my_program

However this gives me an undefined reference error to mystery . I've looked for methods on forums and found that converting this elf file into a shared object file is not possible. I've also looked into compiling main.c into a relocatable object file with

gcc -c main.c

and then using ld to link the elf with main.o but I could not figure out how to do it. The elf is 32 bit but I've omitted the -m32 flag. If the flag is different for ld please let me know. Any help would be very much appreciated.

edit: output of readelf -h not_my_program

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x10e0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          15116 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         11
  Size of section headers:           40 (bytes)
  Number of section headers:         30
  Section header string table index: 29

Upvotes: 0

Views: 1448

Answers (2)

ranga
ranga

Reputation: 380

This hacky way worked with a very simple case.

[ aquila ~ ] $ cat 1.c
int func (int a) { return a * (a-1) ; }
int main(int argc) { return func (argc) ; }
[ aquila ~ ] $ cc 1.c
[ aquila ~ ] $ ./a.out ; echo $?
0
[ aquila ~ ] $ readelf -s a.out | grep func
    43: 0000000000400487    19 FUNC    GLOBAL DEFAULT   11 func
[ aquila ~ ] $ cat 2.c
#include <stdlib.h>
static __attribute__((constructor)) void main() {
  int (*func)() = (int (*)())0x0000000000400487;
  exit(func(3));
}
[ aquila ~ ] $ cc -fPIC -shared 2.c -o a.so
[ aquila ~ ] $ LD_PRELOAD=./a.so ./a.out ; echo $?
6

The caller in 2.c is made into a constructor with an exit so that the main program's main() is not called, in an attempt to limit the execution of the code other than the caller and func() itself. The return value being 6 instead of 0 shows both that the call worked and that the main program's main() did not get called.

Upvotes: 1

Employed Russian
Employed Russian

Reputation: 213526

Given only access to a standalone ELF program I want to be able to call a function within the program from my own program

It sounds like you have an XY problem.

While what you desire is technically possible, the difficulty of doing this is approximately 1000x of what you have tried so far. If you are not prepared to spend a month or two getting this working, you should look for other solutions.

Effectively you would have to write a custom ELF loader to load not_my_program into memory and initialize it, but then call mystery instead of main in it.

Note also that mystery may depend on global data, and that data may be initialized in main, so there is no guarantee that mystery will work at all when called before main.

P.S. Would it be sufficient to call mystery from a debugger? That can be achieved in under 30 seconds.

Upvotes: 0

Related Questions