David Kukfa Security student

2016 Flare-On Challenge Write-Up

I had a chance to test my reverse engineering skills in FireEye’s Flare-On challenge this year. While I didn’t get very far, I was still able to learn a ton and sharpen my skills for next year. All of the challenges are available on the Flare-On website, so feel free to follow along. With that said, let’s jump over that function call into the solutions!

Challenge 1

Starting off, we’re given a challenge1.exe binary. Running the binary will prompt the user for a password:

Incorrect password

Let’s take a closer look at the binary. Loading the challenge into Binary Ninja, we can quickly locate the strings used when comparing the passwords:

Comparison strings

Looking at the cross-references to the “Enter password” string, we can jump to the password comparison function. Near the comparison itself, the string “x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q” is pushed to the stack.

Pushing string to stack

This looks fruitful! Let’s try entering this as the password:

Wrong!

Dang, no dice! Let’s use a debugger to see what’s actually being compared. By setting a breakpoint on the function called just before the comparison, then entering the password “test”, we see the string “aDSwaZ==” is passed to the function instead of our original input.

Debugger view

The double equals sign on the end of the string is a dead giveaway for a base64-encoded string. It looks like the program is base64-encoding our input, then comparing it to the comparison string (x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q). If we base64-decode the comparision string, we’ll know the correct input to enter. Using a base64 decoder, let’s see what our comparison value decodes to:

Decoded gobbledegook

Huh, that doesn’t look right. There’s a lot of bytes outside the ASCII byte range. It looks like there’s something fishy going on here…

To understand what’s going on, I needed to do a bit of research about base64. I was looking at an example implementation of a base64 algorithm when I saw the following line of code:

private static final String CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

This looks like an alphabet that’s designed to be easily changed. Curious, I scrolled up on the page and found the following information:

The particular set of 64 characters chosen to represent the 64 place-values for the base varies between implementations. The general strategy is to choose 64 characters that are both members of a subset common to most encodings, and also printable.

So it looks like this alphabet is changeable! Going back to the strings in the binary, we can quickly identify a 64-character value that looks like another alphabet:

Alternative base64 alphabet

A quick Google search reveals a tool that can perform base64 encodings with alternative alphabets for us. Entering the custom alphabet we just found and our comparison string returns [email protected] as output. This looks like our flag! Let’s give it a try:

Correct!

Sweet! Entering the password on the Flare-On website moves us on to the next challenge.

Challenge 2

The next challenge is aptly named DudeLocker.exe, with an included BusinessPapers.doc that appears to be encrypted. Upon inspecting the binary in Binja, we can see there are several initial checks that must be passed.

The first of which involves a call to SHGetFolderPath, which retrieves the paths of special system folders and returns 0 if the operation was successful.

Call to SHGetFolderPath

The 2nd parameter being passed to SHGetFolderPath (the 4th value pushed to the stack), 0x10, is a CSIDL value identifying the folder being retrieved. A quick lookup reveals CSIDL 0x10 corresponds to the user’s desktop directory. So, this function attempt will grab the path of the desktop, and the program will continue if the operation was successful.

The next block checks if the length of our retrieved desktop path is less than or equal to 0xf8, or 248 in decimal. If so, the program continues; otherwise, it returns.

Checking desktop path length

Afterwards, we see a block with a call to CreateFile at the end. CreateFile, according to MSDN, “creates or opens a file or I/O device”. Despite its name, the I/O devices it works with are not limited to files; it also works with file streams, directories, physical disks, volumes, etc. The function takes the name of the I/O device as a parameter (the last value pushed to the stack), followed by 6 additional parameters describing the device’s attributes.

Showing call to CreateFile

The filename parameter (var_244) is constructed earlier in the block. We see it’s being passed to sub_401000 along with var_44c, which contains our desktop path from earlier, and var_3c, which contains the string “Briefcase”. The subroutine will concatenate “\Briefcase” to our desktop path, which is then used in the CreateFile call.

So CreateFile will attempt to open an I/O device located on our desktop named Briefcase. For more information, let’s take a look at the additional parameters. dwDesiredAccess is set to 0x80000000 (GENERIC_READ), dwShareMode is set to 0x1 (FILE_SHARE_READ), lpSecurityAttributes is set to 0, dwCreationDisposition is set to 0x3 (OPEN_EXISTING), and dwFlagsAndAttributes is set to 0x02000000 (FILE_FLAG_BACKUP_SEMANTICS). There’s an important note alongside FILE_FLAG_BACKUP_SEMANTICS: “You must set this flag to obtain a handle to a directory.”

It looks like CreateFile is attempting to open an existing directory named Briefcase located on our desktop. If this operation fails, an error code of 0xffffffff is returned (INVALID_HANDLE_VALUE), which will print a taunting message and exit the program. Otherwise, we proceed onwards.

The next check lands us in a subroutine that calls GetVolumeInformation to retrieve the serial number of our root (C:) volume. This was deduced by tracing the parameters as we just did above, which is left as an exercise to the reader. The serial number is compared to the value 0x7dab1d35 (“The Dude Abides”) – if they aren’t equal, eax is cleared; otherwise, eax remains.

Block comparing serial number

We need eax != 0 to pass this check, so we’ll have to either change our C volume’s serial number or bypass this check with a debugger. I opted to use the handy VolumeID from Sysinternals to change the volume’s serial. (Did I mention it’s important to work on these in a VM?)

Let’s try running the binary at this point. We’re greeted with a ransom note in the briefcase that rudely replaced my desktop background:

Ransom note

Looks like they want a million Bitcoins. Maybe those business papers will suffice? Let’s drop BusinessPapers.doc in the Briefcase aaaaand…

BusinessPapers still encrypted

Dang, still encrypted. However, the Last Modified date on the file changed, so DudeLocker must have done something with it. Taking another look at the binary reveals calls to CryptEncrypt in the program’s Import Address Table:

CryptEncrypt in IAT

This makes sense, since our modified BusinessPapers.doc still appears to be encrypted. However, the IAT doesn’t seem to have any entries for a decryption function. Taking a look at CryptEncrypt quickly points us to CryptDecrypt, which uses the same arguments sans dwBufLen at the end. If we could patch the call to CryptEncrypt with a call to CryptDecrypt, we might be able to decrypt the contents of the BusinessPapers!

Let’s take another look at the IAT. The entry for CryptEncrypt is 0x24fa, which refers to an offset in the DudeLocker binary. If we add that to the image base of 0x400000, we get 0x4024fa. Inspecting the binary at 0x04024fa reveals the following:

Binary contents at 0x4024fa

Hmm, looks like there’s another offset (0x00ba) followed by “CryptEncrypt” in ASCII. To make sense of what we’re looking at, I loaded the Windows DLL containing CryptEncrypt (advapi32.dll) in Dependency Walker and found the exported CryptEncrypt function:

Dependency Walker output for CryptEncrypt

Aha! It looks like 0x00ba was referring to the function’s hint, which contains the index for that function in the DLL’s export table. The hint for CryptDecrypt is 0x00b4. Are you thinking what I’m thinking??

Patching the binary IAT

Well, you are now. Patching the IAT allowed us to decrypt the file instead of encrypting it! The file still doesn’t look like a DOC file, but if we open it in a hex editor, we see the initial bytes FF D8 FF E0. A quick Google search reveals that’s the file signature for a JPEG image. Changing the file type from .doc to .jpg reveals our flag:

Victory at last!

XSS on a Document Converter

When I was switching my blog to Jekyll, I needed to convert a few long Word docs to Markdown; one of which being the Web Application Cheat Sheet. Being about web security, the document contained many XSS payloads and other nastiness. It also had a lot of nested bullet points, which would have made conversion by hand a pain. So, I found a promising conversion app called word-to-markdown, dropped in the Word doc, and lo and behold..

Reflected XSS alert

Great, should have seen this coming.

It turned out the site was treating the document’s contents as HTML, and thus rendering the content on the right side of the page without HTML-encoding it. This opened up a Reflected XSS vulnerability – albeit not very practical, but still bad nonetheless. Thankfully, the source code was available on GitHub and the developer was very receptive to contributions. I made some quick changes, and after a simple fork and pull request the updated version went live.

The fix was pretty simple – since most people wouldn’t write HTML in a Word doc and expect it to be rendered as such, I HTML-encoded the Markdown after conversion so the document’s contents would show up as regular text and not HTML. Here’s how XSS payloads are rendered now:

HTML-encoded XSS payload

Defusing a Binary Bomb with Binary Ninja

Binary Ninja is a new reverse engineering platform with a number of useful tools and features to make the reversing process quicker and easier. I did some experimenting with the beta version this weekend, and got acquainted with its Python API by working through Phase 1 of CMU’s Binary Bomb Lab. The lab has several ‘phases’ that are ‘defused’ by entering the correct input on stdin. If the program receives the wrong input, the bomb explodes and the program terminates. The bomb is defused once all phases have been solved.

This post goes over the steps I took to solve Phase 1 of the lab using the Binary Ninja API. The code is available on GitHub. For reference, here’s how the phase looks in Binary Ninja’s GUI:

Phase 1 in Binary Ninja GUI

Starting out, the binary is loaded and analyzed: (The sleep function is due to Binary Ninja’s threaded analysis, which currently does not have a way to alert when the analysis is completed)

#!/usr/bin/python

import sys, time
sys.path.insert(0, 'binaryninja/python')
import binaryninja

bv = binaryninja.BinaryViewType["ELF"].open("bomb")
bv.update_analysis()
time.sleep(0.1)

Next, we iterate through the functions to find Phase 1:

# find phase_1
for fn in bv.functions:
	if fn.symbol.name == "phase_1":
		phase_1 = fn

We then go to the main block in Phase 1. This phase calls a string comparison function that compares the input from stdin to a string stored in memory. We’ll loop through each instruction to find the call to this function (the first and only call instruction in the block) and grab its address:

# loop through instructions in phase_1's main block
for instr in phase_1.low_level_il.basic_blocks[0]:
	# get address of string comparison function
	if instr.operation == binaryninja.core.LLIL_CALL:
		callAddr = instr.address

Now that we have the address of the call, we can grab the parameters being passed to the function. The address of the comparison string is the second parameter being passed.

# get address of comparison string
strAddr = phase_1.get_parameter_at(bv.arch, callAddr, None, 1).value

We now need to find the string length, so we know how far to read into memory to retrieve the comparison string. The string comparison function compares the strings byte-by-byte and does not use a string length parameter, so we’ll find the string length in a similar fashion – reading byte-by-byte until an ending character is reached:

# get the length of comparison string
strLen = 0
curr = bv.read(strAddr, 1).encode('hex')
while (curr != "2e") and (curr != "00"):
	strLen += 1
	curr = bv.read(strAddr + strLen, 1).encode('hex')

Now that we have the location of the string in memory and know how far to read, we can use a simple call to read the comparison string:

# get the comparison string
cmpStr = bv.read(strAddr, strLen)
print cmpStr

Running this program on the bomb lab linked above, the string “Border relations with Canada have never been better” will defuse Phase 1 and take us to the next phase.

IRSeC 2016

Just a few weeks after red-teaming at Lockdown v0, I had the opportunity to follow up with my second red team experience at IRSeC this weekend! IRSeC (Incident Response Security Competition) is an annual cyber defense competition hosted by RIT’s Competitive Cybersecurity Club. The competition is geared towards beginners, with a focus on the incident response process. Emphasis is placed on how teams react to an intrusion and their ability to identify and report malicious activity.

Red/blue team interaction is crucial during IRSeC, and I was able internalize what I learned at Lockdown to improve as a red-teamer and facilitate a better learning environment overall. Talking things over with blue teams proved once again to be very helpful and important for learning. I picked up some new attacking and persistence techniques in preparation for the event as well.

In reflection, there are some important points to note for future competitions:

  • Having a wide variety of persistence mechanisms is important.

When persisting on boxes during the competition, I wanted to use persistence mechanisms that teams would be able to discover due to the beginner nature of the competition. These included creating scheduled tasks, registry items, users, and services. However, some teams were more advanced than others, and were eventually able to detect and remove both the basic and advanced persistence mechanisms I used. It would have been advantageous to include several persistence techniques that are very difficult to discover in order to ensure access to teams after they think they’ve kicked me out.

  • Get persistence accomplished right away.

In hindsight, I would have benefited from having a more prepared method of persisting. When teams started to discover my more basic methods of persistence, I was still fighting to establish a foothold on several boxes well into the competition. At that point, I wanted to be focusing on taking down services, exfiltrating PII, and messing with teams a bit. By establishing a wide range of persistence early on, I would have been in a more comfortable position to focus on other red team objectives.

  • Be sure to take the entire infrastructure into account.

IRSeC’s network this year included several IP cameras that many red-teamers overlooked until later in the competition. These had really interesting attack vectors, and it would have been cool to get a foothold in them early on to pivot into the rest of the blue teams’ networks.

Overall, IRSeC was an awesome time, and it was great to be able to use what I learned from my previous red team experience just a few weeks later. A huge shout out goes to everyone who helped organize the event and stayed up overnight to make it happen. Looking forward to next year!

Lockdown v0

I had the pleasure of red-teaming at Lockdown v0 today along with a crew of UB and RIT students. Lockdown is a cyber defense competition hosted by NetDef at the University at Buffalo that aims to ease beginners into cybersecurity competitions. In prior years, the event was a small internal event at UB, and this year it was scaled up to support more blue teams and teams from other schools. I had a ton of fun red-teaming and sharpening my exploitation and persistence skills. It felt great to share my knowledge with students who were eager to learn, and be a part of such a conducive environment. My take-away points from this event were:

  • It’s important to keep the intended audience of the competition in mind.

Many of the students on the blue teams were in computing majors that didn’t involve security, and this was their first exposure to a security competition. Some students were from non-computing disciplines who were simply interested in learning more about security. Some of the red team’s attacks were too advanced for this level of competition, and overwhelmed some of the teams while they were trying to juggle injects and get acquainted in an unfamiliar environment.

  • Meeting with the blue teams is super important.

When I went to visit some of the teams I had been attacking, they were relieved to have support while working through the problems they were facing. Many teams benefited from a walkthrough of security competition fundamentals such as changing passwords and auditing connections. Learning is the main goal of the event, and being available to explain things and answer questions is key for accomplishing it. It felt great to receive the question “how can I learn more about this stuff?”.

Huge props to UB for putting on such an awesome event! Scaling a competition like this is no easy task, and you pulled it off beautifully. I had an amazing time, and look forward to next year’s competition.