关于线程

lolin 2000-11-22 09:15:00
知道进程句柄怎样取得其下所有线程的句柄?急!
...全文
512 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
singlerace 2000-11-26
  • 打赏
  • 举报
回复
ntddk.h里有部分说明
lolin 2000-11-24
  • 打赏
  • 举报
回复
虽然还未试,但很厉害。佩服、佩服!值得给100分!
不过我还有一点不太明白,以NT等开头的应是MS未文档载明的函数,
不知singlerace兄是从哪知道它的参数及功能的?(有些唐突,但真的忍不住很想知道)
非常感激你,真的!
singlerace 2000-11-23
  • 打赏
  • 举报
回复
简单调用Mine_OpenThread就可以了,当然用完后记得CloseHandle
singlerace 2000-11-23
  • 打赏
  • 举报
回复
在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;
}
singlerace 2000-11-23
  • 打赏
  • 举报
回复
可以从线程id得到线程句柄的,当然也可以操纵它,比如TerminateThread。

wjf 2000-11-22
  • 打赏
  • 举报
回复
msdn的例子里有Process view的源程序,不妨看看!
wjf 2000-11-22
  • 打赏
  • 举报
回复
要句柄干什么?
记得曾经讨论过,线程的句柄除了创建时能得到之外,其他情况下几乎不可能得到!
你要句柄无非是为了操纵他,请记住要在进程空间外单独操纵线程几乎不可能。
net_worm 2000-11-22
  • 打赏
  • 举报
回复
强制转换呀……
lolin 2000-11-22
  • 打赏
  • 举报
回复
我已看过,但只有如何取得线程ID,不知怎样将ID转化为HANDLE!

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧