Tuesday, March 15, 2022

[SOLVED] Can `dlopen` be used to load and mmap a static ELF executable (not library)?

Issue

If file anexe is static compiled, no symbols, no exports, ELF, can dlopen("anexe", RTLD_LAZY) be used to map it into memory?

My goal isn't to be able to reference symbols -- there are no symbols. Rather, my goal is to be able to call its functions given their addresses (which are fixed, not PIC), and to read its data given address. I was planning on doing this all via mmap, but realized that dlopen, though not designed for thhis, might be able to do it all for me.

Can dlopen be used that way?

When I try it, I get dlerror: cannot dynamically load executable - is there any workaround for this?


Solution

If file anexe is static compiled, no symbols, no exports, ELF, can dlopen("anexe", RTLD_LAZY) be used to map it into memory?

No (but see below).

My goal isn't to be able to reference symbols -- there are no symbols. Rather, my goal is to be able to call its functions given their addresses (which are fixed, not PIC), and to read its data given address.

Note that a non-PIE executable can only be loaded at the address it was linked at. You can find which address that is by examining its program headers (programmatically, or with readelf -Wl).

Once you know which address it should be loaded at (and assuming that address is not already occupied by your own executable), then you can perform a series of mmap calls to "load" that executable into memory, and after that you can call its functions and read its data.

One complication is that the executable's initializers will not have run (you didn't call its _start, nor would you want to), and so functions in it may not run correctly, may crash, etc.

For example, given this binary:

$ echo "int main() { return 0; }" | gcc -xc - -static -no-pie -o a.out
$ readelf -Wl a.out | egrep 'Type|LOAD'

  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  LOAD           0x000000 0x0000000000400000 0x0000000000400000 0x000518 0x000518 R   0x1000
  LOAD           0x001000 0x0000000000401000 0x0000000000401000 0x07fd01 0x07fd01 R E 0x1000
  LOAD           0x081000 0x0000000000481000 0x0000000000481000 0x026660 0x026660 R   0x1000
  LOAD           0x0a7928 0x00000000004a8928 0x00000000004a8928 0x0059c8 0x007298 RW  0x1000

you would need to perform 4 mmap calls (one for each LOAD segment), with MAP_FIXED. The address, file offset, size and protection arguments for mmap are obvious.

The mmap arguments for the last segment may not be: you would need to round address and offset down to Align, and extend the size by 0x928 to account for that rounding.



Answered By - Employed Russian
Answer Checked By - Marilyn (WPSolving Volunteer)