Writeup: FlareOn 2022: 006 - à la mode

Task description

1. TLDR

TLDR graph

2. Input data

The challenge file is here. Password: flare.

The subjects of the task were PE and txt files:

HowDoesThisWork.dll
'IR chat log.txt'

3. Contents of txt file

I first suspected the contents of the text file:

[FLARE Team]  Hey IR Team, it looks like this sample has some other binary that might 
              interact with it, do you have any other files that might be of help.
			  
[IR Team]     Nope, sorry this is all we got from the client, let us know what you got.

4. Analysis of the file as a .NET Assembly file

I verified the file type:

$ file HowDoesThisWork.dll
HowDoesThisWork.dll: PE32 executable (DLL) (GUI) Intel 80386 Mono/.Net assembly, for MS Windows

Seeing that the file was prepared in .NET, I preliminarily analyzed the file using the simple tools Detect-It-Easy:

die

and exeinfo:

exeinfo

Aside from an unusual entry point (0x181A), the programs returned no relevant information.

Using the CFF Explorer tool, I did a preliminary check to see if there were any resources worth keeping in mind during the analysis. At this stage, I have not identified any such resources.

Using dnSpyEx I decompiled the file:

using System;
using System.IO.Pipes;
using System.Text;

namespace FlareOn
{
	// Token: 0x02000002 RID: 2
	public class Flag
	{
		public string GetFlag(string password)
		{
			Decoder decoder = Encoding.UTF8.GetDecoder();
			UTF8Encoding utf8Encoding = new UTF8Encoding();
			string text = "";
			byte[] array = new byte[64];
			char[] array2 = new char[64];
			byte[] bytes = utf8Encoding.GetBytes(password + "\0");
			using (NamedPipeClientStream namedPipeClientStream = new NamedPipeClientStream(".", "FlareOn", PipeDirection.InOut))
			{
				namedPipeClientStream.Connect();
				namedPipeClientStream.ReadMode = PipeTransmissionMode.Message;
				namedPipeClientStream.Write(bytes, 0, Math.Min(bytes.Length, 64));
				int num = namedPipeClientStream.Read(array, 0, array.Length);
				int chars = decoder.GetChars(array, 0, num, array2, 0);
				text += new string(array2, 0, chars);
			}
			return text;
		}
	}
}

Unfortunately, it was all code written in C#….

From the code in C#, I knew that a connection to Named Pipe FlareOn was being established. What I did not know, however, was what creates it… So I ran the sample in x32dbg thinking that maybe I had missed something. Perhaps someone made a patch of the .NET Assembly file with x86 code? That would explain:

  1. the sufficient presence of only one file
  2. the absence of more code in C#, visible in dnSpy
  3. the information about the unusual entry point.

5. Analysis of the file as a PE file

Running the dll file could have been accomplished by calling rundll32.exe, for example. Due to the 32-bit dll, the 32-bit version of rundll32.exe had to be indicated as well. The file had only Entry Point without additional exports. The run therefore could have looked like the following:

>C:\Windows\SysWOW64\rundll32.exe ".\HowDoesThisWork.dll,0"

After loading the file into the IDA environment, I was overwhelmed for a while by the number of functions. I reasoned that most of them came from code overhead generated when compiling code written in C#. If a file should create a Named Pipe, it should have called the CreateFileW function. So I loaded the file into x32dbg and gave the command to add a breakpoint to this function:

bp CreateFileW

After running the file, I captured the moment of creating the file after stopping several times on the breakpoint:

x32dbg-CreateFileW-pipe

Reading the return address from the stack 100010DA``, I returned to the place where the CreateFileWfunction was called, i.e. at the address100010D4``:

x32dbg-call-CreateFileW-pipe

Knowing the place of Named Pipe creation in the program code, I went back to the IDA environment and switched to the same address.

A few instructions above I revealed the function that decodes strings via xor 0x17:

ida-mw_load_string

In this way, I revealed the loaded and used functions:

CloseHandle
ConnectNamedPipe
CreateNamedPipeA
CreateThread
DisconnectNamedPipe
FlushFileBuffers
GetLastError
GetProcessHeap
lstrcmpA
ReadFile
WriteFile

Continuing my analysis, I came across the mw_process_buffer function, which processed the data buffer from Named Pipe:

ida-mw_process_buffer

Analysis of the mw_process_buffer function revealed the fact that the password and flag were encrypted using the rc4 algorithm:

key = 55 8B EC 83 EC 20 EB FE 
password = 3E 39 51 FB A2 11 F7 B9 2C
flag = E1 60 A1 18 93 2E 96 AD 73 BB 4A 92 DE 18 0A AA  41 74 AD C0 1D 9F 3F 19 FF 2B 02 DB D1 CD 1A 

6. Reading the flag

Therefore, it was enough to decrypt the password and flag. To do this, I wrote code in Python:decrypted using the rc4 algorithm:

import malduck

key = b'\x55\x8B\xEC\x83\xEC\x20\xEB\xFE'
password = b'\x3E\x39\x51\xFB\xA2\x11\xF7\xB9\x2C'
flag = b'\xE1\x60\xA1\x18\x93\x2E\x96\xAD\x73\xBB\x4A\x92\xDE\x18\x0A\xAA\x41\x74\xAD\xC0\x1D\x9F\x3F\x19\xFF\x2B\x02\xDB\xD1\xCD\x1A'

ciphertext = password+flag
plaintext = malduck.rc4(key, ciphertext).decode('latin1')
print(plaintext)
MyV0ic3! M1x3d_M0dE_4_l1f3@flare-on.com

Thus, the password is:

MyV0ic3!

… while the flag is:

M1x3d_M0dE_4_l1f3@flare-on.com