Artificial truth

The more you see, the less you believe.

[archives] [latest] | [homepage] | [atom/rss/twitter]

Defeating Thellurik
Sun 30 December 2012 — download

You can get the file here, or here (local mirror)


HI, Thellurik is my first keygen-me for linux systems, i hope you will enjoy it. It's surely easy for veteran but surely interesting for others.



  1. radare2 0.9 @ linux-little-x86 : segfault
  2. IDA v6.3.120730 demo: internal error and crash
  3. GNU objdump (GNU Binutils for Ubuntu) 2.22: BFD: warning: thellurik has a corrupt string table index - ignoring
  4. elfsh-0.81-a8-dev@local: screw you
  5. GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04: some warnings about the string table index

So, looks like our binary has a screwed string table index, this is confirmed by readelf: Section header string table index: 4919 (For those who are wondering why 4919d, it's because 1337h ;) ).

But who cares since gdb is only issuing warnings, and run happily on it? The file tells us that the binary is not stripped, good. Let's check its exports: printf, puts, scanf, memset, main, strcmp, ... Wait, strcmp ? If you are lazy, just set a breakpoint on the strcmp function, or use the LD_PRELOAD trick, and you've got your key. But respectable people write keygens.

If you dissassemble the main function in gdb, (disassemble 0x08048460,0x08048647) you'll see a shitload of asm lines. Don't panic: since we've got the exports, we'll be able to do some educated guess. The main function can be split in two important parts:

First part

0x08048551: mov eax,DWORD PTR [ebp-0xc]
0x08048554: movzx eax,BYTE PTR [ebp+eax*1-0x74]
0x08048559: movsx edx,al
0x0804855c: lea eax,[ebp-0x8]
0x0804855f: add DWORD PTR [eax],edx
0x08048561: lea eax,[ebp-0xc]
0x08048564: add DWORD PTR [eax],0x1
0x08048567: mov edx,DWORD PTR [ebp-0xc]
0x0804856a: lea eax,[ebp-0x74]
0x0804856d: mov ecx,0xffffffff
0x08048572: mov DWORD PTR [ebp-0x118],eax
0x08048578: mov eax,0x0
0x0804857d: cld
0x0804857e: mov edi,DWORD PTR [ebp-0x118]
0x08048584: repnz scas al,BYTE PTR es:[edi]
0x08048586: mov eax,ecx
0x08048588: not eax
0x0804858a: sub eax,0x1
0x0804858d: cmp edx,eax
0x0804858f: jb 0x8048551

[ebp+0x74] is likely a pointer on a chars table (line 2). It seems like [ebp-0x8] is the variable which holds the sum of the chars (line 5)). The rest of the function is just (lightly obfuscated) blackmagic to get the size of the table, that can roughly be translated to:

    sum += name[i];

Second part

0x08048591: mov edx,DWORD PTR [ebp-0x8]
0x08048594: add edx,0x3a2f49
0x0804859a: movzx eax,BYTE PTR [ebp-0x74]
0x0804859e: movsx ecx,al
0x080485a1: mov eax,edx
0x080485a3: shl eax,cl
0x080485a5: xor eax,0x1337
0x080485aa: mov DWORD PTR [ebp-0x10],eax
0x080485ad: mov eax,DWORD PTR [ebp-0x10]
0x080485b0: mov DWORD PTR [esp+0x8],eax
0x080485b4: mov DWORD PTR [esp+0x4],0x8048808
0x080485bc: lea eax,[ebp-0x42]
0x080485bf: mov DWORD PTR [esp],eax
0x080485c2: call 0x80483b0
0x080485c7: lea eax,[ebp-0x42]
0x080485ca: mov DWORD PTR [esp+0xc],eax
0x080485ce: lea eax,[ebp-0xb0]
0x080485d4: mov DWORD PTR [esp+0x8],eax
0x080485d8: mov DWORD PTR [esp+0x4],0x804880c
0x080485e0: lea eax,[ebp-0x114]
0x080485e6: mov DWORD PTR [esp],eax
0x080485e9: call 0x80483b0

Nothing complicated here, except maybe the trick to get al from eax in C:

sum += 0x3a2f49 //EAZ FAG ?
sum = << (name[0] & 0xff) //ecx = al != eax
sum ^= 0x1337

The rest of the function is only functions calls, no more arithmetics. The strings command shows us some this sprintf canvas: ~%s#%s#~ A quick-and-lazy dynamic analysis tells us that the first %s is a constant: 1337.

Our keygen looks like:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char** argv){
    if(argc != 2){
        printf("Error: Usage: %s name", argv[0]);
        return 1;

    const char* name = argv[1];
    int i = 0;
    unsigned long sum = 0;

    for(i=0; i<strlen(name); i++)
        sum +=name[i++];

    sum += 0x3a2f49;
    sum <<= (name[0] & 0xff);
    sum ^= 0x1337;

    printf("name: %sn", argv[1]);
    printf("key: ~1337#%lu#~n", sum);

    return 0;

Editing ELF header

After solving this crackme, I really wanted to give a look to it with IDA. To do so, I used HT editor. Download it - compile it - use it. To select the "elf header" mode among other, press F6. To fix the field, just set it to 0, and voilà, you're able to open it in IDA.


Nothing complicated, since gdb handle the fact that the string table index is fucked up, but this was the opportunity to play around with elf headers (and to do some RE with gdb).

Thank you svenka for this crackme :)

This "defeating ..." was pretty concise, but I'm in holidays !