Since the "Save the Devil" challenge from cvega seems inactive for sometime now, I decided to write my complete solution for it, in case anyone is wondering how I got the correct numbers, and eventually "saved" the devil. So here goes.
There are a couple of things that you need in order to follow me with this guide. You need OllyDbg (A free debugger @ http://www.ollydbg.de/) and a Hex2Char Converter (any would do, to make things easy).
Done getting the tools?
First thing to do is to get to know the target , which is devil.exe . Run it, and observe it. Let's see, there's a timer... there's a textbox... there's a button... So I'm guessing that we must type something on the textbox (duh!?!). Ok, let's try something before the time runs out, then press go. Hmmm.... nothing happens. let's see what happens if the timer reaches 0 - "The Devil is DEAD!!!" (Take note of this message) - that's not what we want.
Let's check cvega 's solution conditions again.
To save the devil, you need to enter the code to unlock the devil's lifestream before you run out of time!
Hint: The code is 8 digit long composed of all numbers!
Cool! There's a hint! This hint is actually the easy way out for this challenge. If he had not mentioned that, it will be alot harder for us to solve this. Ok, back to the challenge, he said 8 digits -- so there's probably a counter set for that, usually stored in the appropriately named "Counter Register", ECX. Let's take note of that.
Here's where the real fun starts. Fire up OllyDbg, and open our target, "devil.exe". Whoa! What's all these. Behold, the disassembled code of devil.exe. Eeekkk! Anyways, remember the message that was displayed when the devil died, let's use that as a starting point. Right click on an empty space in the CPU panel, then click "Search for" then click "All referenced text strings". A new window will appear. Let's look if the message is here.
Oh goodie, there's 2, but the actual one is the one with the three "!", double click that and let's see where it takes us.
Ok, so far so good, there's the message when we fail to save the devil, and above it is the message when we actually saved the devil. So this means that the calculation for the correct number is somewhere above this code. Let's scroll up a little to find out.
Yahoo! Did you spot it? Did you remember cvega 's hints? 8 digits? There we have it!
Let's set a breakpoint to get a better view of what's going on. Hit F2 on the line with the code MOV ECX, 8. The address will have a red marker which means a breakpoint is set. Once done, run the program. (If you receive an error about something unreadable yada yda, just close the program and run again. It will fix itself after a few tries.) Enter any number on the textbox, then click go. You should break. Let's step over the code using the F8 button.
Let's study the code.
01 004012BD MOV ECX,8 ; This is the counter
02 004012C2 JMP SHORT devil.004012DA ; Jump to line 16
03 004012C4 LODS BYTE PTR DS:[ESI] ; Get a character of your input
04 004012C5 PUSH EAX ; Stored character pushed to stack
05 004012C6 MOV EAX,EDX ; Copy something to EAX, stored digit is overwritten
06 004012C8 POP EAX ; Restore top value of stack, stored digit back to EAX
07 004012C9 ADD AL,18 ; Add 18 to stored digit
08 004012CB SUB AL,0C ; Subtract 0C to stored digit
09 004012CD ADD AL,18 ; Add 18 again...
10 004012CF SUB AL,24 ; Subtract 24, duh, it's back to its original value
11 004012D1 XOR AL,4E ; THIS IS THE ONLY IMPORTANT BIT...
12 004012D3 MOV EDX,EAX ; Sigh... Looking at the algo, I think it's quite useless,
13 004012D5 SUB EDX,0E ; except for line 11, so let's carry on to the comparison
14 004012D8 STOS BYTE PTR ES:[EDI] ; section... which is Line 18.
15 004012D9 DEC ECX ; ECX -= 1
16 004012DA CMP ECX,0 ; Is the counter equal to 0?
17 004012DD JA SHORT devil.004012C4 ; If counter is > 0, got to line 3
Almost everything is junk. But line 11 does something, so let's take note of that. let's look further down to the conditional part of the code;
18 004012DF LEA EAX,DWORD PTR DS:[404175] ; Copy something to EAX as pointed by address 404175 then
19 004012E5 MOV EDX,DWORD PTR DS:[EAX] ; Copy 7A7E7F7F from EAX to EDX, whatever that is...
20 004012E7 MOV ECX,DWORD PTR DS:[EAX+4] ; Copy 76787677 to ECX...
21 004012EA LEA EAX,DWORD PTR DS:[40407D] ; Copy our string as pointed by 40407D
22 004012F0 SUB EDX,DWORD PTR DS:[EAX] ; EDX = 7A7E7F7F - our last 4 digits
23 004012F2 SUB ECX,DWORD PTR DS:[EAX+4] ; ECX = 76787677 - our 1st 4 digits
24 004012F5 ADD EDX,ECX ; Add EDX and ECX result in EDX
25 004012F7 OR EDX,EDX ; Check if EDX is equal to 0
26 004012F9 JNZ SHORT devil.0040136E ; If not zero, our number is WRONG!
; EDX will only be 0 if 7A7E7F7F 76787677 (with extra Xor'ing))
; matches our number.... hence...
So this is what's happening. Each character of the number we input is XORed with 4E, and then subtracted with the correct one. So naturally, if ours matches the one cvega coded, the result must always be zero! And since the correct one is hardcoded, we can easily extract it. The answer is right below our noses all the time! It is;
18 004012DF LEA EAX,DWORD PTR DS:[404175] ; Copy something to EAX as pointed by address 404175 then
19 004012E5 MOV EDX,DWORD PTR DS:[EAX] ; Copy 7A7E7F7F from EAX to EDX, whatever that is...
20 004012E7 MOV ECX,DWORD PTR DS:[EAX+4] ; Copy 76787677 to ECX...
See? Since it's hex, it will be in reverse. The correct (raw) string is 777678767F7F7E7A. Take out your converters and let's convert away, character by character.
Hmmmmm.. this is weird, 77 is w, 76 is v... The correct answer are digits, but were getting alpha characters... So why's that? Check line 11 of the code. Each character must be XORed by 4E! Let's try that.
77 XOR 4E = 39h
76 XOR 4E = 38h
78 XOR 4E = 36h
76 XOR 4E = 38h
7F XOR 4E = 31h
7F XOR 4E = 31h
7E XOR 4E = 30h
7A XOR 4E = 34h
Then let's convert each to a char;
39h = 9
38h = 8
36h = 6
38h = 8
31h = 1
31h = 1
30h = 0
34h = 4
Ok, we got - 98681104; It's all digits, it has 8 characters. Do you think we got it? Only one way to find out...
We did it!!! We save cvega 's devil!!! I hope you learned a lot! Until next time! Bye!
Optional: You can also try to stop the timer for additional challenge if you like. :D
PS: Keith, puwede ba ito? Hehehehe. :D