• 获得进程的EPROCESS


    文摘出处:http://www.xfocus.net/articles/200406/706.html

    创建时间:2004-06-01
    文章属性:原创
    文章提交:MustBE (zf35_at_citiz.net)

    By [I.T.S]SystEm32

    Welcome to our web site http://itaq.ynpc.com/itsbbs/

    thanks to SobeIt : P
    ---------------------------------------------------------------------------------------------

      每个Windows进程都有一个相对应的执行体进程(EPROCESS,也就是KTEB),EPROCESS不仅包括了进程的许多属性,还包扩了许多指向其他数据结构的指针,其中包含了大量有用的信息.本文仅讲述如何获得特定进程对应的EPROCESS,EPROCESS的作用及数据结构不在本文讨论范围之内.

    绿盟高手flier在他的文章中提到,使用ZwQuerySystemInformation函数获取所有核心句柄表,线性搜索到进程句柄,其指向的内核对象就是EPROCESS。

    ZwQuerySystemInformation函数原形如下

    NTSYSAPI
    NTSTATUS
    NTAPI
    ZwQuerySystemInformation
    (
        IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
        IN OUT PVOID SystemInformation,
        IN ULONG SystemInformationLength,
        OUT PULONG ReturnLength OPTIONAL
    );

    参数意义如下

    SystemInformationClass:被查询的系统信息的类型,SYSTEM_INFORMATION_CLASS的枚举类型之一

    SystemInformation:指向一个接受系统信息的缓冲区的指针

    SystemInformationLength:缓冲区长度

    ReturnLength:指向一个接受实际返回字节数的变量,可以为0


    为了获取EPROCESS,我们使用SYSTEM_HANDLE_INFORMATION作为第一参数来调用 ZwQuerySystemInformation

    SYSTEM_INFORMATION_CLASS的结构如下

    typedef struct _SYSTEM_HANDLE_INFORMATION
    {
        ULONG            ProcessId;
        UCHAR            ObjectTypeNumber;
        UCHAR            Flags;
        USHORT            Handle;
        PVOID            Object;
        ACCESS_MASK        GrantedAccess;
    } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

    ProcessId:进程标识符

    ObjectTypeNumber;打开的对象的类型

    Flags:句柄属性标志

    Handle:句柄数值,在进程打开的句柄中唯一标识某个句柄

    Object:这个就是句柄对应的EPROCESS的地址

    GrantedAccess:句柄对象的访问权限


    下面我写了一个小程序来获得EPROCESS( GetKTEB.cpp )

    比较faint的是程序写好后发现并未如预期般获得EPROCESS,通过调试发现ZwQuerySystemInformation()返回的进程的句柄中并没有进程本身的句柄

    怎么会这样?难道程序写错了?*_*

    现在只好靠SoftICE给出答案了,CTRL+D唤出SoftICE,随便选了个进程--QQ,让我们来看看SoftICE的输出

    :proc -o QQ
    Process     KPEB      PID  Threads  Pri  User Time  Krnl Time  Status
    QQ         827CD520  11C       2A    8   00000B90   000008D4  Ready

        ---- Handle Table Information ----

        Handle Table:    FFAD93C8  Handle Array: E2BEB000  Entries:   590

        Handle  Ob Hdr *  Object *  Type
        0000    00000000  00000018  ?
        0004    E2DA5E58  E2DA5E70  Section
        0008    FFAB35C8  FFAB35E0  Event
        000C    FFAB3B08  FFAB3B20  Event
        0010    85C70188  85C701A0  Event
        0014    81515778  81515790  Directory
        0018    FFAB7BB2  FFAB7BCA  ?
        001C    814A1858  814A1870  Directory
        0020    80288C88  80288CA0  Event
        0024    E2CFE7F9  E2CFE811  ?
        0028    842D7B08  842D7B20  Event
        002C    80E9B989  80E9B9A1  ?
        0030    E1372198  E13721B0  Section
        0034    814602C0  814602D8  WindowStation
        0038    81455CE0  81455CF8  Desktop
        003C    814602C0  814602D8  WindowStation
        0040    E2B3C1A8  E2B3C1C0  Key
        0044    E286D6E8  E286D700  Key
        0048    E2B3C0E8  E2B3C100  Key
        004C    E2B3C068  E2B3C080  Key
        0050    E2BEE688  E2BEE6A0  Key
        0054    8147C998  8147C9B0  Directory
        0058    829D1128  829D1140  Event
        005C    83F991E8  83F99200  Event
        0060    E2BEE608  E2BEE620  Key
        0064    FFB07568  FFB07580  Event
        0068    801747E8  80174800  Event
        006C    80174828  80174840  Event
        0070    845E8808  845E8820  Event
        0074    81448798  814487B0  Event
        0078    E2B9A888  E2B9A8A0  Key
        007C    845E8648  845E8660  Event
        0080    FF9E2DB8  FF9E2DD0  Mutant
        0084    FF9E2D58  FF9E2D70  Mutant
        0088    83CFC378  83CFC390  Mutant
        008C    801749B0  801749C8  File
        0090    E2C48668  E2C48680  Section
        0094    FF965168  FF965180  Event
        0098    FF9E7D88  FF9E7DA0  Event
        009C    FFAD3DE8  FFAD3E00  Event
        00A0    80AD63C8  80AD63E0  Event
        00A4    E28073A8  E28073C0  Key
        00A8    FF955588  FF9555A0  Thread
        00AC    E2770728  E2770740  Key
        00B0    FF923438  FF923450  Mutant
        00B4    FFAE3B38  FFAE3B50  Mutant
        00B8    83B80728  83B80740  Event
        00BC    83B80668  83B80680  Event
        00C0    E2E3C448  E2E3C460  Section
        00C4    83776A08  83776A20  Thread
        00C8    81489E48  81489E60  Event
        00CC    83776CC8  83776CE0  Event
        00D0    83776C88  83776CA0  Event
        00D4    83776768  83776780  Event
        00D8    E2837D88  E2837DA0  Key
        00DC    8146B3A8  8146B3C0  Event
        00E0    FF908308  FF908320  Event
        00E4    81494868  81494880  Event
        00E8    FF9064C8  FF9064E0  Event
        00EC    FF908FC8  FF908FE0  Event
        00F0    FF908F88  FF908FA0  Event
        00F4    FF955588  FF9555A0  Thread
        00F8    FF908F48  FF908F60  Event
        00FC    E2CB1558  E2CB1570  Port
        0100    FF90A2C8  FF90A2E0  IoCompletion
        0104    E2CFE708  E2CFE720  Port
        0108    FF90A2C8  FF90A2E0  IoCompletion
        010C    837762A8  837762C0  Thread
        0110    8103BBC8  8103BBE0  Event
        0114    813DBDB8  813DBDD0  Event
        0118    FF814788  FF8147A0  Event
        011C    E1358DA8  E1358DC0  Key
        0120    E2CFC428  E2CFC440  Key
        0124    8103B9C8  8103B9E0  Event
        0128    E2C9A968  E2C9A980  Key
        012C    83B34E88  83B34EA0  Event
        0130    E2CFD948  E2CFD960  Key
        0134    83B34E08  83B34E20  Event
        ....
        .....................省略

    看了一阵,确实没有QQ本身进程的Handle,那么怎么办呢?

    想了一会儿...既然Win32子系统是由CSRSS.EXE来管理的,那么用户创建的进程的句柄应该在CSRSS.EXE里面找得到,用SoftICE验证后发现确实如此

    可是这没办法得到指定进程的句柄,和我所需相去甚远,只有另选它路

    后来总算想到解决办法,既然没有进程的句柄,那就创建一个吧,OpenProcess()这个函数可以打开一个进程的句柄,正合所需.

    果然加上这么一句后,ZwQuerySystemInformation()获得了EPROCESS

    修改好的程序代码如下,获得本身进程的EPROCESS地址,稍作修改可获取任意进程

    #include <windows.h>
    #include <stdio.h>
    #include <aclapi.h>
    #include <conio.h>

    /*
    * you'll find a list of NTSTATUS status codes in the DDK header
    * ntstatus.h (\WINDDK\2600.1106\inc\ddk\wxp\)
    */
    #define NT_SUCCESS(status)          ((NTSTATUS)(status)>=0)
    #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
    #define STATUS_ACCESS_DENIED        ((NTSTATUS)0xC0000022L)

    /*
    *************************************************************************
    * ntddk.h
    */
    typedef LONG    NTSTATUS;
    typedef ULONG    ACCESS_MASK;
    /*
    * ntdef.h
    *************************************************************************
    */

    /*
    *************************************************************************
    * <<Windows NT/2000 Native API Reference>> - Gary Nebbett
    */

    typedef enum _SYSTEM_INFORMATION_CLASS
    {
        SystemHandleInformation = 16
    } SYSTEM_INFORMATION_CLASS;

    /*
    *Information Class 16
    */
    typedef struct _SYSTEM_HANDLE_INFORMATION
    {
        ULONG            ProcessId;
        UCHAR            ObjectTypeNumber;
        UCHAR            Flags;
        USHORT            Handle;
        PVOID            Object;
        ACCESS_MASK        GrantedAccess;
    } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

    #define InitializeObjectAttributes( p, n, a, r, s ) { (p)->Length = sizeof( OBJECT_ATTRIBUTES ); (p)->RootDirectory = r; (p)->Attributes = a; (p)->ObjectName = n; (p)->SecurityDescriptor = s; (p)->SecurityQualityOfService = NULL; }
    /*
    *************************************************************************
    * <<Windows NT/2000 Native API Reference>> - Gary Nebbett
    *************************************************************************
    */
    typedef ULONG    ( __stdcall *RTLNTSTATUSTODOSERROR    ) ( IN NTSTATUS Status );
    typedef NTSTATUS ( __stdcall *ZWQUERYSYSTEMINFORMATION ) ( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );
    /************************************************************************
    *                                                                      *
    *                            Function Prototype                        *
    *                                                                      *
    ************************************************************************/

    static DWORD GetEprocessFromPid    ( ULONG PID );
    static BOOL  LocateNtdllEntry ( void );


    /************************************************************************
    *                                                                      *
    *                            Static Global Var                         *
    *                                                                      *
    ************************************************************************/

    static RTLNTSTATUSTODOSERROR    RtlNtStatusToDosError    = NULL;
    static ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;

    static HMODULE                    hModule                     = NULL;
    /************************************************************************/


    static DWORD GetEprocessFromPid ( ULONG    PID )
    {
        NTSTATUS                    status;
        PVOID                        buf   = NULL;
        ULONG                        size  = 1;
        ULONG                        NumOfHandle = 0;
        ULONG                        i;
        PSYSTEM_HANDLE_INFORMATION    h_info  = NULL;

        for ( size = 1; ; size *= 2 )
        {
            if ( NULL == ( buf = calloc( size, 1 ) ) )
            {
                fprintf( stderr, "calloc( %u, 1 ) failed\n", size );
                goto GetEprocessFromPid_exit;
            }
            status = ZwQuerySystemInformation( SystemHandleInformation, buf, size, NULL );
            if ( !NT_SUCCESS( status ) )
            {
                if ( STATUS_INFO_LENGTH_MISMATCH == status )
                {
                    free( buf );
                    buf = NULL;
                }
                else
                {
                    printf( "ZwQuerySystemInformation() failed");
                    goto GetEprocessFromPid_exit;
                }
            }
            else
            {
                break;
            }
        }  /* end of for */

        //返回到缓冲区的首先是一个ULONG类型的数据,表示有多少数组
        NumOfHandle = (ULONG)buf;

        h_info = ( PSYSTEM_HANDLE_INFORMATION )((ULONG)buf+4);
        
        for(i = 0; i<NumOfHandle ;i++)
        {
            if( ( h_info[i].ProcessId == PID )&&( h_info[i].ObjectTypeNumber == 5  ))//&&( h_info[i].Handle==0x3d8 ) )
            {
                printf("Handle:0x%x,OBJECT 0x%x\n\r",h_info[i].Handle,h_info[i].Object);
                return((DWORD)(h_info[i].Object));
            }
        }
    GetEprocessFromPid_exit:
        if ( buf != NULL )
        {
            free( buf );
            buf = NULL;
        }
        return(FALSE);
    }


    /*
    * ntdll.dll
    */
    static BOOL LocateNtdllEntry ( void )
    {
        BOOL    ret         = FALSE;
        char    NTDLL_DLL[] = "ntdll.dll";
        HMODULE ntdll_dll   = NULL;


        if ( ( ntdll_dll = GetModuleHandle( NTDLL_DLL ) ) == NULL )
        {
            printf( "GetModuleHandle() failed");
            return( FALSE );
        }
        if ( !( ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( ntdll_dll, "ZwQuerySystemInformation" ) ) )
        {
            goto LocateNtdllEntry_exit;
        }
        ret = TRUE;

    LocateNtdllEntry_exit:

        if ( FALSE == ret )
        {
            printf( "GetProcAddress() failed");
        }
        ntdll_dll = NULL;
        return( ret );
    }  /* end of LocateNtdllEntry */


    int main(int argc,char **argv)
    {

        LocateNtdllEntry( );

        //打开自身句柄,这样才能在handle列表中找到自己,PROCESS 对应 ObjectTypeNum 为5
        OpenProcess( PROCESS_ALL_ACCESS,FALSE,GetCurrentProcessId() );

        DWORD Addr = GetEprocessFromPid( (DWORD)GetCurrentProcessId() );

        printf("result: Current EPROCESS's Address is 0x%x \n\r",Addr);

        return TRUE;
    }
  • 相关阅读:
    Jmeter实际操作
    Windows+JMeter+InfluxDB+Grafana搭建可视化实时监控
    c# 新语法
    js 判断打印或取消 打印插件
    BACnet协议
    串口偶尔出现串口乱码原因
    面向流程葵花宝典
    lwip框架示意图
    linux 算法介绍
    什么是序列化与反序列化
  • 原文地址:https://www.cnblogs.com/Safe3/p/1334639.html
Copyright © 2020-2023  润新知