Keygenning ESET’s CONfidence 2012 Crackme

Intro

Hi again. First, sorry for delaying this post so much, but i am currently so busy, that barly i am finding time for something more than neccessities. Anyways, i dont forget what i promiss, so here comes the post about keygenning the CONfidence 2012 Crackme…

In contrary to my previous post (focused on obtaining the key) now i will focus on  analysis of the obfuscated algorithm used in generating MMX instructions. I assume, that you read my previous post, so if not – please refer to it.

If you don’t care about tutorial, just want to see the keygen – it’s here:

* requires: Microsoft Visual C++ 2008 Redistributable Package

Tools used

  • ImmunityDbg (for it’s very useful & handy feature, which i will use a lot in deobfuscating  – from context menu : Analysis -> During next analysis treat selection as -> Commands)

Analysis

As we know, the MMX instructions are stored in a piece of memory starting at 403090. Generation of MMX instructions comes directly before the call to it, so it’s easy to spot. Before, the piece of memory from 403090 to 4044d0 is cleared (with RtlZeroMemory).

Pay attention at arguments, which are passed to the generating function (40118A). Content of EBX is pretty obvious – it is a pointer to the memory to be filled (304090). But in ESI there is 403000 and it means…

The piece of memory, where the hashes are stored. From 403000 to 40300f there is a copy of hash#1 (md5 of the given username). It is important information – this hash will be used in generating MMX instructions.

So, lets follow inside the generating function. Before the user-specific instructions will be genetated, first the MMX prolog is decrypted.

Six dwords, stored at memory addresses from 417a8 are XOR-ed with 45534554. And the result is:

Looks familiar? Yeah, it was easy, but now the real fun begins… :)

Some initial values are set. ECX = 100h = 256… If you remember, there are 256 blocks of MMX instructions, so it may have something to deal with it…

Then it comes to processing of the hash#1. This part is slightly obfuscated, so i will explain it.

004010B6   $ 56             PUSH ESI
004010B7   . 52             PUSH EDX
004010B8   . 8B7424 0C      MOV ESI,DWORD PTR SS:[ESP+C]             ;  Unpacked.00403000
004010BC   . 8B16           MOV EDX,DWORD PTR DS:[ESI]               ;  EDX = DS:[403000]
004010BE   . 81E2 87000000  AND EDX,87
004010C4   . 0F9BC2         SETPO DL
[...]
004010EA   . 33C0           XOR EAX,EAX
004010EC   . D126           SHL DWORD PTR DS:[ESI],1
004010EE   . D156 04        RCL DWORD PTR DS:[ESI+4],1
[...]
004010F6   > D156 08        RCL DWORD PTR DS:[ESI+8],1
004010F9   . D156 0C        RCL DWORD PTR DS:[ESI+C],1
[...]
0040111A   > 13C0           ADC EAX,EAX
0040111C   . 33C2           XOR EAX,EDX
0040111E   . 0906           OR DWORD PTR DS:[ESI],EAX
00401120   . 5A             POP EDX
00401121   . 5E             POP ESI
00401122   . C2 0400        RETN 4

As we see, the piece of memory containing hash#1 is modified after each execution of those instructions. Value of EAX is modified – it changes according to the content of memory at 403000 – that’s how the value of hash influences the process of generating MMX instructions. But obviously, we need to know details… The question is, how exectly every MMX instruction is generated and what is the connection between it and the hash/processed hash?

The previously described function is called twice. The result of first call is stored in EDX. (I will denote this function as get_cmd_base).

00401125   $ 52             PUSH EDX
00401126   . 56             PUSH ESI
00401127   . 8B7424 0C      MOV ESI,DWORD PTR SS:[ESP+C]             ;  ESI = 403000
0040112B   > 51             PUSH ECX                                 ;  bgn#1
[...]
0040114C   . 59             POP ECX
0040114D   . 56             PUSH ESI
0040114E   . E8 63FFFFFF    CALL Unpacked.004010B6        ; modify memory at 403000
00401153   . 8BD0           MOV EDX,EAX    ; EAX  = result of function at 4010B6
00401155   . 56             PUSH ESI
00401156   . E8 5BFFFFFF    CALL Unpacked.004010B6            ; modify (again) memory at 403000
0040115B   . 8D0450         LEA EAX,DWORD PTR DS:[EAX+EDX*2]
[...]
00401181   . 85C0           TEST EAX,EAX
00401183   >^74 A6          JE SHORT Unpacked.0040112B               ;  ;goto #bgn1
00401185   . 5E             POP ESI
00401186   . 5A             POP EDX
00401187   . C2 0400        RETN 4

Then, the first result is multiplied by 2 and added to second result in EAX.

DWORD get_cmd_base(BYTE *hashBuffer)
{
    DWORD eax, edx;
do {
edx = process_hash(hashBuffer);
eax = process_hash(hashBuffer);
eax = eax + edx * 2;
} while (eax == 0);

return eax;
}

What are the possible valueas of EAX?

EAX = EAX + EDX * 2

where right side EAX and EDX are results from 403000 modifying function. So, EAX, EDX can take a value either 0 or 1. Means left side EAX (res) is:

| EAX | EDX | res |
-------------------
|  0  |  0  |  0  |
|  1  |  0  |  1  |
|  0  |  1  |  2  |
|  1  |  1  |  3  |
-------------------

If EAX == 0, then everything is repeated once again – (after some obfuscation) we go back to the same piece of code. If EAX != 0, then instruction is generated on its base.

Below is how the first instruction comes. The first instruction is MOVQ [MM6/MM7], [MM0/MM1]

0040120A   > 56             PUSH ESI
0040120B   . E8 15FFFFFF    CALL Unpacked.00401125
00401210   . D1E8           SHR EAX,1
00401212   . F7D8           NEG EAX
00401214   . 83E0 01        AND EAX,1
[...]
0040122B   > 8BEB           MOV EBP,EBX
[...]
0040124B   > 81E5 00070000  AND EBP,700
00401251   . C1ED 05        SHR EBP,5
00401254   . 81CD C6000000  OR EBP,0C6
0040125A   . 33E8           XOR EBP,EAX
[...]
0040147D   $ 8BC5           MOV EAX,EBP
0040147F   . C1E0 18        SHL EAX,18
[...]
004014A5   . 0D CC0F7F00    OR EAX,7F0FCC                            ;  MOVQ MMx, MMy
004014AA   . C1C8 08        ROR EAX,8
004014AD   . 8907           MOV DWORD PTR DS:[EDI],EAX
004014AF   . 83C7 03        ADD EDI,3
[...]
004014D0   > 8BC3           MOV EAX,EBX
004014D2   . C1E8 1F        SHR EAX,1F
004014D5   . 33D8           XOR EBX,EAX
004014D7   . C3             RETN

The first out of 6 instructions is generated…

And then, generating next instruction: MOVQ [MM7/MM6],[MM2/MM3/MM4/MM5].

The choise of first register depends on the perevious. if previuosly we had MOVQ MM6,[...] now there must be MOV MM7,[...]. The second choise is independent.

00401284   . 81CB 00000080  OR EBX,80000000
[...]
004012A8   > 8BC3           MOV EAX,EBX
004012AA   . 83E0 07        AND EAX,7
004012AD   . C1E0 03        SHL EAX,3
004012B0   . 81E5 C7000000  AND EBP,0C7
004012B6   . 0BE8           OR EBP,EAX
004012B8   . 83F5 01        XOR EBP,1
[...]
0040147D   $ 8BC5           MOV EAX,EBP
0040147F   . C1E0 18        SHL EAX,18
[...]
004014A5   . 0D CC0F7F00    OR EAX,7F0FCC                            ;  MOVQ MMx, MMy
004014AA   . C1C8 08        ROR EAX,8
004014AD   . 8907           MOV DWORD PTR DS:[EDI],EAX
004014AF   . 83C7 03        ADD EDI,3
[...]
004014D0   > 8BC3           MOV EAX,EBX
004014D2   . C1E8 1F        SHR EAX,1F
004014D5   . 33D8           XOR EBX,EAX
004014D7   . C3             RETN

The second out of 6 instructions…

Third instruction:

As we know, 3-rd, 4-ty and 5-th instructions are various. Here we see from where this variety comes. The call to an instruction generating procedure is done to various places in memory, depeending on EAX.

004012DE   > 56             PUSH ESI                                 ;  Unpacked.00403000
004012DF   . E8 41FEFFFF    CALL Unpacked.00401125
[...]
00401307   . 8BEB           MOV EBP,EBX
00401309   . 83E5 07        AND EBP,7
0040130C   . 81CD F0000000  OR EBP,0F0
00401312   . FF1485 6D14400>CALL DWORD PTR DS:[EAX*4+40146D]
00401319   . E8 07000000    CALL Unpacked.00401325                   ;  //after #3

EAX = {1, 2, 3}
[EAX*4+40146D] = {401471, 401475, 401479}

EAX = 1 -> call 4015A6
EAX = 2 -> call 4016C3
EAX = 3 -> call 4014D8

As we see, in each of these 3 cases, the function at 401125 is called. It leads, after some obfuscation, again to 40114D (described above, which result is “res”). Then, the “res” is used in further operations. After deobfuscation it is:

If EAX = 1

004015A6   $ 56             PUSH ESI                                 ;  Unpacked.00403000
004015A7   . E8 79FBFFFF    CALL Unpacked.00401125
004015AC   . 8AE0           MOV AH,AL
004015AE   . 80E4 01        AND AH,1
004015B1   . C0E4 04        SHL AH,4
004015B4   . 80CC EF        OR AH,0EF
[...]
004015DA   . 8AD0           MOV DL,AL
004015DC   . 80E2 02        AND DL,2
004015DF   . D0E2           SHL DL,1
004015E1   . 80CA FB        OR DL,0FB
[...]
00401602   > 22D4           AND DL,AH
[...]
00401618   > 8AF0           MOV DH,AL
0040161A   . 80E6 01        AND DH,1
0040161D   . F6DE           NEG DH
[...]
00401642   . 56             PUSH ESI
00401643   . E8 DDFAFFFF    CALL Unpacked.00401125
00401648   . 22F0           AND DH,AL
0040164A   . 32D6           XOR DL,DH
[...]
0040166A   > 8BC5           MOV EAX,EBP
0040166C   . 0FB6D2         MOVZX EDX,DL
0040166F   . 0FB6C0         MOVZX EAX,AL
00401672   . C1E0 10        SHL EAX,10
00401675   . C1E2 08        SHL EDX,8
[...]
00401691   > 33C2           XOR EAX,EDX
00401693   . 35 0F0000CC    XOR EAX,CC00000F
00401698   . 8907           MOV DWORD PTR DS:[EDI],EAX
0040169A   . 83C7 03        ADD EDI,3
[...]
004016BB   > 8BC3           MOV EAX,EBX
004016BD   . C1E8 1F        SHR EAX,1F
004016C0   . 33D8           XOR EBX,EAX
004016C2   . C3             RETN

If  (EAX = 2):

004016C3   $ 51             PUSH ECX
004016C4   . 56             PUSH ESI
004016C5   . E8 5BFAFFFF    CALL Unpacked.00401125
004016CA   . 8AC8           MOV CL,AL
[...]
004016D1   > 80E1 01        AND CL,1
004016D4   . B4 01          MOV AH,1
004016D6   . D2E4           SHL AH,CL
004016D8   . F6D4           NOT AH
004016DA   . C0C4 04        ROL AH,4
[...]
00401700     24 02          AND AL,2
00401702     F6D0           NOT AL
00401704     D0C0           ROL AL,1
00401706     22E0           AND AH,AL
[...]
0040172B     8BCD           MOV ECX,EBP
0040172D     25 00FF0000    AND EAX,0FF00
00401732     0FB6C9         MOVZX ECX,CL
00401735     C1E1 10        SHL ECX,10
00401738     0BC1           OR EAX,ECX
0040173A     35 0F0000CC    XOR EAX,CC00000F
[...]
0040175D   > 8907           MOV DWORD PTR DS:[EDI],EAX
0040175F   . 83C7 03        ADD EDI,3
00401762   . 8BC3           MOV EAX,EBX
00401764   . C1E8 1F        SHR EAX,1F
00401767   . 33D8           XOR EBX,EAX
00401769   . 59             POP ECX
0040176A   . C3             RETN

If (EAX =3)

004014D8   $ 56             PUSH ESI
004014D9   . E8 47FCFFFF    CALL Unpacked.00401125
[...]
004014DE   . D0E8             SHR AL,1
004014E0   . 8AD0             MOV DL,AL
004014E2   . C0E2 05          SHL DL,5
[...]
00401503   > 56               PUSH ESI                               ;  Unpacked.00403000
00401504   . E8 1CFCFFFF      CALL Unpacked.00401125
00401509   . 8AF0             MOV DH,AL
0040150B   . 8BC5             MOV EAX,EBP
0040150D   . C0E8 03          SHR AL,3
[...]
00401533   > 24 07            AND AL,7
00401535   . 0C F0            OR AL,0F0
00401537   . 32D0             XOR DL,AL
[...]
00401557   > 56               PUSH ESI                                 ;  Unpacked.00403000
00401558   . E8 C8FBFFFF      CALL Unpacked.00401125
0040155D   . 0C 70            OR AL,70
[...]
00401573   > C1E0 08          SHL EAX,8
00401576   . 0C 0F            OR AL,0F
00401578   . C1E2 10          SHL EDX,10
0040157B   . 33C2             XOR EAX,EDX
[...]
004015A0   . 8907             MOV DWORD PTR DS:[EDI],EAX
004015A2   . 83C7 04          ADD EDI,4
004015A5   . C3               RETN

As we see, when the EAX = 3 some 4-byte instruction is created (like PSLLD MM6,2). Other two cases creates 3-byte instructions (like PSUBW MM6,MM3).

Fourth instruction:

0040132D   > 56               PUSH ESI
0040132E   . E8 F2FDFFFF      CALL Unpacked.00401125
[...]
00401351   > 8BEB             MOV EBP,EBX
00401353   . 83E5 07          AND EBP,7
00401356   . 81CD F8000000    OR EBP,0F8
0040135C   . FF1485 6D14400>  CALL DWORD PTR DS:[EAX*4+40146D]

- then if follows analogicaly like 3-rd.

Fifth

[...]
00401377   > 81E3 FFFFFF7F  AND EBX,7FFFFFFF
0040137D   . 56             PUSH ESI                                 ;  Unpacked.00403000
0040137E   . E8 A2FDFFFF    CALL Unpacked.00401125
00401383   . D1E8           SHR EAX,1
[...]
004013A8   . F7D8           NEG EAX
004013AA   . 83E0 09        AND EAX,9
004013AD   . BD F7000000    MOV EBP,0F7
004013B2   . 33E8           XOR EBP,EAX
[...]
004015A6   $ 56             PUSH ESI                                 ;  Unpacked.00403000
004015A7   . E8 79FBFFFF    CALL Unpacked.00401125
004015AC   . 8AE0           MOV AH,AL
004015AE   . 80E4 01        AND AH,1
004015B1   . C0E4 04        SHL AH,4
004015B4   . 80CC EF        OR AH,0EF
[...]
004015DA   . 8AD0           MOV DL,AL
004015DC   . 80E2 02        AND DL,2
004015DF   . D0E2           SHL DL,1
004015E1   . 80CA FB        OR DL,0FB
[...]
00401602   > 22D4           AND DL,AH
[...]
00401618   > 8AF0           MOV DH,AL
0040161A   . 80E6 01        AND DH,1
0040161D   . F6DE           NEG DH
[...]
00401642   . 56             PUSH ESI                                 ;  Unpacked.00403000
00401643   . E8 DDFAFFFF    CALL Unpacked.00401125
00401648   . 22F0           AND DH,AL
0040164A   . 32D6           XOR DL,DH
[...]
0040166A   > 8BC5           MOV EAX,EBP
0040166C   . 0FB6D2         MOVZX EDX,DL
0040166F   . 0FB6C0         MOVZX EAX,AL
00401672   . C1E0 10        SHL EAX,10
00401675   . C1E2 08        SHL EDX,8
[...]
00401691   > 33C2           XOR EAX,EDX
00401693   . 35 0F0000CC    XOR EAX,CC00000F
00401698   . 8907           MOV DWORD PTR DS:[EDI],EAX
0040169A   . 83C7 03        ADD EDI,3
[...]
004016BB   > 8BC3           MOV EAX,EBX
004016BD   . C1E8 1F        SHR EAX,1F
004016C0   . 33D8           XOR EBX,EAX
004016C2   . C3             RETN

Sixth:

004013EB   > 8BC3           MOV EAX,EBX
004013ED   . C1E8 05        SHR EAX,5
004013F0   . 83F0 08        XOR EAX,8
004013F3   . 83E0 38        AND EAX,38
004013F6   . C1ED 03        SHR EBP,3
[...]
0040141C     83E5 07        AND EBP,7
0040141F     0BE8           OR EBP,EAX
00401421     81CD C0000000  OR EBP,0C0
[...]
004015A6   $ 56             PUSH ESI                                 ;  Unpacked.00403000
004015A7   . E8 79FBFFFF    CALL Unpacked.00401125
004015AC   . 8AE0           MOV AH,AL
004015AE   . 80E4 01        AND AH,1
004015B1   . C0E4 04        SHL AH,4
004015B4   . 80CC EF        OR AH,0EF
[...]
004015DA   . 8AD0           MOV DL,AL
004015DC   . 80E2 02        AND DL,2
004015DF   . D0E2           SHL DL,1
004015E1   . 80CA FB        OR DL,0FB
[...]
00401602   > 22D4           AND DL,AH
[...]
00401618   > 8AF0           MOV DH,AL
0040161A   . 80E6 01        AND DH,1
0040161D   . F6DE           NEG DH
[...]
00401642   . 56             PUSH ESI                                 ;  Unpacked.00403000
00401643   . E8 DDFAFFFF    CALL Unpacked.00401125
00401648   . 22F0           AND DH,AL
0040164A   . 32D6           XOR DL,DH
[...]
0040166A   > 8BC5           MOV EAX,EBP
0040166C   . 0FB6D2         MOVZX EDX,DL
0040166F   . 0FB6C0         MOVZX EAX,AL
00401672   . C1E0 10        SHL EAX,10
00401675   . C1E2 08        SHL EDX,8
[...]
00401691   > 33C2           XOR EAX,EDX
00401693   . 35 0F0000CC    XOR EAX,CC00000F
00401698   . 8907           MOV DWORD PTR DS:[EDI],EAX
0040169A   . 83C7 03        ADD EDI,3
[...]
004016BB   > 8BC3           MOV EAX,EBX
004016BD   . C1E8 1F        SHR EAX,1F
004016C0   . 33D8           XOR EBX,EAX
004016C2   . C3             RETN

After that…

00401454   . C0C3 04        ROL BL,4
00401457   . 81F3 00010000  XOR EBX,100                   ;  ECX = 100h
0040145D   . 49             DEC ECX                       ; ECX = 0FFh
0040145E   .^0F85 88FDFFFF  JNZ Unpacked.004011EC

and navigation goes back to generation of first instruction. As we see, ECX is decremented -  exactly 256 blocks of 6 instructions are generated.

The full MMX Generating code for any given login You can find in attached example: Generator.cpp

Keygenning

The MMX Generator was a missing piece of puzzle. Other pieces are described in my previous post. Now we must put them together and the keygen is ready!
But as we know, the generated MMX instructions must be reversed. There are two things to be done about it:

  1. Reversing the last (6-th instruction) in every block
  2. Reversing the order of blocks (first block must be the last and so on)

Ok, let’s do it one by one.

Reversing the last (6-th instruction) in every block:

The set of possible instructions occuring in the 6-th line is: {PADDB, PADDW, PADDQ, PSUBB,PSUBW, PSUBQ, XOR}. Three type of addition (add BYTE, add DWORD, add QWORD), analogical substractions and XOR. Reversing table will look like this:

PADDB -> PSUBB
PADDW -> PSUBW
PADDD -> PSUBD
PSUBB -> PADDB
PSUBW -> PADDW
PSUBD -> PADDD
XOR   -> XOR

But we can operate on opcodes only. The representation of following instruction is:

 PADDB = 0xfc
 PADDW = 0xfd
 PADDQ = 0xfe
 PSUBB = 0xf8
 PSUBW = 0xf9
 PSUBQ = 0xfa
 XOR   = 0xef

So, when the 6-th instruction is generated, we must substitute one opcode by another – representing reversed operation. Take a look at the code generating 6-th instruction in Generator.cpp:

Instruction6:
    MOV EAX,EBX
    SHR EAX,5
    XOR EAX,8
    AND EAX,0x38
    SHR EBP,3
    AND EBP,7
    OR EBP,EAX
    OR EBP,0xC0

    call get_cmd_base
    MOV AH,AL
    AND AH,1
    SHL AH,4
    OR AH,0xEF
    MOV DL,AL
    AND DL,2
    SHL DL,1
    OR DL,0xFB
    AND DL,AH
    MOV DH,AL
    AND DH,1
    NEG DH

    call get_cmd_base
    AND DH,AL
    XOR DL,DH
    MOV EAX,EBP
    MOVZX EDX,DL
    MOVZX EAX,AL
    SHL EAX,0x10
    SHL EDX,8
    XOR EAX,EDX
    XOR EAX,0xCC00000F
    MOV EDI, bufIndex
    MOV DWORD PTR buffer[EDI], EAX
    ADD bufIndex,3

    MOV EAX,EBX
    SHR EAX,0x1F
    XOR EBX,EAX
RET

thus, instruction in EDX should be reversed before the XORing wih EAX (line 332). It can be done easyli:

if (EDX == 0xef) -> don’t do anything (it’s XOR)
else if (EDX < 0xfc) -> EDX += 4
else -> EDX -= 4

I hope everything is clear :)

Reversing the order of blocks

We must fill the buffer of blocks from the back to front. Here the only problem is, we don’t know the exact length in bytes of a single block, because instructions{3, 4} can be either of 3 or of 4 bytes. That’s why we have to reserve memory for the maximal case and fill the gaps with NOPs (0×90).

Then, adding RET at the end of the buffer, and we can call the generated code as a function, from within assembler code. Mind that the keygen must be compiled with DEP (Data Execution Prevention) switched off (eventualy you can set this page of memory executable by VirtualProtect).

It’s time to look at the Keygen.cpp!

//---------------------------------------------------------------------------
// the code published under Creative Commons (CC-BY-NC) license
// author: hasherezade (http://hshrzd.wordpress.com)
// the keygenerator for ESET CrackMe, CONfidence2012 (http://2012.confidence.org.pl)
// remarks: compile with DEP disabled
//---------------------------------------------------------------------------

#include <windows.h>
#include <iostream>

using namespace std;

BYTE hsh[16];
BYTE hashes[4][16];
BYTE output[16];

/*
maxBlock =
    6 instructions total:
    instruction[1,2,5,6] -> 3 bytes
    instruction[3,4] -> 3 or 4 bytes -> max 4 bytes
    + 1 byte -> NOP at the end of 6-th instruction (padding)
*/
const DWORD maxBlock = 4 * 3 + 2 * 4 + 1;

const DWORD bufMax = maxBlock * 256;
BYTE buffer[bufMax];
DWORD bufIndex = bufMax - maxBlock;
DWORD blockStart = bufMax;

//----------------------------------------
typedef struct {
    ULONG i[2];
    ULONG buf[4];
    unsigned char in[64];
    unsigned char digest[16];
} MD5_CTX;

typedef void (WINAPI *t_MD5Init)(
    MD5_CTX *context
);

t_MD5Init MD5Init;
typedef void (WINAPI *t_MD5Update)(
    MD5_CTX *context,
    const unsigned char *input,
    unsigned int inlen
);

t_MD5Update MD5Update;

typedef void (WINAPI *t_MD5Final)
(
    MD5_CTX *context
);
t_MD5Final MD5Final;

char revrs(int a)
{
    a += 0x41;
    if (a >= 'A' && a <= 'Z')
        return a;
    a += 6;
    return a;
}

void decode_chunks()
{
    int V = 0x29, i = 0;
    WORD* out = (WORD*)output;
    while (i < 8) {
        WORD chunk = out[i];
        i++;
        //printf("\n%4X",chunk);

        int x,y,z;
        int a;
        z = chunk % V;
        a = chunk / V;
        y = a % V;
        x = a / V;
        printf("%c%c%c", revrs(x), revrs(y), revrs(z));
    }
}
//----------------------------------------
void call_generated()
{
    memset(output,0,16);

    void* generated = (void*)buffer;
    _asm {
        EMMS
        MOVQ MM0,QWORD PTR hashes[0]
        MOVQ MM1,QWORD PTR hashes[8]
        MOVQ MM2,QWORD PTR hashes[0x10]
        MOVQ MM3,QWORD PTR hashes[0x18]
        MOVQ MM4,QWORD PTR hashes[0x20]
        MOVQ MM5,QWORD PTR hashes[0x28]

        call generated

        MOVQ QWORD PTR output[0], MM0
        MOVQ QWORD PTR output[8], MM1
    };
}

void genetrateReversed()
{
    memset(buffer, 0x90, bufMax);

    __asm {
    push ebp
    mov EBX, 0x42
    mov ECX, 0x100

    jmp start

process_hsh:
    PUSH ESI
    PUSH EDX

    MOV EDX, dword ptr hsh[0]
    AND EDX,0x87
    SETPO DL
    XOR EAX,EAX
    SHL dword ptr hsh[0],1
    RCL DWORD PTR hsh[4],1
    RCL DWORD PTR hsh[8],1
    RCL DWORD PTR hsh[0xC],1
    ADC EAX,EAX
    XOR EAX,EDX
    OR DWORD PTR hsh[0],EAX

    POP EDX
    POP ESI
RET

get_cmd_base:
    PUSH EDX
    PUSH ESI
    bgn1:

        call process_hsh
        MOV EDX,EAX
        call process_hsh
        LEA EAX,DWORD PTR DS:[EAX+EDX*2]
        TEST EAX,EAX

    JE bgn1

    POP ESI
    POP EDX
RET

Instruction1:
    call get_cmd_base
    SHR EAX,1
    NEG EAX
    AND EAX,1
    MOV EBP,EBX
    AND EBP,0x700
    SHR EBP,5
    OR EBP,0xC6
    XOR EBP,EAX
    MOV EAX,EBP
    SHL EAX,0x18
    OR EAX,0x7F0FCC
    ROR EAX,8

    MOV EDI, bufIndex
    MOV DWORD PTR buffer[EDI], EAX
    ADD bufIndex,3

    MOV EAX,EBX
    SHR EAX,0x1F
    XOR EBX,EAX
RET

Instruction2:
    OR EBX,0x80000000
    MOV EAX,EBX
    AND EAX,7
    SHL EAX,3
    AND EBP,0xC7
    OR EBP,EAX
    XOR EBP,1
    MOV EAX,EBP
    SHL EAX,0x18
    OR EAX,0x7F0FCC
    ROR EAX,8

    MOV EDI, bufIndex
    MOV DWORD PTR buffer[EDI], EAX
    ADD bufIndex,3

    MOV EAX,EBX
    SHR EAX,0x1F
    XOR EBX,EAX
RET

case1:
        call get_cmd_base
        MOV AH,AL
        AND AH,1
        SHL AH,4
        OR AH,0xEF
        MOV DL,AL
        AND DL,2
        SHL DL,1
        OR DL,0xFB
        AND DL,AH
        MOV DH,AL
        AND DH,1
        NEG DH

        call get_cmd_base
        AND DH,AL
        XOR DL,DH
        MOV EAX,EBP
        MOVZX EDX,DL
        MOVZX EAX,AL
        SHL EAX,0x10
        SHL EDX,8
        XOR EAX,EDX
        XOR EAX,0xCC00000F

        MOV EDI, bufIndex
        MOV DWORD PTR buffer[EDI], EAX
        ADD bufIndex,3

        MOV EAX,EBX
        SHR EAX,0x1F
        XOR EBX,EAX
RET

case2:
        PUSH ECX
        call get_cmd_base
        MOV CL,AL
        AND CL,1
        MOV AH,1
        SHL AH,CL
        NOT AH
        ROL AH,4
        AND AL,2
        NOT AL
        ROL AL,1
        AND AH,AL

        MOV ECX,EBP
        AND EAX,0xFF00
        MOVZX ECX,CL
        SHL ECX,0x10
        OR EAX,ECX
        XOR EAX,0xCC00000F

        MOV EDI, bufIndex
        MOV DWORD PTR buffer[EDI], EAX
        ADD bufIndex,3

        MOV EAX,EBX
        SHR EAX,0x1F
        XOR EBX,EAX
        POP ECX
RET

case3:
        call get_cmd_base
        SHR AL,1
        MOV DL,AL
        SHL DL,5

        call get_cmd_base
        MOV DH,AL
        MOV EAX,EBP
        SHR AL,3

        AND AL,7
        OR AL,0xF0
        XOR DL,AL

        call get_cmd_base
        OR AL,0x70

        SHL EAX,8
        OR AL,0x0F
        SHL EDX,0x10
        XOR EAX,EDX

        MOV EDI, bufIndex
        MOV DWORD PTR buffer[EDI], EAX
        ADD bufIndex,4
RET

Instruction3:
    call get_cmd_base
    MOV EBP,EBX
    AND EBP,7
    OR EBP,0x0F0
the_switch:
        cmp eax, 1
        jne c2
        jmp case1
c2:
        cmp eax, 2
        jne c3
        jmp case2
c3:
        cmp eax, 3
        jne c4
        jmp case3
c4:
RET

Instruction4:
    call get_cmd_base
    MOV EBP,EBX
    AND EBP,7
    OR EBP,0x0F8
    jmp the_switch
RET

Instruction5:
    AND EBX,0x7FFFFFFF
    call get_cmd_base
    SHR EAX,1
    NEG EAX
    AND EAX,9
    MOV EBP,0xF7
    XOR EBP,EAX

    call get_cmd_base
    MOV AH,AL
    AND AH,1
    SHL AH,4
    OR AH,0xEF
    MOV DL,AL
    AND DL,2
    SHL DL,1
    OR DL,0xFB
    AND DL,AH
    MOV DH,AL
    AND DH,1
    NEG DH

    call get_cmd_base
    AND DH,AL
    XOR DL,DH
    MOV EAX,EBP
    MOVZX EDX,DL
    MOVZX EAX,AL
    SHL EAX,0x10
    SHL EDX,8
    XOR EAX,EDX
    XOR EAX,0xCC00000F

    MOV EDI, bufIndex
    MOV DWORD PTR buffer[EDI], EAX
    ADD bufIndex,3

    MOV EAX,EBX
    SHR EAX,0x1F
    XOR EBX,EAX
RET

Instruction6:
    MOV EAX,EBX
    SHR EAX,5
    XOR EAX,8
    AND EAX,0x38
    SHR EBP,3
    AND EBP,7
    OR EBP,EAX
    OR EBP,0xC0

    call get_cmd_base
    MOV AH,AL
    AND AH,1
    SHL AH,4
    OR AH,0xEF
    MOV DL,AL
    AND DL,2
    SHL DL,1
    OR DL,0xFB
    AND DL,AH
    MOV DH,AL
    AND DH,1
    NEG DH

    call get_cmd_base
    AND DH,AL
    XOR DL,DH
    MOV EAX,EBP
    MOVZX EDX,DL
    MOVZX EAX,AL
    SHL EAX,0x10

    call reverseInstruction6
    SHL EDX,8
    XOR EAX,EDX
    XOR EAX,0x9000000F ;// i want NOP at the end of the last instruction (instead of INT 3: XOR EAX,0xCC00000F)

    MOV EDI, bufIndex
    MOV DWORD PTR buffer[EDI], EAX
    ADD bufIndex,3

    MOV EAX,EBX
    SHR EAX,0x1F
    XOR EBX,EAX
RET

reverseInstruction6:
;/*
;    0xfc -> 0xf8    (PADDB -> PSUBB)
;    0xfd -> 0xf9    (PADDW -> PSUBW)
;    0xfe -> 0xfa    (PADDD -> PSUBD)
;
;    0xf8 -> 0xfc    (PSUBB -> PADDB)
;    0xf9 -> 0xfd    (PSUBW -> PADDW)
;    0xfa -> 0xfe    (PSUBD -> PADDD)
;
;    0xef -> 0xef (reversed XOR is XOR)
;*/
    cmp EDX, 0xef
    je revEnd
    cmp EDX, 0xfc
    jb r1
    SUB EDX,4
    jmp revEnd
    r1:
    ADD EDX,4
    revEnd:
RET

start:
    push ebx
    mov ebx,blockStart
    sub ebx, maxBlock
    mov blockStart, ebx
    mov bufIndex, ebx
    pop ebx
    call Instruction1
    call Instruction2
    call Instruction3
    call Instruction4
    call Instruction5
    call Instruction6

    ROL BL,4
    XOR EBX,0x100
    DEC ECX
JNZ start

    pop ebp
    };
    BYTE ret = 0xc3;
    buffer[bufMax-1] = ret;
}

int main(){
    //load
    int i;
    HMODULE hCryptdll = LoadLibraryA("Cryptdll.dll");
    if (hCryptdll==NULL) return (-1);

    MD5Init = (t_MD5Init)GetProcAddress(hCryptdll, "MD5Init");
    MD5Update = (t_MD5Update)GetProcAddress(hCryptdll, "MD5Update");
    MD5Final = (t_MD5Final)GetProcAddress(hCryptdll, "MD5Final");

    //Get input
    const int MAX = 33;
    char input[MAX];
    printf("Name:\n");
    scanf("%[ A-Za-z]s", input); //including space

    int len = strlen(input);

    MD5_CTX md5;
    MD5Init(&md5);
    MD5Update(&md5,(const unsigned char *)input, len);
    MD5Final(&md5);
    memcpy(hsh, md5.digest, 16);
    //other hashes

    memcpy(hashes[0], md5.digest, 16);

    char backup[16];
    memcpy(backup, md5.digest, 16);

        int x;
    for (x = 1; x < 3; x++) {
        MD5Init(&md5);
        MD5Update(&md5,(const unsigned char *)backup, 16);
        MD5Final(&md5);
        memcpy(hashes[x], md5.digest, 16);
        memcpy(backup, md5.digest, 16);
    }

    //---
    genetrateReversed();
    call_generated();
    printf("\nRegistration key:\n");
    decode_chunks();
    printf("\n\n---\n");
    system("pause");
    return 0;
}
About these ads

About hasherezade

high and low level programmer, malware analyst
This entry was posted in ConFidence, CrackMe, RCE and tagged , , , . Bookmark the permalink.

2 Responses to Keygenning ESET’s CONfidence 2012 Crackme

  1. Krzywy says:

    Hey
    Good job with crackme. I read your solution and instantly noticed this:
    // remarks: compile with DEP disabled

    It’s caused by this lines:
    BYTE buffer[bufMax];
    void* generated = (void*)buffer;
    call generated

    You can just do VirtualProtect with PAGE_EXECUTE to get it work flowlessly with DEP.
    It would work on xpsp3 without that because ther’s no PAE kernel loaded at default.

    Pozdr

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s