zoukankan      html  css  js  c++  java
  • NtQuerySystemInformation获取进程/线程状态

    __kernel_entry NTSTATUS NtQuerySystemInformation(
      SYSTEM_INFORMATION_CLASS SystemInformationClass,
      PVOID                    SystemInformation,
      ULONG                    SystemInformationLength,
      PULONG                   ReturnLength
    );
    

    这是一个NT函数,需要通过LoadLibrary()和GetProcAddress()来获取其地址继而调用它。其第一个参数SystemInformationClass指定要检索的系统信息的类型,如果要检测进程和线程的信息就让参数的值为SystemProcessInformation。由SystemInformation参数指向的缓冲区包含每个进程的SYSTEM_PROCESS_INFORMATION结构。这些结构中的每一个紧随其后的是内存中的一个或多个SYSTEM_THREAD_INFORMATION结构,这些结构为上一个进程中的每个线程提供信息。

    typedef struct _SYSTEM_THREAD_INFORMATION {
        LARGE_INTEGER Reserved1[3];
        ULONG Reserved2;
        PVOID StartAddress;                  //线程开始的虚拟地址;
        CLIENT_ID ClientId;                  //线程标识符;
        KPRIORITY Priority;                  //线程优先级;
        LONG BasePriority;                   //基本优先级;
        ULONG Reserved3;
        ULONG ThreadState;                   //当前状态;
        ULONG WaitReason;                    //等待原因;
    } SYSTEM_THREAD_INFORMATION;
    

    ThreadState的值与WaitReason的值都等于5则表示线程被挂起了。如果我们要判断进程的状态就可以通过判断进程中所有线程是不是都被挂起了。

    #include <winternl.h>
    typedef NTSTATUS(_stdcall * pfnNtQuerySystemInformation)(
    	SYSTEM_INFORMATION_CLASS SystemInformationClass,
    	PVOID                    SystemInformation,
    	ULONG                    SystemInformationLength,
    	PULONG                   ReturnLength
    );
    
    int main()
    {
          pfnNtQuerySystemInformation NtQuerySystemInformation = (pfnNtQuerySystemInformation)::GetProcAddress(::LoadLibrary(TEXT("ntdll.dll")),TEXT("NtQuerySystemInformation"));
    
          LPVOID dwBufferProcess = 0;         //接收数据的缓冲区
          DWORD dwBufferProcessSize = 0;      //需要接收的数据的缓冲区大小
          DWORD dwThreadNum;                  //进程中所含线程数目
    
          NtQuerySystemInformation(SystemProcessInformation, 0, 0, &dwBufferProcessSize);
          dwBufferProcess = new BYTE[dwBufferProcessSize + 0x10000]();    //为了防止进程/线程信息发生突变,多申请0x10000内存
          LPVOID dwOldBufferProcess = dwBufferProcess;                    //保存缓冲区地址                                       
          NtQuerySystemInformation(SystemProcessInformation, dwBufferProcess, dwBufferProcessSize + 0x10000, &dwBufferProcessSize);
    
          dwThreadNum = ((SYSTEM_PROCESS_INFORMATION*)dwBufferProcess)->NumberOfThreads;		//线程数目
          while(TRUE)
          {
    	      LPVOID dwAddress = dwBufferProcess;
    	      dwStatus = 0;
    	      dwBufferProcess = (BYTE*)dwBufferProcess + sizeof(SYSTEM_PROCESS_INFORMATION);
    	      for (DWORD i = 0; i < dwThreadNum; i++)
    	      {		
    		      //检测进程状态和导致此状态的原因
    	      	      if (((SYSTEM_THREAD_INFORMATION*)dwBufferProcess)->ThreadState == 5 && ((SYSTEM_THREAD_INFORMATION*)dwBufferProcess)->WaitReason == 5)
    			      dwStatus = 0;
    		      else
    			      dwStatus = 1;
    
    		      dwBufferProcess = (BYTE*)dwBufferProcess + sizeof(SYSTEM_THREAD_INFORMATION);                  //指向此进程的下一个线程结构	
    	      }
    				
    	      dwBufferProcess = ((BYTE*)dwAddress + ((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset);				//指向下一个进程
    	      if (((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset == 0)							//遍历完成结束
    		      break;
          }
          delete[] dwOldBufferProcess;      //释放内存    
    }
    
    //如果进程对应的dwStatus的值为0则表示进程的所有线程都被挂起了,也就说明进程被挂起了。
    
  • 相关阅读:
    python爬虫requests json与字典对象互相转换
    python爬虫requests的使用
    Django 使用celery任务队列的配置
    Django实现发邮件
    leetcode算法:Two Sum II
    Python中使用hashlib进行加密的简单使用
    leetcode算法: Average of Levels in Binary Tree
    Django中自定义过滤器的使用
    linux下git常用命令
    cocos2d-x 父节点和子节点执行不同动作
  • 原文地址:https://www.cnblogs.com/revercc/p/14064418.html
Copyright © 2011-2022 走看看