Я пытаюсь вызвать FreeLibraryAndExitThread извне в другом процессе (используя CreateRemoteThread), чтобы я мог выгрузить модуль, загруженный извне, через LoadLibrary.
Я понимаю, что хотя CreateRemoteThread принимает 1 параметр, вы можете предоставить ему структуру из нескольких аргументов, если вам нужно более одного.
Если вы попробовали следующее, которое не выгрузило модуль. На самом деле это, казалось, ничего не делает.
Примечание. Я удалил все проверки ошибок, чтобы сделать этот пост простым и коротким
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetProcAddress(IntPtr moduleHandle, string procName);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr VirtualAllocEx(IntPtr processHandle, IntPtr baseAddress, int size, int allocationType, int protection);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool WriteProcessMemory(IntPtr processHandle, IntPtr baseAddress, byte[] buffer, int size, int bytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr CreateRemoteThread(IntPtr processHandle, IntPtr threadAttributes, int stackSize, IntPtr startAddress, IntPtr parameter, int creationFlags, int threadId);
private struct FreeLibraryAndExitThreadParameters
{
internal IntPtr ModuleAddress;
internal int ExitCode;
}
var process = Process.GetProcessesByName("notepad")[0];
var freeLibraryAndExitThreadAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "FreeLibraryAndExitThread");
// Get an instance of the module - dllName is the name of the module I am trying to unload
var module = process.Modules.Cast<ProcessModule>().SingleOrDefault(m => string.Equals(m.ModuleName, dllName, StringComparison.OrdinalIgnoreCase));
var freeLibraryAndExitThreadParameters = new FreeLibraryAndExitThreadParameters { ModuleAddress = module.BaseAddress, ExitCode = 0 };
// This code turns the struct into a byte array
var structureSize = Marshal.SizeOf(freeLibraryAndExitThreadParameters);
var structureBytes = new byte[structureSize];
var buffer = Marshal.AllocHGlobal(structureSize);
Marshal.StructureToPtr(freeLibraryAndExitThreadParameters, buffer, true);
Marshal.Copy(buffer, structureBytes, 0, structureSize);
Marshal.FreeHGlobal(buffer);
// Allocate memory in the remote process with commit and reserve allocation type and PageExecuteReadWrite permissions
var remoteAddress = VirtualAllocEx(process.Handle, IntPtr.Zero, structureSize, 0x01000 | 0x02000, 0x040);
// Write the structure into the remote process
WriteProcessMemory(process.Handle, remoteAddress, buffer, structureSize, 0);
// Finally call CreateRemoteThread to execute the function in the remote process
CreateRemoteThread(process.Handle, IntPtr.Zero, 0, freeLibraryAndExitThreadAddress, remoteAddress, 0, 0);
Ни один из вызовов pinvoke на самом деле не работает, и я вижу, что байты записываются в память, но, кажется, ничего не происходит после создания удаленного потока. В моем реальном коде я вызываю WaitForSingleObject, и поток завершает свою задачу также нет проблем.
Может ли кто-нибудь указать, что я делаю неправильно и как я могу исправить эту проблему, чтобы я мог внешне вызвать FreeLibraryAndExitThread в удаленном процессе?
Возможно, стоит упомянуть, что я могу использовать FreeLibrary с этим методом - он работает нормально (удаляя структуру, так как она принимает только 1 параметр), но мне специально нужно использовать FreeLibraryAndExitThread для модуля, который мне нужно выгрузить, поэтому я не используется более простая FreeLibrary.