Tuesday, August 30, 2016

FLARE On 2015 - Challenge 9

About:

This is the 9th challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)


Solution:

From hearing what other people had written about this one, it sounded like this was where things start getting pretty difficult.

Challenge 9 was somewhat of a repeat of Challenge 1 & 2, however this one had a number of tricky anti-analysis tricks thrown in.

It starts out by letting you know it's evolved from the first challenge:




Taking a look at the strings, it looks like we may be able to trace back from the spot in the code that uses "You are success" again...



... but after some basic debugging & breakpoint-setting, it becomes clear we don't actually hit that section of the code. Something funny's going on... :-/

(As it turns out, that entire subroutine is a decoy and is not used at all in the validation process...)

Let's break out IDA and take a look:




Almost immediately after we start stepping through the code, we hit some early trickery designed to throw off static analysis by jumping to the middle of an instruction:



This is pretty standard stuff, and since we're going through it with our debugger, it's no problem -- we can just have IDA re-disassemble the instruction, this time starting from the new EIP address.

As we keep going, it becomes clear they're also doing sneaky things by manually crafting/modifying stack frames (as opposed to simple call/return patterns).

After determining things were going to be not simple, I decided to do a execution trace, like so:



This unfortunately ran into issues related to my IDA version being the free version :-(



But it provided enough information to be useful -- it's now clear that they're crafting/assembling tables of some kind based off of static hex values, with lots of anti-analysis crap stuck in between:



Grabbing those tables out of memory and stepping through the program one more time let's us see that the tables are (a) used as XOR key values, (b) used as lookup values, (c) as ROR values, and (d) as the final expected values to validate the email address.

Reversing the logic gives us the final answer:

Is_th1s_3v3n_mai_finul_foarm@flare-on.com

Saturday, August 27, 2016

FLARE On 2015 - Challenge 8

About:

This is the 8th challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)


Solution:

The 8th challenge was the stego one. Running the initial EXE file doesn't give too much info...





And opening it up in IDA shows there's really not much going on:




Looking through the data embedded in the file, it looks like there is some kind of structured data, however. Possibly Base64:




After using a hex editor to cut out the non-base64 data, I wrote a quick python script to translate the data to un-base64'd form.

This looks good -- Opening the written file in Notepad++ shows it has as PNG header!



Let's see what it looks like:



From here, I tried taking a look at it with StegSolve:



You can see something may be up when you look at the data planes on a per-bit level. Here's the 7th bit in the red plane:



Here are the 0th bits in each of the RGB planes. See the black bar at the top?



It makes sense that there may be some data hidden in there as the 0th bit would affect the picture the least and could easily be used for hiding some additional data.

From here, I pulled it apart with "zsteg", which immediately detected a PE32 executable file and extracted it easily:



Running this EXE file gives you the email for the next level!







FLARE On 2015 - Challenge 7


About:


This is the 7th challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)


Solution:

Our prompt this time looks like this:



When I was initially working through these challenges during the contest, this was the one I failed out on.

The obfuscation they used here is really nasty, and you can see it below:




Fortunately, this time I'm going to use de4dot to attempt to deobfuscate the code:



Scanning through the cleaned code, ns2's Class3 looks like the best bet for where the application logic resides. 

We can see it starts out with a few bytearrays:



.... and ends with some interesting logic:



So from this, we can guess "bytes" is our "Warning!" message, "bytes2" is our prompt for the correct password, "text" is the value we type in, and "b" is some combination of other values (and is the value our text needs to match in order to succeed...).

Let's take a closer look at smethod_0:



Looks like an xor loop! We know the raw bytes passed in are (31,100,116,97,0,84,69,21,115,97,109,29,79,68,21,104,115,104,21,84,78) and the key is generated from Class3.smethod_2().

So this is good. We know that the data we pass into the prompt has to be equal to (byte_2 xor Class3.smethod_2()) + '_' + Class3.smethod_3().

Can we invoke these functions directly from powershell? Turns out yes, you can.




So now we have everything we need. After doing the xor computation, string concatenation, and entering the resulting value in the prompt, we get this:



Woo hoo!

FLARE On 2015 - Challenge 6


About:


This is the 6th challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)


Solution:

This one was the first one I got legitimately stuck on.

Off the bat, it's clear that this one is an Android application that takes a string as input and returns "No" or possibly "Yes" when the correct string is entered.

Digging into this one was tricky for a couple reasons, but I was pretty quickly able to extract/decompile the Android code and see that the app was quite simple and seemed to use a native library to perform the main "checking" functionality.





Based on the function that triggers the call into the library being named "validateEmail", it seems pretty likely that we just need to find what string will cause an "OK" output and that'll be our email address.

The full path of the library where our function is implemented is lib/armeabi/libvalidate.so, so let's open this up in IDA. Here we can see the part where it chooses between "No" and "That's it!":



From here, it looks like we just need to work backwards to find out what will make us go to the green code block.

Looking to the left a bit, we can see a particular section of memory referenced that seems to contain a list of prime numbers...



Strange....  Although when we look at how the string we pass in is validated, it looks like an integer value (coming from two bytes of the string) are decomposed into its prime factors, and these factors are compared against static lists of values. For example, here is one that says we should have two of the fifth prime (11), one of the seventh (17), etc.:



If we go through the list of all expected prime numbers, generate the composite numbers from them, and convert these integer values into two-byte strings, we get the following email address:

Should_have_g0ne_to_tashi_$tation@flare-on.com

Thursday, August 25, 2016

FLARE On 2015 - Challenge 5


About:


This is the 5th challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)


Solution:

Challenge 5 is different again from the ones before. 

This time we get an exe file called "sender" and a pcap file called "challenge.pcap", so it seems likely we'll need to reverse-engineer the exe to understand some piece of data hidden in the pcap.

Let's take a quick look at the pcap:


For better or worse, it looks like the only data transmitted went out via HTTP POST requests, where the only data sent was 4 bytes in each packet (here: UDYs).

The server responds with simple "1"s. 

So we have it, the full data transmitted in hex was:

55445973314437624e6d6445316f3367356d733156365272594356764f444a46314470784b5478414a3978755a573d3d

In binary this looks like:

UDYs1D7bNmdE1o3g5ms1V6RrYCVvODJF1DpxKTxAJ9xuZW==

Base64?? Un-base64'd it looks like:

P6,\xd4>\xdb6gD\xd6\x8d\xe0\xe6k5W\xa4k`%o82E\xd4:q)<@'\xdcne

Hmmm.... Alright let's break open the exe file with IDA:



Right off the bat, it looks like we're reading a key file "key.txt". So first guess, maybe this will send off the key.txt file after it's been encrypted/encoded and our task is to recover the original file?

Jumping ahead into the part of the code where the imported HTTP-related libraries are used, we get this:



Ok this is looking pretty good & simple. If we explore the calling tree a bit more, we come across what looks like a pretty straightforward XOR loop:



It seems to be using the "flarebearstare" string as a fixed key.

Once we notice that the base64 routine uses a custom, case-swapped alphabet ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/"), it looks like we may be getting pretty close to being done....


Writing out a python3 routine to take the data sent over the network interface, decode it using the special base64 alphabet, and then decrypt it with the constant key XOR, we get something like this:


from base64 import b64decode

KEY = 'flarebearstare'

def decrypt(str):
    result = ""
    for i, b in enumerate(str):
        result += chr(b - ord(KEY[i % len(KEY)]))
     
    return result

data = b64decode('UDYs1D7bNmdE1o3g5ms1V6RrYCVvODJF1DpxKTxAJ9xuZW=='.swapcase())

print(decrypt(data))


Running this code, we see the following printed out:

Sp1cy_7_layer_OSI_dip@flare-on.com

Woo hoo!

FLARE On 2015 - Challenge 4


About:


This is the 4th challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)


Solution:

For a couple reasons this one took me a while to get going on... First, my VM didn't have the required mfc100u.dll:



Ok, I'll just grab a random dll off the internet and try that :)



Taking a closer look at the youPecks.exe file, it looks like it's UPX packed. Let's see what happens when we unpack it with the UPX utility's -d option and run the two versions:


Hmm, that's interesting.

While I didn't look into why exactly the manually unpacked version crashes instead of printing the "2 + 2 = 5" I saw from other people, knowing that the behavior is somehow changed, we're good enough to keep going...


Let's review what happens when we (a) execute a UPX-packed binary and (b) use UPX to unpack a packed binary.

In (a), a bit of unpacking code that's embedded within the .exe file is executed first. This performs the unpacking procedure, loads imports, and continues the execution of the original program.

In (b), the UPX utility is executed, which reads the UPX header of the packed binary and unpacks the EXE. The stub from (a) is not directly used and will be subsequently ignored.

This means that with the case of (a), additional code can be patched into the original packed binary that will cause the behavior of the EXE to be different between the packed & unpacked versions.


Let's look at the original youPecks.exe in IDA.

One spot that sticks out is at the end of the unpacking stub, it looks like a value in memory is being set to a hard-coded '4' value:



This seems to be right after an XOR loop that looks to be swapping the case of an alphabet string.

Setting a breakpoint confirms that that's the section of code critical to ensuring what's printed is "2 + 2 = 4" and the other function it performs is swapping the case in the string that will later be used for base64 decoding...

If we keep moving on and let the execution jump to the unpacked code, it looks more like a traditional program:



Looking at the unpacked code in IDA, we can see some nice structure if/else chains kicked off after it does something with GetCommandLineW, atoi, and the current hour from _localtime64_s:






It also seems to be checking something with or using specific base64-encoded strings in each block...

Looking closer, it looks like it creates a vector object using these strings and then decides which to use with the current hour & value passed in on the command line.

If we pick the base64 text coming from each of the first blocks, we should be able to try to manually decrypt the data:


from base64 import b64decode

data = b64decode("XTd3NiPLZBQ5N1FqkBN+a/Av6SpqBS/K".swapcase())
xor = b64decode("K7IfRF4nOiNn9Jsqt9wFCq==".swapcase())

for x in range(len(data)):
    print(chr(xor[x % len(xor)] ^ data[x]))


Running this with python3 gives us our answer :)

U
h
r
1
t
h
m
3
t
i
c
@
f
l
a
r
e
-
o
n
.
c
o
m


FLARE On 2015 - Challenge 3


About:


This is the 3rd challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)


Solution:

This one looks a little different from the first two.

This time we're given a single executable file that, given the icon, looks like it may be derived from a python file using something like py2exe:



Let's see what happens when we run it.... Looks like a picture pops up like this:



So it's not immediately clear what this gets us, but let's go ahead and see if there's a way to recover the original source code if it was indeed made from Python code.


I decided to use pyinstallerextractor, which confirmed it was derived from some Python2.7 code:



Now let's take a look through the extracted code....

The file that immediately stuck out was "elfie", which looks like more obfuscated Python code:




Thousands and thousands of lines.... until finally:




Ok, let's see if we change the "exec()" call to a print() and dump the results to a new file:



Looks pretty good.... wait what's this?


Woo hoo!

Elfie.L0000ves.YOOOO@flare-on.com









FLARE On 2015 - Challenge 2


About:


This is the 2nd challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)


Solution:

The first thing to notice about this one is how similar it looks to the last challenge.

Although this time, instead of a simple XOR loop, it looks like we're calling sub_401084 to decide if "You are success" or if "You are failure":





Let's take a closer look at that subroutine:



While it looks like there are some weird instructions used in there, it does look rather small and hopefully we can replicate the logic in a separate Python script.

After writing this out by hand on a piece of paper, reducing & rewriting it a few times, I came up with something along the lines of this:


def rol(byte, count): 
    byte = (byte << count | byte >> (8 - count)) & 0xFF 
    return byte 


data = '\xAF\xAA\xAD\xEB\xAE\xAA\xEC\xA4\xBA\xAF\xAE\xAA\x8A\xC0\xA7\xB0\xBC\x9A\xBA\xA5\xA5\xBA\xAF\xB8\x9D\xB8\xF9\xAE\x9D\xAB\xB4\xBC\xB6\xB3\x90\x9A\xA8'[::-1]

AH = AL = AX = BX = DX = 0 
result = '' 

for c in data: 
    AH = rol(1, DX) 
    AL = (ord(c) - AH - 1) ^ 0xC7 
    BX += ord(c)
    DX = BX & 3 
    result += chr(AL)

print(result)


Running this across the data stored in memory gives you something like this:

a_Little_b1t_harder_plez@flare-on.com


Woo hoo!

FLARE On 2015 - Challenge 1


About:


This is the 1st challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)

I'll be writing up solutions to last year's challenges as a way to prep for the 2016 challenges, coming out (hopefully) soon :)


Solution:

Opening up the first challenge .exe in IDA, the functionality looks quite simple:





So this doesn't look too bad. It prompts for a password, copies the string to memory, runs a loop over it (xor decryption?), and then decides if "You are failure" or if "You are success".

Given that it's such an early level, it seems definitely possible it's just that simple.

Let's look at the section of memory that's used in or XOR loop:



Hmm ok this looks pretty good.... definitely seems plausible it's just ciphertext that's been xor'd with the value 0x7B.

Let's write a quick Python script to un-xor the raw bytes:



Woohoo! Looks like we're all done :)

bunny_sl0pe@flare-on.com