[Write-up] Chal7 {Flareon4}

m4n0w4r
tradahacking
Published in
10 min readOct 19, 2017

Write-up for Chal7 of Flareon4. This may not be a good solution, but that’s the method how I found the final flag.

1. Collect information

- Target is an exe file: zsud.exe

- Check the basic information:

o File format: PE32

o Target is written in Visual C ++: Microsoft Visual C/C++(2013)[-]

o Searching string, find some interesting strings as follows:

Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Versio..

M:\whiskey_tango_flareon.dll

soooooo_sorry_zis_is_not_ze_flag

http://127.0.0.1:9999/some/thing.asp

o Searching information related to Crypto: possible target use Base64; Rijndael

Open the binary with any Hex Editor, searching around and I detected the signature of another PE file. Maybe when zsud.exe is executed, it will drop this PE file. The new PE file is located at the offset as the following image:

o Observe the above PE information, I recognized that this is a dll file with name is flareon.dll. This .dll file can be coded in .NET and its code can call something related to PowerShell:

o Try to run zsud.exe, get the Escape Room interface:

o Through the game’s help, I see that this is a mini game, the player must follow the author’s intentions, then do some actions such as picking up something, wear thing, drop item, talk to someone …

2. Extract embedded flareon.dll

Use other third-party tool to cross check, the embedded PE file is a DLL and file’s size:

Win32 executable found at offset 0x0 size 385536 bytes

Win32 DLL found at offset 0x570b0 size 4608 bytes

2 PE file(s) found from the whole file.

Perform extract the entire DLL from zsud.exe and save it as flareon.dll:

[+] Size of PE file: (0x1200) 4608 bytes = 4.50 kb

PE file successfully carved!

Re-check flareon.dll, knowing that this file is coded in .NET (as mentioned above): .NET(v4.0.30319)[-]. By using dnSpy to decompile it, get the information about class four with two methods is Smth and Decrypt2 as follows:

Review all the above code:

- Smth(string arg): This method takes one parameter as a string of Base64String which is converted and stored into a byte array is cipherText. It then calls the Decrypt2 method to decrypt the cipherText.

- Decrypt2(byte[] cipherText, string key): Perform decrypt the entire cipherText with decryption key is: “soooooo_sorry_zis_is_not_ze_flag”.

- The result after decryption is a PowerShell script and is saved to the script. Then execute this script via powerShell.Invoke ().

So to get the final PowerShell script, I have to find the Base64 input string.

3. Find the Base64 string and get the PowerShell script

By using IDA for static analysis and debugging via OllyDbg, I found the location at sub_4023D0() where the Base64 string is generated and the string length is 0x0000E12D (57645).

Retrieve the entire contents of this Base64 string, then rewrite a small program that performs the same operation as flareon.dll to decrypt that string. The result is the PowerShell script that I want to find. This PowerShell contains the complete source code of the Escape Room mini game:

Running this ps script, the game appears similar as we execute zsud.exe:

4. Dig into code of PowerShell

After a few days of reading code and debug the PowerShell script, I found some very important information:

  • This script uses srand() and rand() functions of msvcr.dll:
  • When entering the game, will stand at $map.StartingRoom = $vestibule. The information at this location: “You are in the vestibule. Try looking around.”
  • From $vestibule, if press ‘s’ to go to the South, I will definitely be ‘locked out’. Because this is a one-way direction:
  • So, from the $vestibule, only press ’n’ to go to the North and then reach the $lobby:
  • At $lobby, will see the “reception desk”. Observing the reception desk will see “a sign-in sheet and laptop on top and a few drawers on the sides”. Reading the script’s code, I know that at the drawers will have a “key”.
  • key” is defined as an encrypted string as follows:
  • When I picked up the “key” at the drawer, script will call Invoke-TransferThing([PSObject][ref]$container_old,[PSObject][ref]$container_new, $thing). This code examines if the key is picked up, it calls srand (42) function to generates a random number with seed number is 42. Normally, the srand () is called before calling the rand () function
  • After got the key, each movement step of player in the maze will call to the Invoke-MoveDirection($char, $room, $direction, $trailing). This function will call rand() % 6 to generate a random number between 0–5. The code of this function is as following:
  • $dir_short variable contains information about the player’s movement, ${N} will contains the random number generated by rand()%6. The $directions_enum[$dir_short] -eq ($n) instruction checks to see if the movement that user entered matches the random number generated by the rand () function. If match, call Invoke-XformKey([String]$keytext, [String]$desc) function to transform the original key’s content.
  • The code of Invoke-XformKey([String]$keytext, [String]$desc) that performs key transformation as following image:
  • Check out $directions_enum, I obtain a very valuable information as follows:
  • Based on the above information, I realize that for each move in the maze, it will use $directions_enum to mapping input characters corresponding to the number. For example, if you input “w” then the corresponding number is “3”, input “e” corresponding to “2”
  • From here, I found a pretty absurd thing, it would be difficult for the movement step in the maze that coincides with the random number in the range of 0–5 is generated by the command rand ()% 6. Luckily have the same number, I also have several times accidentally entered the same number that rand created, lolz..
  • When execute zsud.exe, it unpacks PowerShell to run the game, and when PowerShell calls to srand (42) and rand ()% 6, these functions may be intercepted by the binary file.

The question is how to know the location in the binary that interfering srand() and rand() functions?

5. Using FLOSS to deobfuscate strings

During the time research this binary, I did not find any information about msvcrt.dll library as well as functions like srand () and rand (). I think that the information about them has been encrypted / obfuscated in binary file.

At this point, I remembered that FLARE team has pubished a tool called FLOSS (FireEye Labs Obfuscated String Solver) that dedicated to deobfuscate strings. Try to run this tool with zsud.exe, get the results as follows:

As a result, FLOSS has decoded the strings associated with msvcrt.dll and srand. Using the FLOSS with -i option to genrate an IDAPython script that annotates where the strings was decoded into IDA’s IDB.

$ floss -i zsud_decoded_strings.py zsud.exe

The result after running the script in IDA:

6. Determine the index table for moving in the maze

Following to information that FLOSS offered, we will find the code is responsible for decoding msvcrt.dll and srand:

int __cdecl sub_406530()

{

int result; // eax@1

int result_cpy; // ebx@1

HANDLE hThread; // eax@2

HMODULE h_msvcrt; // edi@2

int (*v4)(void); // eax@3

int v5; // [sp+8h] [bp-10h]@1

LPCSTR lpFileName; // [sp+Ch] [bp-Ch]@1

int v7; // [sp+10h] [bp-8h]@1

LPCSTR lpProcName; // [sp+14h] [bp-4h]@1

v5 = 1;

lpFileName = “bitsigd.dll”;

v7 = 1;

lpProcName = “InitializeEx”;

result = sub_40114A();

result_cpy = result;

if ( !result )

{

return result;

}

sub_42A020();

hThread = GetCurrentThread();

sub_42A500(hThread);

sub_4298C0((int)UnmapViewOfFile_0, a2);

sub_4298C0((int)CloseHandle_0, sub_401145);

sub_4298C0((int)GetFileInformationByHandle_0, sub_401082);

sub_4298C0((int)FreeLibrary_0, sub_401078);

sub_4298C0((int)OpenFile_0, sub_401032);

sub_4298C0((int)MapViewOfFile_0, sub_40114F);

sub_4298C0((int)MapViewOfFileEx_0, sub_4010E6);

sub_4298C0((int)GetFileSize_0, sub_40104B);

sub_4298C0((int)GetFileSizeEx_0, sub_401023);

sub_4298C0((int)ReadFile_0, sub_401014);

sub_4298C0((int)ReadFileEx_0, sub_401005);

sub_4298C0((int)ReadFileScatter_0, sub_401091);

sub_4298C0((int)CreateFileA_0, sub_40109B);

sub_4298C0((int)CreateFileW_0, sub_40111D);

sub_4298C0((int)CreateFileMappingA_0, sub_401055);

sub_4298C0((int)CreateFileMappingW_0, sub_401122);

sub_4298C0((int)GetFileAttributesA_0, sub_40102D);

sub_4298C0((int)GetFileAttributesW_0, sub_4010D2);

sub_4298C0((int)GetFileAttributesExA_0, sub_40112C);

sub_4298C0((int)GetFileAttributesExW_0, sub_4010F0);

sub_4298C0((int)LoadLibraryA_0, sub_40100A);

sub_4298C0((int)LoadLibraryW_0, sub_4010FF);

sub_4298C0((int)&LoadLibraryExA_0, sub_401037);

sub_4298C0((int)LoadLibraryExW_0, sub_401087);

decode_string(&v5, (const char *)&unk_43F6E8);// FLOSS: msvcrt.dll

decode_string(&v7, (const char *)&unk_43F6F8);// FLOSS: srand

h_msvcrt = LoadLibraryA(lpFileName);

if ( h_msvcrt )

{

rand_func = (int (*)(void))GetProcAddress(h_msvcrt, lpProcName + 1);// address of the rand function

v4 = (int (*)(void))GetProcAddress(h_msvcrt, lpProcName);// address of the srand function

srand_func = v4;

}

else

{

v4 = srand_func;

result_cpy = 0;

}

if ( !rand_func || !v4 )

{

result_cpy = 0;

}

sub_4298C0((int)&rand_func, sub_401019); // rand is hooked

sub_4298C0((int)&srand_func, sub_4010B9); // srand is hooked

if ( _ms_p5_mp_test_fdiv() )

{

result_cpy = 0;

}

result = result_cpy;

return result;

}

In summary, sub_406530 () performs the following tasks:

- Call the decode_string function to decode msvcrt.dll and srand strings.

- Using LoadLibraryA to gets handle of msvcrt.dll.

- Using GetProcAddress to gets address of rand and srand functions.

- Perform hooks the rand and srand functions.

After executing the above code, the original rand () function is changed, jumping to the jmp zsud.00401019 ← rand_mod()

The old instruction of rand() function is stored at:

The original srand () function is also changed, it jumps to jmp zsud.004010B9 ← srand_mod()

The old instructions of srand() function are stored at:

Back to the code of PowerShell script, after the game completely executed, when the player picked up the key, script will call srand (42). At that time, srand is hooked to jump to 0x004010B9. Following the 0x004010B9 address, we will go to sub_407140:

int __cdecl sub_407140(int seed_number)

{

signed int flag; // ecx@1

flag = dword_45BD28;

if ( seed_number == 42 ) // seed = 42?

{

flag = 1;

}

dword_45BD28 = flag;

return srand_func(); // jump to location that stored original instruction of srand()

}

The code at sub_407140 will assign 1 to dword_45BD28. As described, after receiving the key, any further steps in the maze will call rand ()% 6 to generate a random number in the range of 0–5 and compared with mapping number that relative with player’s movement. If equal, the Invoke-XformKey will be called to transform the key. The rand function was hooked to jump to 0x00401019. Following the 0x00401019 address, we will go to sub_4070F0:

int __cdecl sub_4070F0()

{

int result; // eax@3

const WCHAR *retaddr; // [sp+0h] [bp+0h]@2

if ( dword_45BD28 && j_au_re_GetModuleHandleExW(retaddr) )

{

result = index_table[i]; // index table is located at 0x459CB8

i = (i + 1) % val_53; // i in range 0 .. 52

}

else

{

result = rand_func(); // jump to location that stored original instruction of rand()

}

return result;

}

The code at sub_4070F0 will take the value of index_table that located at address 0x459CB8. This table contains the following indexes:

Based on the above table, we can see after picked up the key, the next move in the maze must follow this table. Combine this table and mapping table is found above will derive the corresponding step.

After arriving at Kevin’s room, do the following steps to retrieve the final key:

With the hex string provided by Kevin, we get the flag to submit: mudd1ng_by_y0ur53lph@flare-on.com

“You are in the maze. The maze you are in…

In the maze, you saw the maze …

See some thing, you get some thing

Go around, North, South, East, West, Up, Down..

Long long long … Nightmare..so long

Shell shell shell … the Ghost in the shell

Wear some thing, You drop some thing…

Say to Kevin, Kevin: “Hello mate!! Long time no see .. you look tired, lolz!!”

Here is something, you become the king!!!…..”

--

--