获得进程的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;
}
posted @ 2008-11-16 21:17  有安科技  阅读(1075)  评论(0编辑  收藏  举报