有关线程的一些函数
1. 根据线程ID找出其所在的模块名
#define
WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x400
#include < stdio.h >
#include < tchar.h >
#include < locale.h >
#include < windows.h >
#include < psapi.h >
#pragma comment(lib, " psapi.lib " )
#include < Tlhelp32.h >
//
// Thread Information Classes
//
typedef enum _THREADINFOCLASS {
ThreadBasicInformation,
ThreadTimes,
ThreadPriority,
ThreadBasePriority,
ThreadAffinityMask,
ThreadImpersonationToken,
ThreadDescriptorTableEntry,
ThreadEnableAlignmentFaultFixup,
ThreadEventPair_Reusable,
ThreadQuerySetWin32StartAddress,
ThreadZeroTlsCell,
ThreadPerformanceCount,
ThreadAmILastThread,
ThreadIdealProcessor,
ThreadPriorityBoost,
ThreadSetTlsArrayAddress,
ThreadIsIoPending,
ThreadHideFromDebugger,
ThreadBreakOnTermination,
MaxThreadInfoClass
} THREADINFOCLASS;
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID * PCLIENT_ID;
typedef struct _THREAD_BASIC_INFORMATION { // Information Class 0
LONG ExitStatus;
PVOID TebBaseAddress;
CLIENT_ID ClientId;
LONG AffinityMask;
LONG Priority;
LONG BasePriority;
} THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION;
typedef LONG (__stdcall * PFN_ZwQueryInformationThread)(
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
typedef LONG (__stdcall * PFN_RtlNtStatusToDosError)(IN ULONG status);
typedef DWORD (__stdcall * PFN_RtlGetLastWin32Error)();
EXTERN_C PFN_ZwQueryInformationThread pfn_ZwQueryInformationThread = NULL;
EXTERN_C PFN_RtlNtStatusToDosError pfn_RtlNtStatusToDosError = NULL;
EXTERN_C PFN_RtlGetLastWin32Error pfn_RtlGetLastWin32Error = NULL;
BOOL ShowThreadInfo (DWORD tid)
{
THREAD_BASIC_INFORMATION tbi = { 0 };
PVOID startaddr = NULL;
LONG status = 0 ;
HANDLE hThread = NULL, process = NULL;
TCHAR modname [ 0x100 ] = { 0 };
BOOL bResult = FALSE;
do
{
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
if (hThread == NULL) {
SetLastError(pfn_RtlGetLastWin32Error());
break ;
}
status = pfn_ZwQueryInformationThread (hThread,
ThreadQuerySetWin32StartAddress,
& startaddr,
sizeof (startaddr),
NULL);
if (status < 0 ) {
SetLastError(pfn_RtlNtStatusToDosError(status));
break ;
};
_tprintf(TEXT( " Thread %08x start address is %p\n " ), tid, startaddr);
status = pfn_ZwQueryInformationThread(hThread,
ThreadBasicInformation,
& tbi,
sizeof (tbi),
NULL);
if (status < 0 )
{
SetLastError(pfn_RtlNtStatusToDosError(status));
break ;
};
_tprintf (TEXT ( " Thread %08x 's process ID is %08x\n " ),
tid,
(DWORD)tbi.ClientId.UniqueProcess);
process = OpenProcess (PROCESS_ALL_ACCESS,
FALSE,
(DWORD)tbi.ClientId.UniqueProcess);
if (process == NULL) {
SetLastError(pfn_RtlGetLastWin32Error());
break ;
};
GetModuleFileNameEx(process, NULL, modname, 0x100 );
_tprintf(TEXT( " Thread %08x Located in Process Image %s\n " ), tid, modname);
GetMappedFileName(process, startaddr, modname, 0x100 );
_tprintf(TEXT( " Thread %08x Located in module \ " % s\ " \n " ), tid, modname);
bResult = TRUE;
} while (FALSE);
if (process) {
CloseHandle(process);
}
if (hThread) {
CloseHandle(hThread);
}
return TRUE;
};
int main ( void )
{
HINSTANCE hNTDLL = NULL;
HANDLE h = NULL;
THREADENTRY32 te = { sizeof (te) };
setlocale(LC_ALL, " .ACP " );
hNTDLL = GetModuleHandle(TEXT( " ntdll " ));
pfn_ZwQueryInformationThread = (PFN_ZwQueryInformationThread)
GetProcAddress(hNTDLL, " ZwQueryInformationThread " );
pfn_RtlNtStatusToDosError = (PFN_RtlNtStatusToDosError)
GetProcAddress(hNTDLL, " RtlNtStatusToDosError " );
pfn_RtlGetLastWin32Error = (PFN_RtlGetLastWin32Error)
GetProcAddress(hNTDLL, " RtlGetLastWin32Error " );
h = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0 );
te.dwSize = sizeof (te);
if (Thread32First(h, & te))
{
do
{
if (ShowThreadInfo (te.th32ThreadID))
{
}
else
{
_tprintf(TEXT( " Can't get thread %08x information, Error code is %d\r\n " ),
te.th32ThreadID, GetLastError());
};
} while (Thread32Next (h, & te));
};
CloseHandle (h);
}
#define _WIN32_WINNT 0x400
#include < stdio.h >
#include < tchar.h >
#include < locale.h >
#include < windows.h >
#include < psapi.h >
#pragma comment(lib, " psapi.lib " )
#include < Tlhelp32.h >
//
// Thread Information Classes
//
typedef enum _THREADINFOCLASS {
ThreadBasicInformation,
ThreadTimes,
ThreadPriority,
ThreadBasePriority,
ThreadAffinityMask,
ThreadImpersonationToken,
ThreadDescriptorTableEntry,
ThreadEnableAlignmentFaultFixup,
ThreadEventPair_Reusable,
ThreadQuerySetWin32StartAddress,
ThreadZeroTlsCell,
ThreadPerformanceCount,
ThreadAmILastThread,
ThreadIdealProcessor,
ThreadPriorityBoost,
ThreadSetTlsArrayAddress,
ThreadIsIoPending,
ThreadHideFromDebugger,
ThreadBreakOnTermination,
MaxThreadInfoClass
} THREADINFOCLASS;
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID * PCLIENT_ID;
typedef struct _THREAD_BASIC_INFORMATION { // Information Class 0
LONG ExitStatus;
PVOID TebBaseAddress;
CLIENT_ID ClientId;
LONG AffinityMask;
LONG Priority;
LONG BasePriority;
} THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION;
typedef LONG (__stdcall * PFN_ZwQueryInformationThread)(
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
typedef LONG (__stdcall * PFN_RtlNtStatusToDosError)(IN ULONG status);
typedef DWORD (__stdcall * PFN_RtlGetLastWin32Error)();
EXTERN_C PFN_ZwQueryInformationThread pfn_ZwQueryInformationThread = NULL;
EXTERN_C PFN_RtlNtStatusToDosError pfn_RtlNtStatusToDosError = NULL;
EXTERN_C PFN_RtlGetLastWin32Error pfn_RtlGetLastWin32Error = NULL;
BOOL ShowThreadInfo (DWORD tid)
{
THREAD_BASIC_INFORMATION tbi = { 0 };
PVOID startaddr = NULL;
LONG status = 0 ;
HANDLE hThread = NULL, process = NULL;
TCHAR modname [ 0x100 ] = { 0 };
BOOL bResult = FALSE;
do
{
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
if (hThread == NULL) {
SetLastError(pfn_RtlGetLastWin32Error());
break ;
}
status = pfn_ZwQueryInformationThread (hThread,
ThreadQuerySetWin32StartAddress,
& startaddr,
sizeof (startaddr),
NULL);
if (status < 0 ) {
SetLastError(pfn_RtlNtStatusToDosError(status));
break ;
};
_tprintf(TEXT( " Thread %08x start address is %p\n " ), tid, startaddr);
status = pfn_ZwQueryInformationThread(hThread,
ThreadBasicInformation,
& tbi,
sizeof (tbi),
NULL);
if (status < 0 )
{
SetLastError(pfn_RtlNtStatusToDosError(status));
break ;
};
_tprintf (TEXT ( " Thread %08x 's process ID is %08x\n " ),
tid,
(DWORD)tbi.ClientId.UniqueProcess);
process = OpenProcess (PROCESS_ALL_ACCESS,
FALSE,
(DWORD)tbi.ClientId.UniqueProcess);
if (process == NULL) {
SetLastError(pfn_RtlGetLastWin32Error());
break ;
};
GetModuleFileNameEx(process, NULL, modname, 0x100 );
_tprintf(TEXT( " Thread %08x Located in Process Image %s\n " ), tid, modname);
GetMappedFileName(process, startaddr, modname, 0x100 );
_tprintf(TEXT( " Thread %08x Located in module \ " % s\ " \n " ), tid, modname);
bResult = TRUE;
} while (FALSE);
if (process) {
CloseHandle(process);
}
if (hThread) {
CloseHandle(hThread);
}
return TRUE;
};
int main ( void )
{
HINSTANCE hNTDLL = NULL;
HANDLE h = NULL;
THREADENTRY32 te = { sizeof (te) };
setlocale(LC_ALL, " .ACP " );
hNTDLL = GetModuleHandle(TEXT( " ntdll " ));
pfn_ZwQueryInformationThread = (PFN_ZwQueryInformationThread)
GetProcAddress(hNTDLL, " ZwQueryInformationThread " );
pfn_RtlNtStatusToDosError = (PFN_RtlNtStatusToDosError)
GetProcAddress(hNTDLL, " RtlNtStatusToDosError " );
pfn_RtlGetLastWin32Error = (PFN_RtlGetLastWin32Error)
GetProcAddress(hNTDLL, " RtlGetLastWin32Error " );
h = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0 );
te.dwSize = sizeof (te);
if (Thread32First(h, & te))
{
do
{
if (ShowThreadInfo (te.th32ThreadID))
{
}
else
{
_tprintf(TEXT( " Can't get thread %08x information, Error code is %d\r\n " ),
te.th32ThreadID, GetLastError());
};
} while (Thread32Next (h, & te));
};
CloseHandle (h);
}
2. 获取线程当前状态, 是挂起还是终止, 没有直接的 API. 这段代码比较实用
#include
<
stdio.h
>
#include < windows.h >
#include < winbase.h >
#include < ntsecapi.h >
#define UNICODE
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_SUCCESS ((NTSTATUS) 0x00000000)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004)
#define SystemProcessesAndThreadsInformation 5
#define NTAPI __stdcall
typedef enum _THREAD_STATE
{
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
}THREAD_STATE;
typedef enum _KWAIT_REASON
{
Executive,
FreePage,
PageIn,
PoolAllocation,
DelayExecution,
Suspended,
UserRequest,
WrExecutive,
WrFreePage,
WrPageIn,
WrPoolAllocation,
WrDelayExecution,
WrSuspended,
WrUserRequest,
WrEventPair,
WrQueue,
WrLpcReceive,
WrLpcReply,
WrVirtualMemory,
WrPageOut,
WrRendezvous,
Spare2,
Spare3,
Spare4,
Spare5,
Spare6,
WrKernel,
MaximumWaitReason
}KWAIT_REASON;
typedef NTSTATUS (WINAPI * PNTRAISE)(NTSTATUS,
ULONG,
ULONG,
PULONG,
UINT,
PULONG);
typedef LONG NTSTATUS;
typedef LONG KPRIORITY;
typedef struct _CLIENT_ID {
DWORD UniqueProcess;
DWORD UniqueThread;
} CLIENT_ID, * PCLIENT_ID;
typedef struct _VM_COUNTERS {
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
} VM_COUNTERS;
typedef struct _SYSTEM_THREAD_INFORMATION {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
LONG State;
LONG WaitReason;
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[ 6 ];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[ 2 ];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters;
SYSTEM_THREAD_INFORMATION Threads[ 5 ];
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;
typedef DWORD (WINAPI * PQUERYSYSTEM)(UINT, PVOID, DWORD,PDWORD);
/* ********************************************************************** */
/* 函数说明:
参数:dwThreadID 代表线程ID ,这里主要是验证线程的ID
szProcessName,表示线程所在的进程名
返回值:
true: 表示线程被挂起
false: 表示线程正常。
*/
/* ********************************************************************** */
BOOL IsThreadSuspend(DWORD dwThreadID,wchar_t * szProcessName)
{
ULONG cbBuffer = 0x5000 ;
BOOL bRet = FALSE;
LPVOID pBuffer = NULL;
NTSTATUS Status;
DWORD b = 0 ;
PQUERYSYSTEM NtQuerySystemInformation;
PSYSTEM_PROCESS_INFORMATION pInfo ;
NtQuerySystemInformation = (PQUERYSYSTEM) GetProcAddress(
LoadLibrary( " ntdll.dll " ),
" NtQuerySystemInformation " );
do
{
pBuffer = malloc(cbBuffer);
if (pBuffer == NULL)
{
break ;
}
Status = NtQuerySystemInformation(
SystemProcessesAndThreadsInformation,
pBuffer, cbBuffer, NULL);
if (Status == STATUS_INFO_LENGTH_MISMATCH)
{
free(pBuffer);
cbBuffer *= 2 ;
}
else if ( ! NT_SUCCESS(Status))
{
free(pBuffer);
}
} while (Status == STATUS_INFO_LENGTH_MISMATCH);
pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
for (;;)
{
if (pInfo -> NextEntryDelta == 0 )
break ;
if (pInfo -> ProcessName.Buffer != NULL &&
! _wcsicmp(pInfo -> ProcessName.Buffer,szProcessName))
{
for (b = 0 ;b < pInfo -> ThreadCount ;b ++ )
{
if (pInfo -> Threads[b].ClientId.UniqueThread == dwThreadID ) // 找到线程
{
if (pInfo -> Threads[b].State == StateWait && pInfo -> Threads[b].WaitReason == Suspended) // 线程被挂起
{
bRet = TRUE;
break ;
}
}
}
break ;
}
pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo) + pInfo -> NextEntryDelta);
}
free(pBuffer);
return bRet;
}
/* ************************************************************ */
/* 判断线程是否被终止 , 如果终止返回FALSE,如果还活着返回TRUE
/************************************************************* */
BOOL IsThreadAlive(DWORD dwThreadID)
{
BOOL bRet = FALSE;
DWORD ExitCode = 0 ;
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION,FALSE,dwThreadID);
if (hThread != NULL)
{
if (GetExitCodeThread(hThread, & ExitCode))
{
if ( ExitCode == STILL_ACTIVE)
bRet = TRUE;
}
CloseHandle(hThread);
}
return bRet;
}
int _tmain( int argc, _TCHAR * argv[])
{
BOOL bRET = IsThreadSuspend( 2320 ,L " EXPLORER.EXE " );
if (bRET)
{
printf( " 2320线程被挂起了! " );
}
return 0 ;
}
#include < windows.h >
#include < winbase.h >
#include < ntsecapi.h >
#define UNICODE
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_SUCCESS ((NTSTATUS) 0x00000000)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004)
#define SystemProcessesAndThreadsInformation 5
#define NTAPI __stdcall
typedef enum _THREAD_STATE
{
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
}THREAD_STATE;
typedef enum _KWAIT_REASON
{
Executive,
FreePage,
PageIn,
PoolAllocation,
DelayExecution,
Suspended,
UserRequest,
WrExecutive,
WrFreePage,
WrPageIn,
WrPoolAllocation,
WrDelayExecution,
WrSuspended,
WrUserRequest,
WrEventPair,
WrQueue,
WrLpcReceive,
WrLpcReply,
WrVirtualMemory,
WrPageOut,
WrRendezvous,
Spare2,
Spare3,
Spare4,
Spare5,
Spare6,
WrKernel,
MaximumWaitReason
}KWAIT_REASON;
typedef NTSTATUS (WINAPI * PNTRAISE)(NTSTATUS,
ULONG,
ULONG,
PULONG,
UINT,
PULONG);
typedef LONG NTSTATUS;
typedef LONG KPRIORITY;
typedef struct _CLIENT_ID {
DWORD UniqueProcess;
DWORD UniqueThread;
} CLIENT_ID, * PCLIENT_ID;
typedef struct _VM_COUNTERS {
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
} VM_COUNTERS;
typedef struct _SYSTEM_THREAD_INFORMATION {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
LONG State;
LONG WaitReason;
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[ 6 ];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[ 2 ];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters;
SYSTEM_THREAD_INFORMATION Threads[ 5 ];
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;
typedef DWORD (WINAPI * PQUERYSYSTEM)(UINT, PVOID, DWORD,PDWORD);
/* ********************************************************************** */
/* 函数说明:
参数:dwThreadID 代表线程ID ,这里主要是验证线程的ID
szProcessName,表示线程所在的进程名
返回值:
true: 表示线程被挂起
false: 表示线程正常。
*/
/* ********************************************************************** */
BOOL IsThreadSuspend(DWORD dwThreadID,wchar_t * szProcessName)
{
ULONG cbBuffer = 0x5000 ;
BOOL bRet = FALSE;
LPVOID pBuffer = NULL;
NTSTATUS Status;
DWORD b = 0 ;
PQUERYSYSTEM NtQuerySystemInformation;
PSYSTEM_PROCESS_INFORMATION pInfo ;
NtQuerySystemInformation = (PQUERYSYSTEM) GetProcAddress(
LoadLibrary( " ntdll.dll " ),
" NtQuerySystemInformation " );
do
{
pBuffer = malloc(cbBuffer);
if (pBuffer == NULL)
{
break ;
}
Status = NtQuerySystemInformation(
SystemProcessesAndThreadsInformation,
pBuffer, cbBuffer, NULL);
if (Status == STATUS_INFO_LENGTH_MISMATCH)
{
free(pBuffer);
cbBuffer *= 2 ;
}
else if ( ! NT_SUCCESS(Status))
{
free(pBuffer);
}
} while (Status == STATUS_INFO_LENGTH_MISMATCH);
pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
for (;;)
{
if (pInfo -> NextEntryDelta == 0 )
break ;
if (pInfo -> ProcessName.Buffer != NULL &&
! _wcsicmp(pInfo -> ProcessName.Buffer,szProcessName))
{
for (b = 0 ;b < pInfo -> ThreadCount ;b ++ )
{
if (pInfo -> Threads[b].ClientId.UniqueThread == dwThreadID ) // 找到线程
{
if (pInfo -> Threads[b].State == StateWait && pInfo -> Threads[b].WaitReason == Suspended) // 线程被挂起
{
bRet = TRUE;
break ;
}
}
}
break ;
}
pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo) + pInfo -> NextEntryDelta);
}
free(pBuffer);
return bRet;
}
/* ************************************************************ */
/* 判断线程是否被终止 , 如果终止返回FALSE,如果还活着返回TRUE
/************************************************************* */
BOOL IsThreadAlive(DWORD dwThreadID)
{
BOOL bRet = FALSE;
DWORD ExitCode = 0 ;
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION,FALSE,dwThreadID);
if (hThread != NULL)
{
if (GetExitCodeThread(hThread, & ExitCode))
{
if ( ExitCode == STILL_ACTIVE)
bRet = TRUE;
}
CloseHandle(hThread);
}
return bRet;
}
int _tmain( int argc, _TCHAR * argv[])
{
BOOL bRET = IsThreadSuspend( 2320 ,L " EXPLORER.EXE " );
if (bRET)
{
printf( " 2320线程被挂起了! " );
}
return 0 ;
}