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

. 7 min read

#11 – covfefe.exe

Wait, “covfefe”? What does that even mean?  Jokes and memes aside that’s indeed the name of the binary for the 11th challenge. The task description reads:

Only two challenges to go. We have some bad hombres here but you’re going to get the keys out.

The binary requests a password on running.

Providing an incorrect password displays a humorous message.

Analyzing IDA

Let’s have a quick look in IDA.

IDA identifies only a handful of functions. The purpose of the function name exec_instruction  and exec_vm  will be explained a bit later. The call flow graph is simple as well.

The entry function start  calls exec_vm  which in turns calls exec_instruction. Apart from this, we can observe calls to time, rand, srand , printf  and scanf.

start seeds the random number generator with the current time. arr is an array of DWORDs. A random number modulo 8 is then stored at arr[273]. Lastly, it calls exec_vm  passing the array as a parameter. The second argument is the size of the array.

Let’s have a look at the decompiled code of exec_vm .

The code fetches three consecutive elements from the array and passes it to the exec_instruction  function. The return value decides the next three elements be passed at the next call. All of this is wrapped in a while loop. The experienced eye will immediately recognize this as the dispatch stub used in virtualization based code protection.  Let’s have a look at exec_instruction.

The function subtracts array[i] from array[j] storing the difference back in array[j] . If the third parameter passed is non zero, it returns the comparison of difference <= 0. The virtual machine instruction set comprises of only a single instruction and referred to as One Instruction Set Computer (OSIC). The algorithm implemented is Subleq.

Writing the Subleq in Python

The logic is simple enough to be implemented in Python. The bytecode for the VM is located at 403008 and can be extracted using IDA Python.

The code for the emulator is as follows


from __future__ import print_function 
from vm import code import random 

userinput = None 
input_idx = -1 # printf("%c", char) 
def printfc(char): 
print(chr(char), end='') # 
scanf("%c", &returned) 

def scanfc(): 

global userinput, input_idx 

if userinput is None: 

userinput = raw_input() 
input_idx = 0 

if userinput == '': 
    return 0xA 
    
else: 
    return ord(userinput[input_idx]) 
    
else: 
    input_idx += 1 
    
if input_idx == len(userinput): 
    input_idx -= 1 return 0xA 

else: 
    return ord(userinput[input_idx]) 

def exec_instruction(a, b, c): 
    code[b] -= code[a] 
    
if c != 0: return code[b] <= 0 else: return False 

def exec_vm(entry, size): 
    global ins_count, scanf_count, printf_count 
    pc = entry 
    while pc + 3 <= size: 
        if exec_instruction(code[pc], code[pc+1], code[pc+2]): 
            if code[pc+2] == -1: 
                return 1 
                pc = code[pc+2] 
            else: pc += 3 
            if code[4] == 1: 
                printfc(code[2]) 
                code[4] = 0 
                code[2] = 0 

            if code[3] == 1: 
                code[1] = scanfc() 
                code[3] = 0 
    
def main(): 

    code[273] = random.randint(0, 32767) % code[272] exec_vm(1123, 4352) 

if __name__ == '__main__': 
    main()

Let’s’ test out our shiny new emulator.

That’s perfect. At this point, we have a working emulator that mimics the exact operation of the VM. We no longer need the original binary for testing. However, we still have no idea about how the password is checked.

Visualizing execution pattern

Let us try to get a high-level overview of the password checking algorithm by plotting the value of the instruction pointer during the execution of the VM. To obtain deterministic execution pattern, the random number was replaced with a fixed number 0. Plotting the value of the Instruction Pointer we get the following image when trying with the password “12”.

Similarly, trying with the password “1212” yields the following plot.

By comparing the two plots, we can observe the number of executed instructions increases with the length of the password. The sawtooth patterns indicate loop. We can also notice that characters of the password are checked two at a time. The value of the instruction pointer never goes below 1000, indicating that offsets 0-1000 stores data.

The first and last sawtooth patterns indicate the printing of the welcome and failure message respectively. Correspondingly, this means the function which prints a string is located near offset 4000 in the bytecode. The function which handles input is located near 4200. The four peaks in the input pattern correspond to the four-letter password we provided. Characters at odd position in the password are processed near 3000 whereas those at even-numbered position are processed near 3500.

Visualizing memory read patterns

A subleq instruction is a tuple of three values (a,b,c) which performs arr[b] -= arr[a] . We can say the value at a is accessed for reading whereas the value at b is accessed for writing. We can plot the address the program reads from as the execution proceeds. The graph below is for the password “1212”.

The plot is quite similar to the execution pattern which implies the data and the code that uses it are located close to each other. Memory address 0 has the highest read count suggesting that its used as a temporary variable for storing the results of intermediate calculations. We can reason that the checking algorithm works by performing some calculations on the password characters and comparing the result to a hardcoded value. By intuition, this check seems to be done at the two points marked, close to 3700.

Tracing execution

We can trace the executed subleq instructions by modifying the exec_vm  function.

def exec_vm(entry, size): global trace pc = entry while pc + 3 <= size: print('loc_{} [{}]={} [{}]={}'.format(pc, code[pc], code[code[pc]], code[pc+1], code[code[pc+1]]), file=trace) if exec_instruction(code[pc], code[pc+1], code[pc+2]): if code[pc+2] == -1: return 1 pc = code[pc+2] else: pc += 3 if code[4] == 1: printfc(code[2]) code[4] = 0 code[2] = 0 if code[3] == 1: code[1] = scanfc() code[3] = 0

The number of lines in the trace for password “1212” is close to 15k. Let us inspect the trace using the execution flow graph as a reference.

The first preprocess stage occurs when the instruction count is in the range 1800 – 2700. In the trace file, we can see that the ASCII value of the first character of the password is multiplied by 15. The multiplication is done by repeated addition.

ASCII value of ‘1’ = 49
49 * 15 = 735

735 is then left shifted 7 times to obtain 94080. This calculation when the instruction count is in the range 2700-2800.

Getting the flag

From the memory read plot, we have identified 3700 as the possible location where the result of the previous calculation might be stored. If we inspect the bytecode near offset 3700, we indeed get a list of values.

In order to get back the initial ASCII values of the letters, we have to reverse the calculation. This can simply be done by right shifting 7 times followed by dividing by 15, i.e.  (x >> 7) / 15

Thus, we have the characters at the odd-numbered positions.

This is a subleq challenge, hence the first word seems to be subleq.

Lets, try to guess the remaining words using this list of English words. We will be using regex search. Searching for .b.u.d.m we get exactly 1 hit – absurdum.

The password formed till now is

Searching for absurdum on google reveals the word reductio ad absurdum.

The password is most likely to be subleq_and_reductio_ad_absurdum

If we try this as the password we get the much-coveted success message.

The flag for this challenge is subleq_and_reductio_ad_absurdum@flare-on.com



Barun

Reverse Engineer with an interest in low level stuff and anything about security.

Get IoT Security Training

IoT Pentesting Exploitation Training

Tags

analog modulation Android android application security android hands on security and exploitation training android security Apktool application auditing application security auditing appsec usa appwatch arduino nano arm ARM binaries ARM course ARM exploitation book ARM exploitation video training ARM gadgets ARM Training attify attify badge attify training best security practices biggest iot attacks of all time binwalk blackberry pentesting blackhat ble BLE attacks BLE dangers BLE hacking and exploitation BLE security issues BLE sniffing BLE vulnerabilities bleah bluetooth technology box brut Exception BtleJuice capture radio traffic career in cybersecurity CCTV cameras challenges in iot retail chroot cloud based mobile application security scanner consulting CTF cyber attacks cybersecurity Damn Vulnerable iOS App dangers of iot DDoS attacks devops digital modulation dumping memory embedded hacking expert Exploit ARM devices exploitation exploiting ble exploiting smart devices firmadyne firmware analysis toolkit firmware emulation Firmware hacking firmware reverse engineering Flare-on frida getting started with firmware hacking GSMA guide to ARM exploitation hacked security IP cameras hacked smart devices hackers hackfest hacking smart devices healthcare business protection against iot threats healthcare cyber security how can healthcare fight iot threats How Mirai botnet infects your device How Mirai works how retail can prevent cyber attacks how to exploit ble how to hack radio waves how to protect iot devices how to secure iot device IDA internet of things Internet of Things Security internet security ios application security ios security iot iot attacks iot bots, malwares iot device IoT Devices IoT Exploitation iot hacking iot hacks IoT hacks on ARM devices iot penetration testing iot pentest iot pentesting iot security IoT security guidelines iot security training iot threats iot threats to healthcare industry iotsecurity IP cameras jtag jtag debugging latest iot attacks learn ARM exploitation measures to prevent cyber attacks on healthcare organisations Mirai Botnet mirai history mobile app mobile application security mobile application security testing mobile security monitor iot devices Mozilla network security in retail ninja recon technique NIST offensive iot exploitation ola cabs owasp owasp appsec penetration testers penetration testing pentesting pentesting mobile apps phishing attacks powerofcommunity PrinterSecurity privacy protection profession professional qemu quizup radio communication protocol radio coomunication radio waves hacking recent ARM attacks recent cyber attacks recent iot attacks recent security camera attacks retail iot Reversing safety measures to protect privacy sdr secure coding guidelines security security cameras security challenges in retail IoT security in healthcare iot security issue security issues faced by e-retailers security services security training security vulnerability setup smart devices smart user security social networking spi steps to prevent iot attacks on healthcare surveillance cameras hijacked threat modeling tools to exploit ble training uart Understanding Mirai Botnet virus vulnerabilities discovered in popular IoT IP cameras vulnerabilities in internet connected cameras vulnerability vulnerable ARM devices What is mirai botnet? why choose career in cybersecurity writeups xposed hooking zigbee zigbee exploitation zigbee security zwave

Instagram