magic_elf (ELF File Format Analyzer)
Posted: April 4, 2009
The ELF File Format
Here's a program for dumping out the contents of ELF files. There are lots of other ELF dumping programs around, but this has been very useful to me for several projects, including analyzing core dumps when a lot of information was missing.
One of the original reasons I wrote this was to see if it's possible to get a function in a library compiled on Linux (with no calls to other libraries) to execute on Windows. In 32 bit mode, since the ABI is the same this works.
At my job this tool has been very useful in analyzing core files when the only thing I had is the core and a version of the library I needed to debug that had symbols in it. I gave magic_elf the ability to change registers in the core file to point the stack and instruction pointer to the library (past code that I didn't have symbols for which caused gdb to not be able to show a proper stack trace). There is an example of this below using a forced crash in Java.
I have also been using this to debug creating ELF files with naken_asm and to modify libraries to force certain functions in other libraries to not execute but to return a specified value instead.
Related Projects @mikekohn.net
Key Features (from the version below)
At the bottom of the page is a link to the git repository. After cloning just type: make
Analyzing A Java Core File
I added a Java/JNI program in the samples directory of the repository that forces a crash / core file that can be analyzed with magic_elf. I put a small tutorial up: Analyzing Core Files. It shows how to reset the stack pointer using magic_elf so that gdb can pull up a stack trace even if the orginal java executable is missing.
The core dump has all the .class files that were loaded embedded in it so there is a feature -extract_java that can search for them (by looking for the siganture 0xcafebabe) and dump them back to disk with their original name:
All the .class files are dumped to the current directory.
Loading an ELF On Windows
Currently this program only compiles on Unix due to the mmap stuff, although I do plan on fixing this when I get a chance. But just out of curiousity, I made some changes to magic_elf so it would compile on Windows temporarily so I could test the test_lib.c program to see if I could load a UNIX ELF library on Windows and call a function.
So I updated test_lib.c so instead of calling elf_open() it mallocs a chunk of memory the size of test32.so, dumps the entire library into a memory buffer, and calls elf_open_from_mem() on the buffer. Because I was running this on Windows XP with a CPU that doesn't support the NX bit, it's possible to run code out of malloc()'d RAM. Had this been done on a CPU with the NX bit and Windows supports NX, the memory would have to had been allocated using VirtualAlloc() or CreateFileMapping() with execute permission on the memory pages. So, after doing an elf_open_from_mem() I could find the address of my int add_nums(int,int) function using the same find_symbol_address() call and since the library was compiled as position independant code (-fPIC) I was able to call this function on Windows. Cool eh? :). The only thing left is to replace external libraries with Windows libraries. For example if printf() is on rh library import list, i could automatically replace it with a LoadLibrary to msvcrt.dll's printf().
How To Use
So actually there are other ELF tools out there that are much more useful such as objdump and readelf, but I made this one mostly to learn stuff and I have a couple features these don't have. First of all (as stated above) magic_elf can be built into a library so that a .so file can be loaded into memory and functions can be called into the .so file from another program without using dlopen() giving the option to call into Linux .so libraries on Windows. Secondly I added a -modify_function option to the magic_elf program so that functions can be changed to just return some set value.
So after typing "make" in the magic_elf directory, 3 things will be built: magic_elf, test.so, and test32.so. The magic_elf program is just a simple program to parse out sections from an elf file and display them similar to objdump and readelf. So to test this, type:
A bunch of headers will come out of that. So really this isn't much more interesting than what objdump / readelf can do, but there is a command line option -modify_function. Knowing that test.so has a function defined as: int return10_32(); and that this function will simply return 10 when I call it, if I do:
Then this function is changed to be simply:
As of October 15, 2011 I added a feature that if your library or standard executable has something like: char *version = "10.1"; for example, magic_elf can find these symbols and display their value to the screen with:
After typing that magic_elf will show: version="10.1"
So lastly, magic_elf can be compiled as a library and used in other programs also. Typing "make lib" will create a libmagic_elf.so that can be linked into other programs. There is an included sample program called test_lib.c that demonstrates simply opening up a library, returning a pointer to a function, and calling that function.
Copyright 1997-2023 - Michael Kohn