发新话题
打印

[转载]获得进程的EPROCESS

[转载]获得进程的EPROCESS

信息来源:blacksky

  每个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&#39;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&#39;s Address is 0x%x \n\r",Addr);

   return TRUE;
}
qq310926是我唯一用号,除此之外有其他号码号自称邪八冰血封情,则非本人。

TOP

发新话题