private void CallTlsCallbacks(InjectionProperties injectionProperties, IntPtr remoteDllAddress) { foreach (var tlsCallback in injectionProperties.PeParser.GetTlsCallbacks()) { CallEntryPoint(injectionProperties, remoteDllAddress, remoteDllAddress.AddOffset(tlsCallback.Offset)); } }
public bool Call(InjectionProperties injectionProperties) { // Get the address of the LoadLibraryW function in the target process var loadLibraryAddress = injectionProperties.RemoteProcess.GetFunctionAddress("kernel32.dll", "LoadLibraryW"); // Write the DLL path into the target process var dllPathBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, injectionProperties.DllPath.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); var dllPathBytes = Encoding.Unicode.GetBytes(injectionProperties.DllPath); injectionProperties.MemoryManager.WriteVirtualMemory(dllPathBuffer, dllPathBytes); // Create a thread to call LoadLibraryW in the target process var ntStatus = PInvoke.RtlCreateUserThread(injectionProperties.RemoteProcess.Handle, IntPtr.Zero, false, 0, IntPtr.Zero, IntPtr.Zero, loadLibraryAddress, dllPathBuffer, out var remoteThreadHandle, IntPtr.Zero); if (ntStatus != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to create a thread in the target process", ntStatus); } PInvoke.WaitForSingleObject(remoteThreadHandle, uint.MaxValue); injectionProperties.MemoryManager.FreeVirtualMemory(dllPathBuffer); remoteThreadHandle.Dispose(); return(true); }
public bool Call(InjectionProperties injectionProperties) { // Get the address of FreeLibraryAndExitThread function in the target process var freeLibraryAndExitThreadAddress = injectionProperties.RemoteProcess.GetFunctionAddress("kernel32.dll", "FreeLibraryAndExitThread"); // Look for the DLL in the module list of the target process var dllName = Path.GetFileName(injectionProperties.DllPath); var module = injectionProperties.RemoteProcess.Modules.Find(m => m.Name == dllName); if (module.Equals(default(ModuleInstance))) { throw new ArgumentException($"No DLL with the name {dllName} was found in the target processes module list"); } // Create a thread to call FreeLibraryAndExitThread in the target process var remoteThreadHandle = (SafeThreadHandle)injectionProperties.SyscallManager.InvokeSyscall <NtCreateThreadEx>(injectionProperties.RemoteProcess.Handle, freeLibraryAndExitThreadAddress, module.BaseAddress); PInvoke.WaitForSingleObject(remoteThreadHandle, uint.MaxValue); remoteThreadHandle.Dispose(); return(true); }
public bool Call(InjectionProperties injectionProperties) { // Look for the DLL in the module list of the target process var dllName = Path.GetFileName(injectionProperties.DllPath); var module = injectionProperties.RemoteProcess.Modules.Find(m => m.Name == dllName); if (module.Equals(default(ModuleInstance))) { throw new ArgumentException($"No DLL with the name {dllName} was found in the target processes module list"); } // Query the header region of the DLL in the target process var memoryInformationBuffer = (IntPtr)injectionProperties.SyscallManager.InvokeSyscall <NtQueryVirtualMemory>(injectionProperties.RemoteProcess.Handle, module.BaseAddress); var memoryInformation = Marshal.PtrToStructure <Structures.MemoryBasicInformation>(memoryInformationBuffer); // Write over the header region with random bytes var randomBuffer = new byte[(int)memoryInformation.RegionSize]; new Random().NextBytes(randomBuffer); injectionProperties.MemoryManager.WriteVirtualMemory(module.BaseAddress, randomBuffer); return(true); }
private void MapSections(InjectionProperties injectionProperties, IntPtr localDllAddress, IntPtr remoteDllAddress) { foreach (var section in injectionProperties.PeParser.GetHeaders().SectionHeaders) { // Get the data of the section var sectionDataAddress = localDllAddress.AddOffset(section.PointerToRawData); var sectionData = new byte[section.SizeOfRawData]; Marshal.Copy(sectionDataAddress, sectionData, 0, (int)section.SizeOfRawData); // Write the section into the target process var sectionAddress = remoteDllAddress.AddOffset(section.VirtualAddress); injectionProperties.MemoryManager.WriteVirtualMemory(sectionAddress, sectionData); // Adjust the protection of the section var sectionProtection = GetSectionProtection(section.Characteristics); injectionProperties.MemoryManager.ProtectVirtualMemory(sectionAddress, (int)section.SizeOfRawData, sectionProtection); } }
public bool Call(InjectionProperties injectionProperties) { // Get the address of the LoadLibraryW function in the target process var loadLibraryAddress = injectionProperties.RemoteProcess.GetFunctionAddress("kernel32.dll", "LoadLibraryW"); // Write the DLL path into the target process var dllPathBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, injectionProperties.DllPath.Length, Native.Enumerations.MemoryProtectionType.ExecuteReadWrite); var dllPathBytes = Encoding.Unicode.GetBytes(injectionProperties.DllPath); injectionProperties.MemoryManager.WriteVirtualMemory(dllPathBuffer, dllPathBytes); foreach (var thread in injectionProperties.RemoteProcess.TargetProcess.Threads.Cast <ProcessThread>()) { using (var threadHandle = (SafeThreadHandle)injectionProperties.SyscallManager.InvokeSyscall <NtOpenThread>(thread.Id)) { // Add an APC to call LoadLibraryW to the APC queue of the thread injectionProperties.SyscallManager.InvokeSyscall <NtQueueApcThread>(threadHandle, loadLibraryAddress, dllPathBuffer); } } injectionProperties.MemoryManager.FreeVirtualMemory(dllPathBuffer); return(true); }
public bool Call(InjectionProperties injectionProperties) { // Get the address of the LoadLibraryW function in the target process var loadLibraryAddress = injectionProperties.RemoteProcess.GetFunctionAddress("kernel32.dll", "LoadLibraryW"); // Write the DLL path into the target process var dllPathBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, injectionProperties.DllPath.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); var dllPathBytes = Encoding.Unicode.GetBytes(injectionProperties.DllPath); injectionProperties.MemoryManager.WriteVirtualMemory(dllPathBuffer, dllPathBytes); // Create a thread to call LoadLibraryW in the target process var remoteThreadHandle = (SafeThreadHandle)injectionProperties.SyscallManager.InvokeSyscall <NtCreateThreadEx>(injectionProperties.RemoteProcess.Handle, loadLibraryAddress, dllPathBuffer); PInvoke.WaitForSingleObject(remoteThreadHandle, uint.MaxValue); injectionProperties.MemoryManager.FreeVirtualMemory(dllPathBuffer); remoteThreadHandle.Dispose(); return(true); }
internal InjectionManager(int targetProcessId, string dllPath, bool isExtension, bool randomiseDllName) { // Ensure the users operating system is valid ValidationHandler.ValidateOperatingSystem(); // Ensure the arguments passed in are valid if (targetProcessId <= 0 || string.IsNullOrWhiteSpace(dllPath)) { throw new ArgumentException("One or more of the arguments provided were invalid"); } // Ensure a valid DLL exists at the provided path if (!File.Exists(dllPath) || Path.GetExtension(dllPath) != ".dll") { throw new ArgumentException("No DLL file exists at the provided path"); } if (randomiseDllName && isExtension) { // Assume the DLL is the newest file in the directory var directoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "Bleak")); var newestFile = directoryInfo.GetFiles().OrderByDescending(file => file.LastWriteTime).First(); _injectionProperties = new InjectionProperties(targetProcessId, newestFile.FullName); } else if (randomiseDllName) { // Create a temporary DLL on disk var temporaryDllPath = DllTools.CreateTemporaryDll(DllTools.GenerateRandomDllName(), File.ReadAllBytes(dllPath)); _injectionProperties = new InjectionProperties(targetProcessId, temporaryDllPath); } else { _injectionProperties = new InjectionProperties(targetProcessId, dllPath); } // Ensure the architecture of the DLL is valid ValidationHandler.ValidateDllArchitecture(_injectionProperties); }
internal static void ValidateDllArchitecture(InjectionProperties injectionProperties) { // Ensure the architecture of the target process matches the architecture of the DLL if (injectionProperties.RemoteProcess.IsWow64 != (injectionProperties.PeParser.GetArchitecture() == Enumerations.MachineType.X86)) { throw new ApplicationException("The architecture of the target process did not match the architecture of the DLL"); } // Ensure that x64 injection is not being attempted from an x86 build if (!Environment.Is64BitProcess && !injectionProperties.RemoteProcess.IsWow64) { throw new ApplicationException("x64 injection is not supported when compiled under x86"); } }
internal InjectionManager(int targetProcessId, byte[] dllBytes, bool manualMap, bool isExtension, bool randomiseDllName) { // Ensure the users operating system is valid ValidationHandler.ValidateOperatingSystem(); // Ensure the arguments passed in are valid if (targetProcessId <= 0 || dllBytes is null || dllBytes.Length == 0) { throw new ArgumentException("One or more of the arguments provided were invalid"); } if (manualMap) { _injectionProperties = new InjectionProperties(targetProcessId, dllBytes); } else if (randomiseDllName && isExtension) { // Assume the DLL is the newest file in the directory var directoryInfo = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "Bleak")); var newestFile = directoryInfo.GetFiles().OrderByDescending(file => file.LastWriteTime).First(); _injectionProperties = new InjectionProperties(targetProcessId, newestFile.FullName); } else { // Create a temporary DLL on disk var temporaryDllName = randomiseDllName ? DllTools.GenerateRandomDllName() : DllTools.GenerateDllName(dllBytes); _injectionProperties = new InjectionProperties(targetProcessId, DllTools.CreateTemporaryDll(temporaryDllName, dllBytes)); } // Ensure the architecture of the DLL is valid ValidationHandler.ValidateDllArchitecture(_injectionProperties); }
private void MapHeaders(InjectionProperties injectionProperties, IntPtr remoteDllAddress) { // Determine the size of the PE headers of the DLL var headerSize = injectionProperties.RemoteProcess.IsWow64 ? injectionProperties.PeParser.GetHeaders().NtHeaders32.OptionalHeader.SizeOfHeaders : injectionProperties.PeParser.GetHeaders().NtHeaders64.OptionalHeader.SizeOfHeaders; var headerBytes = new byte[headerSize]; // Fill the header bytes with random bytes new Random().NextBytes(headerBytes); // Write the PE headers into the target process injectionProperties.MemoryManager.WriteVirtualMemory(remoteDllAddress, headerBytes); // Adjust the protection of the PE header region injectionProperties.MemoryManager.ProtectVirtualMemory(remoteDllAddress, (int)headerSize, Enumerations.MemoryProtectionType.ReadOnly); }
private void RemoveDoublyLinkedListEntry(InjectionProperties injectionProperties, Structures.ListEntry64 entry) { // Read the previous entry from the doubly linked list var previousEntry = injectionProperties.MemoryManager.ReadVirtualMemory <Structures.ListEntry64>((IntPtr)entry.Blink); // Change the front link of the previous entry to the front link of the entry previousEntry.Flink = entry.Flink; injectionProperties.MemoryManager.WriteVirtualMemory((IntPtr)entry.Blink, previousEntry); // Read the next entry from the doubly linked list var nextEntry = injectionProperties.MemoryManager.ReadVirtualMemory <Structures.ListEntry64>((IntPtr)entry.Flink); // Change the back link of the next entry to the back link of the entry nextEntry.Blink = entry.Blink; injectionProperties.MemoryManager.WriteVirtualMemory((IntPtr)entry.Flink, nextEntry); }
private void CallEntryPoint(InjectionProperties injectionProperties, IntPtr remoteDllAddress, IntPtr entryPointAddress) { // Write the shellcode used to call the entry point of the DLL or TLS callback in the target process var shellcode = injectionProperties.RemoteProcess.IsWow64 ? CallDllMainX86.GetShellcode(remoteDllAddress, entryPointAddress) : CallDllMainX64.GetShellcode(remoteDllAddress, entryPointAddress); var shellcodeBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, shellcode.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); injectionProperties.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode); // Create a thread to call the shellcode in the target process var remoteThreadHandle = (SafeThreadHandle)injectionProperties.SyscallManager.InvokeSyscall <NtCreateThreadEx>(injectionProperties.RemoteProcess.Handle, shellcodeBuffer, IntPtr.Zero); PInvoke.WaitForSingleObject(remoteThreadHandle, uint.MaxValue); injectionProperties.MemoryManager.FreeVirtualMemory(shellcodeBuffer); remoteThreadHandle.Dispose(); }
private void BuildImportTable(InjectionProperties injectionProperties, IntPtr localDllAddress) { var importedFunctions = injectionProperties.PeParser.GetImportedFunctions(); if (importedFunctions.Count == 0) { // The DLL has no imported functions return; } // Group the imported functions by the DLL they reside in var groupedFunctions = importedFunctions.GroupBy(importedFunction => importedFunction.DllName).ToList(); // Get the API set mappings List <ApiSetMapping> apiSetMappings; using (var peParser = new PeParser(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "apisetschema.dll"))) { apiSetMappings = peParser.GetApiSetMappings(); } var systemFolderPath = injectionProperties.RemoteProcess.IsWow64 ? Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) : Environment.GetFolderPath(Environment.SpecialFolder.System); foreach (var dll in groupedFunctions) { var dllName = dll.Key; if (dllName.StartsWith("api-ms")) { dllName = apiSetMappings.Find(apiSetMapping => apiSetMapping.VirtualDll.Equals(dllName, StringComparison.OrdinalIgnoreCase)).MappedToDll; } // Ensure the DLL is loaded in the target process if (!injectionProperties.RemoteProcess.Modules.Any(module => module.Name.Equals(dllName, StringComparison.OrdinalIgnoreCase))) { // Load the DLL into the target process new Injector().CreateRemoteThread(injectionProperties.RemoteProcess.TargetProcess.Id, Path.Combine(systemFolderPath, dllName)); } } injectionProperties.RemoteProcess.Refresh(); foreach (var importedFunction in groupedFunctions.SelectMany(dll => dll.Select(importedFunction => importedFunction))) { var dllName = importedFunction.DllName; if (dllName.StartsWith("api-ms")) { dllName = apiSetMappings.Find(apiSetMapping => apiSetMapping.VirtualDll.Equals(dllName, StringComparison.OrdinalIgnoreCase)).MappedToDll; } // Get the address of the imported function var importedFunctionAddress = injectionProperties.RemoteProcess.GetFunctionAddress(dllName, importedFunction.Name); // Write the imported function into the local process Marshal.WriteInt64(localDllAddress.AddOffset(importedFunction.Offset), (long)importedFunctionAddress); } }
private void PerformRelocations(InjectionProperties injectionProperties, IntPtr localDllAddress, IntPtr remoteDllAddress) { var baseRelocations = injectionProperties.PeParser.GetBaseRelocations(); if (baseRelocations.Count == 0) { // No relocations need to be applied return; } var peHeaders = injectionProperties.PeParser.GetHeaders(); var baseAddress = injectionProperties.RemoteProcess.IsWow64 ? peHeaders.NtHeaders32.OptionalHeader.ImageBase : peHeaders.NtHeaders64.OptionalHeader.ImageBase; // Calculate the base address delta var delta = (long)remoteDllAddress - (long)baseAddress; if (delta == 0) { // The DLL is loaded at its default base address and no relocations need to be applied return; } foreach (var baseRelocation in baseRelocations) { // Calculate the base address of the relocation block var relocationBlockAddress = localDllAddress.AddOffset(baseRelocation.Offset); foreach (var relocation in baseRelocation.Relocations) { // Calculate the address of the relocation var relocationAddress = relocationBlockAddress.AddOffset(relocation.Offset); switch (relocation.Type) { case Enumerations.RelocationType.HighLow: { // Perform the relocation var relocationValue = Marshal.ReadInt32(relocationAddress) + (int)delta; Marshal.WriteInt32(relocationAddress, relocationValue); break; } case Enumerations.RelocationType.Dir64: { // Perform the relocation var relocationValue = Marshal.ReadInt64(relocationAddress) + delta; Marshal.WriteInt64(relocationAddress, relocationValue); break; } } } } }
public bool Call(InjectionProperties injectionProperties) { var localDllAddress = injectionProperties.DllPath is null ? LocalMemoryTools.StoreBytesInBuffer(injectionProperties.DllBytes) : LocalMemoryTools.StoreBytesInBuffer(File.ReadAllBytes(injectionProperties.DllPath)); // Build the import table of the DLL BuildImportTable(injectionProperties, localDllAddress); var peHeaders = injectionProperties.PeParser.GetHeaders(); // Allocate memory for the DLL in the target process var allocationBaseAddress = injectionProperties.RemoteProcess.IsWow64 ? peHeaders.NtHeaders32.OptionalHeader.ImageBase : peHeaders.NtHeaders64.OptionalHeader.ImageBase; var dllSize = injectionProperties.RemoteProcess.IsWow64 ? peHeaders.NtHeaders32.OptionalHeader.SizeOfImage : peHeaders.NtHeaders64.OptionalHeader.SizeOfImage; IntPtr remoteDllAddress; try { remoteDllAddress = injectionProperties.MemoryManager.AllocateVirtualMemory((IntPtr)allocationBaseAddress, (int)dllSize, Enumerations.MemoryProtectionType.ExecuteReadWrite); } catch (Win32Exception) { remoteDllAddress = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, (int)dllSize, Enumerations.MemoryProtectionType.ExecuteReadWrite); } // Perform any needed relocations PerformRelocations(injectionProperties, localDllAddress, remoteDllAddress); // Map the sections of the DLL MapSections(injectionProperties, localDllAddress, remoteDllAddress); // Map randomised PE headers MapHeaders(injectionProperties, remoteDllAddress); // Call any TLS callbacks CallTlsCallbacks(injectionProperties, remoteDllAddress); // Call the entry point of the DLL var dllEntryPointAddress = injectionProperties.RemoteProcess.IsWow64 ? remoteDllAddress.AddOffset(peHeaders.NtHeaders32.OptionalHeader.AddressOfEntryPoint) : remoteDllAddress.AddOffset(peHeaders.NtHeaders64.OptionalHeader.AddressOfEntryPoint); if (dllEntryPointAddress != remoteDllAddress) { CallEntryPoint(injectionProperties, remoteDllAddress, dllEntryPointAddress); } LocalMemoryTools.FreeMemoryForBuffer(localDllAddress); return(true); }
public bool Call(InjectionProperties injectionProperties) { // Get the address of the LoadLibraryW function in the target process var loadLibraryAddress = injectionProperties.RemoteProcess.GetFunctionAddress("kernel32.dll", "LoadLibraryW"); // Write the DLL path into the target process var dllPathBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, injectionProperties.DllPath.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); var dllPathBytes = Encoding.Unicode.GetBytes(injectionProperties.DllPath); injectionProperties.MemoryManager.WriteVirtualMemory(dllPathBuffer, dllPathBytes); // Open a handle to the first thread in the target process var threadHandle = (SafeThreadHandle)injectionProperties.SyscallManager.InvokeSyscall <NtOpenThread>(injectionProperties.RemoteProcess.TargetProcess.Threads[0].Id); if (injectionProperties.RemoteProcess.IsWow64) { // Suspend the thread if (PInvoke.Wow64SuspendThread(threadHandle) == -1) { ExceptionHandler.ThrowWin32Exception("Failed to suspend a thread in the target process"); } // Get the context of the thread var threadContextBuffer = LocalMemoryTools.StoreStructureInBuffer(new Structures.Wow64Context { ContextFlags = Enumerations.ContextFlags.Control }); if (PInvoke.Wow64GetThreadContext(threadHandle, threadContextBuffer) == 0) { ExceptionHandler.ThrowWin32Exception("Failed to get the context of a thread in the target process"); } var threadContext = Marshal.PtrToStructure <Structures.Wow64Context>(threadContextBuffer); LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer); // Write the shellcode used to call LoadLibraryW from the thread into the target process var shellcode = ThreadHijackX86.GetShellcode((IntPtr)threadContext.Eip, dllPathBuffer, loadLibraryAddress); var shellcodeBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, shellcode.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); injectionProperties.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode); // Overwrite the instruction pointer of the thread with the address of the shellcode buffer threadContext.Eip = (uint)shellcodeBuffer; threadContextBuffer = LocalMemoryTools.StoreStructureInBuffer(threadContext); // Update the context of the thread if (PInvoke.Wow64SetThreadContext(threadHandle, threadContextBuffer) == 0) { ExceptionHandler.ThrowWin32Exception("Failed to set the context of a thread in the target process"); } LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer); } else { // Suspend the thread injectionProperties.SyscallManager.InvokeSyscall <NtSuspendThread>(threadHandle); // Get the context of the thread var threadContextBuffer = (IntPtr)injectionProperties.SyscallManager.InvokeSyscall <NtGetContextThread>(threadHandle); var threadContext = Marshal.PtrToStructure <Structures.Context>(threadContextBuffer); LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer); // Write the shellcode used to call LoadLibraryW from the thread into the target process var shellcode = ThreadHijackX64.GetShellcode((IntPtr)threadContext.Rip, dllPathBuffer, loadLibraryAddress); var shellcodeBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, shellcode.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); injectionProperties.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode); // Overwrite the instruction pointer of the thread with the address of the shellcode buffer threadContext.Rip = (ulong)shellcodeBuffer; threadContextBuffer = LocalMemoryTools.StoreStructureInBuffer(threadContext); // Update the context of the thread injectionProperties.SyscallManager.InvokeSyscall <NtSetContextThread>(threadHandle, threadContextBuffer); LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer); } // Resume the thread injectionProperties.SyscallManager.InvokeSyscall <NtResumeThread>(threadHandle); PInvoke.SwitchToThisWindow(injectionProperties.RemoteProcess.TargetProcess.MainWindowHandle, true); threadHandle.Dispose(); return(true); }
public bool Call(InjectionProperties injectionProperties) { var dllUnlinked = false; if (injectionProperties.RemoteProcess.IsWow64) { var entryFilePathRegex = new Regex("System32", RegexOptions.IgnoreCase); foreach (var entry in injectionProperties.RemoteProcess.GetWow64PebEntries()) { // Read the file path of the entry var entryFilePathBytes = injectionProperties.MemoryManager.ReadVirtualMemory((IntPtr)entry.FullDllName.Buffer, entry.FullDllName.Length); var entryFilePath = entryFilePathRegex.Replace(Encoding.Unicode.GetString(entryFilePathBytes), "SysWOW64"); if (entryFilePath.Equals(injectionProperties.DllPath, StringComparison.OrdinalIgnoreCase)) { // Remove the entry from the doubly linked lists RemoveDoublyLinkedListEntry(injectionProperties, entry.InLoadOrderLinks); RemoveDoublyLinkedListEntry(injectionProperties, entry.InMemoryOrderLinks); RemoveDoublyLinkedListEntry(injectionProperties, entry.InInitializationOrderLinks); // Remove the entry from the LdrpHashTable RemoveDoublyLinkedListEntry(injectionProperties, entry.HashLinks); // Write over the entry strings with zeroes injectionProperties.MemoryManager.WriteVirtualMemory((IntPtr)entry.BaseDllName.Buffer, new byte[entry.BaseDllName.MaximumLength]); injectionProperties.MemoryManager.WriteVirtualMemory((IntPtr)entry.FullDllName.Buffer, new byte[entry.FullDllName.MaximumLength]); dllUnlinked = true; break; } } } else { foreach (var entry in injectionProperties.RemoteProcess.GetPebEntries()) { // Read the file path of the entry var entryFilePathBytes = injectionProperties.MemoryManager.ReadVirtualMemory((IntPtr)entry.FullDllName.Buffer, entry.FullDllName.Length); var entryFilePath = Encoding.Unicode.GetString(entryFilePathBytes); if (entryFilePath.Equals(injectionProperties.DllPath, StringComparison.OrdinalIgnoreCase)) { // Remove the entry from the doubly linked lists RemoveDoublyLinkedListEntry(injectionProperties, entry.InLoadOrderLinks); RemoveDoublyLinkedListEntry(injectionProperties, entry.InMemoryOrderLinks); RemoveDoublyLinkedListEntry(injectionProperties, entry.InInitializationOrderLinks); // Remove the entry from the LdrpHashTable RemoveDoublyLinkedListEntry(injectionProperties, entry.HashLinks); // Write over the entry strings with zeroes injectionProperties.MemoryManager.WriteVirtualMemory((IntPtr)entry.BaseDllName.Buffer, new byte[entry.BaseDllName.MaximumLength]); injectionProperties.MemoryManager.WriteVirtualMemory((IntPtr)entry.FullDllName.Buffer, new byte[entry.FullDllName.MaximumLength]); dllUnlinked = true; break; } } } if (!dllUnlinked) { throw new ArgumentException($"No DLL with the name {Path.GetFileName(injectionProperties.DllPath)} was found in the target processes module list"); } return(true); }