Вызов FreeLibraryAndExitThread извне для удаленного процесса - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь вызвать 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.

1 Ответ

0 голосов
/ 16 января 2019

формально это просто, все что нам нужно

CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)FreeLibraryAndExitThread, hmod, 0, 0)

где hmod - адрес модуля в удаленном процессе. адрес FreeLibraryAndExitThread может быть взят из текущего процесса kernel32!FreeLibraryAndExitThread - до тех пор, пока kernel32.dll не будет загружен по одному базовому адресу во всех процессах.

, что

DECLSPEC_NORETURN
VOID
WINAPI
FreeLibraryAndExitThread(
    _In_ HMODULE hLibModule,
    _In_ DWORD dwExitCode
    );

принять 2 параметра в конкретном случае без проблем. в результате вызова - CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)FreeLibraryAndExitThread, hmod, 0, 0) FreeLibraryAndExitThread будет вызываться через stdcal l (WINAPI) соглашение о вызовах с одним параметром - hmod. второй параметр dwExitCode в этом случае будет неопределенным, но он не играет никакой роли - любой код возврата потока в порядке. Система не интерпретирует это значение. и потому, что этот конкретный API никогда не вернется - разные по количеству параметров также не играют роли.

еще один вопрос - для чего, какой смысл выгружать модуль в удаленный процесс. и если модуль действительно будет выгружен (счетчик загрузки модуля FreeLibrary уменьшает только вызов, поэтому модуль не всегда будет выгружен во время этого вызова), и после этого некоторый код в коде вызова удаленного процесса модуля выгрузки - думаю, не нужно объяснять, что является быть в этом случае

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...