160 crackme training for novice crackers
The purpose of this series of articles is to try to crack all 160 CrackMe step by step from the perspective of a novice with no experience. If possible, write something similar to a registered machine by any means.
Among them, the article is arranged according to the following logic (to solve the following problems):
1. What environment and tools to use
2. Program analysis
3. Thinking analysis and cracking process
4. Exploring the registration machine
1. Tools and environment:
WinXP SP3 + OD + PEID + compilation cheat.
Note:
1). The Win7 system enables the function of random initial addresses for modules and programs, which will bring a great burden to the analysis, so it is not recommended to use Win7 for analysis.
2). The above tools are all original programs, NOD32 does not report viruses, and I promise that I will never carry out any content related to Trojan horse viruses.
2. Program analysis:
To crack a program, you must first understand the program. Therefore, in the cracking process, the analysis of the original program is very important. It can help us understand the author’s purpose and intention, especially the processing details of the registration code, so as to facilitate our backward tracking and derivation.
Open the CHM file, save the first file Acid burn.exe, create a folder of 01, put the exe here, and store the future analysis files here. Open Acid burn.exe, enter and click at will, familiar with the program flow.
We found that this software is divided into two parts, one is Serial/Name, you need to enter the user name and registration code to pass, and the other Serial only needs to enter a registration code and other things. We randomly choose a start, for example, the first one.
We randomly enter a username and serial number (pseudo code):
Pseudo code:
Name:112233
Serial:44556677
Click Check it Baby! It will pop up a dialog box prompt: Sorry, The Serial is incorrect!
Change a few more and try at will, and found that this is the case.
OK, the dialog box appears, which is easy to handle. It means that after checking the registration code, the author will pop up the window if it is wrong. We only need to find the place where the dialog box pops up and follow up to find out whether the judgment is correct. Yes, jmp or Nop is blasted.
3. The specific steps are as follows:
We randomly enter a username and serial number (pseudo code):
Name:112233
Serial:44556677
Click Check it Baby! It will pop up a dialog box prompt: Sorry, The Serial is incorrect!
Do not click the OK button at this time, return to OD pause (F12), click the stack-K small icon (Ctrl+K), as shown in the following figure:
There are two MessageBox addresses. The first address is 77D5082F. This address is obviously too large, not in the airspace of the module, it is not. The second address is 0042A1AE, which is very close to the address 00400100, and it will probably be it.
Right click show call and set a breakpoint on Call.
View nearby code:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
0042A170 /$ 55 push ebp 0042A171 |. 8BEC mov ebp , esp 0042A173 |. 83C4 F4 add esp ,-0xC 0042A176 |. 53 push ebx 0042A177 |. 56 push esi 0042A178 |. 57 push edi 0042A179 |. 8BF9 mov edi , ecx 0042A17B |. 8BF2 mov esi , edx 0042A17D |. 8BD8 mov ebx , eax 0042A17F |. E8 7CB4FDFF call < jmp .&user32.GetActiveWindow> ; [GetActiveWindow 0042A184 |. 8945 F8 mov [ local .2], eax 0042A187 |. 33C0 xor eax , eax 0042A189 |. E8 12A0FFFF call 004241A0 0042A18E |. 8945 F4 mov [ local .3], eax 0042A191 |. 33C0 xor eax , eax 0042A193 |. 55 push ebp 0042A194 |. 68 D0A14200 push 0042A1D0 0042A199 |. 64:FF30 push dword ptr fs :[ eax ] 0042A19C |. 64:8920 mov dword ptr fs :[ eax ], esp 0042A19F |. 8B45 08 mov eax ,[arg.1] 0042A1A2 |. 50 push eax ; /Style 0042A1A3 |. 57 push edi ; |Title 0042A1A4 |. 56 push esi ; |Text 0042A1A5 |. 8B43 24 mov eax , dword ptr ds :[ ebx +0x24] ; | 0042A1A8 |. 50 push eax ; |hOwner 0042A1A9 |. E8 FAB5FDFF call < jmp .&user32.MessageBoxA> ; \MessageBoxA |
It is found that there is no jump statement, and the logic is very simple. There is retn in the upper few lines, break under push ebp at the head, and click the Check it baby button again to find the most recent Return statement on the stack in the lower right corner:
0012F974 0042FB37 RETURN to Acid_bur.0042FB37 from Acid_bur.0042A170
Right click Follow in Disassm.. (disassembly follow), here is a jump directly connected, the code is as follows:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
0042FAD5 |. 68 C8FB4200 push 0042FBC8 ; UNICODE "-" 0042FADA |. FF75 F8 push [ local .2] 0042FADD |. 8D45 F4 lea eax ,[ local .3] 0042FAE0 |. BA 05000000 mov edx ,0x5 0042FAE5 |. E8 C23EFDFF call 004039AC 0042FAEA |. 8D55 F0 lea edx ,[ local .4] 0042FAED |. 8B83 E0010000 mov eax , dword ptr ds :[ ebx +0x1E0] 0042FAF3 |. E8 60AFFEFF call 0041AA58 0042FAF8 |. 8B55 F0 mov edx ,[ local .4] 0042FAFB |. 8B45 F4 mov eax ,[ local .3] 0042FAFE |. E8 F93EFDFF call 004039FC 0042FB03 75 1A jnz short 0042FB1F ; // This JNZ condition judgment is critical? 0042FB05 |. 6A 00 push 0x0 0042FB07 |. B9 CCFB4200 mov ecx ,0042FBCC 0042FB0C |. BA D8FB4200 mov edx ,0042FBD8 0042FB11 |. A1 480A4300 mov eax , dword ptr ds :[0x430A48] 0042FB16 |. 8B00 mov eax , dword ptr ds :[ eax ] 0042FB18 |. E8 53A6FFFF call 0042A170 0042FB1D |. EB 18 jmp short 0042FB37 ; // Is this jump suspicious? 0042FB1F |> 6A 00 push 0x0 0042FB21 |. B9 74FB4200 mov ecx ,0042FB74 ; ASCII 54,"ry Again!" 0042FB26 |. BA 80FB4200 mov edx ,0042FB80 ; ASCII 53,"orry , The serial is incorect !" 0042FB2B |. A1 480A4300 mov eax , dword ptr ds :[0x430A48] 0042FB30 |. 8B00 mov eax , dword ptr ds :[ eax ] 0042FB32 |. E8 39A6FFFF call 0042A170 ; This CALL is the statement that caused the jump 0042FB37 |> 33C0 xor eax , eax ; Returned here |
Does it feel very cordial to see the same text as the prompt box? OK, let’s go through the code. There are two suspicious jumps JNZ and JMP in the recent part. JNZ will use the call 004039FC on it to judge whether our pseudo code is correct. The judgment result is stored in EAX. If EAX is not equal to it, jump Go to the error message box. Our goal is to pass the verification regardless of whether the pseudocode is correct or not, so the easiest way is to fill the sentence jnz with NOP. Let’s try it: select the sentence JNZ, right-click Binary->Fill with NOPS. Go back to the original program, and again Click Check it baby!
Haha, remind Good Job! Passed!
Comparing MessageBox and the last call of the stack (Ctrl+K) window again, is there anything special? right! That CALL is where the MessageBox is called, so next time we don’t need to break the trace at the MessageBox, just go to the last address, show call.
4. Registration machine part
The above part is blasting analysis, let’s see if we can analyze the algorithm of the registration machine.
Break CALL on the line above the original JNZ: Click the Ckeck it Baby! button, the program breaks:
1
2
3
|
0042FAF8 |. 8B55 F0 mov edx ,[ local .4] ; // EDX=44556677 0042FAFB |. 8B45 F4 mov eax ,[ local .3] ; // EAX=CW-4018-CRACKED 0042FAFE |. E8 F93EFDFF call 004039FC |
We found that EDX stores our fake serial number, EAX looks like a correct serial number, or it may be the corresponding user name, we can try it.
Now restore the code we modified before: select those two lines of NOP, right click Undo… Cancel the breakpoint. First try to see if it is Name, enter the value of EAX for Name, continue to 44556677 on the next line, and continue to play wrong. Then try as the serial number, Name is 112233, Serial is CW-4018-CRACKED, try again, OK! Completely correct!
Summary: Before this CALL, the program has already calculated the serial number corresponding to the user name, and then compared with the Serial we entered through this CALL, and finally gave a prompt message. The algorithm we want is not in this CALL.
The next step is to continue to break the CALL above this CALL, and analyze the CALL that produced this serial number. Since the return value of CALL is generally stored in EAX, we can check the value of EAX after nearby CALL to determine the correct registration code generation function.
Two CALLs nearby:
1
2
3
4
5
6
7
8
9
|
0042FADD |. 8D45 F4 lea eax ,[ local .3] 0042FAE0 |. BA 05000000 mov edx ,0x5 0042FAE5 |. E8 C23EFDFF call 004039AC ; // The nearest CALL2 0042FAEA |. 8D55 F0 lea edx ,[ local .4] 0042FAED |. 8B83 E0010000 mov eax , dword ptr ds :[ ebx +0x1E0] 0042FAF3 |. E8 60AFFEFF call 0041AA58 ; // The nearest CALL1 0042FAF8 |. 8B55 F0 mov edx ,[ local .4] ; // EDX=44556677 0042FAFB |. 8B45 F4 mov eax ,[ local .3] ; // EAX=CW-4018-CRACKED 0042FAFE |. E8 F93EFDFF call 004039FC |
Break off the sentence after CALL, click the button, step F8, and find that the correct registration code appears in CALL 1 nearby, indicating that it may be the key registration code CALL. The following is an analysis of it:
Disconnect again at call 0041AA58,
1
2
3
|
0042FAEA |. 8D55 F0 lea edx ,[ local .4] ; edx=0012F998 0042FAED |. 8B83 E0010000 mov eax , dword ptr ds :[ ebx +0x1E0] ; eax=00A85E4C 0042FAF3 |. E8 60AFFEFF call 0041AA58 ; // The most recent CALL 1, registration code CALL |
There is no special information about edx and eax, we can be more sure that the registration code is generated in the call.
At this time, we have two solutions, one is to analyze the parameters of CALL and call CALL remotely to generate the correct registration code, and the other is to analyze the content of CALL and write a generation process based on his algorithm. There is no obvious difference between these two, it just depends on where they are used.
According to my understanding, the first type, memory call is suitable for programs with complex algorithms or infrequent updates. This can save time and complexity. The second is that the algorithm is not particularly complicated, or the software is updated frequently, the complexity of the algorithm is not to say, no matter how frequently the software is updated, the general registration code algorithm will not change, so the generated registration machine can be applied All versions save trouble for everyone.
Well, having said so much, start a formal analysis:
(Since CALL has been called many times here, the parameters of each register are messy, it is recommended to load the program again for easy analysis)
Enter CALL 0041AA58, the code is as follows:
(Because this CALL has been called in many places, we must single-step F7 tracking from the upper CALL each time until we find the correct CALL)
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
0041AA58 /$ 53 push ebx 0041AA59 |. 56 push esi 0041AA5A |. 57 push edi 0041AA5B |. 8BFA mov edi , edx 0041AA5D |. 8BF0 mov esi , eax 0041AA5F |. 8BC6 mov eax , esi 0041AA61 |. E8 A2FFFFFF call 0041AA08 ; // I jumped out directly here, so I need to continue tracking 0041AA66 |. 8BD8 mov ebx , eax 0041AA68 |. 8BC7 mov eax , edi 0041AA6A |. 8BCB mov ecx , ebx 0041AA6C |. 33D2 xor edx , edx 0041AA6E |. E8 E18CFEFF call 00403754 0041AA73 |. 85DB test ebx , ebx 0041AA75 |. 74 0C je short 0041AA83 0041AA77 |. 8D4B 01 lea ecx , dword ptr ds :[ ebx +0x1] 0041AA7A |. 8B17 mov edx , dword ptr ds :[ edi ] 0041AA7C |. 8BC6 mov eax , esi 0041AA7E |. E8 95FFFFFF call 0041AA18 0041AA83 |> 5F pop edi 0041AA84 |. 5E pop esi 0041AA85 |. 5B pop ebx 0041AA86 \. C3 retn Continue to follow up here:
0041AA08 /$ 6A 00 push 0x0 ; /Arg1 = 00000000 0041AA0A |. 33C9 xor ecx , ecx ; | 0041AA0C |. BA 0E000000 mov edx ,0xE ; | 0041AA11 |. E8 F6070000 call 0041B20C ; \Acid_bur.0041B20C 0041AA16 \. C3 retn Continue: 0041B20C /$ 55 push ebp 0041B20D |. 8BEC mov ebp , esp 0041B20F |. 83C4 F0 add esp ,-0x10 0041B212 |. 53 push ebx 0041B213 |. 8955 F0 mov [ local .4], edx 0041B216 |. 894D F4 mov [ local .3], ecx 0041B219 |. 8B55 08 mov edx ,[arg.1] 0041B21C |. 8955 F8 mov [ local .2], edx 0041B21F |. 33D2 xor edx , edx 0041B221 |. 8955 FC mov [ local .1], edx 0041B224 |. 85C0 test eax , eax 0041B226 |. 74 0B je short 0041B233 0041B228 |. 8D55 F0 lea edx ,[ local .4] 0041B22B |. 8BD8 mov ebx , eax 0041B22D |. 8B43 2C mov eax , dword ptr ds :[ ebx +0x2C] 0041B230 |. FF53 28 call dword ptr ds :[ ebx +0x28] 0041B233 |> 8B45 FC mov eax ,[ local .1] 0041B236 |. 5B pop ebx 0041B237 |. 8BE5 mov esp , ebp 0041B239 |. 5D pop ebp 0041B23A \. C2 0400 retn 0x4 Continue to F7 to enter: 0041CB64 /$ 53 push ebx 0041CB65 |. 56 push esi 0041CB66 |. 57 push edi 0041CB67 |. 83C4 F0 add esp ,-0x10 0041CB6A |. 8BF2 mov esi , edx 0041CB6C |. 8BD8 mov ebx , eax 0041CB6E |. 8B06 mov eax , dword ptr ds :[ esi ] 0041CB70 |. 3D 84000000 cmp eax ,0x84 ; Switch (cases 7..20A) 0041CB75 |. 7F 18 jg short 0041CB8F 0041CB77 |. 74 69 je short 0041CBE2 ... |
We found that there is no place to generate the registration code, and all CALLs are constantly being called. Therefore, it is preliminarily determined that the registration code is not generated here. But thinking like this completely overturned the previous speculation, indicating that there is a problem with our thinking, that is, there is a problem with our thinking. Since his registration code was not calculated instantly, it must have been calculated in advance. Let us go back to the CALL where the registration code was generated, look up, and press F8 to view it in a single step.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
0042FA4D |. A1 6C174300 mov eax , dword ptr ds :[0x43176C] ; // name/Tag 0042FA52 |. E8 D96EFDFF call 00406930 ; // key CALL 0042FA57 |. 83F8 04 cmp eax ,0x4 ; // Judge whether tag/serial is qualified 0042FA5A |. 7D 1D jge short 0042FA79 0042FA5C |. 6A 00 push 0x0 0042FA5E |. B9 74FB4200 mov ecx ,0042FB74 ; ASCII 54,"ry Again!" 0042FA63 |. BA 80FB4200 mov edx ,0042FB80 ; ASCII 53,"orry , The serial is incorect !" 0042FA68 |. A1 480A4300 mov eax , dword ptr ds :[0x430A48] 0042FA6D |. 8B00 mov eax , dword ptr ds :[ eax ] 0042FA6F |. E8 FCA6FFFF call 0042A170 0042FA74 |. E9 BE000000 jmp 0042FB37 0042FA79 |> 8D55 F0 lea edx ,[ local .4] 0042FA7C |. 8B83 DC010000 mov eax , dword ptr ds :[ ebx +0x1DC] 0042FA82 |. E8 D1AFFEFF call 0041AA58 0042FA87 |. 8B45 F0 mov eax ,[ local .4] ; EAX=112233的地址 0042FA8A |. 0FB600 movzx eax , byte ptr ds :[ eax ] ; The first byte 1=0x31 0042FA8D |. F72D 50174300 imul dword ptr ds :[0x431750] ; *0x29 0042FA93 |. A3 50174300 mov dword ptr ds :[0x431750], eax ; eax=0x7d9=0x29*0x31 0042FA98 |. A1 50174300 mov eax , dword ptr ds :[0x431750] 0042FA9D |. 0105 50174300 add dword ptr ds :[0x431750], eax ; Doubled 0042FAA3 |. 8D45 FC lea eax ,[ local .1] 0042FAA6 |. BA ACFB4200 mov edx ,0042FBAC 0042FAAB |. E8 583CFDFF call 00403708 0042FAB0 |. 8D45 F8 lea eax ,[ local .2] 0042FAB3 |. BA B8FB4200 mov edx ,0042FBB8 0042FAB8 |. E8 4B3CFDFF call 00403708 0042FABD |. FF75 FC push [ local .1] 0042FAC0 |. 68 C8FB4200 push 0042FBC8 ; UNICODE "-" 0042FAC5 |. 8D55 E8 lea edx ,[ local .6] ; 12F990 0042FAC8 |. A1 50174300 mov eax , dword ptr ds :[0x431750] ; 4018 0042FACD |. E8 466CFDFF call 00406718 0042FAD2 |. FF75 E8 push [ local .6] ; // The middle value of the registration code 0042FAD5 |. 68 C8FB4200 push 0042FBC8 ; UNICODE "-" 0042FADA |. FF75 F8 push [ local .2] 0042FADD |. 8D45 F4 lea eax ,[ local .3] 0042FAE0 |. BA 05000000 mov edx ,0x5 0042FAE5 |. E8 C23EFDFF call 004039AC 0042FAEA |. 8D55 F0 lea edx ,[ local .4] ; edx=0012F998 0042FAED |. 8B83 E0010000 mov eax , dword ptr ds :[ ebx +0x1E0] ; eax=00A85E4C 0042FAF3 |. E8 60AFFEFF call 0041AA58 ; // Registration code CALL 0042FAF8 |. 8B55 F0 mov edx ,[ local .4] ; // EDX=44556677 0042FAFB |. 8B45 F4 mov eax ,[ local .3] ; // EAX=CW-4018-CRACKED 0042FAFE |. E8 F93EFDFF call 004039FC 0042FB03 75 1A jnz short 0042FB1F ; // This JNZ condition judgment is critical? 0042FB05 |. 6A 00 push 0x0 0042FB07 |. B9 CCFB4200 mov ecx ,0042FBCC 0042FB0C |. BA D8FB4200 mov edx ,0042FBD8 0042FB11 |. A1 480A4300 mov eax , dword ptr ds :[0x430A48] 0042FB16 |. 8B00 mov eax , dword ptr ds :[ eax ] 0042FB18 |. E8 53A6FFFF call 0042A170 0042FB1D |. EB 18 jmp short 0042FB37 ; // Is this jump suspicious? 0042FB1F |> 6A 00 push 0x0 0042FB21 |. B9 74FB4200 mov ecx ,0042FB74 ; ASCII 54,"ry Again!" 0042FB26 |. BA 80FB4200 mov edx ,0042FB80 ; ASCII 53,"orry , The serial is incorect !" |
Summary: Take the ASNI number of the first letter. For example, the first character 1 in 112233 corresponds to the number 0x31, and then multiply it by 0x29, and the result is doubled (ie x2), and the resulting number is converted to 10 The registered character string, add “CW-” in front and “-CRACKED” at the end to form the registration code corresponding to the user name.
C/CPP program:
// CrackMe160.cpp : Define the entry point of the console application. // NameSerial part #include "stdafx.h" #include "iostream" int _tmain( int argc, _TCHAR* argv[]) { printf ( "Input Name:\r\n" ); //Take the first character value int cName = getchar (); if ( cName > 0x21) // Only process visible characters { cName *= 0x29; // multiplication cName *= 2; // Doubled printf ( "Serial: CW-%4d-CRACKED\r\n" ,cName); } else { printf ( "input error!\r\n" ); } system ( "pause" ); return 0; } |
The second single Serial
The process is the same as the first one,
But this is very simple, you can basically understand it by pressing F8 upwards directly in the call to CALL.
Core code:
The JNZ before CALL is the key to blasting, and NOP is OK.
The CALL before JNZ is the key to the serial judgment, and it is found that it is a fixed value through single-step tracking.
code show as below:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
0042F470 /. 55 push ebp 0042F471 |. 8BEC mov ebp , esp 0042F473 |. 33C9 xor ecx , ecx 0042F475 |. 51 push ecx 0042F476 |. 51 push ecx 0042F477 |. 51 push ecx 0042F478 |. 51 push ecx 0042F479 |. 53 push ebx 0042F47A |. 8BD8 mov ebx , eax 0042F47C |. 33C0 xor eax , eax 0042F47E |. 55 push ebp 0042F47F |. 68 2CF54200 push 0042F52C 0042F484 |. 64:FF30 push dword ptr fs :[ eax ] 0042F487 |. 64:8920 mov dword ptr fs :[ eax ], esp 0042F48A |. 8D45 FC lea eax ,[ local .1] 0042F48D |. BA 40F54200 mov edx ,0042F540 ; ASCII 48,"ello" 0042F492 |. E8 7142FDFF call 00403708 0042F497 |. 8D45 F8 lea eax ,[ local .2] 0042F49A |. BA 50F54200 mov edx ,0042F550 ; ASCII 44,"ude!" 0042F49F |. E8 6442FDFF call 00403708 0042F4A4 |. FF75 FC push [ local .1] 0042F4A7 |. 68 60F54200 push 0042F560 ; UNICODE " " 0042F4AC |. FF75 F8 push [ local .2] 0042F4AF |. 8D45 F4 lea eax ,[ local .3] 0042F4B2 |. BA 03000000 mov edx ,0x3 0042F4B7 |. E8 F044FDFF call 004039AC 0042F4BC |. 8D55 F0 lea edx ,[ local .4] 0042F4BF |. 8B83 E0010000 mov eax , dword ptr ds :[ ebx +0x1E0] 0042F4C5 |. E8 8EB5FEFF call 0041AA58 0042F4CA |. 8B45 F0 mov eax ,[ local .4] ; // eax=112233 0042F4CD |. 8B55 F4 mov edx ,[ local .3] ; // edx=Hello Dude! 0042F4D0 |. E8 2745FDFF call 004039FC 0042F4D5 75 1A jnz short 0042F4F1 ; // The key to blasting 0042F4D7 |. 6A 00 push 0x0 0042F4D9 |. B9 64F54200 mov ecx ,0042F564 0042F4DE |. BA 70F54200 mov edx ,0042F570 0042F4E3 |. A1 480A4300 mov eax , dword ptr ds :[0x430A48] 0042F4E8 |. 8B00 mov eax , dword ptr ds :[ eax ] 0042F4EA |. E8 81ACFFFF call 0042A170 0042F4EF |. EB 18 jmp short 0042F509 0042F4F1 |> 6A 00 push 0x0 0042F4F3 |. B9 84F54200 mov ecx ,0042F584 0042F4F8 |. BA 8CF54200 mov edx ,0042F58C 0042F4FD |. A1 480A4300 mov eax , dword ptr ds :[0x430A48] 0042F502 |. 8B00 mov eax , dword ptr ds :[ eax ] 0042F504 |. E8 67ACFFFF call 0042A170 0042F509 |> 33C0 xor eax , eax |
This registration code, which is not dynamically generated, is a fixed one: Hello Dude!
Reviews
There are no reviews yet.