In this challenge we were given a corrupt ELF file. Looking at it under a hex editor we can see that the parts of the header had been replaced by the byte 0xCC. By comparing this to other headers of ELF binaries, we were able to figure out the replaced bytes and get the ELF to run.
There were 3 blocks of replaced bytes.
First block was replaced with 01 01 01 00 00 00 00 00 00 00 00 00
Second block with 34 80 04 08
Third block with 00 80 04 08 00 80 04 08
When we run the ELF we are requested to input a key. Looking at the code in IDA we can see that the key needs to be a 32-bit integer inputted in hex.
mov dword ptr [esp], offset s ; "Here's no way,\nyou must give the key:" call _puts mov dword ptr [esp+4], 20h ; n lea eax, [esp+3Ch] mov [esp], eax ; s call _bzero mov dword ptr [esp+8], 1Fh ; nbytes lea eax, [esp+3Ch] mov [esp+4], eax ; buf mov dword ptr [esp], 0 ; fd call _read mov dword ptr [esp+8], 10h ; base mov dword ptr [esp+4], 0 ; endptr lea eax, [esp+3Ch] mov [esp], eax ; nptr call _strtoul
Our input is then hashed and checked against 2 DWORDs 0x23D18103 and 0x32F5E109. These hash functions use data stored at address 0x1060 in the binary file. Brute forcing the input yielded the key: 0xE13EEE37
Now it was time to figure out what to do with this key. The data at address 0x1060 was definitely not random data, so we tried different ways to decrypt it using the key. It turns out that by adding the key 0xE13EEE37 to each DWORD of the encrypted data produced a 20 byte ELF header, with unrecognizable data after it. It was at this point that the meaning of the title "ElfQuest 2" became clear. We found a writeup to ElfQuest here. By analysing frequencies on the first 20902 bytes of the decrypted data, we were able to obtain a 256-byte file, with another ELF header.
This resulting file had patterns to it, especially with the null bytes, recognizable addresses such as 8C 80 04 08 and recognizable code such as 0xCD 0x80, opcode for the instruction int 0x80. This caused us to this file and here are the results:
The code reads 0x28 bytes starting at address 0x804808C and multiplies it by constant 0x4B. By multiplying the bytes at that corresponding address in the binary file, we were able to get the flag.