When we open the patchme with Ollydbg, we will see the following piece of code:
Address Hex dump Command Comments
00401030 \BA 00504000 MOV EDX,OFFSET Patch-2.00405000 ; ASCII "Modify calls/instructions to output the correct number, not your initial number
"
00401035 E8 F20F0000 CALL 0040202C
0040103A BA 52504000 MOV EDX,OFFSET Patch-2.00405052 ; ASCII "Eliminating CMPS and JMPS is not the goal here ;) look at the logic and flow
"
0040103F E8 E80F0000 CALL 0040202C
00401044 BA A1504000 MOV EDX,OFFSET Patch-2.004050A1 ; ASCII "Your initial number is: "
00401049 E8 DE0F0000 CALL 0040202C
0040104E A1 BA504000 MOV EAX,DWORD PTR DS:[4050BA]
00401053 E8 F90C0000 CALL 00401D51
00401058 E8 B8010000 CALL 00401215
0040105D E8 4B0C0000 CALL 00401CAD
00401062 E8 AE010000 CALL 00401215
00401067 B9 04000000 MOV ECX,4
0040106C A1 BA504000 MOV EAX,DWORD PTR DS:[4050BA]
00401071 D1E8 SHR EAX,1
00401073 A3 BE504000 MOV DWORD PTR DS:[4050BE],EAX
00401078 E2 F7 LOOP SHORT 00401071
0040107A E8 4E000000 CALL 004010CD
0040107F BA C2504000 MOV EDX,OFFSET Patch-2.004050C2 ; ASCII "Your number is now: "
00401084 E8 A30F0000 CALL 0040202C
00401089 A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
0040108E E8 BE0C0000 CALL 00401D51
00401093 E8 7D010000 CALL 00401215
00401098 A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
0040109D 3D 47250000 CMP EAX,2547
004010A2 75 11 JNE SHORT 004010B5
004010A4 BA D7504000 MOV EDX,OFFSET Patch-2.004050D7 ; ASCII "Congrats! The numbers match! Now get the md5 Hash and enter it as your password!
"
004010A9 E8 7E0F0000 CALL 0040202C
004010AE E8 FA0B0000 CALL 00401CAD
004010B3 EB 11 JMP SHORT 004010C6
004010B5 BA 2A514000 MOV EDX,OFFSET Patch-2.0040512A ; ASCII "Sorry, not the right patching...
"
004010BA E8 6D0F0000 CALL 0040202C
004010BF E8 E90B0000 CALL 00401CAD
004010C4 EB 00 JMP SHORT 004010C6
004010C6 6A 00 PUSH 0
004010C8 E8 39100000 CALL <JMP.&KERNEL32.ExitProcess> ; Jump to kernel32.ExitProcess
004010CD A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
004010D2 83C0 01 ADD EAX,1
004010D5 A3 BE504000 MOV DWORD PTR DS:[4050BE],EAX
004010DA E8 01000000 CALL 004010E0
004010DF C3 RETN
004010E0 A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
004010E5 3305 BE504000 XOR EAX,DWORD PTR DS:[4050BE]
004010EB A3 BE504000 MOV DWORD PTR DS:[4050BE],EAX
004010F0 C3 RETN
There are many ways to get the goodguy message, but there is only one way to get the correct hash. Let us take a look at the first part of the code:
00401030 \BA 00504000 MOV EDX,OFFSET Patch-2.00405000 ; ASCII "Modify calls/instructions to output the correct number, not your initial number
"
00401035 E8 F20F0000 CALL 0040202C
0040103A BA 52504000 MOV EDX,OFFSET Patch-2.00405052 ; ASCII "Eliminating CMPS and JMPS is not the goal here ;) look at the logic and flow
"
0040103F E8 E80F0000 CALL 0040202C
00401044 BA A1504000 MOV EDX,OFFSET Patch-2.004050A1 ; ASCII "Your initial number is: "
00401049 E8 DE0F0000 CALL 0040202C
0040104E A1 BA504000 MOV EAX,DWORD PTR DS:[4050BA] ; the address [4050BA] holds the number 12a34h (76340 in decimal)
00401053 E8 F90C0000 CALL 00401D51
00401058 E8 B8010000 CALL 00401215
0040105D E8 4B0C0000 CALL 00401CAD
00401062 E8 AE010000 CALL 00401215
00401067 B9 04000000 MOV ECX,4 ; loop counter
0040106C A1 BA504000 MOV EAX,DWORD PTR DS:[4050BA] ; load 12a34h in eax
00401071 D1E8 SHR EAX,1 ; eax >>= 1
00401073 A3 BE504000 MOV DWORD PTR DS:[4050BE],EAX ; load eax in [4050BE]
00401078 E2 F7 LOOP SHORT 00401071 ; jump back to 00401071 (SHR EAX, 1) until ecx is zero
The initial number that will be loaded is 76340. After some bitshifting the result will be compared against the value 2547h (9543 in decimal), as we can see
in the following piece of code:
0040107A E8 4E000000 CALL 004010CD
0040107F BA C2504000 MOV EDX,OFFSET Patch-2.004050C2 ; ASCII "Your number is now: "
00401084 E8 A30F0000 CALL 0040202C
00401089 A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
0040108E E8 BE0C0000 CALL 00401D51
00401093 E8 7D010000 CALL 00401215
00401098 A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE] ; remember that the code we saw earlier stored the result of the bitshifting in the address [4050BE]
0040109D 3D 47250000 CMP EAX,2547 ; eax ([4050BE]) is equal to 2547h ?
004010A2 75 11 JNE SHORT 004010B5 ; if not equal jump to the badguy message (Sorry, not the right patching)
We now know that the result of the bitshifting has to be equal to the number 2547h. So we are going to take a look at the results of the loop:
0x12a34 >> 1 = 0x951a
0x951a >> 1 = 0x4a8d
0x4a8d >> 1 = 0x2546 ; we would get this result if we change 'mov ecx, 4' to 'mov ecx, 3'
0x2546 >> 1 = 0x12a3
The value we are looking for isn't there, but there is one value that is really close to it. If we would follow the jump at address 0040107A, we would see
the following piece of code:
CPU Disasm
Address Hex dump Command Comments
004010CD \A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
004010D2 83C0 01 ADD EAX,1
004010D5 A3 BE504000 MOV DWORD PTR DS:[4050BE],EAX
004010DA E8 01000000 CALL 004010E0
004010DF C3 RETN
This piece of code adds 1 to the result of the bitshifting, and 0x2546 + 1 equals 0x2547. But we aren't done yet. This piece of code also
makes a jump to the following piece of code:
004010E0 A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
004010E5 3305 BE504000 XOR EAX,DWORD PTR DS:[4050BE] ; n xor n = 0
004010EB A3 BE504000 MOV DWORD PTR DS:[4050BE],EAX
004010F0 C3 RETN
When this piece of code gets executed, it will set the value of the result to zero. So it is better that this piece of code never gets executed. We can eleminate this call
by filling it with nops.
The final code will be:
CPU Disasm
Address Hex dump Command Comments
00401030 |> \BA 00504000 MOV EDX,OFFSET Patch-2crackedfinal.00405 ; ASCII "Modify calls/instructions to output the correct number, not your initial number
"
00401035 |. E8 F20F0000 CALL 0040202C ; [Patch-2crackedfinal.0040202C
0040103A |. BA 52504000 MOV EDX,OFFSET Patch-2crackedfinal.00405 ; ASCII "Eliminating CMPS and JMPS is not the goal here ;) look at the logic and flow
"
0040103F |. E8 E80F0000 CALL 0040202C ; [Patch-2crackedfinal.0040202C
00401044 |. BA A1504000 MOV EDX,OFFSET Patch-2crackedfinal.00405 ; ASCII "Your initial number is: "
00401049 |. E8 DE0F0000 CALL 0040202C ; [Patch-2crackedfinal.0040202C
0040104E |. A1 BA504000 MOV EAX,DWORD PTR DS:[4050BA]
00401053 |. E8 F90C0000 CALL 00401D51 ; [Patch-2crackedfinal.00401D51
00401058 |. E8 B8010000 CALL 00401215 ; [Patch-2crackedfinal.00401215
0040105D |. E8 4B0C0000 CALL 00401CAD ; [Patch-2crackedfinal.00401CAD
00401062 |. E8 AE010000 CALL 00401215 ; [Patch-2crackedfinal.00401215
00401067 |. B9 03000000 MOV ECX,3
0040106C |. A1 BA504000 MOV EAX,DWORD PTR DS:[4050BA]
00401071 |> D1E8 /SHR EAX,1
00401073 |. A3 BE504000 |MOV DWORD PTR DS:[4050BE],EAX
00401078 |.^ E2 F7 \LOOP SHORT 00401071
0040107A |. E8 4E000000 CALL 004010CD
0040107F |. BA C2504000 MOV EDX,OFFSET Patch-2crackedfinal.00405 ; ASCII "Your number is now: "
00401084 |. E8 A30F0000 CALL 0040202C ; [Patch-2crackedfinal.0040202C
00401089 |. A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
0040108E |. E8 BE0C0000 CALL 00401D51 ; [Patch-2crackedfinal.00401D51
00401093 |. E8 7D010000 CALL 00401215 ; [Patch-2crackedfinal.00401215
00401098 |. A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
0040109D |. 3D 47250000 CMP EAX,2547
004010A2 |. 75 11 JNE SHORT 004010B5
004010A4 |. BA D7504000 MOV EDX,OFFSET Patch-2crackedfinal.00405 ; ASCII "Congrats! The numbers match! Now get the md5 Hash and enter it as your password!
"
004010A9 |. E8 7E0F0000 CALL 0040202C ; [Patch-2crackedfinal.0040202C
004010AE |. E8 FA0B0000 CALL 00401CAD ; [Patch-2crackedfinal.00401CAD
004010B3 |. EB 11 JMP SHORT 004010C6
004010B5 |> BA 2A514000 MOV EDX,OFFSET Patch-2crackedfinal.00405 ; ASCII "Sorry, not the right patching...
"
004010BA |. E8 6D0F0000 CALL 0040202C ; [Patch-2crackedfinal.0040202C
004010BF |. E8 E90B0000 CALL 00401CAD ; [Patch-2crackedfinal.00401CAD
004010C4 |. EB 00 JMP SHORT 004010C6
004010C6 |> 6A 00 PUSH 0 ; /ExitCode = 0
004010C8 \. E8 39100000 CALL ; \KERNEL32.ExitProcess
004010CD /$ A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
004010D2 |. 83C0 01 ADD EAX,1
004010D5 |. A3 BE504000 MOV DWORD PTR DS:[4050BE],EAX
004010DA |. 90 NOP
004010DB |. 90 NOP
004010DC |. 90 NOP
004010DD |. 90 NOP
004010DE |. 90 NOP
004010DF \. C3 RETN
004010E0 /> A1 BE504000 MOV EAX,DWORD PTR DS:[4050BE]
004010E5 |. 3305 BE504000 XOR EAX,DWORD PTR DS:[4050BE]
004010EB |. A3 BE504000 MOV DWORD PTR DS:[4050BE],EAX
004010F0 \. C3 RETN
The MD5 hash of the final executable will be:
e0766a5ee9aa6edc5fb972a789c27e1e