前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >WinAPI之NtQueryInformationThread

WinAPI之NtQueryInformationThread

原创
作者头像
lealc
发布于 2025-01-18 12:34:16
发布于 2025-01-18 12:34:16
20300
代码可运行
举报
运行总次数:0
代码可运行

介绍

Windows操作系统的内核级编程和系统管理领域,NtQueryInformationThread 是一个非常强大且具有重要意义的函数。它允许开发者获取关于线程的各种详细信息,为深入理解系统线程的行为和状态提供了有力的工具。

NtQueryInformationThread 属于Windows NT内核API的一部分。其作用是查询指定线程的各种信息,包括但不限于线程的基本信息(如线程ID、线程状态等)、线程的优先级、线程的上下文(包含寄存器值等重要信息)以及线程的安全属性等。

官网API说明:NtQueryInformationThread function (winternl.h) - Win32 apps | Microsoft Learn

函数原型

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
NTSTATUS NtQueryInformationThread(
    HANDLE ThreadHandle,
    THREADINFOCLASS ThreadInformationClass,
    PVOID ThreadInformation,
    ULONG ThreadInformationLength,
    PULONG ReturnLength
);
  • ThreadHandle:要查询的线程的句柄。这个句柄需要具有适当的访问权限,以确保能够获取所需的信息。
  • ThreadInformationClass:指定要查询的线程信息的类型。这是一个枚举值,涵盖了众多不同的线程信息类别,例如 ThreadBasicInformation 用于获取基本信息,ThreadPriority 用于获取线程优先级等。
  • ThreadInformation:一个指向缓冲区的指针,用于接收查询到的线程信息。
  • ThreadInformationLength:指定 ThreadInformation 缓冲区的长度。
  • ReturnLength:一个可选参数,用于接收实际返回的线程信息的长度。

基本用法

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
#include <windows.h>
#include <winternl.h>

// 定义必要的结构体和常量
typedef NTSTATUS (WINAPI *PNtQueryInformationThread)(
    HANDLE ThreadHandle,
    THREADINFOCLASS ThreadInformationClass,
    PVOID ThreadInformation,
    ULONG ThreadInformationLength,
    PULONG ReturnLength
);

int main() {
    HANDLE hThread = /* 获取线程句柄 */;
    THREAD_BASIC_INFORMATION tbi;
    ULONG returnLength;

    PNtQueryInformationThread NtQueryInformationThread = /* 加载函数地址 */;

    NTSTATUS status = NtQueryInformationThread(hThread, ThreadBasicInformation, &tbi, sizeof(tbi), &returnLength);
    if (NT_SUCCESS(status)) {
        // 处理查询到的信息
    } else {
        // 处理错误
    }

    return 0;
}

需要注意的是,实际使用时需要正确加载 NtQueryInformationThread 函数的地址,并处理相关的错误情况。

注意事项

  • 权限问题 调用该函数需要有足够的权限。如果权限不足,可能会导致查询失败。
  • 错误处理 开发者需要仔细处理函数的返回值,以应对可能出现的各种错误情况,如无效的句柄、缓冲区溢出等。
  • 兼容性 由于 NtQueryInformationThread 属于内核级API,在不同的Windows版本中可能会有一些细微的差异,需要注意兼容性问题。

拓展用法

下面是ThreadInformationClass官方公开的用法

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
typedef enum _THREADINFOCLASS {
    ThreadIsIoPending = 16,
    ThreadNameInformation = 38
} THREADINFOCLASS;

实际上ThreadInformationClass还有许多官方未公开的用法,

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
typedef enum _THREADINFOCLASS {
    ThreadBasicInformation, // q: THREAD_BASIC_INFORMATION
    ThreadTimes, // q: KERNEL_USER_TIMES
    ThreadPriority, // s: KPRIORITY
    ThreadBasePriority, // s: LONG
    ThreadAffinityMask, // s: KAFFINITY
    ThreadImpersonationToken, // s: HANDLE
    ThreadDescriptorTableEntry,
    ThreadEnableAlignmentFaultFixup, // s: BOOLEAN
    ThreadEventPair,
    ThreadQuerySetWin32StartAddress, // q: PVOID
    ThreadZeroTlsCell, // 10
    ThreadPerformanceCount, // q: LARGE_INTEGER
    ThreadAmILastThread, // q: ULONG
    ThreadIdealProcessor, // s: ULONG
    ThreadPriorityBoost, // qs: ULONG
    ThreadSetTlsArrayAddress,
    ThreadIsIoPending, // q: ULONG
    ThreadHideFromDebugger, // s: void
    ThreadBreakOnTermination, // qs: ULONG
    ThreadSwitchLegacyState,
    ThreadIsTerminated, // 20, q: ULONG
    ThreadLastSystemCall, // q: THREAD_LAST_SYSCALL_INFORMATION
    ThreadIoPriority, // qs: ULONG
    ThreadCycleTime, // q: THREAD_CYCLE_TIME_INFORMATION
    ThreadPagePriority, // q: ULONG
    ThreadActualBasePriority,
    ThreadTebInformation, // q: THREAD_TEB_INFORMATION (requires THREAD_GET_CONTEXT + THREAD_SET_CONTEXT)
    ThreadCSwitchMon,
    ThreadCSwitchPmu,
    ThreadWow64Context, // q: WOW64_CONTEXT
    ThreadGroupInformation, // 30, q: GROUP_AFFINITY
    ThreadUmsInformation,
    ThreadCounterProfiling,
    ThreadIdealProcessorEx, // q: PROCESSOR_NUMBER
    ThreadCpuAccountingInformation, // since WIN8
    ThreadSuspendCount, // since WINBLUE
    MaxThreadInfoClass
} THREADINFOCLASS;

来源于:none/src/unone/native/unone-native.h at master · BlackINT3/none

拓展示例

利用ThreadInformationClass拓展值,可以检测是否存在指定名称的进程挂起,如果有挂起则终止挂起的进程

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
bool IsThreadSuspended(HANDLE hThread) {
    qInfo() << QOperatingSystemVersion::current();
    if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1) {
        //qInfo() << "IsThreadSuspended system version lower for win8.1";
        DWORD suspendCount = SuspendThread(hThread);
        ResumeThread(hThread);
        //qInfo() << "SuspendThread previse count = " << suspendCount;
        return suspendCount != 0;
    }
    PNtQueryInformationThread NtQueryInformationThread =
        (PNtQueryInformationThread)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationThread");
    if (!NtQueryInformationThread) {
        //qWarning() << "GetProcAddress [NtQueryInformationThread] failed. Error: %lu" << GetLastError();
        return false;
    }
    ULONG suspendCount;
    NTSTATUS status = NtQueryInformationThread(hThread, (THREADINFOCLASS)35, &suspendCount,
                                               sizeof(suspendCount), NULL);
    if (status != 0) {
        //qWarning() << "NtQueryInformationThread failed. Error: %lu" << GetLastError();
        return false;
    }
    return suspendCount > 0;
}

bool TerminateSuspendedProcesses(const std::wstring& processName, DWORD currentProcessID) {
    bool bFound = false;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        //qWarning() << "CreateToolhelp32Snapshot failed. Error: " << GetLastError();
        return bFound;
    }
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);
    if (!Process32First(hSnapshot, &pe32)) {
        //qWarning() << "Process32First failed. Error: " << GetLastError();
        CloseHandle(hSnapshot);
        return bFound;
    }
    do {
        if (pe32.szExeFile == processName && pe32.th32ProcessID != currentProcessID) {
            HANDLE hProcess =
                OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pe32.th32ProcessID);
            if (hProcess != NULL) {
                HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
                if (hThreadSnap != INVALID_HANDLE_VALUE) {
                    THREADENTRY32 te32;
                    te32.dwSize = sizeof(THREADENTRY32);
                    if (Thread32First(hThreadSnap, &te32)) {
                        do {
                            if (te32.th32OwnerProcessID == pe32.th32ProcessID) {
                                HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SUSPEND_RESUME, FALSE,
                                                            te32.th32ThreadID);
                                if (hThread != NULL) {
                                    if (IsThreadSuspended(hThread)) {
                                        //qInfo() << L"Terminating suspended process " << processName << L" with PID "
                                        //        << pe32.th32ProcessID;
                                        TerminateProcess(hProcess, EXIT_CODE_HUNG_KILL);
                                        bFound = true;
                                        break;  // Assuming only one suspended thread is enough to terminate the process
                                    }
                                    CloseHandle(hThread);
                                } else {
                                    //qWarning() << "Failed to open thread. Error: " << GetLastError();
                                }
                            }
                        } while (Thread32Next(hThreadSnap, &te32));
                    }
                    CloseHandle(hThreadSnap);
                } else {
                    //qWarning() << "CreateToolhelp32Snapshot for threads failed. Error: " << GetLastError();
                }
                if (bFound) {
                    DWORD dwExitCode;  // 进程退出代码
                    // 等待进程终止
                    if (WaitForSingleObject(hProcess, INTERVAL_MAX_WAIT_PROCESS_EXIT) == WAIT_FAILED) {
                        //qWarning() << "WaitForSingleObject Process terminated failed. Error: " << GetLastError();
                    } else {
                        //qInfo() << "Process terminated successfully";
                    }
                    // 获取进程退出代码
                    if (!GetExitCodeProcess(hProcess, &dwExitCode)) {
                        //qWarning() << "GetExitCodeProcess failed. Error: " << GetLastError();
                    } else {
                        //qInfo() << "Process exit code: " << dwExitCode;
                    }
                }
                CloseHandle(hProcess);
            } else {
                //qWarning() << "Failed to open process. Error: " << GetLastError();
            }
        }
    } while (Process32Next(hSnapshot, &pe32));
    CloseHandle(hSnapshot);
    return bFound;
}

bool ApplicationHandler::CheckSuspendAndKill() {
    return TerminateSuspendedProcesses(TARGET_PROCESS_NAME, GetCurrentProcessId());
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 函数原型
  • 基本用法
    • 注意事项
  • 拓展用法
  • 拓展示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档