X64进程遍历并获取进程主线程

x64下windbg显示的进程结构体

1: kd> dt _SYSTEM_PROCESS_INFORMATION
ole32!_SYSTEM_PROCESS_INFORMATION
   +0x000 NextEntryOffset  : Uint4B
   +0x004 NumberOfThreads  : Uint4B
   +0x008 WorkingSetPrivateSize : _LARGE_INTEGER
   +0x010 HardFaultCount   : Uint4B
   +0x014 NumberOfThreadsHighWatermark : Uint4B
   +0x018 CycleTime        : Uint8B
   +0x020 CreateTime       : _LARGE_INTEGER
   +0x028 UserTime         : _LARGE_INTEGER
   +0x030 KernelTime       : _LARGE_INTEGER
   +0x038 ImageName        : _UNICODE_STRING
   +0x048 BasePriority     : Int4B
   +0x050 UniqueProcessId  : Ptr64 Void
   +0x058 InheritedFromUniqueProcessId : Ptr64 Void
   +0x060 HandleCount      : Uint4B
   +0x064 SessionId        : Uint4B
   +0x068 UniqueProcessKey : Uint8B
   +0x070 PeakVirtualSize  : Uint8B
   +0x078 VirtualSize      : Uint8B
   +0x080 PageFaultCount   : Uint4B
   +0x088 PeakWorkingSetSize : Uint8B
   +0x090 WorkingSetSize   : Uint8B
   +0x098 QuotaPeakPagedPoolUsage : Uint8B
   +0x0a0 QuotaPagedPoolUsage : Uint8B
   +0x0a8 QuotaPeakNonPagedPoolUsage : Uint8B
   +0x0b0 QuotaNonPagedPoolUsage : Uint8B
   +0x0b8 PagefileUsage    : Uint8B
   +0x0c0 PeakPagefileUsage : Uint8B
   +0x0c8 PrivatePageCount : Uint8B
   +0x0d0 ReadOperationCount : _LARGE_INTEGER
   +0x0d8 WriteOperationCount : _LARGE_INTEGER
   +0x0e0 OtherOperationCount : _LARGE_INTEGER
   +0x0e8 ReadTransferCount : _LARGE_INTEGER
   +0x0f0 WriteTransferCount : _LARGE_INTEGER
   +0x0f8 OtherTransferCount : _LARGE_INTEGER

 kd> dt    _IO_COUNTERS
ole32!_IO_COUNTERS
   +0x000 ReadOperationCount : Uint8B
   +0x008 WriteOperationCount : Uint8B
   +0x010 OtherOperationCount : Uint8B
   +0x018 ReadTransferCount : Uint8B
   +0x020 WriteTransferCount : Uint8B
   +0x028 OtherTransferCount : Uint8B


kd> dt _VM_COUNTERS
ole32!_VM_COUNTERS
   +0x000 PeakVirtualSize  : Uint8B
   +0x008 VirtualSize      : Uint8B
   +0x010 PageFaultCount   : Uint4B
   +0x018 PeakWorkingSetSize : Uint8B
   +0x020 WorkingSetSize   : Uint8B
   +0x028 QuotaPeakPagedPoolUsage : Uint8B
   +0x030 QuotaPagedPoolUsage : Uint8B
   +0x038 QuotaPeakNonPagedPoolUsage : Uint8B
   +0x040 QuotaNonPagedPoolUsage : Uint8B
   +0x048 PagefileUsage    : Uint8B
   +0x050 PeakPagefileUsage : Uint8B


 kd> dt _SYSTEM_THREAD_INFORMATION
ole32!_SYSTEM_THREAD_INFORMATION
   +0x000 KernelTime       : _LARGE_INTEGER
   +0x008 UserTime         : _LARGE_INTEGER
   +0x010 CreateTime       : _LARGE_INTEGER
   +0x018 WaitTime         : Uint4B
   +0x020 StartAddress     : Ptr64 Void
   +0x028 ClientId         : _CLIENT_ID
   +0x038 Priority         : Int4B
   +0x03c BasePriority     : Int4B
   +0x040 ContextSwitches  : Uint4B
   +0x044 ThreadState      : Uint4B
   +0x048 WaitReason       : Uint4B

实际测试发现windbg列出的这个进程结构不完整,需要通过一项Reserved14个字节来补齐才行。后面列出我的代码。


#include "stdafx.h"
#include "windows.h"

#pragma pack(8)

#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_SUCCESS         ((NTSTATUS) 0x00000000)
#define SystemProcessesAndThreadsInformation    5 // 功能号
#define NTAPI    __stdcall

// 线程状态的枚举常量
typedef enum _THREAD_STATE
{
    StateInitialized , // 初始化状态
    StateReady , // 准备状态
    StateRunning , // 运行状态
    StateStandby , //
    StateTerminated ,//关闭
    StateWait , // 等待
    StateTransition , // 切换???
    StateUnknown
}THREAD_STATE;

// 线程处于等待的原因的枚举常量
typedef enum _KWAIT_REASON
{
    Executive ,
    FreePage ,
    PageIn ,
    PoolAllocation ,
    DelayExecution ,
    Suspended ,
    UserRequest ,
    WrExecutive ,
    WrFreePage ,
    WrPageIn ,
    WrPoolAllocation ,
    WrDelayExecution ,
    WrSuspended ,
    WrUserRequest ,
    WrEventPair ,
    WrQueue ,
    WrLpcReceive ,
    WrLpcReply ,
    WrVirtualMemory ,
    WrPageOut ,
    WrRendezvous ,
    Spare2 ,
    Spare3 ,
    Spare4 ,
    Spare5 ,
    Spare6 ,
    WrKernel ,
    MaximumWaitReason
}KWAIT_REASON;

typedef LONG   NTSTATUS;
typedef LONG    KPRIORITY;

typedef struct _UNICODE_STRING
{
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;

} UNICODE_STRING, *PUNICODE_STRING;


typedef struct _CLIENT_ID_64
{
    ULONG64 UniqueProcess;
    ULONG64 UniqueThread;
}CLIENT_ID_64, *PCLIENT_ID_64;

typedef struct _VM_COUNTERS
{
    ULONG64        PeakVirtualSize;
    ULONG64        VirtualSize;
    ULONG         PageFaultCount;
    ULONG64        PeakWorkingSetSize;
    ULONG64        WorkingSetSize;
    ULONG64        QuotaPeakPagedPoolUsage;
    ULONG64        QuotaPagedPoolUsage;
    ULONG64        QuotaPeakNonPagedPoolUsage;
    ULONG64        QuotaNonPagedPoolUsage;
    ULONG64        PagefileUsage;
    ULONG64        PeakPagefileUsage;
} VM_COUNTERS;

// 线程信息结构体
typedef struct _SYSTEM_THREAD_INFORMATION
{
    LARGE_INTEGER   KernelTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   CreateTime;
    ULONG64         WaitTime;
    ULONG64         StartAddress;
    CLIENT_ID_64    ClientId;
    KPRIORITY       Priority;
    KPRIORITY       BasePriority;
    ULONG           ContextSwitchCount;
    LONG            State;// 状态,是THREAD_STATE枚举类型中的一个值
    LONG            WaitReason;//等待原因, KWAIT_REASON中的一个值
} SYSTEM_THREAD_INFORMATION , *PSYSTEM_THREAD_INFORMATION;


// 进程信息结构体
typedef struct _SYSTEM_PROCESS_INFORMATION
{
    ULONG            NextEntryDelta; // 指向下一个结构体的指针
    ULONG            ThreadCount; // 本进程的总线程数
    LARGE_INTEGER    WorkingSetPrivateSize;
    ULONG            HardFaultCount;  
    ULONG            NumberOfThreadsHighWatermark;
    LARGE_INTEGER    CycleTime;
    LARGE_INTEGER    CreateTime; // 进程的创建时间
    LARGE_INTEGER    UserTime; // 在用户层的使用时间
    LARGE_INTEGER    KernelTime; // 在内核层的使用时间
    UNICODE_STRING   ProcessName; // 进程名
    KPRIORITY        BasePriority; //
    ULONG64          ProcessId; // 进程ID
    ULONG64          InheritedFromProcessId;
    ULONG            HandleCount; // 进程的句柄总数
    ULONG            SessionId;  
    ULONG64          UniqueProcessKey;

    VM_COUNTERS      VmCounters;
    IO_COUNTERS      IoCounters;
    ULONG            Reserved1;
    SYSTEM_THREAD_INFORMATION Threads[1]; // 子线程信息数组
}SYSTEM_PROCESS_INFORMATION , *PSYSTEM_PROCESS_INFORMATION;

#pragma pack()


// NtQuerySystemInformation 函数的原型
// 由于该没有导出,所以得自己定义函数的原型
typedef DWORD(WINAPI* PQUERYSYSTEM)(UINT , PVOID , DWORD , PDWORD);
DWORD __stdcall GetMainThread(DWORD dwProcessId)
{
    int nRet = 0;
    NTSTATUS Status = 0;
    DWORD dwThreadId = 0;

    PQUERYSYSTEM NtQuerySystemInformation = NULL;
    PSYSTEM_PROCESS_INFORMATION pInfo = { 0 };

    // 获取函数地址
    NtQuerySystemInformation = (PQUERYSYSTEM)GetProcAddress(LoadLibrary(L"ntdll.dll") , "NtQuerySystemInformation");


    DWORD   dwSize = 0;
    // 获取信息所需的缓冲区大小
    Status = NtQuerySystemInformation(SystemProcessesAndThreadsInformation ,//要获取的信息的类型
        NULL , // 用于接收信息的缓冲区
        0 ,  // 缓冲区大小
        &dwSize
        );
    // 申请缓冲区
    char* pBuff = new char[dwSize];
    pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuff ;
    if(pInfo == NULL)
        return -1;
    // 再次调用函数, 获取信息
    Status = NtQuerySystemInformation(SystemProcessesAndThreadsInformation ,//要获取的信息的类型
        pInfo , // 用于接收信息的缓冲区
        dwSize ,  // 缓冲区大小
        &dwSize
        );
    if(!NT_SUCCESS(Status)) {/*如果函数执行失败*/
        printf("失败\n");
        delete[] pInfo;
        return -1;
    }

    // 遍历结构体,找到对应的进程
    while(1)
    {
        // 判断是否还有下一个进程
        if(pInfo->NextEntryDelta == 0)
            break;

        // 判断是否找到了ID
        if(pInfo->ProcessId == dwProcessId)
        {


            //这里罗列出所有的进程中活着的线程。

            for(int i = 0 ; iThreadCount; i ++)
            {
                dwThreadId = (DWORD)pInfo->Threads[i].ClientId.UniqueThread;

                printf("thread id = %d",dwThreadId);

            }

            dwThreadId = (DWORD)pInfo->Threads[0].ClientId.UniqueThread;   //这个是主线程的ID
        
            break;
        }
        // 迭代到下一个节点
        pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo) + pInfo->NextEntryDelta);
    }

    delete[] pBuff;

    return dwThreadId;
}


int _tmain(int argc, _TCHAR* argv[])
{
    GetMainThread(6592);
}

你可能感兴趣的:(c/c++)