Reverseme – windows
February 17, 2008 1 Comment
This was pretty easy. Again, from crackmes.de, here is a mirror to the executable
Hardcoded serial is:
“Reversing raises knowledge!”
This could have potetially been guessed eventually with a hex dump, but I noticed it when setting a break point at
0x00401462 and doing a registry dump (eax points to the string). That address is the start of a loop that compares
the hardcoded serial byte by byte witht the entered serial.
Name/Serial Combination:
The Name/Serial combination is calculated in the following lines of the assembly file (generated by ollydbg).
004014F7 |. 33C0 XOR EAX,EAX ; start calculation of key 004014F9 |. 8D35 10314000 LEA ESI,DWORD PTR DS:[403110] 004014FF |. 8B0D 5C314000 MOV ECX,DWORD PTR DS:[40315C] 00401505 |. 33DB XOR EBX,EBX 00401507 |> 8A4431 FF /MOV AL,BYTE PTR DS:[ECX+ESI-1] 0040150B |> 43 |/INC EBX ; loop while eax is not between 44 and 4d (E to L) 0040150C |. 33C3 ||XOR EAX,EBX 0040150E |. 3C 44 ||CMP AL,44 00401510 |.^72 F9 ||JB SHORT Assessme.0040150B 00401512 |. 3C 4D ||CMP AL,4D 00401514 |.^77 F5 |\JA SHORT Assessme.0040150B 00401516 |. 884431 FF |MOV BYTE PTR DS:[ECX+ESI-1],AL 0040151A |. 806C31 FF 14 |SUB BYTE PTR DS:[ECX+ESI-1],14 0040151F |. 49 |DEC ECX 00401520 |. 83F9 00 |CMP ECX,0 00401523 |.^77 E2 \JA SHORT Assessme.00401507 00401525 |. 61 POPAD 00401526 |. 8D05 10314000 LEA EAX,DWORD PTR DS:[403110] 0040152C |. 8D1D 30314000 LEA EBX,DWORD PTR DS:[403130] 00401532 |> 8038 00 /CMP BYTE PTR DS:[EAX],0 00401535 |. 74 0C |JE SHORT Assessme.00401543 ; jump to correct combination
The important stuff is in lines 0040150B to 00401520 which contains the algorithm for calculating the serial based
on the name. Basically it has an index (ebx) that simply iterates and is xored with the current character until the
result is a number between 44 and 4d. Finally, 140x is subtracted from this number which results in the serial.
This algorithm is replicated in the keygen (keygen.cpp).
#include <cstdlib> #include <iostream> #include <string> using namespace std; int main(int argc, char *argv[]) { cout<<"Enter name: "<<endl; string name; cin>>name; char* backpass = new char[name.length()+1]; char j = 0; int xorinc = 0; for(int i = name.length()-1; i>=0; i--) { char thischar = name[i]; while(thischar < 'D' || thischar > 'M') { thischar = thischar ^ xorinc; xorinc++; } //cout<<"thischar["<<i<<"] "<<char(thischar - 20) <<endl; backpass[i] = char(thischar-20); } cout<<"Serial for this name:"<<endl; for(int i = 0; i< name.length(); i++) { cout<<backpass[i]; } cout<<endl; system("PAUSE"); return EXIT_SUCCESS; }
To get rid of the double click nag, you can go to where the function is called:
00401062 E8 13010000 CALL Assessme.0040117A
and fill it with nops:
00401062 90 NOP
00401063 90 NOP
00401064 90 NOP
00401065 90 NOP
00401066 90 NOP
There are 5 because that is the space the call takes.