diff --git a/DInvoke/DInvoke/DynamicInvoke/Generic.cs b/DInvoke/DInvoke/DynamicInvoke/Generic.cs index e229c08..de05fc8 100644 --- a/DInvoke/DInvoke/DynamicInvoke/Generic.cs +++ b/DInvoke/DInvoke/DynamicInvoke/Generic.cs @@ -256,7 +256,7 @@ public static string GetAPIHash(string APIName, long Key) /// The name of the export to search for (e.g. "NtAlertResumeThread"). /// Whether or not to resolve export forwards. Default is true. /// IntPtr for the desired function. - public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName, bool ResolveForwards = true) + public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName, bool ResolveForwards = true, bool CanLoadFromDisk = false, bool Overload = false) { IntPtr FunctionPtr = IntPtr.Zero; try @@ -303,7 +303,7 @@ public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName, bool if (ResolveForwards == true) // If the export address points to a forward, get the address - FunctionPtr = GetForwardAddress(FunctionPtr); + FunctionPtr = GetForwardAddress(FunctionPtr, CanLoadFromDisk, Overload); break; } @@ -331,7 +331,7 @@ public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName, bool /// The ordinal number to search for (e.g. 0x136 -> ntdll!NtCreateThreadEx). /// Whether or not to resolve export forwards. Default is true. /// IntPtr for the desired function. - public static IntPtr GetExportAddress(IntPtr ModuleBase, short Ordinal, bool ResolveForwards = true) + public static IntPtr GetExportAddress(IntPtr ModuleBase, short Ordinal, bool ResolveForwards = true, bool CanLoadFromDisk = false, bool Overload = false) { IntPtr FunctionPtr = IntPtr.Zero; try @@ -400,7 +400,7 @@ public static IntPtr GetExportAddress(IntPtr ModuleBase, short Ordinal, bool Res /// 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). /// Whether or not to resolve export forwards. Default is true. /// IntPtr for the desired function. - public static IntPtr GetExportAddress(IntPtr ModuleBase, string FunctionHash, long Key, bool ResolveForwards = true) + public static IntPtr GetExportAddress(IntPtr ModuleBase, string FunctionHash, long Key, bool ResolveForwards = true, bool CanLoadFromDisk = false, bool Overload = false) { IntPtr FunctionPtr = IntPtr.Zero; try @@ -467,8 +467,9 @@ public static IntPtr GetExportAddress(IntPtr ModuleBase, string FunctionHash, lo /// The Wover (@TheRealWover) /// Function of an exported address, found by parsing a PE file's export table. /// Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + /// Optional, indicates if the dll should be loaded using overload /// IntPtr for the forward. If the function is not forwarded, return the original pointer. - public static IntPtr GetForwardAddress(IntPtr ExportAddress, bool CanLoadFromDisk = false) + public static IntPtr GetForwardAddress(IntPtr ExportAddress, bool CanLoadFromDisk = false, bool Overload = false) { IntPtr FunctionPtr = ExportAddress; try @@ -492,7 +493,15 @@ public static IntPtr GetForwardAddress(IntPtr ExportAddress, bool CanLoadFromDis IntPtr hModule = GetPebLdrModuleEntry(ForwardModuleName); if (hModule == IntPtr.Zero && CanLoadFromDisk == true) - hModule = LoadModuleFromDisk(ForwardModuleName); + if (Overload) + { + StringBuilder ForwardModulePath = new StringBuilder("",256); + IntPtr ForwardModulePathOut; + Data.Native.NTSTATUS res = Win32.SearchPathW(null, ForwardModuleName, null, (UInt32)ForwardModulePath.Capacity, ForwardModulePath, out ForwardModulePathOut); + hModule = ManualMap.Overload.OverloadModule(ForwardModulePath.ToString()).ModuleBase; + } + else + hModule = LoadModuleFromDisk(ForwardModuleName); if (hModule != IntPtr.Zero) { FunctionPtr = GetExportAddress(hModule, ForwardExportName); @@ -728,8 +737,10 @@ public static void CallMappedDLLModule(Data.PE.PE_META_DATA PEINFO, IntPtr Modul /// Prototype for the function, represented as a Delegate object. /// Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference. /// Specify whether to invoke the module's entry point. + /// Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + /// Optional, indicates if the dll should be loaded using overload /// void - public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, string ExportName, Type FunctionDelegateType, object[] Parameters, bool CallEntry = true) + public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, string ExportName, Type FunctionDelegateType, object[] Parameters, bool CallEntry = true, bool CanLoadFromDisk = false, bool Overload = false) { // Call entry point if user has specified if (CallEntry) @@ -738,7 +749,7 @@ public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntP } // Get export pointer - IntPtr pFunc = GetExportAddress(ModuleMemoryBase, ExportName); + IntPtr pFunc = GetExportAddress(ModuleMemoryBase, ExportName, CanLoadFromDisk: CanLoadFromDisk, Overload: Overload); // Call export return DynamicFunctionInvoke(pFunc, FunctionDelegateType, ref Parameters); @@ -754,8 +765,10 @@ public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntP /// Prototype for the function, represented as a Delegate object. /// Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference. /// Specify whether to invoke the module's entry point. + /// Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + /// Optional, indicates if the dll should be loaded using overload /// void - public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, short Ordinal, Type FunctionDelegateType, object[] Parameters, bool CallEntry = true) + public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, short Ordinal, Type FunctionDelegateType, object[] Parameters, bool CallEntry = true, bool CanLoadFromDisk = false, bool Overload = false) { // Call entry point if user has specified if (CallEntry) @@ -764,7 +777,7 @@ public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntP } // Get export pointer - IntPtr pFunc = GetExportAddress(ModuleMemoryBase, Ordinal); + IntPtr pFunc = GetExportAddress(ModuleMemoryBase, Ordinal, CanLoadFromDisk: CanLoadFromDisk, Overload: Overload); // Call export return DynamicFunctionInvoke(pFunc, FunctionDelegateType, ref Parameters); @@ -781,8 +794,10 @@ public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntP /// Prototype for the function, represented as a Delegate object. /// Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference. /// Specify whether to invoke the module's entry point. + /// Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + /// Optional, indicates if the dll should be loaded using overload /// void - public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, string FunctionHash, long Key, Type FunctionDelegateType, object[] Parameters, bool CallEntry = true) + public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, string FunctionHash, long Key, Type FunctionDelegateType, object[] Parameters, bool CallEntry = true, bool CanLoadFromDisk = false, bool Overload = false) { // Call entry point if user has specified if (CallEntry) @@ -791,7 +806,7 @@ public static object CallMappedDLLModuleExport(Data.PE.PE_META_DATA PEINFO, IntP } // Get export pointer - IntPtr pFunc = GetExportAddress(ModuleMemoryBase, FunctionHash, Key); + IntPtr pFunc = GetExportAddress(ModuleMemoryBase, FunctionHash, Key, CanLoadFromDisk: CanLoadFromDisk, Overload: Overload); // Call export return DynamicFunctionInvoke(pFunc, FunctionDelegateType, ref Parameters); diff --git a/DInvoke/DInvoke/DynamicInvoke/Win32.cs b/DInvoke/DInvoke/DynamicInvoke/Win32.cs index 8abb291..4210bce 100644 --- a/DInvoke/DInvoke/DynamicInvoke/Win32.cs +++ b/DInvoke/DInvoke/DynamicInvoke/Win32.cs @@ -57,6 +57,29 @@ public static IntPtr CreateRemoteThread( return retValue; } + public static Data.Native.NTSTATUS SearchPathW( + string lpPath, + string lpFileName, + string lpExtension, + UInt32 nBufferLength, + StringBuilder lpBuffer, + out IntPtr filePartOut) + { + filePartOut = IntPtr.Zero; + // Craft an array for the arguments + object[] funcargs = + { + lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, filePartOut + }; + + Data.Native.NTSTATUS retValue = (Data.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"kernel32.dll", @"SearchPathW", typeof(Delegates.SearchPathW), ref funcargs); + + // Update the modified variables + filePartOut = (IntPtr)funcargs[5]; + + return retValue; + } + /// /// Uses DynamicInvocation to call the IsWow64Process Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf-wow64apiset-iswow64process /// @@ -67,7 +90,7 @@ public static bool IsWow64Process(IntPtr hProcess, ref bool lpSystemInfo) // Build the set of parameters to pass in to IsWow64Process object[] funcargs = { - hProcess, lpSystemInfo + hProcess,lpSystemInfo }; bool retVal = (bool)Generic.DynamicAPIInvoke(@"kernel32.dll", @"IsWow64Process", typeof(Delegates.IsWow64Process), ref funcargs); @@ -100,9 +123,24 @@ public static bool CloseHandle(IntPtr handle) public static class Delegates { // Kernel32.dll + + // https://github.com/Tarkiyah/ansible/blob/b0c8e7926f4ed31c37fabfad7803bd378f8aaba4/lib/ansible/module_utils/csharp/Ansible.Process.cs + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate Data.Native.NTSTATUS SearchPathW( + [MarshalAs(UnmanagedType.LPWStr)] + string lpPath, + [MarshalAs(UnmanagedType.LPWStr)] + string lpFileName, + [MarshalAs(UnmanagedType.LPWStr)] + string lpExtension, + UInt32 nBufferLength, + [MarshalAs(UnmanagedType.LPTStr)] + StringBuilder lpBuffer, + ref IntPtr lpFilePart); [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate IntPtr CreateRemoteThread(IntPtr hProcess, + public delegate IntPtr CreateRemoteThread( + IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress,