如何匹配线程的起始地址和模块名称?

时间:2016-12-28 13:35:40

标签: delphi delphi-10.1-berlin

我正在尝试关闭属于特定模块名称的线程。到目前为止,我可以在进程中获取线程的起始地址,但不知道如何将其与特定模块名称相匹配。如何才能做到这一点?

program Project1;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  Winapi.Windows,
  TlHelp32;

type
  HANDLE = NativeUInt;

type
  _THREADINFOCLASS = DWORD;
  THREADINFOCLASS = _THREADINFOCLASS;

type
  NTSTATUS = LONGWORD;

const 
  ThreadQuerySetWin32StartAddress = 9;

  THREAD_QUERY_INFORMATION   = $0040;
  STATUS_SUCCESS             = $00000000;

function OpenThread(
  dwDesiredAccess: DWORD;
  bInheritHandle: BOOL;
  dwThreadId: DWORD
): DWORD; WINAPI; external 'Kernel32.dll' name 'OpenThread';

function GetShellWindow: HWND; WINAPI; external 'User32.dll' name 'GetShellWindow';

function NtQueryInformationThread(
  ThreadHandle: HANDLE;
  ThreadInformationClass: THREADINFOCLASS;
  ThreadInformation: PVOID;
  ThreadInformationLength: ULONG;
  ReturnLength: PULONG
): NTSTATUS; WINAPI; external 'Ntdll.dll' name 'NtQueryInformationThread';

function GetThreadStartAddress(ThreadID: DWORD): Pointer;
var
  hThread: HANDLE;
begin
  Result := 0;
  hThread := OpenThread(THREAD_QUERY_INFORMATION, False, ThreadID);
  if hThread > 0 then
  NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, @Result, SizeOf(Result), nil);
  CloseHandle(hThread);
end;

var
  PId: Cardinal;
  hSnapshot: HANDLE;
  ThreadEntry: THREADENTRY32;
  ThreadStartAddr: Pointer;
begin
  GetWindowThreadProcessId(GetShellWindow, PId);

  hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, PId);

  ThreadEntry.dwSize := sizeof(THREADENTRY32);
  ThreadEntry.cntUsage := 0;

  Thread32First(hSnapshot, ThreadEntry);
  repeat
    if ThreadEntry.th32OwnerProcessID = PId then
    begin
      ThreadStartAddr := GetThreadStartAddress(ThreadEntry.th32ThreadID);
      // Match ThreadStartAddr to module name (kernel32.dll etc)?
    end;
  until not Thread32Next(hSnapshot, ThreadEntry);

  Readln;
end.

1 个答案:

答案 0 :(得分:2)

此处描述了一种方式:https://msdn.microsoft.com/en-us/library/windows/desktop/ms684232.aspx

总结:

  1. 调用EnumProcessModules枚举加载到流程中的模块。
  2. 为每个模块调用GetModuleInformation以获取模块的加载地址和线性地址大小。如果您的地址位于该地址范围内,则这是目标模块。
  3. 另一种方法是使用工具帮助API枚举流程中的模块,从而找到相同的信息。在致电TH32CS_SNAPMODULE时,您会使用CreateToolhelp32Snapshot