⬆️ ⬇️

Brutim crackme # 03 from korsader

Introduction



I have no experience in reverse, there is some basic knowledge of the assembler that allows you to make a bithak of conditional jumps so that this application always goes to the success-path regardless of the entered value. But since it is too banal to be published here, and until the reproduction of the algorithm for checking the entered key is complete, I have not grown enough, I decided to try the brutus method, i.e. consistent selection of keys. Of course, I can not say that this method is distinguished by its steepness, but at least a detailed description of this method is not so often found among the articles on the reverse.



image




A source



Link to the original crackme # 03 .



In the thread where this crack is published, the user ARCHANGEL published the Brutus method in C ++, which really gives the correct password for this crack. He could afford to write brut in a high level language, since he was able to reproduce the algorithm and found the value 0x23a06032, with which the crc obtained is compared.

')

I have not yet learned how to analyze algorithms so deeply on asm, so I will work without departing from the cash register, using the check algorithm in the cracks itself as a black box.



Conditional Transition Analysis



We launch the quacks and turn off the sound on the computer (apparently, this is what the author was trying to achieve by adding sound).



image


I run OllyDbg 2.01 with the OllyExt plugin, in which the settings below are set:



image


This plugin will help get rid of some of the potential anti-debugging techniques.



Attach from Olga to the running process crackme # 03.exe: File β†’ Attach ...



image


Next, we try to enter any value in the input field and easily find the code in which it is processed. You can do this by setting breakpoint on potential text retrieval functions (in particular, GetDlgItemTextA) or scrolling through the code of the source module - the benefit here is small. Click the Check button.



image


It works breakpoint, press F8 once and look at the listing. We see that the string we entered is stored at 004095BC . Also look at the instructions at 0040101F . It compares the length of the entered string with the value 12 and in case of inequality throws us at 004010AF .



Next, pay attention to the instruction at address 00401028 , which compares the 12th byte of the entered value with a value of 72, which is the letter r in ASCII-encoding. In case of inequality, again throws us on 004010AF . What kind of address is this? More on this later.



Now pay attention to the instructions in the range 00401031 - 0040104C . Having smoked the directory of the assembler commands with the repne and scas commands, as well as tracing the selected code area, we conclude that aehnprwy is a valid alphabet of the required key.



image



Now let's see what we have at 004010AF . There is a message about a failed password.



image



So let's summarize the primary analysis:



1) The key must consist of 12 characters;

2) The last character of the key must be r;

3) Key symbols must belong to the alphabet aehnprwy.



Brutfors



We proceed to the implementation of the brute method. We implement it first at the conceptual level. It is possible on the flowchart, it is possible in high level language. I implemented its prototype in C ++. To understand further material, it is necessary to digest the code under the spoiler.



Hidden text
#include <stdio.h> #include <string.h> const char *Alphabet = "aeyhpnwr"; int Password_len = 12; int CheckPassword(char pass[]) //    . { if (strcmp(pass, "aaaaaaahaahr") == 0) //    return 0; return 1; } int main() { int Alphabet_len = strlen(Alphabet); char* CodeArray = new char[Password_len + 1]; char* Password = new char[Password_len + 1]; int n; //  ,       (.. )   Password[Password_len] = 0; for (int i = 0; i < Password_len; i++) { CodeArray[i] = 0; Password[i] = Alphabet[CodeArray[i]]; } //    r Password[Password_len - 1] = 'r'; while (true) { //printf("\nCurrent pass = %s", Password); if (CheckPassword(Password) == 0) { printf("\nRight Password = %s\n", Password); break; } n = Password_len - 2; while (n >= 0) { CodeArray[n]++; if (CodeArray[n] >= Alphabet_len) { CodeArray[n] = 0; Password[n] = Alphabet[0]; n--; continue; } Password[n] = Alphabet[CodeArray[n]]; break; } } delete[] CodeArray; delete[] Password; } 


Main steps:



1) Initialization of the key (password) initial value.

2) Key verification.

3) If the key is incorrect, then generate the next key and go to step 2. If the key is correct, go to step 4. If we have sifted through all the keys and none of them came up, go to step 5.

4) Crackme hacked.

5) Crackme is not hacked. Somewhere we were wrong.



Key initialization



The program stores and accesses the key at 004095BC - there we will initialize it. The alphabet is located at 00409071 .



004095CC is the memory address where we will store our CodeArray array.



To initialize the key, we find the unused area of ​​the code section and insert our instructions there. I chose the address 00404122 .



To actually complete this initialization, go to the place where GetDlgItemTextA is called, carefully replace its call with an unconditional transition to our code at 00404122 , and replace the preceding push commands with nop-s. We do everything carefully so that the address of the CMP EAX, 0C command remains the same: 0040101F .



image



The figure below shows the initialization code itself. At its end, we proceed to the key validation algorithm as a result of the unconditional transition to 0040101F .



image



Hidden text
You can reset the CodeArray array consisting of 12 single-byte values ​​in 3 iterations of 4 bytes per iteration.



 00404122 B9 03000000 MOV ECX,3 00404127 BA CC954000 MOV EDX,004095CC ;   CodeArray 0040412C C7448A FC 000 MOV DWORD PTR DS:[ECX*4+EDX-4],0 00404134 E2 F6 LOOP SHORT 0040412C 


Next, we perform the first (ie, zero) character of the alphabet for each byte of the line at 004095BC



 for (int i = 0; i < Password_len; i++) { Password[i] = Alphabet[CodeArray[i]]; } 


 00404136 BB BC954000 MOV EBX,004095BC ;   ,    crackme 0040413B B9 0C000000 MOV ECX,0C 00404140 31C0 XOR EAX,EAX 00404142 8A4411 FF MOV AL,BYTE PTR DS:[EDX+ECX-1] 00404146 8A80 71904000 MOV AL,BYTE PTR DS:[EAX+409071] ; 409071 -   0040414C 884419 FF MOV BYTE PTR DS:[EBX+ECX-1],AL 00404150 E2 F0 LOOP SHORT 00404142 00404152 C643 0B 72 MOV BYTE PTR DS:[EBX+0B],72 ;    r 00404156 C643 0C 00 MOV BYTE PTR DS:[EBX+0C],0 ;     0040415A B8 0C000000 MOV EAX,0C ;     12 0040415F ^ E9 BFCEFFFF JMP 0040101F ;      




Getting the next key value



Now we need to implement the code to get the next key value. We select the address 00404165 for this (immediately after the initialization code) and make the transition to it from the place where the program calls us lamers.



We modify the instructions for the addresses 004010AF and 004010B1 .



image



Well, at the address 00404165 we implement the code for obtaining a new key.



image



Hidden text
 00404165 B9 0B000000 MOV ECX,0B ;   ,    0040416A BA CC954000 MOV EDX,004095CC ;   CodeArray 0040416F BB BC954000 MOV EBX,004095BC ;   ,    crackme 00404174 31C0 XOR EAX,EAX 00404176 FE4411 FF INC BYTE PTR DS:[EDX+ECX-1] ;        0040417A 807C11 FF 08 CMP BYTE PTR DS:[EDX+ECX-1],8 ; ,       0040417F 7D 15 JGE SHORT 00404196 00404181 8A4411 FF MOV AL,BYTE PTR DS:[EDX+ECX-1] ;   ,    AL 00404185 8A80 71904000 MOV AL,BYTE PTR DS:[EAX+409071] ;       . 409071 -   0040418B 884419 FF MOV BYTE PTR DS:[EBX+ECX-1],AL ;    -   0040418F B8 0C000000 MOV EAX,0C ;     12 00404194 ^ EB C9 JMP SHORT 0040415F ;      00404196 83F9 01 CMP ECX,1 ;     , ,       00404199 7F 02 JG SHORT 0040419D ; 0040419B CD 03 INT 3 ;  ,     0040419D C64411 FF 00 MOV BYTE PTR DS:[EDX+ECX-1],0 ;  ecx (i) > 1, CodeArray[i] = 0; 004041A2 A0 71904000 MOV AL,BYTE PTR DS:[409071] ;  AL   ()  . 409071 -   004041A7 884419 FF MOV BYTE PTR DS:[EBX+ECX-1],AL ;    -   004041AB 49 DEC ECX ;   .  004041AC ^ EB C6 JMP SHORT 00404174 ;      




Launch



Click the Check button and go to drink tea. Damn, and the tea is already boiled long ago, will have to boil again.



image


After some time, we get:



image


Look what we have at 004095BC



image



happynewyear is the desired key.

Source: https://habr.com/ru/post/324884/



All Articles