I have encountered a quite obscure 32-bit ELF file (that is a crackme) and I still cannot figure out how can it execute. First, beside some "understandable" property that it has not any section:
# readelf --sections SimpleVM There are no sections in this file.
Considering the segments:
# readelf --segments SimpleVM Elf file type is EXEC (Executable file) Entry point 0xc023dc There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x00c01000 0x00c01000 0x013c7 0x013c7 RWE 0x1000 LOAD 0x00019c 0x0804b19c 0x0804b19c 0x00000 0x00000 RW 0x1000
I observe that the first segments
LOAD has size
0x13c7 bytes, and mapped into memory at
0xc01000; the second one is not important because its size is zero. But, the entry point of the ELF file is at
0xc023dc, that means outside any segment
I use also IDA 6.8 (evaluation ver.) to load this file, and IDA says that the entry point is illegal.
Since the program has no
INTERP segment, the first executed instruction must be at
0xc023dc. But this address is outside any "reliably" mapped data, we cannot sure which instruction will be executed. I think that this ELF should have some random behaviors (e.g. it should be crashed usually), but it is not, it executes normally, without any crash.
So my question is: how can this happen?
NB1. In case of someone wants to look at this file, I give the link here, but please do not give directly the solution. I want to handle it myself.
NB2. Using a Pintool to trace out what happens, I find the
OEP of the program is at
0xc01dfa since its trace is:
0xc023dc mov dword ptr [0xc01bf0], 0x252e8 <=== modify address 0xc01bf0 0xc023e6 jmp 0xc01bf0 0xc01bf0 call 0xc01e47 <=== modified instruction 0xc01e47 pop ebp <=== OEP 0xc01e48 call 0xc01dfa 0xc01dfa pop esi 0xc01dfb lea eax, ptr [ebp-0x9] 0xc01dfe mov edi, dword ptr [eax] 0xc01e00 sub eax, edi 0xc01e02 mov edx, eax 0xc01e04 add eax, dword ptr [eax+0x48] 0xc01e07 add eax, 0xfff 0xc01e0c and eax, 0xfffff000 0xc01e11 push 0x1 0xc01e13 push eax ....
But I still cannot understand why the instruction at
0xc023dc is always
mov dword ptr [0xc01bf0], 0x252e8 (so the binary is somehow "self-modified")