about:blog Archives

reversing, python, cookies
Friends: aj deadrom1 fr33tux kiwie


Anatomy of a shitty crack

For obvious reasons, the name of the software analysed in this article will be kept secret. "If you like it, buy it". I also contacted the editor of the software before publishing this blogpost.

As always with articles implying radare2, the goal is more to show what can be done with it rather than to focus on strict efficiency.

Yesterday, I was bored and stumbled upon a cracked version of [...], and was curious about how well it was protected and hard to crack. The pirated GNU/Linux x64 version is from a Turkish guy, and has the sha1sum 49fca1f18a97[...]d04ff407b2f.

radiff2 legit_version cracked_version
0x000081e0 85c00f94c0 => 9090909090 0x000081e0
0x0007c805 85c0 => 9090 0x0007c805
0x0007c80a 84d2 => 9090 0x0007c80a

Only tree offsets, two nearly adjacent and with NOP. Smells like a quick'n'dirty crack.

[0x00406a70]> pd 3 @0x4081e0
         0x004081e0    85c0         test eax, eax
         0x004081e2    0f94c0       sete al
         0x004081e5    84c0         test al, al
[0x00406a70]> pd 3 @0x47c805
         0x0047c805    85c0         test eax, eax
         0x0047c807    0f94c2       sete dl
         0x0047c80a    84d2         test dl, dl
[0x00406a70]>

This looks like a test from the return value from a function.

[0x00406a70]> pd -2 @  0x47c805
         0x0047c7fe    8e00         mov es, [rax]
         0x0047c800    e8eaf7ffff   call fcn.0047bfef
[0x00406a70]> pd -2 @0x4081e0
         0x004081d9    8e00         mov es, [rax]
         0x004081db    e80f3e0700   call fcn.0047bfef
[0x00406a70]>

This is likely this routine that checks the serial.

[0x00406a70]> afi 0x0047c805
[0x00406a70]>

It seems that r2 didn't detected the function. Since it's a x64 binary, parameters are passed by register.

[0x0047c805]> pd -32 @ 0x0047c805~push
         0x0047c77e    4154         push r12
         0x0047c780    55           push rbp
         0x0047c781    53           push rbx

Three pushes in a row, likely the function prologue. The af commands tells radare2 to analyse the function at the given offset.

[0x0047c805]> af @ 0x0047c77e
[0x0047c805]>

For the second function, lets try something else. Some compiler are padding function with 'nop; ret' pairs.

[0x00406a70]> pd -30 @ 0x004081e0~ret
         0x0040817a    c3           ret
         0x0040817c    c3           ret
[0x00406a70]> pd -30 @ 0x004081e0~nop
         0x0040817b    90           nop
         0x0040817d    90           nop
[0x00406a70]> pd 4 @ 0x0040817a
         0x0040817a    c3           ret
         0x0040817b    90           nop
         0x0040817c    c3           ret
         0x0040817d    90           nop
[0x00406a70]> pd 10 @0x0040817d + 1
         0x0040817e    4154         push r12
         0x00408180    4989fc       mov r12, rdi
         0x00408183    55           push rbp
         0x00408184    4c89c5       mov rbp, r8
         0x00408187    53           push rbx
         0x00408188    4889cb       mov rbx, rcx
         0x0040818b    4883ec70     sub rsp, 0x70
         0x0040818f    488d7c2418   lea rdi, [rsp+0x18]
         0x00408194    488d4c2428   lea rcx, [rsp+0x28]
         0x00408199    48893424     mov [rsp], rsi
[0x00406a70]> af @0x0040817e
[0x00406a70]> 

It seems that we're right! Now that we helped radare2 with analysis, it should display XREF correctly:

[0x00406a70]> pd 1 @ 0x0047bfef
           ; CALL XREF from 0x0047c800 (fcn.0047c77e)
           ; CALL XREF from 0x0040a199 (fcn.0040a0e5)
           ; CALL XREF from 0x004081db (fcn.0040817e)
           ; CALL XREF from 0x00408218 (fcn.004081e5)
         0x0047bfef    4155         push r13

It seems that the crack author missed some checks, and they may be even more, but at least, this crack wasn't malicious.

Instead of patching some of the return value checks, the right way to do it would be to overwrite 0x0047bfef prologue with something like this:

xor eax, eax
inc eax
ret