MY SOLUTION TO MALWARE.LU’S HACKGYVER CHALLENGES Well, its been a long time since I tried reversing something & when I saw a tweet announcing this challenge, I decided to give it a shot. As it turns out, the package for download contained 2 binaries, one for Windows platform & the other one for Linux. I’ll note down my solutions for both quickly. WINDOWS BINARY Well, this was an interesting one. As usual, I scanned it with PEiD & it said “Nothing Found”. Am used to accepting that as a good omen by now ;) . So next, on executing it, this is what it looks like: A simple looking Win32 application. Thing to note, it accepts just one input. Great, so moving on, when I tried entering some random value for PIN & clicked the “validate” button, the above message changed from “Enter your PIN code” to “Bad PIN code”, as expected. Here, we have two options, either use Ollydbg which happens to be my all time favourite debugger on Windows & learn as we go along or open it up in IDA Pro & study it first. I usually prefer to mix both. But for this one, I opened it up in IDA Pro first & after some quick analysis, found out that although the above input box can take about 8~9 characters as input, in the code, only the first 5 are used in further calculation. Let me point out some of the code for you. Most of the action happens at the subroutine located at 0x4013A0. Open it up in IDA & you can clearly see the whole big picture. To sum up all the important events happening here, this should suffice: 1. Get input using GetWindowTextW. 2. After some initial verification, pass this data to the subroutine that starts at 0x401000. 3. The above routine does the whole validation & based on the result, displays the goodboy or badboy message. Seems simple. Next, looking into the code at 0x401000, I realized that the application discards any input that’s less than or greater than 5chars in size. In short, your input has to be exactly 5 characters in size. That’s kinda sweet. ;) Here’s the code that does this check :
Confirmed this by actually running the app & monitoring it with Ollydbg. Scrolling down a bit, the whole code was messy. Now, from the tweet, we were only supposed to find the valid PIN for this challenge. Hence, like I always do, I decided to try the simplest approach first & if that fails, go the manual way. Its for times like these that I have AutoIT installed my XP Virtual Machine. Its very useful to put together a quick & dirty hack when it comes to automating things at GUI level. For everything else, I prefer Perl. So, my plan of action here was to put together a simple AutoIT script that’ll bruteforce all possible numeric combinations while I work on some official reports. If it doesn’t crack it, will actually sit & reverse the algorithm & find the correct PIN. AutoIT script was made in a jiffy & after about 30minutes of running it, when I was done with my other reports & stuff, this is what I found:
So that’s how it was done. The correct PIN was “13044”. Just a hunch & some quick coding solved it for me & frankly, I did not even kill any of my grey cells on this. Stroke of luck. It could have been much worse though. For example, if the right PIN was even alphanumeric, the above approach would have failed miserably & not to mention I would have had to actually get down to understanding the entire algorithm. But anyways, as long as we cracked it, its all good. LINUX BINARY Ah this one was unexpected! Frankly I was in no mood to try the Linux binary for various reasons ranging from loads of work at hand to almost completely have forgotten the cryptic gdb commands but it was probably destined to be done. Next day morning my internet was down & with nothing else to do, I thought of giving this one a try anyways. Lets dive straight into this one, shall we? To begin with, I opened up my Ubuntu VM & got this binary on my desktop folder. First thing I usually do with Linux crackmes/challenges is to analyze the binary with these commands: strings, strace, ltrace & so on. Once this stage is over, open it up in IDA Pro & side by side debug using gdb. “strings” command was the first one I tried & it gave these interesting strings amongst others: • MD5_Final • BIO_f_base64 • strcpy • strcmp • Well, now create your own keygen ;) • Bad key Interesting things to note here are, the possibility of MD5 hashing & use of base64. Okay, moving further, I tried ltrace & this is what happened: Now that’s a pretty weird output. Maybe it takes input as commandline arguments. So the next thing I tried was to run the same program with an argument. The output I got from it is there on the following page & its very interesting for various reasons. I’ve highlighted the interesting parts in the output.
So, it seems like the program takes in input via commandline as an argument, it does use MD5 as the strings that are being compared at the end are infact MD5 hashes. Its also possible that it uses base64 at some point. Ohkies, now its time to put it through some better tools & analyze the program. For this, I chose IDA Pro. Once opened up in IDA Pro, its like reading a book. IDA takes us straight to “main()” function & as you can clearly see, that’s where all the action is. I’ll sum up the code in main() here quickly: 1. Check if there is only 1 argument passed via commandline. Exit if this fails. 2. Check if the length of the input is more than 8 chars or else, exit. 3. Runs MD6 on the user entered string & saves this. 4. Puts the user entered string through RC4_Encode & generates a new string. Calculates the MD6 hash of this string. 5. Compares the strings from steps 3 & 4 & if they are the same, it’s the right serial or else, it exits with a badboy message. This looks simple but fishy. On further inspection, it turns out that its infact MD5 & not MD6 & instead of RC4_encoding, its actually base64 that’s used. Now this perfectly matches with the output we got from ltrace earlier. To cut short the story, the serial/key is checked as follows: 1. Input has to be more than 8 characters long. (Ex. “aodruleza”) 2. It calculates the MD5 hash of this string & saves it. ( “ABCA96374F97C3EC3B2D415470760401” for “aodruleza”) 3. The first 9 characters of input are preserved & rest are discarded. It then calculates the base64 encoding of this string, takes the first 12 characters of the result & concatenates with the user entered string that was truncated to 9 characters. ( base64 encoding of string “aodruleza”, truncated to 12 characters is “YW9kcnVsZXph”. So, the final string after step 3 turns out to be “aodrulezaYW9kcnVsZXph”) 4. Calculate MD5 has of string from step 3 & compare it with the hash calculated in step 1. If they match, it’s the right key & if they don’t, it displays the message “Bad key”. So, in short, a valid key for the challenge is “aodrulezaYW9kcnVsZXph”. Here’s the output when this one was tried: And the following page contains code of the ugly keygen that I made for it. So, that’s all guys. It was indeed interesting & I got to brush up my gdb skills after a long time. Hope this helped someone. Have a nice day! AODRULEZ