[ACCEPTED]-Object file to binary code-ld

Accepted answer
Score: 14

First of all, as other said you should consider 8 using a DLL or SO.

That said, if you really 7 want to do this, you need to replace the 6 linker script. Something like this (not 5 very well tested, but I think it works):

ENTRY(_dummy_start)
SECTIONS
{
    _dummy_start = 0;
    _GLOBAL_OFFSET_TABLE_ = 0;
    .all : { 
        _all = .;
        LONG(f1 - _all);
        *( .text .text.* .data .data.* .rodata .rodata.* ) 
    }
}

Then 4 compile with:

$ gcc -c -fPIC test.c

Link with:

$ ld -T script.ld test.o -o test.elf

And extract the binary 3 blob with:

$ objcopy -j .all -O binary test.elf test.bin

Probably some explanation of the 2 script is welcome:

  • ENTRY(_dummy_start) That just avoids the warning about the program not having an entry point.
  • _dummy_start = 0; That defines the symbol used in the previous line. The value is not used.
  • _GLOBAL_OFFSET_TABLE_ = 0; That prevents another linker error. I don't think you really need this symbol, so it can be defined as 0.
  • .all That's the name of the section that will collect all the bytes of your blob. In this sample it will be all the .text, .data and .rodata sections together. You may need some more if you have complicated functions, in this case objdump -x test.o is your friend.
  • LONG(f1 - _all) Not really needed, but you want to know the offset of your function into the blob, don't you? You cannot assume that it will be at offset 0. With this line the very first 4 bytes in the blob will be the offset of the symbol f1 (your function). Change LONG with QUAD if using 64-bit pointers.

UPDATE: And now a quick'n'dirty 1 test (it works!):

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

typedef void (*f1_t)(char *a, char *b, int len);
f1_t f1;

int main()
{
    char *blob = (char*)valloc(4096);
    FILE *f = fopen("test.bin", "rb");
    fread(blob, 1, 4096, f);
    fclose(f);

    unsigned offs = *(unsigned*)blob;
    f1 = (f1_t)(blob + offs);
    mprotect(blob, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
    char txt[] = "¡hello world!";
    char txt2[sizeof(txt)] = "";
    f1(txt, txt2, sizeof(txt) - 1);
    printf("%s\n%s\n", txt, txt2);
    return 0;

}
Score: 2

You should consider building a shared library 14 (.dll for windows, or .so for linux).

Build the 13 lib like this :

gcc -c -fPIC test.c
gcc -shared test.o -o libtest.so

If you want to load the library 12 dynamically from your code, have a look 11 at the functions dlopen(3) and dlsym(3).

Or if you want to link 10 the library at the compile time, build the 9 program with

gcc -c main.c
gcc main.o -o <binary name> -ltest

EDIT:

I'm really not sure about what I will say here, but this could give you a clue to progress in your research ...

If you don't want to use dlopen and 8 dlsym, you can try to read the symbol table from 7 the .o file in order to find the function 6 address, and then, mmap the object file in 5 memory with the read and execute rights. Then 4 you should be able to execute the loaded 3 code at the address you found. But be carefull 2 with the other dependencies you could meet 1 in this code.

You can check man page elf(5)

Score: 0

Use a cast function pointer.

Here's an example:

#include <stdio.h>

int main()
{
    unsigned char *dst, *src;
    int len;
    void (*f1)(unsigned char *, unsigned char *, int);
    *(void **)(&f1) = 0x..........;
    f1(src,dst,len);
    return 0;
}

To 2 do any more, you'd really need a linker 1 and a dynamic loader.

More Related questions