How to match start address of a thread to a module name?

1k views Asked by At

I am trying to close a thread that belongs to a particular module name. So far I can get the start address of a thread in a process but don't know how to match it to a specific module name. How can this be done?

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

There are 1 answers

3
David Heffernan On

One way is described here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684232.aspx

In summary:

  1. Call EnumProcessModules to enumerate the modules loaded into the process.
  2. For each module call GetModuleInformation to obtain the load address and linear address size of the module. If your address lies in that range of addresses then this is the target module.

Yet another way would be to use the tool help API to enumerate the modules in the process and so find the same information. You would use TH32CS_SNAPMODULE when calling CreateToolhelp32Snapshot.