Flare-On 4 CTF write-up (part 3)

21.Oct.2017

#7 – zsud.exe

The 7th one looks to be sort of a game.

In fact, it’s a game of maze. The game supports a few commands. We can walk inside the maze in 6 possible directions – north, south, east, west, up and down. There are other commands to say, wear, get an object etc.

Initial triage

Let’s have a look at the running process in Process Hacker. The point to note is that it’s a .NET process. A .NET executable can be identified by the presence of metadata within it. However, if we open the binary in CFF Explorer, there are no signs of any such metadata. The astute reader might have noticed the HostedCLR flag in the image above. CLR Hosting in simple words means the .NET runtime is started by the started by the application rather than by the PE loader.

We can also see the presence of PowerShell in the list of loaded assemblies. Besides this, we also have an assembly named flareon loaded. Let’s use dnSpy to inspect this while it’s running. After attaching to the running zsud.exe process we can have a look at the loaded modules.

We can dump the assembly whisky_tango_flareon.dll to disk. Opening this module, we can see can see a function named Smth which decrypts a string,

Dumping the PowerShell script

We can set a breakpoint at line 48 and rerun the program in dnSpy. When the breakpoint hits, we can save the contents of the script variable.

Analyzing the PowerShell script

The implementation of the game is in the PowerShell which is partly obfuscated. If we execute the script, we get back the original game window. Analyzing the code we can see the presence of rand and srand strings perhaps indicating this has something to do with random numbers.

Let’s have a look at the function Invoke-MoveDirection which executes a move.

Get-RoomAdjoining returns the adjacent room in the movement direction. If there is no such room, our move is invalid. Going down a random number modulo 6 is generated. This number is used as in index into directions_enum which is a dictionary mapping the 6 movement directions to numbers. If our movement direction matched with the randomly generated direction, function Invoke-XformKey would be called.

The random number generator is initialized by the Invoke-TransferThing function by a call to srand .

Additionally also note that we need to be in possession of a “key” for srand to be invoked.

Drawing the level map

The Get-Map function constructs the map of the maze. The New-Room function creates a new room and the rooms are linked with each other by the Add-RoomLink function.

Following the code, we can sketch the floor plan as below. We will use this sketch as a guide for travelling in the maze.

The case of the random number generator

Our first objective is thus to fetch the key from the drawers of the reception table at the lobby. Doing that would invoke srand . Next, we need to move according to the random numbers generated. The question is how do we predict random numbers?

True random numbers cannot be predicted. If they can be predicted they are not random anymore. Generating truly random numbers is a very difficult task. For the majority of our purposes, we use what’s called a pseudo-random number. These numbers are generated by a deterministic algorithm based on an initial value called as a seed. Using the same seed will generate the exact same sequence of random numbers.

The generated numbers are mapped using the directions map. If we try to follow this path after obtaining the key from the drawer, we will notice that the path is not valid after the two moves – west and north.

Clearly, this means our generated random numbers are not the same as the ones generated by the program.

Dynamic analysis in Windbg

Let’s debug the program in Windbg. You can also use x64dbg for the same. Disassembling the srand function we can see that the very first instruction is an unconditional jump. This implies that the function is actually working differently than expected. We can also notice that it is comparing whether the seed value passed to srand is 42 (0x2a). If we recall, the PowerShell script was also using 42 as the seed value.

Similarly, rand is also hooked.

Going down the disassembly listing we can see that the code is accessing the location 0x1359cb8 as an array. If we dump the memory at this location we can see a list of integers.

In fact the hooked rand implementation is returning numbers from the above list. If we convert these numbers to the respective directions we get the following.

#8 – flair.apk

This is an android challenge, a welcome refreshment from the Windows-based problems faced so far. We can run the apk on an emulator or a device. Here I have used Android-x86. The challenge is comprised of multiple levels in the form of activities. We can use an online apk decompiler for reversing the apk back to its source code.

Analysis of the decompiled code

Lets have a look at the app manifest file AndroidManifest.xml

There are five activities named Chotchkies, Michael, Brian, Milton and Printer. Among them, the first one is the main activity. Let’s have a look at it.

From the above decompiled code, we can notice the main activity has a switch case to start the four activities depending on the value in flairIndex. These four activities are the four levels.

Activity Michael

This activity is straightforward. We need to enter a password and the app would check it.

The teraljdknh function compare our input password to a string generated at runtime. This string is built in the function asdjfnhaxshcvhuw by taking several pieces of information like the color of the TextView etc. We can solve this in the same way as previous by building the string manually but an easier way is through dynamic analysis. If we run the app and hook the string comparison function we can easily find the password by inspecting the value of the parameters. We will be using frida for dynamic analysis.

Using Frida

A short tutorial on setting up Frida can be found here. Frida uses a Python API with a JavaScript debugging logic. We will hook the string comparison function and log the parameters when it’s called. The hook code will be in JavaScript.