Nytro Posted March 1, 2013 Report Posted March 1, 2013 [h=2]Keygenning ESET’s CONfidence 2012 Crackme[/h][h=4]Intro[/h] 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: Keygen.cpp Keygen.exe* * requires: Microsoft Visual C++ 2008 Redistributable Package [h=4]Tools used[/h] 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) [h=4]Analysis[/h] 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 ESI004010B7 . 52 PUSH EDX004010B8 . 8B7424 0C MOV ESI,DWORD PTR SS:[ESP+C] ; Unpacked.00403000004010BC . 8B16 MOV EDX,DWORD PTR DS:[ESI] ; EDX = DS:[403000]004010BE . 81E2 87000000 AND EDX,87004010C4 . 0F9BC2 SETPO DL[...]004010EA . 33C0 XOR EAX,EAX004010EC . D126 SHL DWORD PTR DS:[ESI],1004010EE . D156 04 RCL DWORD PTR DS:[ESI+4],1[...]004010F6 > D156 08 RCL DWORD PTR DS:[ESI+8],1004010F9 . D156 0C RCL DWORD PTR DS:[ESI+C],1[...]0040111A > 13C0 ADC EAX,EAX0040111C . 33C2 XOR EAX,EDX0040111E . 0906 OR DWORD PTR DS:[ESI],EAX00401120 . 5A POP EDX00401121 . 5E POP ESI00401122 . C2 0400 RETN 4As 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 EDX00401126 . 56 PUSH ESI00401127 . 8B7424 0C MOV ESI,DWORD PTR SS:[ESP+C] ; ESI = 4030000040112B > 51 PUSH ECX ; bgn#1[...]0040114C . 59 POP ECX0040114D . 56 PUSH ESI0040114E . E8 63FFFFFF CALL Unpacked.004010B6 ; modify memory at 40300000401153 . 8BD0 MOV EDX,EAX ; EAX = result of function at 4010B600401155 . 56 PUSH ESI00401156 . E8 5BFFFFFF CALL Unpacked.004010B6 ; modify (again) memory at 4030000040115B . 8D0450 LEA EAX,DWORD PTR DS:[EAX+EDX*2][...]00401181 . 85C0 TEST EAX,EAX00401183 >^74 A6 JE SHORT Unpacked.0040112B ; ;goto #bgn100401185 . 5E POP ESI00401186 . 5A POP EDX00401187 . C2 0400 RETN 4Then, 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 ESI0040120B . E8 15FFFFFF CALL Unpacked.0040112500401210 . D1E8 SHR EAX,100401212 . F7D8 NEG EAX00401214 . 83E0 01 AND EAX,1[...]0040122B > 8BEB MOV EBP,EBX[...]0040124B > 81E5 00070000 AND EBP,70000401251 . C1ED 05 SHR EBP,500401254 . 81CD C6000000 OR EBP,0C60040125A . 33E8 XOR EBP,EAX[...]0040147D $ 8BC5 MOV EAX,EBP0040147F . C1E0 18 SHL EAX,18[...]004014A5 . 0D CC0F7F00 OR EAX,7F0FCC ; MOVQ MMx, MMy004014AA . C1C8 08 ROR EAX,8004014AD . 8907 MOV DWORD PTR DS:[EDI],EAX004014AF . 83C7 03 ADD EDI,3[...]004014D0 > 8BC3 MOV EAX,EBX004014D2 . C1E8 1F SHR EAX,1F004014D5 . 33D8 XOR EBX,EAX004014D7 . C3 RETNThe 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,EBX004012AA . 83E0 07 AND EAX,7004012AD . C1E0 03 SHL EAX,3004012B0 . 81E5 C7000000 AND EBP,0C7004012B6 . 0BE8 OR EBP,EAX004012B8 . 83F5 01 XOR EBP,1[...]0040147D $ 8BC5 MOV EAX,EBP0040147F . C1E0 18 SHL EAX,18[...]004014A5 . 0D CC0F7F00 OR EAX,7F0FCC ; MOVQ MMx, MMy004014AA . C1C8 08 ROR EAX,8004014AD . 8907 MOV DWORD PTR DS:[EDI],EAX004014AF . 83C7 03 ADD EDI,3[...]004014D0 > 8BC3 MOV EAX,EBX004014D2 . C1E8 1F SHR EAX,1F004014D5 . 33D8 XOR EBX,EAX004014D7 . C3 RETNThe 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.00403000004012DF . E8 41FEFFFF CALL Unpacked.00401125[...]00401307 . 8BEB MOV EBP,EBX00401309 . 83E5 07 AND EBP,70040130C . 81CD F0000000 OR EBP,0F000401312 . FF1485 6D14400>CALL DWORD PTR DS:[EAX*4+40146D]00401319 . E8 07000000 CALL Unpacked.00401325 ; //after #3EAX = {1, 2, 3}[EAX*4+40146D] = {401471, 401475, 401479} EAX = 1 -> call 4015A6EAX = 2 -> call 4016C3EAX = 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 = 1004015A6 $ 56 PUSH ESI ; Unpacked.00403000004015A7 . E8 79FBFFFF CALL Unpacked.00401125004015AC . 8AE0 MOV AH,AL004015AE . 80E4 01 AND AH,1004015B1 . C0E4 04 SHL AH,4004015B4 . 80CC EF OR AH,0EF[...]004015DA . 8AD0 MOV DL,AL004015DC . 80E2 02 AND DL,2004015DF . D0E2 SHL DL,1004015E1 . 80CA FB OR DL,0FB[...]00401602 > 22D4 AND DL,AH[...]00401618 > 8AF0 MOV DH,AL0040161A . 80E6 01 AND DH,10040161D . F6DE NEG DH[...]00401642 . 56 PUSH ESI00401643 . E8 DDFAFFFF CALL Unpacked.0040112500401648 . 22F0 AND DH,AL0040164A . 32D6 XOR DL,DH[...]0040166A > 8BC5 MOV EAX,EBP0040166C . 0FB6D2 MOVZX EDX,DL0040166F . 0FB6C0 MOVZX EAX,AL00401672 . C1E0 10 SHL EAX,1000401675 . C1E2 08 SHL EDX,8[...]00401691 > 33C2 XOR EAX,EDX00401693 . 35 0F0000CC XOR EAX,CC00000F00401698 . 8907 MOV DWORD PTR DS:[EDI],EAX0040169A . 83C7 03 ADD EDI,3[...]004016BB > 8BC3 MOV EAX,EBX004016BD . C1E8 1F SHR EAX,1F004016C0 . 33D8 XOR EBX,EAX004016C2 . C3 RETNIf (EAX = 2):004016C3 $ 51 PUSH ECX004016C4 . 56 PUSH ESI004016C5 . E8 5BFAFFFF CALL Unpacked.00401125004016CA . 8AC8 MOV CL,AL[...]004016D1 > 80E1 01 AND CL,1004016D4 . B4 01 MOV AH,1004016D6 . D2E4 SHL AH,CL004016D8 . F6D4 NOT AH004016DA . C0C4 04 ROL AH,4[...]00401700 24 02 AND AL,200401702 F6D0 NOT AL00401704 D0C0 ROL AL,100401706 22E0 AND AH,AL[...]0040172B 8BCD MOV ECX,EBP0040172D 25 00FF0000 AND EAX,0FF0000401732 0FB6C9 MOVZX ECX,CL00401735 C1E1 10 SHL ECX,1000401738 0BC1 OR EAX,ECX0040173A 35 0F0000CC XOR EAX,CC00000F[...]0040175D > 8907 MOV DWORD PTR DS:[EDI],EAX0040175F . 83C7 03 ADD EDI,300401762 . 8BC3 MOV EAX,EBX00401764 . C1E8 1F SHR EAX,1F00401767 . 33D8 XOR EBX,EAX00401769 . 59 POP ECX0040176A . C3 RETNIf (EAX =3)004014D8 $ 56 PUSH ESI004014D9 . E8 47FCFFFF CALL Unpacked.00401125[...]004014DE . D0E8 SHR AL,1004014E0 . 8AD0 MOV DL,AL004014E2 . C0E2 05 SHL DL,5[...]00401503 > 56 PUSH ESI ; Unpacked.0040300000401504 . E8 1CFCFFFF CALL Unpacked.0040112500401509 . 8AF0 MOV DH,AL0040150B . 8BC5 MOV EAX,EBP0040150D . C0E8 03 SHR AL,3[...]00401533 > 24 07 AND AL,700401535 . 0C F0 OR AL,0F000401537 . 32D0 XOR DL,AL[...]00401557 > 56 PUSH ESI ; Unpacked.0040300000401558 . E8 C8FBFFFF CALL Unpacked.004011250040155D . 0C 70 OR AL,70[...]00401573 > C1E0 08 SHL EAX,800401576 . 0C 0F OR AL,0F00401578 . C1E2 10 SHL EDX,100040157B . 33C2 XOR EAX,EDX[...]004015A0 . 8907 MOV DWORD PTR DS:[EDI],EAX004015A2 . 83C7 04 ADD EDI,4004015A5 . C3 RETNAs 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 ESI0040132E . E8 F2FDFFFF CALL Unpacked.00401125[...]00401351 > 8BEB MOV EBP,EBX00401353 . 83E5 07 AND EBP,700401356 . 81CD F8000000 OR EBP,0F80040135C . FF1485 6D14400> CALL DWORD PTR DS:[EAX*4+40146D]- then if follows analogicaly like 3-rd. Fifth[...]00401377 > 81E3 FFFFFF7F AND EBX,7FFFFFFF0040137D . 56 PUSH ESI ; Unpacked.004030000040137E . E8 A2FDFFFF CALL Unpacked.0040112500401383 . D1E8 SHR EAX,1[...]004013A8 . F7D8 NEG EAX004013AA . 83E0 09 AND EAX,9004013AD . BD F7000000 MOV EBP,0F7004013B2 . 33E8 XOR EBP,EAX[...]004015A6 $ 56 PUSH ESI ; Unpacked.00403000004015A7 . E8 79FBFFFF CALL Unpacked.00401125004015AC . 8AE0 MOV AH,AL004015AE . 80E4 01 AND AH,1004015B1 . C0E4 04 SHL AH,4004015B4 . 80CC EF OR AH,0EF[...]004015DA . 8AD0 MOV DL,AL004015DC . 80E2 02 AND DL,2004015DF . D0E2 SHL DL,1004015E1 . 80CA FB OR DL,0FB[...]00401602 > 22D4 AND DL,AH[...]00401618 > 8AF0 MOV DH,AL0040161A . 80E6 01 AND DH,10040161D . F6DE NEG DH[...]00401642 . 56 PUSH ESI ; Unpacked.0040300000401643 . E8 DDFAFFFF CALL Unpacked.0040112500401648 . 22F0 AND DH,AL0040164A . 32D6 XOR DL,DH[...]0040166A > 8BC5 MOV EAX,EBP0040166C . 0FB6D2 MOVZX EDX,DL0040166F . 0FB6C0 MOVZX EAX,AL00401672 . C1E0 10 SHL EAX,1000401675 . C1E2 08 SHL EDX,8[...]00401691 > 33C2 XOR EAX,EDX00401693 . 35 0F0000CC XOR EAX,CC00000F00401698 . 8907 MOV DWORD PTR DS:[EDI],EAX0040169A . 83C7 03 ADD EDI,3[...]004016BB > 8BC3 MOV EAX,EBX004016BD . C1E8 1F SHR EAX,1F004016C0 . 33D8 XOR EBX,EAX004016C2 . C3 RETNSixth:004013EB > 8BC3 MOV EAX,EBX004013ED . C1E8 05 SHR EAX,5004013F0 . 83F0 08 XOR EAX,8004013F3 . 83E0 38 AND EAX,38004013F6 . C1ED 03 SHR EBP,3[...]0040141C 83E5 07 AND EBP,70040141F 0BE8 OR EBP,EAX00401421 81CD C0000000 OR EBP,0C0[...]004015A6 $ 56 PUSH ESI ; Unpacked.00403000004015A7 . E8 79FBFFFF CALL Unpacked.00401125004015AC . 8AE0 MOV AH,AL004015AE . 80E4 01 AND AH,1004015B1 . C0E4 04 SHL AH,4004015B4 . 80CC EF OR AH,0EF[...]004015DA . 8AD0 MOV DL,AL004015DC . 80E2 02 AND DL,2004015DF . D0E2 SHL DL,1004015E1 . 80CA FB OR DL,0FB[...]00401602 > 22D4 AND DL,AH[...]00401618 > 8AF0 MOV DH,AL0040161A . 80E6 01 AND DH,10040161D . F6DE NEG DH[...]00401642 . 56 PUSH ESI ; Unpacked.0040300000401643 . E8 DDFAFFFF CALL Unpacked.0040112500401648 . 22F0 AND DH,AL0040164A . 32D6 XOR DL,DH[...]0040166A > 8BC5 MOV EAX,EBP0040166C . 0FB6D2 MOVZX EDX,DL0040166F . 0FB6C0 MOVZX EAX,AL00401672 . C1E0 10 SHL EAX,1000401675 . C1E2 08 SHL EDX,8[...]00401691 > 33C2 XOR EAX,EDX00401693 . 35 0F0000CC XOR EAX,CC00000F00401698 . 8907 MOV DWORD PTR DS:[EDI],EAX0040169A . 83C7 03 ADD EDI,3[...]004016BB > 8BC3 MOV EAX,EBX004016BD . C1E8 1F SHR EAX,1F004016C0 . 33D8 XOR EBX,EAX004016C2 . C3 RETNAfter that…00401454 . C0C3 04 ROL BL,400401457 . 81F3 00010000 XOR EBX,100 ; ECX = 100h0040145D . 49 DEC ECX ; ECX = 0FFh0040145E .^0F85 88FDFFFF JNZ Unpacked.004011ECand 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 [h=4]Keygenning[/h] 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:Reversing the last (6-th instruction) in every blockReversing the order of blocks (first block must be the last and so on) Ok, let’s do it one by one. [h=5]Reversing the last (6-th instruction) in every block:[/h] 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: 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 += 4else -> EDX -= 4 I hope everything is clear [h=5]Reversing the order of blocks[/h] 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 bytesinstruction[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 {EMMSMOVQ 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 generatedMOVQ QWORD PTR output[0], MM0MOVQ QWORD PTR output[8], MM1};}void genetrateReversed(){memset(buffer, 0x90, bufMax);__asm {push ebpmov EBX, 0x42mov ECX, 0x100jmp startprocess_hsh:PUSH ESIPUSH EDXMOV EDX, dword ptr hsh[0]AND EDX,0x87SETPO DLXOR EAX,EAXSHL dword ptr hsh[0],1RCL DWORD PTR hsh[4],1RCL DWORD PTR hsh[8],1RCL DWORD PTR hsh[0xC],1ADC EAX,EAXXOR EAX,EDXOR DWORD PTR hsh[0],EAXPOP EDXPOP ESIRETget_cmd_base:PUSH EDXPUSH ESIbgn1:call process_hshMOV EDX,EAXcall process_hshLEA EAX,DWORD PTR DS:[EAX+EDX*2]TEST EAX,EAXJE bgn1POP ESIPOP EDXRETInstruction1:call get_cmd_baseSHR EAX,1NEG EAXAND EAX,1MOV EBP,EBXAND EBP,0x700SHR EBP,5OR EBP,0xC6XOR EBP,EAXMOV EAX,EBPSHL EAX,0x18OR EAX,0x7F0FCCROR EAX,8MOV EDI, bufIndexMOV DWORD PTR buffer[EDI], EAXADD bufIndex,3MOV EAX,EBXSHR EAX,0x1FXOR EBX,EAXRETInstruction2:OR EBX,0x80000000MOV EAX,EBXAND EAX,7SHL EAX,3AND EBP,0xC7OR EBP,EAXXOR EBP,1MOV EAX,EBPSHL EAX,0x18OR EAX,0x7F0FCCROR EAX,8MOV EDI, bufIndexMOV DWORD PTR buffer[EDI], EAXADD bufIndex,3MOV EAX,EBXSHR EAX,0x1FXOR EBX,EAXRETcase1:call get_cmd_baseMOV AH,ALAND AH,1SHL AH,4OR AH,0xEFMOV DL,ALAND DL,2SHL DL,1OR DL,0xFBAND DL,AHMOV DH,ALAND DH,1NEG DHcall get_cmd_baseAND DH,ALXOR DL,DHMOV EAX,EBPMOVZX EDX,DLMOVZX EAX,ALSHL EAX,0x10SHL EDX,8XOR EAX,EDXXOR EAX,0xCC00000FMOV EDI, bufIndexMOV DWORD PTR buffer[EDI], EAXADD bufIndex,3MOV EAX,EBXSHR EAX,0x1FXOR EBX,EAXRETcase2:PUSH ECXcall get_cmd_baseMOV CL,ALAND CL,1MOV AH,1SHL AH,CLNOT AHROL AH,4AND AL,2NOT ALROL AL,1AND AH,ALMOV ECX,EBPAND EAX,0xFF00MOVZX ECX,CLSHL ECX,0x10OR EAX,ECXXOR EAX,0xCC00000FMOV EDI, bufIndexMOV DWORD PTR buffer[EDI], EAXADD bufIndex,3MOV EAX,EBXSHR EAX,0x1FXOR EBX,EAXPOP ECXRETcase3:call get_cmd_baseSHR AL,1MOV DL,ALSHL DL,5call get_cmd_baseMOV DH,ALMOV EAX,EBPSHR AL,3AND AL,7OR AL,0xF0XOR DL,ALcall get_cmd_baseOR AL,0x70SHL EAX,8OR AL,0x0FSHL EDX,0x10XOR EAX,EDXMOV EDI, bufIndexMOV DWORD PTR buffer[EDI], EAXADD bufIndex,4RETInstruction3:call get_cmd_baseMOV EBP,EBXAND EBP,7OR EBP,0x0F0the_switch:cmp eax, 1jne c2jmp case1c2:cmp eax, 2jne c3jmp case2c3:cmp eax, 3jne c4jmp case3c4:RETInstruction4:call get_cmd_baseMOV EBP,EBXAND EBP,7OR EBP,0x0F8jmp the_switchRETInstruction5:AND EBX,0x7FFFFFFFcall get_cmd_baseSHR EAX,1NEG EAXAND EAX,9MOV EBP,0xF7XOR EBP,EAXcall get_cmd_baseMOV AH,ALAND AH,1SHL AH,4OR AH,0xEFMOV DL,ALAND DL,2SHL DL,1OR DL,0xFBAND DL,AHMOV DH,ALAND DH,1NEG DHcall get_cmd_baseAND DH,ALXOR DL,DHMOV EAX,EBPMOVZX EDX,DLMOVZX EAX,ALSHL EAX,0x10SHL EDX,8XOR EAX,EDXXOR EAX,0xCC00000FMOV EDI, bufIndexMOV DWORD PTR buffer[EDI], EAXADD bufIndex,3MOV EAX,EBXSHR EAX,0x1FXOR EBX,EAXRETInstruction6:MOV EAX,EBXSHR EAX,5XOR EAX,8AND EAX,0x38SHR EBP,3AND EBP,7OR EBP,EAXOR EBP,0xC0call get_cmd_baseMOV AH,ALAND AH,1SHL AH,4OR AH,0xEFMOV DL,ALAND DL,2SHL DL,1OR DL,0xFBAND DL,AHMOV DH,ALAND DH,1NEG DHcall get_cmd_baseAND DH,ALXOR DL,DHMOV EAX,EBPMOVZX EDX,DLMOVZX EAX,ALSHL EAX,0x10call reverseInstruction6SHL EDX,8XOR EAX,EDXXOR EAX,0x9000000F ;// i want NOP at the end of the last instruction (instead of INT 3: XOR EAX,0xCC00000F)MOV EDI, bufIndexMOV DWORD PTR buffer[EDI], EAXADD bufIndex,3MOV EAX,EBXSHR EAX,0x1FXOR EBX,EAX RETreverseInstruction6:;/*; 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, 0xefje revEndcmp EDX, 0xfcjb r1SUB EDX,4jmp revEndr1:ADD EDX,4revEnd:RETstart:push ebxmov ebx,blockStartsub ebx, maxBlockmov blockStart, ebxmov bufIndex, ebxpop ebxcall Instruction1call Instruction2call Instruction3call Instruction4call Instruction5call Instruction6ROL BL,4XOR EBX,0x100DEC ECXJNZ startpop ebp};BYTE ret = 0xc3;buffer[bufMax-1] = ret;}int main(){//loadint 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 inputconst int MAX = 33;char input[MAX];printf("Name:\n");scanf("%[ A-Za-z]s", input); //including spaceint len = strlen(input);MD5_CTX md5;MD5Init(&md5);MD5Update(&md5,(const unsigned char *)input, len);MD5Final(&md5);memcpy(hsh, md5.digest, 16);//other hashesmemcpy(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;} Sursa: Keygenning ESET’s CONfidence 2012 Crackme | hasherezade's 1001 nights Quote