Welcome to another tutorial on how to resolve a small reverse challenge from Hack The Box. The specified challenge is "Eat the Cake!", the exe file is cake.exe and we are going to reverse it.
As soon as it is disassembled, there seems to be something strange; IDA PRO informs me that the IAT has not been loaded or seems to be outside of the memory allocated for the program if I launch in debug I am in an internal function of an imported library, a little further on some cycle that rewrites a memory location where there should be some code. So I give a look on "program segmentation" and faint memories flow to my mind; something that I haven't seen for years attracts my attention, so I have another old tool to which I had to dust.
I launch the PeID tool, version 0.95, a packer, cryptos and compilers detector for PE files. At first look, I can't notice anything, but also the tool, can't identify the exe file (Nothing found *).
So, I decided to give a hard scan and...
...surprise, this time the tool identifies the UPX patcher. I remember the UPX patcher, is not so complex, but sometimes present some problem to unpack it.
Anyway, go on and try to dump... No, rest assured, I won't waste you hours trying to restore the original version of the software when I didn't. However, I present the approaches that I adopted in the attempt:
- original upx packer/unpacker
- PeID (itself)
I'm not so good at restoring the OEP, but some autonomous tools have not been able to do the same, surely someone else who has solved this challenge has dumped it, but reaching the solution in the way you think is most comfortable is still a good goal, so I will describe my solution.
Ok, after these approaches I decide to go on with a full debug session. IDA PRO seems to give me so many problems, so I chose another debugger: ollydbg.
Before to start, I view some old tutorials and articles about how to work UPX packer (my skills are a little rusted, I'm many years that I don't reverse).
So, finally, I remember and apply the correct steps to leave the program in memory and debug without the original binary file. This would mean, that, considering how UPX work, every time I launch debug, the address generated in memory will be different, so I have to execute all the code without relevant breakpoint, so prepare to repeat the same steps for many many times, but let's not be discouraged.
Launching with ollydbg, the starting point of the program will be always the same (it stop the process at the same point).
The first instruction, a PUSHAD, load in the ESP the starting procedure where the rewriting procedure of the original code was restored. Here you can find a small loop and immediately after a jump to the starting program. To stop in the right address, anyway, step for a single instruction (F7 or F8), right-click on the ESP register, "Follow in Dump", select the our byte on the ASCII representation of the memory and set an "hardware break on write" of a word and continue to execute to arrive at that point (Like in the animation below).
Ok, if you are in the right place, you have to execute a small loop and then jump at the real entrypoint (let me call it so) to debug the real piece of code. To be fast, you can locate on the last line of code where the final jump will bring you at the start of the rewritten procedure (three-line after the point where you are landing) and press F4 (to execute all the loop) and after F7 or F8.
Well, I tried much time to understand which the next interesting function to follow, and after a lot of debugging session I arrive at this instruction:
009B24AA E8 A1EEFFFF CALL cake.009B1350
Run inside (F7) and take open your eyes. Here you can identify some known message.
If you execute the code straight on it will stop at this line of code:
009B1447 E8 94090000 CALL cake.009B1DE0
The program is asking for the 10 digit password. If you try the program as is (without debug) you can see that it asking for 10 digit password before and 15 digit password after..... have you try to pass a generic password of 15 digits immediate? Yes, the second message is ignored. If you specify then a 15 digit password the program take it as the answer to the second question. Then, also if the code asks for a 10 digit password you can insert a 15 digit password. To identify when the program elaborates our code, write something that you can identify immediately when showed, something like "123456789012345". When you press "enter" the code comes back to the debugger and you can go on with your session.
Well, execute not so fast and ee the code pass in front of your eyes. You should arrive at a code like this:
where I'd like to be attention on the strccpy instruction (used in c++ to put a string in a variable), the block immediately after and the messages at the end of the code.
Well, I want that you understand what I mean, then execute until the strcpy instruction and press F8 to execute also it.
Well done, after the instruction our 15 digit password is in the ECX register. The code after is really interesting, it check, char by char, in a spread order, the characters of our password, when it turns out wrong the code jump on the message "Better luck next time!". Well try to put the chars in the correct order and identify the letter it is checking. This is the original code:
009B14AA 83C4 10 ADD ESP,10 009B14AD C68424 23040000 >MOV BYTE PTR SS:[ESP+423],0 009B14B5 8D4C24 24 LEA ECX,DWORD PTR SS:[ESP+24] 009B14B9 E8 32FEFFFF CALL cake.009B12F0 009B14BE 807C24 27 6B CMP BYTE PTR SS:[ESP+27],6B 009B14C3 8AD0 MOV DL,AL 009B14C5 75 34 JNZ SHORT cake.009B14FB 009B14C7 807C24 2C 61 CMP BYTE PTR SS:[ESP+2C],61 009B14CC 75 2D JNZ SHORT cake.009B14FB 009B14CE 807C24 24 68 CMP BYTE PTR SS:[ESP+24],68 009B14D3 75 20 JNZ SHORT cake.009B14F5 009B14D5 807C24 2E 61 CMP BYTE PTR SS:[ESP+2E],61 009B14DA 75 19 JNZ SHORT cake.009B14F5 009B14DC 807C24 29 68 CMP BYTE PTR SS:[ESP+29],68 009B14E1 75 18 JNZ SHORT cake.009B14FB 009B14E3 807C24 2D 72 CMP BYTE PTR SS:[ESP+2D],72 009B14E8 75 11 JNZ SHORT cake.009B14FB 009B14EA 807C24 2F 64 CMP BYTE PTR SS:[ESP+2F],64 009B14EF 75 0A JNZ SHORT cake.009B14FB 009B14F1 B0 01 MOV AL,1 009B14F3 EB 08 JMP SHORT cake.009B14FD 009B14F5 8A4424 0B MOV AL,BYTE PTR SS:[ESP+B] 009B14F9 EB 02 JMP SHORT cake.009B14FD 009B14FB 32C0 XOR AL,AL 009B14FD 807C24 25 40 CMP BYTE PTR SS:[ESP+25],40 009B1502 75 1F JNZ SHORT cake.009B1523 009B1504 807C24 32 45 CMP BYTE PTR SS:[ESP+32],45 009B1509 75 18 JNZ SHORT cake.009B1523 009B150B 807C24 26 63 CMP BYTE PTR SS:[ESP+26],63 009B1510 75 0B JNZ SHORT cake.009B151D 009B1512 807C24 31 24 CMP BYTE PTR SS:[ESP+31],24 009B1517 75 04 JNZ SHORT cake.009B151D 009B1519 B1 01 MOV CL,1 009B151B EB 08 JMP SHORT cake.009B1525 009B151D 8A4C24 0B MOV CL,BYTE PTR SS:[ESP+B] 009B1521 EB 02 JMP SHORT cake.009B1525 009B1523 32C9 XOR CL,CL 009B1525 84D2 TEST DL,DL 009B1527 74 0D JE SHORT cake.009B1536 009B1529 84C0 TEST AL,AL 009B152B 74 09 JE SHORT cake.009B1536
The correct order should be this...
00CD14CE 807C24 24 68 CMP BYTE PTR SS:[ESP+24],68 00CD14FD 807C24 25 40 CMP BYTE PTR SS:[ESP+25],40 00CD150B 807C24 26 63 CMP BYTE PTR SS:[ESP+26],63 00CD14BE 807C24 27 6B CMP BYTE PTR SS:[ESP+27],6B ....................................................... 00CD14DC 807C24 29 68 CMP BYTE PTR SS:[ESP+29],68 ....................................................... ....................................................... 00CD14C7 807C24 2C 61 CMP BYTE PTR SS:[ESP+2C],61 00CD14E3 807C24 2D 72 CMP BYTE PTR SS:[ESP+2D],72 00CD14D5 807C24 2E 61 CMP BYTE PTR SS:[ESP+2E],61 00CD14EA 807C24 2F 64 CMP BYTE PTR SS:[ESP+2F],64 ....................................................... 00CD1512 807C24 31 24 CMP BYTE PTR SS:[ESP+31],24 00CD1504 807C24 32 45 CMP BYTE PTR SS:[ESP+32],45
mmmm..... some character is missing, but, don't worry, identify the characters and start to read what is available...
...if I replace the number with the relative char (68 = h, 40 = @, 63 = c and so on)...
6840636B..68....61726164..2445 h @ c k . h . . a r a d . $ E
I know, most of you are reading the hidden letters identifying the missing ones. Ok, but let me explain here you can find the rest of the chars.
There's a function after the strcpy, you have to enter inside and here are verified the missing letter, or at least two of the missing letter.
009B14B9 E8 32FEFFFF CALL cake.009B12F0
The additional two chars verified are the "t" and the "p" letters that are the fifth and the eighth letters of the entire password, so, our secret word at this moment is:
h @ c k t h . p a r a d . $ E
Well, it's clear that the sentence is "hack the paradise", but knowing the hacking community, will be not a simple letter, but number that replaces the original letters, so I suppose the "e" or "E" letter was replaced by the number "3" and the "i" or "I" letter is replaced by the number "1".
Our final password should be h@ckth3parad1$E.
And also this challenge is done.
P.S.: Well, last part of the chars identification, is done by supposition, but, let me say that, sure you can turn around the code and you will find the last part of the verification process where is checked the two letter missing.