在windows调试体系中当被调试进程创建线程时, 内核会用DbgkpOpenHandles来打开线程句柄
这样一来调试器句柄表里就会有创建的线程句柄,那么如何来检测呢
NTSTATUS
ZwQuerySystemInformation (
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
ULONG *ReturnLength);
ZwQuerySystemInformation这个函数具有枚举系统所有进程句柄表的功能
SystemHandleInformation (0x10) 以及 SystemExtendedHandleInformation (0x40)
typedef struct _SYSTEM_HANDLE_INFORMATION_OBJECT
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
}SYSTEM_HANDLE_INFORMATION_OBJECT, * PSYSTEM_HANDLE_INFORMATION_OBJECT;
所以检测思路,第一步拿到创建线程的句柄 在使用SystemHandleInformation 判断 HandleInfo->Information[i].ProcessId == 自身PID
为什么要判断呢, 因为我们要拿到线程标志,去判断这个线程句柄是否是我们创建的线程
在判断 HandleInfo->Information[i].ObjectTypeNumber == 8
ObjectTypeNumber 是对象类型 8就是Thread 7是Process
之后判断 Handle == 线程句柄 拿到Object 这个就是内核对象,我们判断也是判断这个
过滤system进程是必要的
然后重复操作 只要判断Object是否是自身线程的即可,新创建的线程 系统进程是不会去打开的 除了system
完事后NtClose 结束线程.
调试器如何应对呢 断链内核句柄表 和 虚拟句柄 只要线程进程无句柄就行