A Successful Yet Failed Flare ON Challenge - The Write-up
Introduction
Before I start going discussing how I solved challenges 1-9 (yes, I did not complete binary 10 or 11) I wanted to give my reasoning for doing a write-up despite not finishing. I had started challenge 1 with little expectation that I would make it very far (ie: finishing). Perhaps this is due to my feeling of not being “great” at reverse engineering (you’ll see lolz in my solutions) or because I simply assumed they would be too hard (the FLARE team is top notch). With that said… advancing as far as I did has left me with a greater level of confidence in my ability in RE and I am glad I pushed myself to learn new skills and tactics along the way! I do wish I would of had the time to mess with 10 as judging from other write-ups I might have gotten it!
Secondly, reading other write-ups has shown me that we all solved these challenges very differently and I wanted to put mine forth into the community to have more methodologies of obtaining the same result. I love this aspect of challenges like these and enjoy the knowledgeable bombs associated with write-ups. Reading some of them has shown me how little I actually understood on some of these at the internal level. Next year I will spend more time on the higher level logic instead of trying to do random things (you’ll see).
I also wanted to thank the FLARE team for providing such a fun set of binaries!
You’ll see in my solutions that I had crooked logic, some luck and overall some hilarious code! Like the FLARE team say though, “There is no such thing as cheating in malware analysis”.
Note: I apologize for the memes... but they suit my approaches.
Challenge 1
Challenge 1 was a fun yet easy start as the e-mail will later show. The binary is i_am_happy_you_are_to_playing_the_flareon_challenge.exe. Me too. Let’s go.
Popping the binary into IDA we see it is not very complicated
We need to view the byte_402140 location to grab the values we are comparing each character of our password to after the XOR.
User input get XOR’d with 0x7d and compared to a byte at location byte_402140
Let’s write a Python script to solve! (I have IDA Demo so no IDAPython)
Challenge 2
Another console binary! This one, like the first, asks for a password!
Opening the file in IDA I saw the main routine asking for the string and traced it into the decryption loop at sub_401084. I noticed it was using a lot of weird x86 instructions and saw the location were it would validate a character in our inputted password.
loc_4010A2 causes the program to continue to traverse our password. Looking at the assembly closer I realized that eax is always xor’d with itself when a character is not in the right location… I’ll come back to this.
I also saw what the minimum length of the string needed to be based off of a counter and that the EDI register is always subtracted by 2 when a character matches
Tracing back to the applications entry point we see at the first call we obtain a series of bytes as our saved EIP on the stack and that value is later popped into EAX, which will eventually become “EDI” in our decryption loop.
At this point I knew enough about the program and decided to take a brute force approach by patching the binary! I replaced the xor which will be our return value (0) when the program exits, telling us are failure, to take in the value in EDI instead! Knowing EDI decrements every time we get a character correct, we can use that to build a forcer.
becomes
I also had to patch some bytes in sub_401000 in order to return the value of EDI
becomes
and my python script to do this was
and eventually I got the password!
See what I meant about my methods being crude? :) Yeah yeah I know this is a horrible way to solve this one (or is it?), but hey it worked!
Challenge 3
Good ol’ Elfie…
Knowing this binary, elfie.exe, was a python compiled exe (you can tell by the icon in this case) I ran pyinstxtractor on it to get the source files.
Performing this action lead to an awful lot of files… in the “out00-PYZ.pyz_extracted” directory that pyinstxtractor left me I noticed the file “elfie” which when opened is a giant blob of garage!
Knowing this was base64, I just added the result into a string and printed it instead of having the program actually run itself
Now having this, I ran elfie as a python script
and obtained another massive file!
Getting lucky and going to the bottom of the file I saw it (on line 15)!
which reversed is our key,
bonus fun: changing the code on line 11 (notepad++) of
to
gives us success elfie without telling elfie our password
Challenge 4
Getting the binary, youPecks.exe we can see it tells us 2+2=4
Using peparser, a script I wrapped around pefile (a crummy one I made when I was bored one evening during my undergrad… surprised it came in handy), we can also see that the binary is packed with upx.
Knowing that, I didn’t even bother trying “upx -d” (I already heard not to) and just went straight to unpacking it manually… this is where I became immensely confused. Not because I can not manually unpack upx, but because I could not get OllyDbg to do it! I eventually was able to unpack using Immunity, but I still could not figure out what to do inside the binary in IDA.
I then just ran the binary in OllyDbg, broke at the point where it was fully unpacked and looked to see what I could find with my eye.
Once the binary was unpacked in OllyDbg, I started looking around in memory for something.. anything. I found stuff.
and set some breakpoints.
Nothing was happening so I decided to throw in an argument to the program
Lo and behold, I did get further in! At this point I just felt pure luck (especially after reading other write-ups).
I was now looking at all of the base64 strings
At this point I took a step back and realized that there were 24 base64 strings
K7IfRF4nOiNn9Jsqt9wFCq==
vAvack0BPyMQiq0MkChFqq==
NMImwkviE46VACNHafRqVW==
HMzOnqAQZzalVvP0Re7FAa==
7h9+E7q3qS6gGux3htE1pa==
I7BbEdHKp5ArZgPn5Suxcq==
bUYHTdFhKeZdZMvgYbebea==
IEDozaUmrIv6kD4gfNLnxq==
4RQqw/mg9g+SOIptYYdIZW==
xNmQghI+i0lB/V9F48PAOW==
AlmP2PIt40czX9ITxlNjqa==
e8J/2xCbnWoNaC+oeD6Szq==
wmIvyVwp0NB1KKiaAnUmcq==
3lM+l2boxFKD65zzVTr0Jq==
tE2YjaOEdWonZCIZ3PiMta==
2dHPhL1k0gH5YNiuqUId1a==
AZg9+N+B/S4Mm4h/QrVwQq==
r+1Zo40qVIjEZRO0tvm1HG==
QerwgAVqJZUG6/YZeyp3+q==
/+uDpN2cLYn1Ihbo7DXQSG==
fFqAlPA640hD5iw7dNJ0Hq==
9AFKD80WqRsAKixwiWFnka==
V21SGz7jDBbdRSucfNW9fq==
Hp8u+Kw+pkrZNNWcDXELqq==
and I was validating against all of them while I was single stepping.. so, I wrote another forcer! :)
I know, I can’t believe that worked either. Reading write-ups I now understand it wanted the system date! While doing this write-up it is currently 5:20 PM so it makes sense the 17th run I got the key.
Challenge 5
This challenge gave us a challenge.pcap file and sender.exe.
Going immediately to the pcap I followed the TCP streams one at a time (there were 12). I did this manually in WireShark as I just wanted to get whatever it was that was hiding in there.
And on and on until I got the base64 value
Anytime I get a base64 string I always decode it just to see what it is and in this case, it was nothing useful.
Thinking that sender.exe was creating this encoded value, I opened it in IDA.
The first thing I noticed was that sender.exe wanted to open a file, key.txt and read its contents into a buffer.
I figured that key.txt would contain the e-mail.
Continuing to do some quick analysis in IDA I came across the subroutine at sub_401000 and saw that it was performing the HTTP requests that the pcap file had.
Note: Anything I come across a binary performing actions such as this
(using win API InternetOpen, InternetConnect, HttpOpenRequest) I try to run it and see what I can observe.
Having the knowledge I had I figured this binary could also be brute forced. (I will later learn this was an awful approach, but bear with me).
I found an easy to use HTTP mockserver in java that I could stand up on my machine to have sender.exe properly send HTTP requests, which contained the encoded base64 data. The one I went with was http://www.mock-server.com/where/downloads.html. I liked this as it puts all HTTP traffic to a log file!
Starting up the mockserver, I began to fill key.txt with strings until I knew the length my input needed to be for the base64 encoding. Each time I ran sender.exe I read the mockserver logs to see how many bytes long the base64 string was.
and then running sender.exe mockServer fills with log entries!
Because I knew the e-mail had to end with @flare-on.com I only had to guess the number of characters to the left. I continued to do this until the base64 string ended with ZW==.
Doing so, I came back with the string
My terrible idea was then that I could brute force the key, grep the output of the mockServer and attempt to brute the key 3 characters at a time (in order to find one of the 4 byte base64 values as I knew I needed 3 chars of input for 4 bytes of base64)
I quickly realized after trying this for about 5 minutes of forcing that it would take FAR too long and I would be sitting for days trying to brute the key this way.
My python script to do this, for the lolz (it is awful), was
So, I tried to think of something else… I went back into IDA to look for more information.
I located sub_401250 by tracing where the input buffer from key.txt was going. In this subroutine there is a lot of shifting of the input string.
What I then decided to do was rewrite this subroutine in inline assembly in a c++ program and see what I could do. I also traced a couple of registers that I needed to know of and placed them into my inline asm.
Note: The following c++ code is some of the worst I have
ever written and I by no means condone using it for any reasons!
I say this because I could not functionalize the inline ASM without crashing :(
base64_encode was just an off the shelf encoder I pulled from cplusplus.com here as I did not want to code one myself at this moment in time.
Note in the code I had already found flarebearstare and had noticed it was being referenced in the subroutine in question.
I then proceeded to run my brute forcer! I noticed immediately that the base64 coming out of mine was switched with the pcaps in that it was lowercase instead of uppercase!
So I made those changes
Now I was on the right track and I was brute forcing the string 3 characters at a time!
Eventually I got the whole e-mail (which is very clever)
Challenge 6
Ah an Andriod .apk file… Should have guessed based off of the last e-mail!
You saved the internet with that one! There is more to reversing than just Windows programs though.
Cell phones and tablets are now on the information superhighway.
We want to see what can do with an Android app.
I've attached the next challenge.
The password to the zip archive is, as always, "flare".
Be the hero this challenge deserves!
-FLARE
Alright, well we can just unzip the .apk file.
Afterwards I was instantly attracted to the lib\armeabi directory and the libvalidate.so library as I figured this was not going to be another “find the magic in the source for Elfie” type challenge.
The function Java_com_flareon_flare_ValidateActivity_validate was too obvious so I started looking there. Opening this in IDA left me confused, scared and anxious! I did my best to look at the ARM disassembly and to my dismay was unable to get very far. I located the tables it was referencing at .data:00005004 off_5004 and the bigger table at .data:00007E7E unk_7E7E but was unable to put it all together.
I decided to try and attempt to live debug the andriod app and installed the andriod dev kit, gdb plugins and more but was unable to get very far and realized this was the wrong approach. (This was about a week at this point on #6)
I managed to obtain the decompiled form of the ASM off the internet and this began to make sense.
This is where I really started pushing myself. With a small amount of help I was able to take the decompiled code and transform it into easier to read c++ code that could be used to brute force the key.
It took awhile but I got some usable c++ code and wrote a small forcer
To populate table i just copied and pasted the huge byte dump from IDA. For char_table (the one that changes with each successive character match) I wrote a small python script after noticing that each one of them was 0x1b27 bytes long to copy them from the binary and into my clipboard for ease of pasting into my c++ program!
Repeatedly performing these actions slowly gave me something that looked like the key, but I was missing something…
Should_havaog0ne_to_tashi_**[email protected]
The “”s above were characters I could not brute. I realized my alphabet must not be big enough so I added some more characters *=.#-_~!$&’()+,;=*. Doing this resulted in
which still did not seem like it was right. Going back to the block with “ao” I realized there were multiple chars that matched and obtained the full key
Challenge 7
I did this write-up before thinking I would do the full one and it is here.
Challenge 8
This challenge gave us a binary, gdssagh.exe, telling us
Okay FLARE Team… what are you saying?
Opening the binary in OllyDbg showed a large chunk of base64 in the code section.
Naturally, I pulled it out and decoded it!
Okay, so we have a PNG image!
How pretty!
I had never played with stenography before and was completely baffled!
I tried doing silly things like running strings.exe on it, opening it in photo editors to see if the string was embedded in the photo and was getting nowhere.
Flailing to figure this out, I discovered Zsteg. This is where I really started to overthink the challenge… being jacked on caffeine did not help at this point, either. I instantly ran Zsteg with the -a flag to perform all possible methods of finding me what I needed.
Not realizing that I needed was right there the whole time, I continued to perform similar actions until going insane.
I then RTFM’d the git README for Zsteg and realized what I needed to do…
Challenge 9
The last challenge I managed to solve! This one was a trip considering I have IDA Pro Demo and have limited amounts of debugging I can do (it stops after n amount of steps).
The binary, you_are_very_good_at_this.exe, starts with a snarky message for us
Not even wanting to input a password as a guess, I ran to IDA. It was instantly noticeable that the binary was going to deobfuscate itself due to the large amount of random bytes in the code section.
Starting up the IDA Demo debugger, I began to step through the code allowing it to fix itself as I progressed. It took me awhile, but I realized the code would build instructions on the stack and execute them. Realizing this, I came across an interesting instruction I had never seen before
With a quick Google I came across this slide deck.
What an interesting instruction… I’ll post the important parts of the slide deck below
– If (accumulator == destination)
{ ZF 1; destination source; }
– If (accumulator != destination)
{ ZF 0; accumulator destination; }
TL;DR; the value in “eax” at the time this instruction is called is important and is going to be compared to the value of a character in our string it expects. We need eax to be the proper character… more on this later.
Realizing this I then saw two more instructions,
that were also playing with that input character.
I also noticed at this time that the value in ah and cl were important to the decoding and began to make a list of their values on each loop.
My C++ code to perform the decoding (for each round of bytes) was
To show how this worked, I prepared a video… (Yes, I know it says FLARE8 in it… I was so excited I did not name it properly!)
/resources/posts/flare/howIDidFlare9.mp4
I know what you are thinking at this point…
Conclusion
Despite only being able to solve through challenge 9, I feel I accomplished a lot with these challenges! Judging from the completion rate by stage the FLARE team released
I actually performed fairly well! Being one of the 277 finishers of 9 feels great!
Not finishing is disappointing but the concepts, tools and struggles I got out of this is worth more than a sweet prize. . .
. . .
. . .
even if that prize was really, really, really cool.
Next year I am coming into the 3rd annual challenge with the urge of redemption! I say to the FLARE team