Flare-on 5 – 1 – MinesweeperChampionshipRegistration

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

Starting off the 5 series of challenges we have a very simple password challenge, when extracting the archive you have one file extracted.

MinesweeperChampionshipRegistration.jar: Java archive data (JAR)

When running the file, you are prompted for an invitation code. I unzipped the jar file finding the metadata and a class file. I ran strings on the class file and was able to see the flag in plain text in the file.

After entering the flag shown in strings into the prompt it is validated!

Flare-on 3 – Challenge 2

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

The archive for this challenge included 2 files.

BusinessPapers.doc: data
DudeLocker.exe: PE32 executable (console) Intel 80386, for MS Windows

I first took a look at the .doc file and it looks to be random data.

BusinessPapers.doc

After doing some initial analysis on the executable file, I found many references to encryption routines in the imports. This program looks to act like ransomware. Diving into the functionality, the program first looks for a directory named “Briefcase.”

If it can not open the directory, it jumps to an error accusing the person of being a reverse engineer!

After it validates, it can open the directory properly; a routine is called checking the drive’s serial number looking for a specific value. If the value doesn’t match, the program errors out. If the hard drive’s serial number matches, it jumps to the routine to decode the encryption key. The drive’s serial number and a pointer, the encoded data stored in the .data section, are passed into the mw_decode_key function.

The mw_decode_key function does what I have named it, it decodes the key used in the data encryption. It uses a simple xor loop to decode the key.

Now that we have the key decoded it is time for the program to set up and execute the encryption routines. As a way to summarize the overall process, I have created the following diagram showing the connections between all of the functions. The boxes colored in blue are handles to data structures and the boxes in green are variables containing a value. The first step in the entire process to set up the Provider which acts as a glue between the key generation functions. From here let us go through each box in numbered order.

Section 1 is used first to create a Hash of the key based on the SHA1 algorithm. Next, it takes this Hash and derives an AES256 key from the Hash and stores it the Key Handle. The key finally has its mode set a CBC cipher.

Section 2 is used to create the IV portion of the key. This is derived from an MD5 hash of the name of the file. This section writes the data to a Hash Handle then copies it out of the handle into the KP_IV parameter of the Key Handle created in section 1.

Finally, in section 3, where files are encrypted, the original file is opened and read into a File Buffer which is then read by the CryptEncrypt function that reads the Key Handle and executes the encryption writing it back to the buffer. The buffer is then written back to the original File Handler, overwriting the data on disk.

After looking over all of this crypto routine and using a debugger to extract both the main AES key and the IV key values, I created a decryption script in python to extract what I had assumed is encrypted data in the BusinessFiles.doc file. The following script uses the wincrypto and cryptodome packages to more or less follow the process I just outlined instead, decrypting the data.

# need wincrypto and cryptodome packages

from Crypto.Cipher import AES
from Crypto.Hash import MD5
from wincrypto import CryptCreateHash, CryptHashData, CryptDeriveKey
from wincrypto.constants import CALG_SHA1, CALG_AES_256
import magic

encryted = 'BusinessPapers.doc'
encypted_data = open(encryted, 'rb').read()

key = b'thosefilesreallytiedthefoldertogether'
md5_clear = bytes(encryted.lower(),"UTF-8")

# Derive Key
sha1_hasher = CryptCreateHash(CALG_SHA1)
CryptHashData(sha1_hasher, key)
d_key = CryptDeriveKey(sha1_hasher, CALG_AES_256)

# Create IV data
iv = MD5.new()
iv.update(md5_clear)

aes = AES.new(d_key.key, AES.MODE_CBC, iv=bytes.fromhex(iv.hexdigest()))
decd = aes.decrypt(encypted_data)

print (decd[:20])
print(magic.from_buffer(decd))

hFireWrite = open("test.bin", 'wb')
hFireWrite.write(decd)
hFireWrite.close()

The output of this script writes the data to disk and provides a preview of the first 20 bytes and the magic block info from the data.

b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00H\x00H\x00\x00'
JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=8, manufacturer=Minolta Co., Ltd., model=DiMAGE G500, orientation=upper-left, xresolution=140, yresolution=148, resolutionunit=2], baseline, precision 8, 576x410, components 3

Success we have found the flag!

Post-Script

A funny feature of this challenge is that it leaves a ransom note. The note is an image in the resources section of the file. This image is extracted and written to the disk. Then it set the wallpaper using the SystemParametersInfoW API call.

Flare-On 3 – Challenges 1

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

This challenge is like a lot of the first levels is a password challenge decoding challenges. In the next screenshot, you can see what happens when you run the executable.

I opened the binary up in IDA and found the main function. The Main function starts off setting up handles to read input and loading a string from the .rdata section to a local variable.

Taking a look at the string that is loaded, it looks like to be some encoded text. I guess that it is more than likely the password.

Back to the main function, after collecting the inputted password guess from the command line, it takes the inputted string and runs a function to encode it.

Looking at the encoder function I found what looks like a non-standard Base64 character set.

I took the custom Base64, the encoded string I found earlier, and entered them into CyberChef to decode the string. It returns what looks to be the flag.

To be sure I re-ran the challenge and enter the output and bingo it validates the flag!

Flare-on 2 – Challenge 5

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

This challenge includes two files, a packet capture formatted in PCAP format and a Windows binary.

Opening up the PCAP in Wireshark, I found multiple HTTP streams submitting POST requests. I looked at each of these POST requests and saw they all have a few bytes of content.

I copied the data from each of these HTTP POST requests and found what looked like a Base64 encoded string.

UDYs1D7bNmdE1o3g5ms1V6RrYCVvODJF1DqxKTxAJ9xuZW=

When I attempted to decode it using standard Base64 character sets I did not find any recognizable data. I knew that it wouldn’t be that easy.

Looking at the strings in the binary, I found two interesting strings, “flarebearstare” which could be a password, and another string that looks like a Base64 alphabet with the uppercase and lower case sections swapped in order.

I following the cross-reference for the “flarebearstare” string, finding a function with a data decoder loop. This function is passed data and loops through each byte, subtracting each character in order of “flarebearstare” from the current byte.

Decoder function

Looking over this functionality, I started to write up some code to decode the flag. I grabbed a Base64 library that needed a small modification to use a custom character set. My fork of the code can be found at this repo.

https://github.com/suidroot/Python-Base64

In the screenshot below, you can see my final script in a Jupyter notebook. As an aside, I have been using it for many challenges and other projects to test out decoder and other functionality. They have been instrumental in quick prototyping and experimentation.

Success there mostly is the flag. You can see there is some weirdness in the decoding of the flag, but this script decodes the main part of it needed in my mind to call it a solution.

Full Code

b64encoded = "UDYs1D7bNmdE1o3g5ms1V6RrYCVvODJF1DqxKTxAJ9xuZW=="
b64_alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'

b = b64()
b64decoded = b.decode(b64encoded, alttable=b64_alphabet)

for i in b64decoded:
    print (hex(ord(i)) + " ", end="")

print ()
count = 1

key = "flarebearstare"
key_len = len(key)

output = ""
counter = 0

for i in b64decoded:
    temp = ord(i) - ord(key[counter])
    
    print (chr(temp),end="")

    #print (i, hex(temp), key[counter], chr(temp))
    output += chr(temp)
    
    if counter+1 < key_len:
        counter+=1
    else:
        counter = 0

        

Flare-on 2 – Challenge 3

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

In the third challenge, you are greeted with a nice goat named Elfie that when you are typing characters show up on the screen. As always I start off by checking out what kind of binary I am looking at

λ file elfie
elfie: PE32 executable (console) Intel 80386, for MS Windows

As I said we are greeted by thie goat that eats magic keys

After doing some initial analysis in Ghidra found some strings that indicate that this file might be a python executable.

Additionally, the icon embedded in the binary should have been a giveaway. I guessed it was probably a pyInstaller executable. I ran it through pyinstextractor.py to expand it out and get a copy of the python source to analyze.

C:\Users\IEUser\Desktop
λ pyinstxtractor.py elfie.exe
C:\Tools\pyinstxtractor\pyinstxtractor.py:86: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
[*] Processing elfie.exe
[*] Pyinstaller version: 2.1+
[*] Python version: 27
[*] Length of package: 12034944 bytes
[*] Found 26 files in CArchive
[*] Beginning extraction...please standby
[!] Warning: The script is running in a different python version than the one used to build the executable
    Run this script in Python27 to prevent extraction errors(if any) during unmarshalling
[*] Found 244 files in PYZ archive
[+] Possible entry point: _pyi_bootstrap
[+] Possible entry point: pyi_carchive
[+] Possible entry point: elfie
[*] Successfully extracted pyinstaller archive: elfie.exe

You can now use a python decompiler on the pyc files within the extracted directory

C:\Users\IEUser\Desktop

I found the file elfie and opened it in VSCode to look at the contents.

it looks to be full of Base64 strings that are concatenated together, decoded, and executed.

Strings

I changed the final operation to print the encoded python code for further analysis.

The next layer down looked more like normal python code with obfuscated variable names.

Even looking at the obfuscated code the is pretty obvious but I wanted to clean up some of the variable names to make sure I was not missing anything else.

After reversing the string the flag is revealed

and Elfie is happy!

Flare-on 2 – Challenge 2

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

The second challenge from this season built on the first challenge. It was another password entry challenge but with a more complicated password encoding scheme.

First things first I validated what kind of file I was looking at.

λ file very_succes
very_succes: PE32 executable (console) Intel 80386, for MS Windows

When running the file I entered some test data to see how it looked to a user.

I switched back to Ghidra to do some static analysis on this binary and found the area of code that looked to handle the password comparison. The first check that jumped out to me was the length check that checked to see if the password was 37 characters long.

Then I found the encoding and matching bulk of the code which I have commented below. This block of code uses a combination of XOR and Bit-wise shifting of the characters to encode each character of the input to match it against the encoded password.

It took me a little bit to see that the SCASB instruction at 0x4010c8 is used to set the zero flag to 1 if the encoded value does not match and jump to a failure condition. Otherwise is set to 0 for success and continues the loop.

I ran the binary using x64dbg to walk through and monitor execution manually setting the Zero Flag to check how the algorithm operated. I also identified the location of the encoded key stored in EDI and copied out that data in hex.

AFAAADEB AEAAECA4 BAAFAEAA 8AC0A7B0 BC9ABAA5 A5BAAFB8 9DB8F9AE 9DABB4BC B6B3909A A8

As with the first challenge in this season I crudely implemented the encoder in python and using brute force was able to successfully generate the key.

Decoder code

encoded = [0xAF, 0xAA, 0xAD, 0xEB, 0xAE, 0xAA, 0xEC, 0xA4, 0xBA, 0xAF, 0xAE, 0xAA, 0x8A, 0xC0, 0xA7, 0xB0, 0xBC, 0x9A, 0xBA, 0xA5, 0xA5, 0xBA, 0xAF, 0xB8, 0x9D, 0xB8, 0xF9, 0xAE, 0x9D, 0xAB, 0xB4, 0xBC, 0xB6, 0xB3, 0x90, 0x9A, 0xA8]

result_key = ""
    
def xchg(s1, s2):
    temp = s1
    s1 = s2
    s2 = temp
    
    return s1, s2

def decoder(text_data):
    global result_key
   
    success_count = 0
    
    bx = 0
    dx = 0
    key_store = 0 # stack
    cl = 37
    eax = 0x1901c7

    for i in text_data:
        dx = bx
        dx = dx & 0x3
        ah = (eax & 0x0000FF00 > 1)
        al = (eax & 0x000000FF)

        dl = (dx & 0x00FF)
        al = (i ^ al)
        dl, cl = xchg(dl, cl)
        ah, cf = ah << cl, ah & 1
        al = al + ah + cf
        ax = al + (ah*0x100)
        dl, cl = xchg(dl, cl)

        dx = 0
        dl = 0
        ax = ax & 0xff
        output = ax
        bx = bx + (ax & 0xff)

        cl = cl - 0x1
        if encoded[cl] != output:
            pass
        else:
            result_key += chr(i)
            success_count += 1
            
    return success_count

test = [65] * 37

for element in range(len(test)):            
    for i in range(0x21,0x7e):
        test[element] = i

        succ_coun = decoder(test)
        if succ_coun < element+1:
            pass
            result_key = ""

        else:
            print (succ_coun, element, chr(i))
            print("Key:", result_key)
            break
            
print (test)
print ("resultkey: \"" + result_key + "\"")
    

Flare-on 2 – Challenge 1

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

The first challenge in the 2015 season on Flare On was a pretty easy enter the password type of challenge. I started off by opening the extracted file in IDA and running it in the debugger. I stepped to the section of code that evaluates the input versus the input

Key encoding and comparison routine

I extracted the encoded key from memory

Encoded Key data

Then I re-implemented the XOR encryption in python and generated the key from the data.

Jupyter notebook key decoder

Which successfully worked!

Successful Key Entry

Flare-on 1 – Challenge 5 – 5get_it

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

Challenge 5 brings us a DLL file, I mainly used Ghidra to statically analyze this file.

5get_it: PE32 executable (DLL) (GUI) Intel 80386, for MS Windows

After Ghidra loaded and analyzed the file, I found this function at 0x1000a680 that does a few things, first to Reads and writes the Run key to setup persistence for this DLL file, and it also copies itself to the C:\windows\system32 directory as svchost.dll to look like a legitimate DLL file. Next, it executes a function that looks to act as a key logger.

This function sets up a buffer to store keystrokes into them write them out to a file named svchost.log. Looking at the mw_key_press_handler function we see how it handles the key presses.

This function has various handler function for each ASCII value for most upper case letters, lower case letter, number, and some other characters. However not all have handler functions, so I took a closer look at the functions.

Below are three examples of functions, some of the functions would set a global variable to 1 or 0 depending on if another variable was set, and/or call another function that sets a group of global variables to 0. Not all of the functions returned the same letter that was pressed. As shown below “`” returns the number “0”.

Returns same character
Returns different character from input
Calls a function to reset all global vars

Taking a closer look at the global variables that are manipulated I could see a pattern of them being written or read depending on the keypress handler functions.

Went through the listing of functions and created a list of the key presses and the return values and saw what looks like the key.

Memory AddressInput CharOutput Char
DAT_10019460Ll
DAT_10019464`0
DAT_10019468Gg
DAT_1001946cGg
DAT_10019470Ii
DAT_10019474Nn
DAT_10019478Gg
DAT_1001947cDd
DAT_10019480Oo
DAT_10019484Tt
DAT_10019488Uu
DAT_1001948cRr
DAT_10019490Dd
DAT_10019494Oo
DAT_10019498Tt
DAT_1001949ce5
DAT_100194a0Tt
DAT_100194a4Rr
DAT_100194a8O0
DAT_100194acKk
DAT_100194b0Ee
DAT_100194b4`5
DAT_100194b8Aa
DAT_100194bcTt
DAT_100194c0Ff
DAT_100194c4Ll
DAT_100194c8Aa
DAT_100194ccRr
DAT_100194d0Ee
DAT_100194d4Dd
DAT_100194d8Aa
DAT_100194dcSs
DAT_100194e0Hh
DAT_100194e4Oo
DAT_100194e8Nn
DAT_100194ecDd
DAT_100194f0Oo
DAT_100194f4Tt
DAT_100194f8Cc
DAT_100194fcOo

But this table does not include the letter “m” at the end of “com” the handler for “M” has an extra function that it calls.

This function that the handler calls has a large number of local variables and makes Ghidra very sad, but its main function shows a message box with the flag: l0gging.ur.5trok5@flare-on.com

Flare-on 1 – Challenge 4 – Sploitastic

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

We start off with a PDF file in Challenge 4, I start off by dumping the contents of the streams using pdf-parser from Didier Stevens PDF-tools

pdf-parser.py -f APT9001.orig.pdf > apt5.txt

Looking through the content I find a block of Javascript code that looks interesting

After copying it out and some manual de-obfuscation I find a block of what looks to be hex-encoded shellcode. I grabbed a script to decode it into a binary file to run and debug.

from binascii import unhexlify as unhx

#encoded = open('encoded.txt').read() # The shellcode dump
out = open('shellcode.bin', 'wb')

encoded ="%u72f9%u4649%u1525%u7f0d%u3d3c%ue084%ud62a%ue139%ua84a%u76b9%u9824%u7378%u7d71%u757f%u2076%u96d4%uba91%u1970%ub8f9%ue232%u467b%u-SNIP-%u2454%u5740%ud0ff"

for s in encoded.split('%'):
    if len(s) == 5:
        HI_BYTE = s[3:]
        LO_BYTE = s[1:3]
        out.write(unhx(HI_BYTE))
        out.write(unhx(LO_BYTE))
out.close()

I took the binary code and loaded it in BlobRunner and attached x64dbg to it.

The first instruction sets the carry flag to 1, the following instruction JMPs to end the code if the CF flag is set, the JB instruction needs to be patched to a NOP or the CF set to 0 to keep running the code.

The code can be walked through until it loads the flag into the stack around offsec of +0x3c1 and it shows up in the register of ECX.

However, if you run the code until completion it shows up as junk in the message box that is displayed.

To get the flag to show up in the message box you need to NOP the look starting at +0x3ce before the CALL to EAX.

Now the flag shows up in the message box!

Flare-on 1 – Challenge 3 – Shellolololol

This is a post in a series where I complete every Flare-on challenge. The landing page for all of these posts can be found here

Challenge 3 brings a PE executable file to take a look at.

such_evil: PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows

I loaded the file up in x64dbg and after navigating to the main function it looks to load a whole lot of data onto the stack then CALL into the loaded code.

I continued to step through the program monitoring and watching the memory region pointed to be ESI.

The shell code (not pictured) is decoded and over written in multiple stages leaving these messages at ESI

Finally revealing the flag

such.5h311010101@flare-on.com

There are more elaborate ways to reveal the flag, the official write up uses IDAPython scripting to manually decode the messages.