I solved it as it was intended. Feeling no glory now anymore with that hint being given by @_py tho …
Anyways… First things first impressive solution @ATGC .
As in the extended solution above I first used tools like
gdb
readelf
objdump
xxd/hexdump
on that file.
I came to the same conclusion that the Program Headers were kinda weird with that unknown type.
I didn’t really know how to continue with my created binary logs and hex dumps, until
I read more into that matter on how such an ELF binary is structured.
Let’s take a look at the hex dump and some explanations along the way…
But first here’s an awesome paper on the ELF specifications
An ELF header is 64 bytes in total (0x40) and structured like shown below.
typedef struct {
unsigned char e_ident[EI_NIDENT]; //red
uint16_t e_type; // yellow
uint16_t e_machine; // green
uint32_t e_version; // turquoise
ElfN_Addr e_entry; // blue
ElfN_Off e_phoff; // pink
ElfN_Off e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} ElfN_Ehdr;
Funky colors inc!
Ok what the hell is this supposed to be.
red
Basically e_ident is 16 bytes and the first 4 bytes are fixed: 0x7F, E, L, F. (7f45 4c46)
The 5th byte determines if the program will be running on 32-bit(0x01) or 64-bit(0x02).
The 6th byte indicates the integer format.
The 7th byte is the ELF version ( always 0x01 btw. )
The 8th byte is the ABI (Application Binary Interface)
The 9th byte is the version.
Rest is padding.
=> This makes the red marked area. If you wanna read more about it or why these values are set click the awesome paper above.
yellow
This field determines if its an executable(0x02), an object file(0x01), a shared library(0x03) or a core file(0x04)
=> executable is set. Ok.
green
This one sets the CPU arch basically.
Look up the EM_values here
We have a 0x3e (int=62) which stands for EM_AMD64
turquoise
This one is always 0x01 so just let it be.
blue
Now it’s getting more interesting!
This 8 byte area ( because of 64-bit ELF), marks the virtual address of the programs entry point.
How it’s calculated is a different story, and takes a lot more text.
Just keep that in mind that we can find it here.
pink
This field holds the program header table’s file offset in bytes.
If the file has no program header table, this member holds zero.
The ELF header is 64 bytes (0x40) and this structure will immediately follow.
It should be set to 0x40 <=> ‘4000 0000 0000 0000’ as well then!
So this one is the match winning one!
So let’s edit it to 0x40 and assembly it again:
$ xxd -r exit.dump > new_exit && chmod +x new_exit
The Segfault is gone!
Edit: We didn’t finish looking at the whole ELF header this time, since we found the error quite early!
So don’t take these 6 colors above as “the whole ELF header” .
Final Words
Py labeled this challenge as easy so I jumped the train and thought I’d be done in a couple of minutes (haha…), but then I realized that I lacked heavy knowledge on this internal stuff!
So he made me read page after page to advance and try out a few things.
After finishing this challenge I got to understand that this whole ELF thing was not a small chapter which I can quickly finish, but that it is a damn big book.
I definitely need some more deep diving into this material to fully grasp the concepts of ELF binaries!
It was fun though. These kind of challenges which make you investigate stuff make you learn the most imho