Nice job, you’re really knocking these out! Here’s the next binary. The password to the zip archive is “malware” again.
Keep up the good work, and good luck!
By the way get used to this; the password will be ‘malware’ for the future zips. There’s nothing in this welcoming message that hints to what we should do for this level (like in the previous one for example), so off we go!
After we unzip the archive we get a file called such_evil and it is 7168 bytes long. The file doesn’t have a file extension, but running file on it reveals it’s a M$ PE32 file, or in common parlance a .exe file! So what does such_evil.exe do?
And then it exits. Given M$’s history of bizarre error codes (I’m looking at you , ERROR_SUCCESS) it wouldn’t be surprising if ‘BrokenByte’ was an error code, but it’s not. So what other information can we get? Googling ‘Fatal Application Exit’ returns its MSDN page, which is not terribly helpful. It just says that an application should use FatalAppExit as its last resort as it may not correctly close file handles or any other open resources used by the application (and also contains a very amusing comment by a confused user!), but the page gives no hints as to what arguments this method accepts. Writing a simple FatalAppExit Hello-World program in VS will inform us that this method accepts two arguments: the first argument is an UINT and the second one an LPCTSTR, or the message to be displayed to the user (gotta love M$ types). After all this I found an actually useful MSDN page on FatalAppExit.
An error occurred and the program crashed, and we should find out what error occurred! Inspecting the environment variable %errorlevel% shows that the exit status of our program was 0. As you might have guessed, error code 0 is ERROR_SUCCESS. So…was there an error or not?
Peering Under the Hood, or IDA
Opening the binary up with IDA we can see that it has only four functions defined. My cunning plan is to find where that string, BrokenByte, is being used and work backwards from there. Genius, I know. Since it is not an M$ error message, it’s unlikely to be in any of the imported DLLs and therefore *has* to be in our application. Right?
So my cunning plan failed, as per Figure 2. What if we track down the call to FatalAppExit?
Another plan goes in the bin. Looks like we’ll have to do some actual thinking for this one. So, let’s have a look at the functions in the application.
There are four functions in this application: sub_401000, sub_40258C, sub_402590 and sub_4025D1. While most of them are dull as ditch water, with the exception of sub_401000 which is very promising. Figure 4 illustrates the end of this huge function:
Although sub_401000 is too large to post, it’s a big repetition of the sample shown in Figure 4, it moves bytes to the stack. Also observe the call eax instruction towards the end of the block, I bet that something interesting is happening after that call (yes, I am very weary of control flow obfuscation like that).
Running this binary in immunity and putting a breakpoint over call eax we see that eax’s value is 0x18FD47, a stack address! Let the single-stepping begin! Figure 5 shows what we first come across when we follow the call:
Huh, valid code. I say valid because if you view the stack segment as code, in a normal program, most of the times the result might appear as broken, very obscure or generally incoherent instructions. We can see that the first bit of assembly is a loop that writes to the stack, so if we place a breakpoint on 0x18FD63 and then inspect the stack:
Aha. So somebody is being “funny” and messing with the stack. It’s amazing how instructions can form a valid sentence, really makes Von Neumann shine! Observe the memory address 0x17FD68 in the CPU and Stack windows and you’ll see that the first XOR loop revealed this message on the stack: “and so it begins“. Continuing our journey one step at a time and inspecting the stack, we get to a second message, shown in Figure 7:
“nopasaurus“. I wonder what that is about, guess I should keep an eye out for a noticeable NOP-sled or something. Stepping forward, we reach another loop in our code. Stepping over it reveals a new message, “get ready to get nop’ed so damn hard in the pain”, and if we continue in this fashion we encounter yet another message, “omg is it almost over?!?”.
At this point it’s worth taking a step back and think about what we’re dealing with. The messages so far suggest that we should keep an eye out for some NOP instructions. Furthermore, it’s worth noting how the code behaves so far. Previous segments use the stack to modify the code that is going to get executed next and to reveal clues. The general format in which this is happening could be abstracted as:
....instructions.... mov ESI, target message address more loop init here jmp in loop XOR target bytes, some stack address increment loop counters JMP looptop JMP next instructions ... more instructions ...
Tracing this pattern has, so far, consistently revealed a message on the stack after the XOR loop. Following the code and watching out for loops, we finally get to Figure 8:
After following this multi-step procedure we’re finally there! The address we’re after is firstname.lastname@example.org, as shown in the memory window. Also, if we keep on stepping for a bit longer, we see a new message crop up in the memory that reads “aaaaaand i’m spent“, as seen in the stack and register windows in Figure 8. Although absent from Figure 8, there were some NOPs preceding the code that revealed the email address and I was looking out for those!
Taking it one step further
If you remember my original ingenious theories you would be curious to know where “BrokenByte” is and where FatalAppExit is called. If we take some more steps we will eventually arrive at a point in the code where BrokenByte is being decrypted on the stack in much the same way as our previous strings. FatalAppExit is being called by the the application enumerating kernel32.dll’s functions in memory, finding out FatalAppExit’s address and loading it into EDI and then doing CALL EDI.
We stepped up to this challenge as well. Although it wasn’t complicated, it did require some vigilance and patience. You had to spot that CALL EAX at the end of sub_401000 and further look into it, but thankfully the first clue that you’re going in the right direction was given very early on and so we didn’t really have to step up our game! The fourth challenge is next 🙂
P.S. Sorry for the puns, there were there and I had to do it.