OpenThread种种
来源:互联网 发布:阿香婆 会员软件 编辑:程序博客网 时间:2024/05/06 22:44
我在Windows NT系统(包括2K和XP)和Windows CE系统各写有一个工具,专门用来研究系统的运行时状态,比如进程、线程的各种信息,哪些DLL被哪些进程加载了,等等。如果某天突然想到一些好玩的东西,我也会把它加到工具里,比如,下图的这个,在系统登陆、锁定界面上运行了一个计算器。
一般情况下,我比较喜欢做的事是观察线程的Call Stack。这就要用到一个关键的API:OpenThread。基本上,想要获得跟线程有关的信息或者控制线程的运行(比如说你可以用 SuspendThread挂起一个线程甚至整个进程),都得先通过它来拿到线程的句柄。不过在Windows系统上,除了Windows 2K/XP/ME等平台,其他平台并没有一个现成的WIN32 API可供使用。这种情况下,我们必须以某种形式模拟OpenThread。
- Windows NT 4.0。在NT 4.0的时代,可能是微软担心它过于危险,OpenThread还没成为一个标准的Win32 API。但是在NTDLL里提供了一个Native API:NtOpenThread。如果你反汇编跟踪过NtOpenProcess和NtOpenThread,会发现除了ClientId的初始化, NtOpenThread和NtOpenProcess基本上完全一样。利用NtOpenThread,OpenThread的NT4可实现如下:
HANDLE OpenThreadNT(DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwThreadId)
{
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID ClientId;
HANDLE hThread;
NTSTATUS Status;
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
if (bInheritHandle)
ObjectAttributes.Attributes = OBJ_INHERIT;
ClientId.UniqueProcess = NULL;
ClientId.UniqueThread = (HANDLE)dwThreadId;
Status = NtOpenThread(&hThread, // Thread handle
dwDesiredAccess, // Access to thread object
&ObjectAttributes, // Object attributes
&ClientId); // Client Id
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return NULL;
}
return hThread;
}
BOOL bInheritHandle,
DWORD dwThreadId)
{
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID ClientId;
HANDLE hThread;
NTSTATUS Status;
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
if (bInheritHandle)
ObjectAttributes.Attributes = OBJ_INHERIT;
ClientId.UniqueProcess = NULL;
ClientId.UniqueThread = (HANDLE)dwThreadId;
Status = NtOpenThread(&hThread, // Thread handle
dwDesiredAccess, // Access to thread object
&ObjectAttributes, // Object attributes
&ClientId); // Client Id
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return NULL;
}
return hThread;
}
- Windows ME/2K/XP。可能是MS觉得OpenThread其实是一个比较有用的API,也可能MS觉得开放OpenThread其实没那么危险,在这些操作系统上就直接提供了WIN32 API。因此如果是这些系统,直接用就是了。
- Windows 95/98。在Windows 9x中,无论是公开还是未公开函数,都没有现成的可用。不过你可以搞点儿诡计,把TDB伪装成PDB,然后利用OpenProcess实现OpenThread的功能:
HANDLE OpenThread9x(DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwThreadId)
{
// Thread Database pointer
PTDB pTDB = dwThreadId ^ dwObsfucator;
pTDB->Type = K32OBJ_PROCESS;
HANDLE hThread = OpenProcess(dwDesiredAccess, bInheritHandle, dwThreadId);
pTDB->Type = K32OBJ_THREAD;
return hThread;
}
DWORD GetObsfucator()
{
DWORD PID, PDB;
PID = GetCurrentProcessId();
__asm mov eax,fs:[0x30]; // PDB
__asm mov PDB,eax
return PDB ^ PID;
}
BOOL bInheritHandle,
DWORD dwThreadId)
{
// Thread Database pointer
PTDB pTDB = dwThreadId ^ dwObsfucator;
pTDB->Type = K32OBJ_PROCESS;
HANDLE hThread = OpenProcess(dwDesiredAccess, bInheritHandle, dwThreadId);
pTDB->Type = K32OBJ_THREAD;
return hThread;
}
DWORD GetObsfucator()
{
DWORD PID, PDB;
PID = GetCurrentProcessId();
__asm mov eax,fs:[0x30]; // PDB
__asm mov PDB,eax
return PDB ^ PID;
}
dwObsfucator这个东西,看过Matt Pietrek的《Windows 95 System Programming SECRETS》应该知道是怎么回事-在最初的Windows 95版本中GetCurrentProcessId和GetCurrentThreadId都是直接返回PDB和TDB指针,后来,MS搞了个小花样,用了一个开机时自动生成的随机值做了个异或加密。Windows桌面操作系统的OpenThread实现,其实在CodeProject上这篇文章里有详细的解释。
- Windows CE。Windows CE也没有现成的公开或未公开的API可用。不过和Windows 9x平台类似(看Windows CE的内核源代码,我有时会怀疑很多代码是不是从Windows 9x抄过来的),你可以用OpenProcess来实现(以前提供的版本有BUG,导致在某些平台上系统挂起,这是版本2):
HANDLE OpenThread(DWORD fdwAccess, BOOL fInherit, DWORD IDThread)
{
HANDLE hThread=NULL;
BOOL fOldMode = SetKMode(TRUE);
PTHREAD pTh = HandleToThread((HANDLE)IDThread);
if (pTh)
{
HANDLE hProcess = pTh->pOwnerProc->hProc;
if (hProcess)
{
HANDLE h = (HANDLE)IDThread;
PHDATA phd;
h2p(h, phd);
if (phd && phd->pci->type == SH_CURTHREAD)
{
const CINFO *pci = phd->pci;
PHDATA phd2;
h2p(hProcess, phd2);
int nOldPrio = CeGetThreadPriority(GetCurrentThread());
CeSetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
__try {
phd->pci = phd2->pci;
hThread = ::OpenProcess(fdwAccess, fInherit, IDThread);
phd->pci = pci;
}__except(EXCEPTION_EXECUTE_HANDLER){
if (hThread) {
CloseHandle(hThread);
hThread = NULL;
}
}
CeSetThreadPriority(GetCurrentThread(), nOldPrio);
}
}
}
else
{
SetLastError(ERROR_INVALID_PARAMETER);
}
SetKMode(fOldMode);
return hThread;
}
- OpenThread种种
- vc6 OpenThread
- OpenThread的解决之道
- OpenThread的调用
- OpenThread GetCurrentThread GetCurrentProcess
- OpenThread的用法
- 图形学优化_2: openthread
- OpenThread中的condition和barrier
- ‘OpenThread”: undeclared identifier 问题的解决之道
- 编译时出现:‘OpenThread”: undeclared identifier
- 刷新种种
- 香水种种
- 其他种种
- 人际关系种种
- 指针 种种
- sizeof 种种
- wcf种种
- ibatis 种种
- linux用户管理命令(添加,删除,修改)
- 二级域名或跨域共享Cookies
- 也来玩转Skype ——基于Skype4Java API编写Skype外壳程序入门介绍
- Linux下程序设计常用函数
- getSnapshot参数可选问题
- OpenThread种种
- poi的几个使用小技巧
- SQL常用语句备忘录(技巧)
- AJAX从零开始--初步接触AJAX.NET(续)
- Visual Studio下的C#学习
- 经典SQL语句集锦
- 运气不好,看天狗吐月亮
- 利用p3p跨域传递COOKIE
- C#中判断空字符串的3种方法性能分析