5,389
社区成员
发帖
与我相关
我的任务
分享
uses
PSAPI,Tlhelp32;
type
_THREADINFOCLASS = (
ThreadBasicInformation,
ThreadTimes,
ThreadPriority,
ThreadBasePriority,
ThreadAffinityMask,
ThreadImpersonationToken,
ThreadDescriptorTableEntry,
ThreadEnableAlignmentFaultFixup,
ThreadEventPair_Reusable,
ThreadQuerySetWin32StartAddress,
ThreadZeroTlsCell,
ThreadPerformanceCount,
ThreadAmILastThread,
ThreadIdealProcessor,
ThreadPriorityBoost,
ThreadSetTlsArrayAddress,
ThreadIsIoPending,
ThreadHideFromDebugger,
ThreadBreakOnTermination,
MaxThreadInfoClass
);
THREADINFOCLASS = _THREADINFOCLASS;
_CLIENT_ID = record
UniqueProcess:THANDLE;
UniqueThread:THANDLE;
end;
CLIENT_ID = _CLIENT_ID;
PCLIENT_ID = ^CLIENT_ID;
_THREAD_BASIC_INFORMATION = record // Information Class 0
ExitStatus: LONGINT;
TebBaseAddress:Pointer;
ClientId:CLIENT_ID;
AffinityMask:LONGINT;
Priority:LONGINT;
BasePriority:LONGInt;
end;
THREAD_BASIC_INFORMATION = _THREAD_BASIC_INFORMATION;
PTHREAD_BASIC_INFORMATION = ^_THREAD_BASIC_INFORMATION;
TZwQueryInformationThread = function (
ThreadHandle: THANDLE;
ThreadInformationClass:THREADINFOCLASS;
ThreadInformation:Pointer;
ThreadInformationLength:LongWord;
ReturnLength:PULONG
) : LongInt;stdcall;
TRtlNtStatusToDosError = function (status: LongWord):LongInt;
function OpenThread(
dwDesiredAccess:DWORD;
bInheritHandle:BOOL;
dwThreadId:DWORD
):Thandle;stdcall; external kernel32 name 'OpenThread';
var
ZwQueryInformationThread:TZwQueryInformationThread = Nil;
RtlNtStatusToDosError:TRtlNtStatusToDosError = Nil;
function ShowThreadInfo(dwThreadID:DWORD;Memo: TStrings):LongBool;
var
tbi:THREAD_BASIC_INFORMATION;
startaddr:Pointer;
status: LongInt;
thread,process: THandle;
error: DWORD;
modname: String;
begin
Result := false;
thread := OpenThread($1fffff(*THREAD_ALL_ACCESS*), FALSE, dwThreadID);
if Thread = 0 then Exit;
status := ZwQueryInformationThread(thread,
ThreadQuerySetWin32StartAddress,
@startaddr,
sizeof(startaddr),
NIL);
if status < 0 then
begin
CloseHandle(thread);
SetLastError(RtlNtStatusToDosError(status));
Exit;
end;
Memo.Add(Format('线程 %08x 的起始地址为 %p',[dwThreadID,startaddr]));
status := ZwQueryInformationThread(thread,
ThreadBasicInformation,
@tbi,
sizeof(tbi),
NIL);
if status < 0 then
begin
CloseHandle(thread);
SetLastError(RtlNtStatusToDosError(status));
Exit;
end;
Memo.Add(Format('线程 %08x 所在进程ID为 %08x',[dwThreadID,LongWord(tbi.ClientId.UniqueProcess)]));
process := OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
DWORD(tbi.ClientId.UniqueProcess));
if process = 0 then
begin
error := GetLastError;
CloseHandle(thread);
SetLastError(error);
Exit;
end;
SetLength(modname,$100);
SetLength(modname,GetModuleFileNameEx(process,0,PChar(modname),$100));
Memo.Add(Format('线程 %08x 所在进程映象为 %s',[dwThreadID,modname]));
SetLength(modname,$100);
SetLength(modname,GetMappedFileName(process,
startaddr,
PChar(modname),
$100));
Memo.Add(Format('线程 %08x 可执行代码所在模块为 %s',[dwThreadID,modname]));
CloseHandle(process);
CloseHandle(thread);
Result := TRUE;
end;
procedure TForm3.Button1Click(Sender: TObject);
var
hNTDLL:HMODULE;
hSnapshot: THandle;
lpTE:THREADENTRY32;
begin
hNTDLL := GetModuleHandle('NTDLL');
if hNTDLL = 0 then
begin
Memo1.Lines.Add('GetModuleHandle(NTDLL) failed!');
Exit;
end;
ZwQueryInformationThread := GetProcAddress(hNTDLL,'ZwQueryInformationThread');
RtlNtStatusToDosError := GetProcAddress(hNTDLL,'RtlNtStatusToDosError');
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
lpTE.dwSize := sizeof(lpTE);
if Thread32First(hSnapshot,lpTE) then
begin
Memo1.Lines.BeginUpdate;
try
Repeat
if Not ShowThreadInfo(lpTE.th32ThreadID,Memo1.Lines) then
Memo1.Lines.Add(Format('无法获得线程 %08x 的相关信息,错误代码为 %d',[lpTE.th32ThreadID,GetLastError]));
Until Not Thread32Next(hSnapshot,lpTE);
finally
Memo1.Lines.EndUpdate;
end;
end;
CloseHandle(hSnapshot);
end;