关于线程
知道进程句柄怎样取得其下所有线程的句柄?急! 问题点数:20、回复次数:9Top
1 楼wjf(ww)回复于 2000-11-22 09:54:00 得分 0
msdn的例子里有Process view的源程序,不妨看看!Top
2 楼lolin(lolin)回复于 2000-11-22 17:18:00 得分 0
我已看过,但只有如何取得线程ID,不知怎样将ID转化为HANDLE!Top
3 楼net_worm(三流)回复于 2000-11-22 19:08:00 得分 0
强制转换呀……Top
4 楼wjf(ww)回复于 2000-11-22 20:58:00 得分 0
要句柄干什么?
记得曾经讨论过,线程的句柄除了创建时能得到之外,其他情况下几乎不可能得到!
你要句柄无非是为了操纵他,请记住要在进程空间外单独操纵线程几乎不可能。Top
5 楼singlerace(独行者)回复于 2000-11-23 15:23:00 得分 0
可以从线程id得到线程句柄的,当然也可以操纵它,比如TerminateThread。
Top
6 楼singlerace(独行者)回复于 2000-11-23 15:25:00 得分 0
在NT下是可以的。我已经试成功了。
用了ntdll.dll里的3个函数:
NtQuerySystemInformation,
NtQueryObject,
NtQueryInformationThread
不光得到线程handle,还可以在系统范围枚举所进程、线程、内核句柄。
回复人:singlerace(2000-11-10 12:15:00 ) 得0分
#include <windows.h>
#include <stdio.h>
#include <TCHAR.h>
typedef DWORD (WINAPI *PNtQueryObject)( HANDLE, DWORD, VOID*, DWORD, VOID* );
typedef DWORD (WINAPI *PNtQuerySystemInformation)( DWORD, VOID*, DWORD, ULONG* );
typedef DWORD (WINAPI *PNtQueryInformationThread)(HANDLE, ULONG, PVOID, DWORD, DWORD* );
typedef DWORD (WINAPI *PNtQueryInformationFile)(HANDLE, PVOID, PVOID, DWORD, DWORD );
typedef DWORD (WINAPI *PNtQueryInformationProcess)(HANDLE, DWORD, PVOID, DWORD, PVOID );
typedef struct _THREAD_INFORMATION
{
DWORD ProcessId;
DWORD ThreadId;
HANDLE ThreadHandle;
} THREAD_INFORMATION;
typedef struct _BASIC_THREAD_INFORMATION {
DWORD u1;
DWORD u2;
DWORD u3;
DWORD ThreadId;
DWORD u5;
DWORD u6;
DWORD u7;
} BASIC_THREAD_INFORMATION;
enum {
OB_TYPE_UNKNOWN = 0,
OB_TYPE_TYPE = 1,
OB_TYPE_DIRECTORY,
OB_TYPE_SYMBOLIC_LINK,
OB_TYPE_TOKEN,
OB_TYPE_PROCESS,
OB_TYPE_THREAD,
OB_TYPE_UNKNOWN_7,
OB_TYPE_EVENT,
OB_TYPE_EVENT_PAIR,
OB_TYPE_MUTANT,
OB_TYPE_UNKNOWN_11,
OB_TYPE_SEMAPHORE,
OB_TYPE_TIMER,
OB_TYPE_PROFILE,
OB_TYPE_WINDOW_STATION,
OB_TYPE_DESKTOP,
OB_TYPE_SECTION,
OB_TYPE_KEY,
OB_TYPE_PORT,
OB_TYPE_WAITABLE_PORT,
OB_TYPE_UNKNOWN_21,
OB_TYPE_UNKNOWN_22,
OB_TYPE_UNKNOWN_23,
OB_TYPE_UNKNOWN_24,
//OB_TYPE_CONTROLLER,
//OB_TYPE_DEVICE,
//OB_TYPE_DRIVER,
OB_TYPE_IO_COMPLETION,
OB_TYPE_FILE
} SystemHandleType;
typedef struct _SYSTEM_HANDLE
{
DWORD ProcessID;
WORD HandleType;
WORD HandleNumber;
DWORD KernelAddress;
DWORD Flags;
} SYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
DWORD Count;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION;
PNtQuerySystemInformation NtQuerySystemInformation = NULL;
PNtQueryObject NtQueryObject = NULL;
PNtQueryInformationThread NtQueryInformationThread = NULL;
PNtQueryInformationFile NtQueryInformationFile = NULL;
PNtQueryInformationProcess NtQueryInformationProcess = NULL;
BOOL Init();
BOOL NtDllStatus = Init();
// Enable the SeDebugPrivilege
static void EnableDebugPriv( void )
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
// enable the SeDebugPrivilege
if ( ! OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
{
_tprintf( _T("OpenProcessToken() failed, Error = %d SeDebugPrivilege is not available.\n") , GetLastError() );
return;
}
if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
{
_tprintf( _T("LookupPrivilegeValue() failed, Error = %d SeDebugPrivilege is not available.\n"), GetLastError() );
CloseHandle( hToken );
return;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
_tprintf( _T("AdjustTokenPrivileges() failed, Error = %d SeDebugPrivilege is not available.\n"), GetLastError() );
CloseHandle( hToken );
}
static BOOL Init()
{
// Get the NtDll function pointers
NtQuerySystemInformation = (PNtQuerySystemInformation)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQuerySystemInformation") );
NtQueryObject = (PNtQueryObject)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQueryObject") );
NtQueryInformationThread = (PNtQueryInformationThread)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQueryInformationThread") );
NtQueryInformationFile = (PNtQueryInformationFile)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQueryInformationFile") );
NtQueryInformationProcess = (PNtQueryInformationProcess)
GetProcAddress( GetModuleHandle( _T( "ntdll.dll" ) ),
_T("NtQueryInformationProcess") );
EnableDebugPriv();
return NtQuerySystemInformation != NULL &&
NtQueryObject != NULL &&
NtQueryInformationThread != NULL &&
NtQueryInformationFile != NULL &&
NtQueryInformationProcess != NULL;
}
void LPCWSTR2CString( LPCWSTR strW, LPTSTR str )
{
#ifdef UNICODE
// if it is already UNICODE, no problem
wcscpy(strW, str);
#else
str[0] = _T('\0');
TCHAR* actChar = (TCHAR*)strW;
if ( actChar == _T('\0') )
return;
ULONG len = wcslen(strW) + 1;
TCHAR* pBuffer = new TCHAR[ len ];
TCHAR* pNewStr = pBuffer;
while ( len-- )
{
*(pNewStr++) = *actChar;
actChar += 2;
}
_tcscpy(str, pBuffer);
delete [] pBuffer;
#endif
}
//Information functions
static BOOL GetTypeToken( HANDLE h, LPTSTR str, DWORD processId )
{
ULONG size = 0x2000;
UCHAR* lpBuffer = NULL;
BOOL ret = FALSE;
HANDLE handle;
HANDLE hRemoteProcess = NULL;
BOOL remote = processId != GetCurrentProcessId();
if ( remote )
{
// Open the remote process
hRemoteProcess = OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId );
if ( hRemoteProcess == NULL )
return FALSE;
// Duplicate the handle
handle = NULL;
DuplicateHandle( hRemoteProcess, h, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS );
}
else
handle = h;
// Query the info size
NtQueryObject( handle, 2, NULL, 0, &size );
lpBuffer = new UCHAR[size];
// Query the info size ( type )
if ( NtQueryObject( handle, 2, lpBuffer, size, NULL ) == 0 )
{
str[0] = _T('\0');
LPCWSTR2CString( (LPCWSTR)(lpBuffer+0x60), str );
ret = TRUE;
}
if ( remote )
{
if ( hRemoteProcess != NULL )
CloseHandle( hRemoteProcess );
if ( handle != NULL )
CloseHandle( handle );
}
if ( lpBuffer != NULL )
delete [] lpBuffer;
return ret;
}
//Thread related functions
static BOOL GetThreadId( HANDLE h, DWORD& threadID, DWORD processId )
{
BASIC_THREAD_INFORMATION ti;
HANDLE handle;
HANDLE hRemoteProcess = NULL;
BOOL remote = processId != GetCurrentProcessId();
if ( remote )
{
// Open process
hRemoteProcess = OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId );
if ( hRemoteProcess == NULL )
return FALSE;
// Duplicate handle
handle = NULL;
DuplicateHandle( hRemoteProcess, h, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS );
}
else
handle = h;
// Get the thread information
if ( NtQueryInformationThread( handle, 0, &ti, sizeof(ti), NULL ) == 0 )
threadID = ti.ThreadId;
if ( remote )
{
if ( hRemoteProcess != NULL )
CloseHandle( hRemoteProcess );
if ( handle != NULL )
CloseHandle( handle );
}
return TRUE;
}
HANDLE Mine_OpenThread(DWORD dwProcessId, DWORD dwThreadId)
{
DWORD size = 0x2000;
DWORD needed = 0;
DWORD i = 0;
TCHAR szFilter[] = _T("Thread");
TCHAR szType[500];
THREAD_INFORMATION ti;
HANDLE h = NULL;
if ( !NtDllStatus )
return NULL;
// Allocate the memory for the buffer
SYSTEM_HANDLE_INFORMATION* pSysHandleInformation = (SYSTEM_HANDLE_INFORMATION*)
VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_READWRITE );
if ( pSysHandleInformation == NULL )
return NULL;
// Query the needed buffer size for the objects ( system wide )
if ( NtQuerySystemInformation( 16, pSysHandleInformation, size, &needed ) != 0 )
{
if ( needed == 0 )
goto cleanup;
// The size was not enough
VirtualFree( pSysHandleInformation, 0, MEM_RELEASE );
pSysHandleInformation = (SYSTEM_HANDLE_INFORMATION*)
VirtualAlloc( NULL, size = needed + 256, MEM_COMMIT, PAGE_READWRITE );
}
if ( pSysHandleInformation == NULL )
return NULL;
// Query the objects ( system wide )
if ( NtQuerySystemInformation( 16, pSysHandleInformation, size, NULL ) != 0 )
goto cleanup;
// Iterating through the objects
for ( i = 0; i < pSysHandleInformation->Count; i++ )
{
// ProcessId filtering check
if ( pSysHandleInformation->Handles[i].ProcessID == dwProcessId || dwProcessId == (DWORD)-1 )
{
// Type filtering
GetTypeToken( (HANDLE)pSysHandleInformation->Handles[i].HandleNumber, szType, pSysHandleInformation->Handles[i].ProcessID );
if( _tcsicmp( szType, szFilter ) == 0 )
{
ti.ProcessId = pSysHandleInformation->Handles[i].ProcessID;
ti.ThreadHandle = (HANDLE)pSysHandleInformation->Handles[i].HandleNumber;
// ThreadId filtering check
if(GetThreadId( ti.ThreadHandle, ti.ThreadId, ti.ProcessId ) && ti.ThreadId == dwThreadId)
{
if(dwProcessId != GetCurrentProcessId())
{
// Open remote process
HANDLE hRemoteProcess = OpenProcess( PROCESS_DUP_HANDLE, TRUE, dwProcessId );
if ( hRemoteProcess == NULL )
goto cleanup;
// Duplicate handle
DuplicateHandle( hRemoteProcess, ti.ThreadHandle, GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS );
CloseHandle( hRemoteProcess );
}
else
DuplicateHandle( GetCurrentProcess(), ti.ThreadHandle, GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS );
break;
}
ti.ThreadHandle = NULL;
}
}
}
cleanup:
if ( pSysHandleInformation != NULL )
VirtualFree( pSysHandleInformation, 0, MEM_RELEASE );
return h;
}
Top
7 楼singlerace(独行者)回复于 2000-11-23 15:27:00 得分 0
简单调用Mine_OpenThread就可以了,当然用完后记得CloseHandleTop
8 楼lolin(lolin)回复于 2000-11-24 12:57:00 得分 0
虽然还未试,但很厉害。佩服、佩服!值得给100分!
不过我还有一点不太明白,以NT等开头的应是MS未文档载明的函数,
不知singlerace兄是从哪知道它的参数及功能的?(有些唐突,但真的忍不住很想知道)
非常感激你,真的!Top
9 楼singlerace(独行者)回复于 2000-11-26 13:12:00 得分 20
ntddk.h里有部分说明Top




