/// <summary> /// Manually map module into remote process. /// </summary> /// <author>Ruben Boonen (@FuzzySec)</author> (modified for external ProcessEx) /// <param name="localModuleHandle">Pointer to the module base.</param> /// <param name="remoteModuleHandle">Pointer to the PEINFO image.</param> /// <param name="PEINFO">PE_META_DATA of the module being mapped.</param> /// <returns>PE_MANUAL_MAP object</returns> private PE_MANUAL_MAP __MapModuleToMemory(IntPtr localModuleHandle, IntPtr remoteModuleHandle, byte[] moduleRaw, PE_META_DATA PEINFO) { // Check module matches the process architecture if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4)) { Marshal.FreeHGlobal(localModuleHandle); throw new InvalidOperationException(DSTR(DSTR_MOD_ARCHITECTURE_WRONG)); } // Write PE header to memory UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders; IntPtr RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; byte[] moduleRemote = new byte[RegionSize.ToInt32()]; moduleRaw.Take((int)SizeOfHeaders).ToArray().CopyTo(moduleRemote, 0); #if DEBUG DLog($"PE Header written at 0x{remoteModuleHandle.ToInt64():X16}"); #endif // Write sections to memory foreach (IMAGE_SECTION_HEADER ish in PEINFO.Sections) { // Calculate offsets IntPtr pVirtualSectionBase = (IntPtr)(ish.VirtualAddress); moduleRaw.Skip((int)ish.PointerToRawData).Take((int)ish.SizeOfRawData).ToArray().CopyTo(moduleRemote, pVirtualSectionBase.ToInt32()); #if DEBUG DLog($"{new string(ish.Name).Trim().Replace('\x00'.ToString(), "")} written at 0x{pVirtualSectionBase.ToInt64():X16}, Size: 0x{ish.SizeOfRawData:X8}"); #endif } // Perform relocations __MMRelocateModule(PEINFO, remoteModuleHandle, moduleRaw, moduleRemote); // Rewrite IAT __MMRewriteModuleIAT(PEINFO, remoteModuleHandle, moduleRaw, moduleRemote); // Write the module to memory SetBytes(remoteModuleHandle, moduleRemote); // Set memory protections MMSetModuleSectionPermissions(PEINFO, remoteModuleHandle, moduleRaw); // Free temp HGlobal Marshal.FreeHGlobal(localModuleHandle); // Prepare return object PE_MANUAL_MAP ManMapObject = new PE_MANUAL_MAP { ModuleBase = remoteModuleHandle, PEINFO = PEINFO }; return(ManMapObject); }
/// <summary> /// Manually map module into current process. /// </summary> /// <author>Ruben Boonen (@FuzzySec)</author> /// <param name="rawModule">Pointer to the module base.</param> /// <param name="allocatedModule">Pointer to the PEINFO image.</param> /// <param name="PEINFO">PE_META_DATA of the module being mapped.</param> /// <returns>PE_MANUAL_MAP object</returns> private static PE_MANUAL_MAP MapModuleToMemory(IntPtr rawModule, IntPtr allocatedModule, PE_META_DATA PEINFO) { // Check module matches the process architecture if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4)) { Marshal.FreeHGlobal(rawModule); throw new Exception(DSTR(DSTR_MOD_ARCHITECTURE_WRONG)); } // Write PE header to memory UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders; UInt32 BytesWritten; Native.NtWriteVirtualMemoryD((IntPtr)(-1), allocatedModule, rawModule, SizeOfHeaders); // Write sections to memory foreach (IMAGE_SECTION_HEADER ish in PEINFO.Sections) { // Calculate offsets IntPtr pVirtualSectionBase = (IntPtr)((UInt64)allocatedModule + ish.VirtualAddress); IntPtr pRawSectionBase = (IntPtr)((UInt64)rawModule + ish.PointerToRawData); // Write data BytesWritten = Native.NtWriteVirtualMemoryD((IntPtr)(-1), pVirtualSectionBase, pRawSectionBase, ish.SizeOfRawData); if (BytesWritten != ish.SizeOfRawData) { throw new Exception(DSTR(DSTR_FAILED_MEMORY_WRITE)); } } // Perform relocations RelocateModule(PEINFO, allocatedModule); // Rewrite IAT RewriteModuleIAT(PEINFO, allocatedModule); // Set memory protections SetModuleSectionPermissions(PEINFO, allocatedModule); // Free temp HGlobal Marshal.FreeHGlobal(rawModule); // Prepare return object PE_MANUAL_MAP ManMapObject = new PE_MANUAL_MAP { ModuleBase = allocatedModule, PEINFO = PEINFO }; return(ManMapObject); }
/// <summary> /// Call a manually mapped DLL by Export. Will load the dll in question if not already loaded, and execute an exported function from it. /// </summary> public static object ManualInvoke(string dllPath, string ExportName, Type FunctionDelegateType, ref object[] Parameters, bool CallEntry = true) { PE_MANUAL_MAP mapData = ModuleMapper.MapModuleToMemory(dllPath); return(CallMappedDLLModuleExport(mapData.PEINFO, mapData.ModuleBase, ExportName, FunctionDelegateType, ref Parameters, CallEntry)); }