internal void Call(IntPtr remoteDllAddress) { if (_injectionMethod == InjectionMethod.ManualMap || _injectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { // Call the entry point of the DLL with DllProcessDetach if (!_process.CallFunction <bool>(CallingConvention.StdCall, remoteDllAddress + _peImage.PeHeaders.PEHeader.AddressOfEntryPoint, (long)remoteDllAddress, Constants.DllProcessDetach, 0)) { throw new RemoteFunctionCallException("Failed to call the entry point of the DLL"); } // Remove the entry for the DLL from the LdrpInvertedFunctionTable var rtRemoveInvertedFunctionTableAddress = _process.PdbFile.Value.Symbols["RtlRemoveInvertedFunctionTable"]; _process.CallFunction(CallingConvention.FastCall, rtRemoveInvertedFunctionTableAddress, (long)remoteDllAddress); // Decrease the reference count of the DLL dependencies var freeLibraryAddress = _process.GetFunctionAddress("kernel32.dll", "FreeLibrary"); if (_peImage.ImportedFunctions.Value.GroupBy(importedFunction => importedFunction.Dll).Select(dll => _process.Modules.Find(module => module.Name.Equals(dll.Key, StringComparison.OrdinalIgnoreCase)).BaseAddress).Any(dependencyAddress => !_process.CallFunction <bool>(CallingConvention.StdCall, freeLibraryAddress, (long)dependencyAddress))) { throw new RemoteFunctionCallException("Failed to call FreeLibrary"); } // Free the memory allocated for the DLL if (_injectionMethod == InjectionMethod.ManualMap) { _process.MemoryManager.FreeVirtualMemory(remoteDllAddress); } else { Ntdll.NtUnmapViewOfSection(_process.Process.SafeHandle, remoteDllAddress); } } else { var freeLibraryAddress = _process.GetFunctionAddress("kernel32.dll", "FreeLibrary"); if (!_process.CallFunction <bool>(CallingConvention.StdCall, freeLibraryAddress, (long)remoteDllAddress)) { throw new RemoteFunctionCallException("Failed to call FreeLibrary"); } } }
private void BuildImportTable() { if (_peImage.ImportedFunctions.Value.Count == 0) { return; } // Group the imported functions by the DLL they are imported from var groupedFunctions = _peImage.ImportedFunctions.Value.GroupBy(importedFunction => importedFunction.Dll).ToList(); // Ensure the dependencies of the DLL are loaded in the remote process var systemFolderPath = _process.IsWow64 ? Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) : Environment.GetFolderPath(Environment.SpecialFolder.System); foreach (var dll in groupedFunctions) { var module = _process.Modules.Find(m => m.Name.Equals(dll.Key, StringComparison.OrdinalIgnoreCase)); if (module != null) { // Increase the reference count of the dependency var ldrAddRefDllAddress = _process.GetFunctionAddress("ntdll.dll", "LdrAddRefDll"); var ntStatus = _process.CallFunction <int>(CallingConvention.StdCall, ldrAddRefDllAddress, 0, (long)module.BaseAddress); if ((NtStatus)ntStatus != NtStatus.Success) { throw new RemoteFunctionCallException("Failed to call LdrAddRefDll", (NtStatus)ntStatus); } continue; } // Load the dependency into the remote process using (var injector = new Injector(_process.Process.Id, Path.Combine(systemFolderPath, dll.Key), InjectionMethod.HijackThread)) { injector.InjectDll(); } _process.Refresh(); } // Build the import table in the local process foreach (var function in groupedFunctions.SelectMany(dll => dll.Select(f => f))) { var importedFunctionAddress = function.Name is null ? _process.GetFunctionAddress(function.Dll, function.Ordinal) : _process.GetFunctionAddress(function.Dll, function.Name); if (_process.IsWow64) { Marshal.WriteInt32(_localDllAddress + function.Offset, (int)importedFunctionAddress); } else { Marshal.WriteInt64(_localDllAddress + function.Offset, (long)importedFunctionAddress); } } }
internal void Call() { if (_process.IsWow64) { foreach (var(entryAddress, entry) in _process.Peb.GetWow64PebEntries()) { // Read the file path of the entry var entryFilePathBytes = _process.MemoryManager.ReadVirtualMemory((IntPtr)entry.FullDllName.Buffer, entry.FullDllName.Length); var entryFilePath = Encoding.Unicode.GetString(entryFilePathBytes); if (entryFilePath != _dllPath) { continue; } // Remove the entry from the InLoadOrder, InMemoryOrder and InInitializationOrder linked lists RemoveDoublyLinkedListEntry(entry.InLoadOrderLinks); RemoveDoublyLinkedListEntry(entry.InMemoryOrderLinks); RemoveDoublyLinkedListEntry(entry.InInitializationOrderLinks); // Remove the entry from the LdrpHashTable RemoveDoublyLinkedListEntry(entry.HashLinks); // Remove the entry from the LdrpModuleBaseAddressIndex var rtlRbRemoveNodeAddress = _process.GetFunctionAddress("ntdll.dll", "RtlRbRemoveNode"); var ldrpModuleBaseAddressIndex = _process.PdbFile.Value.Symbols["LdrpModuleBaseAddressIndex"]; _process.CallFunction(CallingConvention.StdCall, rtlRbRemoveNodeAddress, (long)ldrpModuleBaseAddressIndex, (long)(entryAddress + (int)Marshal.OffsetOf <LdrDataTableEntry32>("BaseAddressIndexNode"))); } } else { foreach (var(entryAddress, entry) in _process.Peb.GetPebEntries()) { // Read the file path of the entry var entryFilePathBytes = _process.MemoryManager.ReadVirtualMemory((IntPtr)entry.FullDllName.Buffer, entry.FullDllName.Length); var entryFilePath = Encoding.Unicode.GetString(entryFilePathBytes); if (entryFilePath != _dllPath) { continue; } // Remove the entry from the InLoadOrder, InMemoryOrder and InInitializationOrder linked lists RemoveDoublyLinkedListEntry(entry.InLoadOrderLinks); RemoveDoublyLinkedListEntry(entry.InMemoryOrderLinks); RemoveDoublyLinkedListEntry(entry.InInitializationOrderLinks); // Remove the entry from the LdrpHashTable RemoveDoublyLinkedListEntry(entry.HashLinks); // Remove the entry from the LdrpModuleBaseAddressIndex var rtlRbRemoveNodeAddress = _process.GetFunctionAddress("ntdll.dll", "RtlRbRemoveNode"); var ldrpModuleBaseAddressIndex = _process.PdbFile.Value.Symbols["LdrpModuleBaseAddressIndex"]; _process.CallFunction(CallingConvention.StdCall, rtlRbRemoveNodeAddress, (long)ldrpModuleBaseAddressIndex, (long)(entryAddress + (int)Marshal.OffsetOf <LdrDataTableEntry64>("BaseAddressIndexNode"))); } } }
public IntPtr Call() { // Write the DLL path into the remote process var dllPathAddress = _process.MemoryManager.AllocateVirtualMemory(_dllPath.Length, MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathAddress, Encoding.Unicode.GetBytes(_dllPath)); // Write a UnicodeString representing the DLL path into the remote process IntPtr dllPathUnicodeStringAddress; if (_process.IsWow64) { var dllPathUnicodeString = new UnicodeString32(_dllPath, dllPathAddress); dllPathUnicodeStringAddress = _process.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString32>(), MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathUnicodeStringAddress, dllPathUnicodeString); } else { var dllPathUnicodeString = new UnicodeString64(_dllPath, dllPathAddress); dllPathUnicodeStringAddress = _process.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString64>(), MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathUnicodeStringAddress, dllPathUnicodeString); } // Create a thread to call LdrLoadDll in the remote process var ldrLoadDllAddress = _process.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var moduleHandleAddress = _process.MemoryManager.AllocateVirtualMemory(IntPtr.Size, MemoryProtectionType.ReadWrite); var ntStatus = _process.CallFunction <int>(CallingConvention.StdCall, ldrLoadDllAddress, 0, 0, (long)dllPathUnicodeStringAddress, (long)moduleHandleAddress); if ((NtStatus)ntStatus != NtStatus.Success) { throw new RemoteFunctionCallException("Failed to call LdrLoadDll", (NtStatus)ntStatus); } // Ensure the DLL is loaded before freeing any memory while (_process.Modules.TrueForAll(module => module.FilePath != _dllPath)) { _process.Refresh(); } _process.MemoryManager.FreeVirtualMemory(dllPathAddress); _process.MemoryManager.FreeVirtualMemory(dllPathUnicodeStringAddress); // Read the address of the DLL that was loaded in the remote process var remoteDllAddress = _process.MemoryManager.ReadVirtualMemory <IntPtr>(moduleHandleAddress); _process.MemoryManager.FreeVirtualMemory(moduleHandleAddress); if (!_injectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { return(remoteDllAddress); } // Write over the header region of the DLL with random bytes var randomBuffer = new byte[_peImage.PeHeaders.PEHeader.SizeOfHeaders]; new Random().NextBytes(randomBuffer); _process.MemoryManager.WriteVirtualMemory(remoteDllAddress, randomBuffer); return(remoteDllAddress); }