• 【旧文章搬运】ZwQuerySystemInformation枚举进线程信息


    原文发表于百度空间,2008-10-15
    ==========================================================================

    很古老的东西了,写一写,权当练手吧.
    本来以为没什么难度,很科普很傻瓜的东西,但是写的时候还是遇到一些问题,进程信息正确,得到的线程信息总是不正确,后来分析了一下,发现这个ntdll sdk中定义的进程信息结构和线程信息结构都有点问题,可能它是来自《Win2000 Native API》一书,不适用于Windows XP。后来参考WRK修正了一下。线程信息结构也有问题,和WRK中的一样,但是结果仍然不正确,简单分析了一下,得出结构大小应为0x40,最终还是修正了一下,才有正确结果。
    最终确定的进程结构如下:

    typedef struct _SYSTEM_PROCESSES {
    ULONG NextEntryDelta;
    ULONG ThreadCount;
    LARGE_INTEGER Reserved1[3];
    LARGE_INTEGER CreateTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER KernelTime;
    UNICODE_STRING ProcessName;
    KPRIORITY BasePriority;
    ULONG ProcessId;
    ULONG InheritedFromProcessId;
    ULONG HandleCount;
    ULONG SessionId;
    ULONG_PTR PageDirectoryBase;
    VM_COUNTERS VmCounters;
    ULONG PrivatePageCount;// add by achillis
    IO_COUNTERS IoCounters;
    SYSTEM_THREADS Threads[1];
    } SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;

    线程信息结构如下:

    typedef struct _SYSTEM_THREADS{
        LARGE_INTEGER KernelTime;
        LARGE_INTEGER UserTime;
        LARGE_INTEGER CreateTime;
        ULONG WaitTime;
        PVOID StartAddress;
        CLIENT_ID ClientId;
        KPRIORITY Priority;
        LONG BasePriority;
        ULONG ContextSwitches;
        ULONG ThreadState;
        ULONG WaitReason;
        ULONG Reversed;//add by achillis
    } SYSTEM_THREAD_INFORMATION,*PSYSTEM_THREADS;

    红色部分是我增加的,也不知道到底对不对,但是目前为止在我的XP SP2上可以得到正确结果。
    枚举进程和线程信息的代码如下:

    int ShowProcess(void)
    {
    NTSTATUS status;
    DWORD retlen,truelen;
    char *buf=NULL,*p=NULL;
    ANSI_STRING ansiStr;
    int cnt=0;
    PSYSTEM_PROCESSES pSysProcess;
    PSYSTEM_THREADS pSysThread;
    status=ZwQuerySystemInformation(SystemProcessInformation,NULL,0,&retlen);
    truelen=retlen;
    status=ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&buf,0,&retlen,MEM_COMMIT,PAGE_READWRITE);
    printf("Size of SYSTEM_THREAD:%d
    ",sizeof(SYSTEM_THREADS));
    p=buf;
    status=ZwQuerySystemInformation(SystemProcessInformation,buf,truelen,&retlen);
    do
    {
       cnt++;
       pSysProcess=(PSYSTEM_PROCESSES)buf;
       RtlUnicodeStringToAnsiString(&ansiStr,&pSysProcess->ProcessName,TRUE);
       printf("Name:%s
    ",ansiStr.Buffer);
       RtlFreeAnsiString(&ansiStr);
       printf("ThreadCnt:%d	",pSysProcess->ThreadCount);
       printf("Priority:%d	",pSysProcess->BasePriority);
       printf("PID:%4d	",pSysProcess->ProcessId);
       printf("PPID:%d
    ",pSysProcess->InheritedFromProcessId);
       printf("HandleCnt:%d
    ",pSysProcess->HandleCount);
       //在每一项SYSTEM_PROCESS结构的最后是一个接一个的SYSTEM_THREAD结构
       //输出每个线程的信息
       if (pSysProcess->ThreadCount&&pSysProcess->ProcessId)
       {
        DWORD i=0;
        pSysThread=pSysProcess->Threads;
        for (;i<pSysProcess->ThreadCount;i++)
        {
         printf("Thread[%d] StartAddr:0x%08x	",i+1,pSysThread->StartAddress);
         printf("TID:%d	",pSysThread->ClientId.UniqueThread);
         printf("SwitchCnt:%d
    ",pSysThread->ContextSwitchCount);
         pSysThread++;
        }
       }
       //若NextEntryDelta为0,则表明已结束
       if (pSysProcess->NextEntryDelta==0)
       {
        break;
       }
       buf=buf+pSysProcess->NextEntryDelta;
       printf("===============================================================
    ");
    }while (1);
    printf("Total:%d
    ",cnt);
    status=ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&p,&truelen,MEM_RELEASE);
    return 0;
    }

    写到这儿又想起了经典的Hook ZwQuerySystemInfoamation隐藏进程,其实SYSTEM_PROCESS结构中的NextEntryDelta作为指向下一个结构的偏移量,其作用类似于指针,使整体构成了一个单链表,要隐藏就是从链表中删除一个元素而已,简单的数据结构知识,呵呵~

  • 相关阅读:
    LeetCode(75) Sort Colors
    大众点评2015 在线笔试(1)
    百度2015 在线笔试题(3)
    百度2015 在线笔试题(2)
    百度2015 在线笔试题(1)
    其他 之网站分享插件
    Flask框架 之request对象
    Flask框架 之路由
    Flask框架 之第一个Flask程序
    微信 之网页授权登录
  • 原文地址:https://www.cnblogs.com/achillis/p/10180184.html
Copyright © 2020-2023  润新知