Wednesday, 18 October 2017

CTF Writeup - Flare-On 2017 - 02: IgniteMe.exe

  • Name - IgniteMe.exe
  • Category - Reverse Engineering
  • Points - 1
  • Binary - Download here

Running the binary and giving it 'somerandomstuff' as input:

Command Prompt
C:\>IgniteMe.exe G1v3 m3 t3h fl4g: somerandomstuff N0t t00 h0t R we? 7ry 4ga1nz plzzz! C:\>

Looking at the start() function of the binary IgniteMe.exe:

The green basic box is the area we would like our execution to go to whilst the red displays the fail message 'N0t t00 h0t R we? 7ry 4ga1nz plzzz!'.

Starting from the top of the graph, after the message is displayed, the program executes sub_4010F0() which reads our input and makes a copy of it (less chars 0xA and 0xD) in global variable byte_403078. The magic happens in subsequent function sub_401050():

signed int sub_401050()
    int v0; // ST04_4
    int i; // [esp+4h] [ebp-8h]
    unsigned int j; // [esp+4h] [ebp-8h]
    char v4; // [esp+Bh] [ebp-1h]

    v0 = strlen(byte_403078);
    v4 = sub_401000();

    for ( i = v0 - 1; i >= 0; --i )
        byte_403180[i] = v4 ^ byte_403078[i];
        v4 = byte_403078[i];

    for ( j = 0; j < 0x27; ++j )
        if ( byte_403180[j] != (unsigned __int8)byte_403000[j] )
            return 0;

    return 1;

On line 8, the string length of our input (less 0xA and 0xD) is computed and stored in v0. The next line executes sub_401000() which is a very simple function:

__int16 sub_401000()
    return (unsigned __int16)__ROL4__(-2147024896, 4) >> 1;

This function returns the value 0x04, which is stored in v4. Lines 11 - 15 iterate over the input string in reverse order, XOR'ing each char with the result of the previous computation. In the first loop it XOR's 0x04 (value of v4) with the last character of our input. The result is then XOR'd with the second from last char, and it keeps on going. Each time, the resultant computations are stored in global variable byte_403180.

Lines 17 - 21 compare the resultant array from the previous algorithm with global variable byte_403000. Each char has to match else the function returns 0 and we end up in the red basic block (refer to 1st image).

Reversing the logic and translate it to a python script:

byte_403000 = '\x0D\x26\x49\x45\x2A\x17\x78\x44\x2B\x6C\x5D\x5E\x45\x12\x2F\x17\x2B\x44\x6F\x6E\x56\x09\x5F\x45\x47\x73\x26\x0A\x0D\x13\x17\x48\x42\x01\x40\x4D\x0C\x02\x69'
xor_value = '\x04'
result = ""

for x in byte_403000[::-1]:
    xor_value = chr(ord(x) ^ ord(xor_value))
    result += xor_value
print result[::-1]

Testing out the result:

Command Prompt
C:\>IgniteMe.exe G1v3 m3 t3h fl4g: G00d j0b! C:\>

No comments:

Post a Comment