Crackme 7: ELF, protection against code changes

Mar 16, 2018

Link: https://www.root-me.org/en/Challenges/Cracking/ELF-No-software-breakpoints (binary)

There are no obvious strings in the binary, but we can disassemble it and follow the logic. In EntryPoint, we set eax, ebx and ecx, and call a function further down:

xor        ecx, ecx
mov        eax, EntryPoint ; // this is 0x8048080
mov        ebx, 0x8048123
call       EntryPoint+149

The function sets ebx to 0x8048123 - 0x8048080 (which is 163) and resets ecx. 0x8048123 is the very end of the program, so eax to ebx covers the full range of the .text segment.

sub        ebx, eax
xor        ecx, ecx

followed by a loop, which adds to cl the byte at eax and rotates ecx left by 3 bits until we’re at the end of the 163-byte range.

loc_8048119:
add        cl, byte [eax]
rol        ecx, 0x3
inc        eax
dec        ebx
jne        loc_8048119 ; back to the top of the loop

This is computing a sort of hash value in ecx which is based on the entire code of EntryPoint. The value will no longer be the same if we make any changes to the function, preventing us from editing the binary. Once we’re done calculating this secret, we copy it to edx and set ecx to 0x19:

mov        edx, ecx
mov        ecx, 0x19

This is followed by a loop, which looks at two arrays in eax and ebx with a cursor at the same offset:

loc_80480c1:
mov        eax, 0x8049155 ; a hardcoded value
mov        ebx, 0x8049188 ; our input

The first 25 bytes are of these two arrays are respectively [0x1e, 0xcd, 0x2a, 0xd5, 0x34, 0x87, 0xfc, 0x78, 0x64, 0x35, 0x9d, 0xec, 0xde, 0x15, 0xac, 0x97, 0x99, 0xaf, 0x96, 0xda, 0x79, 0x26, 0x4f, 0x32, 0xe0] and our input. loc_80480f6 prints the failure message.

Let’s go over it. We rotate edx right by 1 bit, and read two bytes into from eax and ebx into al and bl.

ror        edx, 0x1
mov        al, byte [eax+ecx-1]
mov        bl, byte [ebx+ecx-1]

We XOR al, bl together, and fail if the value does not match dl. So to make it match, we need bl = al ^ dl.

xor        al, bl
xor        al, dl
jne        loc_80480f6 ; prints a failure message
dec        ecx
jne        loc_80480c1 ; loops back up

Let’s write a program that computes the successive values of al ^ dl: crackme7.c.

$ cd /re/crackme/7/
$ cc -o crackme7 crackme7.c
$ ./crackme7
HardW@re_Br3akPoiNT_r0ckS