2013年8月27日星期二

替换进程对象的OpenProcedure函数

#include <ntddk.h>

/*
功能:替换进程对象的OpenProcedure函数.
本代码只适宜于windows server 2008 r2 64位系统.
打开系统任务管理器总是CPU占用率100%.
*/

/*
1: kd> vertarget
Windows 7 Kernel Version 7601 (Service Pack 1) MP (2 procs) Free x64
Product: Server, suite: Enterprise TerminalServer SingleUserTS
Built by: 7601.18205.amd64fre.win7sp1_gdr.130708-1532
Machine Name:
Kernel base = 0xfffff800`01603000 PsLoadedModuleList = 0xfffff800`018466d0
Debug session time: Tue Aug 27 10:19:43.173 2013 (UTC + 8:00)
System Uptime: 0 days 0:02:44.876
1: kd> dq PsProcessType
fffff800`018b0020  fffffa80`03c8fde0 00000040`00026161
fffff800`018b0030  fffffa80`03cc3040 fffffa80`03c2ffc0
fffff800`018b0040  a1db3ffe`00010001 fffffa80`03cdc8a0
fffff800`018b0050  fffffa80`03c8fc90 00000001`00000000
fffff800`018b0060  00000000`000fdd3e 00000040`00000000
fffff800`018b0070  fffffa80`03c01c00 00000000`00000004
fffff800`018b0080  fffff683`ffffff78 0000000f`00000001
fffff800`018b0090  00026161`00000200 00000000`0013ffff
1: kd> dt _object_type fffffa80`03c8fde0
nt!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`03c8fde0 - 0xfffffa80`03c8fde0 ]
   +0x010 Name             : _UNICODE_STRING "Process"
   +0x020 DefaultObject    : (null)
   +0x028 Index            : 0x7 ''
   +0x02c TotalNumberOfObjects : 0x26
   +0x030 TotalNumberOfHandles : 0xc7
   +0x034 HighWaterNumberOfObjects : 0x29
   +0x038 HighWaterNumberOfHandles : 0xc8
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x636f7250
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffff8a0`02a511a0 - 0xfffff8a0`02a511a0 ]
1: kd> dt _OBJECT_TYPE_INITIALIZER fffffa80`03c8fde0+40
nt!_OBJECT_TYPE_INITIALIZER
   +0x000 Length           : 0x70
   +0x002 ObjectTypeFlags  : 0x4a 'J'
   +0x002 CaseInsensitive  : 0y0
   +0x002 UnnamedObjectsOnly : 0y1
   +0x002 UseDefaultObject : 0y0
   +0x002 SecurityRequired : 0y1
   +0x002 MaintainHandleCount : 0y0
   +0x002 MaintainTypeList : 0y0
   +0x002 SupportsObjectCallbacks : 0y1
   +0x002 CacheAligned     : 0y0
   +0x004 ObjectTypeCode   : 0
   +0x008 InvalidAttributes : 0xb0
   +0x00c GenericMapping   : _GENERIC_MAPPING
   +0x01c ValidAccessMask  : 0x1fffff
   +0x020 RetainAccess     : 0x101000
   +0x024 PoolType         : 0 ( NonPagedPool )
   +0x028 DefaultPagedPoolCharge : 0x1000
   +0x02c DefaultNonPagedPoolCharge : 0x528
   +0x030 DumpProcedure    : (null)
   +0x038 OpenProcedure    : 0xfffff800`0194bca0     long  nt!PspProcessOpen+0
   +0x040 CloseProcedure   : 0xfffff800`01932fd0     void  nt!PspProcessClose+0
   +0x048 DeleteProcedure  : 0xfffff800`01932280     void  nt!PspProcessDelete+0
   +0x050 ParseProcedure   : (null)
   +0x058 SecurityProcedure : 0xfffff800`01963cd0     long  nt!SeDefaultObjectMethod+0
   +0x060 QueryNameProcedure : (null)
   +0x068 OkayToCloseProcedure : (null)
1: kd> uf nt!PspProcessOpen
nt!PspProcessOpen:
fffff800`0194bca0 488b4c2428      mov     rcx,qword ptr [rsp+28h]
fffff800`0194bca5 80fa01          cmp     dl,1
fffff800`0194bca8 7516            jne     nt!PspProcessOpen+0x20 (fffff800`0194bcc0)

nt!PspProcessOpen+0xa:
fffff800`0194bcaa 410fbaa03c0400000b bt    dword ptr [r8+43Ch],0Bh
fffff800`0194bcb3 720b            jb      nt!PspProcessOpen+0x20 (fffff800`0194bcc0)

nt!PspProcessOpen+0x15:
fffff800`0194bcb5 410fbaa13c0400000b bt    dword ptr [r9+43Ch],0Bh
fffff800`0194bcbe 7211            jb      nt!PspProcessOpen+0x31 (fffff800`0194bcd1)

nt!PspProcessOpen+0x20:
fffff800`0194bcc0 8b01            mov     eax,dword ptr [rcx]
fffff800`0194bcc2 0fbae00a        bt      eax,0Ah
fffff800`0194bcc6 7306            jae     nt!PspProcessOpen+0x2e (fffff800`0194bcce)

nt!PspProcessOpen+0x28:
fffff800`0194bcc8 0fbae80c        bts     eax,0Ch
fffff800`0194bccc 8901            mov     dword ptr [rcx],eax

nt!PspProcessOpen+0x2e:
fffff800`0194bcce 33c0            xor     eax,eax
fffff800`0194bcd0 c3              ret

nt!PspProcessOpen+0x31:
fffff800`0194bcd1 f701fee70f00    test    dword ptr [rcx],0FE7FEh
fffff800`0194bcd7 74e7            je      nt!PspProcessOpen+0x20 (fffff800`0194bcc0)

nt!PspProcessOpen+0x39:
fffff800`0194bcd9 b8220000c0      mov     eax,0C0000022h
fffff800`0194bcde c3              ret

那些结构就不定义了,直接使用硬编码.
*/

unsigned __int64 g_old = 0;

/*
关于函数原型的说明:
有处理函数的,可以用IDA分析(32位的已经分析出,64位的需要自己分析.).
没有处理函数的,一个想法是可以任意的,另一个想法是任意的如何获取数据信息呢?
关于参数的个数,我猜是宁多勿少,还有一个调用后的平衡问题,有无此问题?
我这里分析的不一定正确.
*/
typedef NTSTATUS (*PspProcessOpen)(unsigned __int64 arg1,unsigned __int64 arg2,unsigned __int64 arg3,unsigned __int64 arg4,
                      unsigned __int64 arg5,unsigned __int64 arg6,unsigned __int64 arg7,unsigned __int64 arg8,unsigned __int64 arg9);
PspProcessOpen g_pPspProcessOpen;

long MyPspProcessOpen(unsigned __int64 arg1,unsigned __int64 arg2,unsigned __int64 arg3,unsigned __int64 arg4,
                      unsigned __int64 arg5,unsigned __int64 arg6,unsigned __int64 arg7,unsigned __int64 arg8
                      ,unsigned __int64 arg9)//,unsigned __int64 arg10
    /*
    PspProcessOpen显示的是long类型,但是经分析是NTSTATUS类型的,这其实是一致的.

    VOID
    typedef
    (*OB_OPEN_METHOD)(
    IN OB_OPEN_REASON OpenReason,
    IN PEPROCESS Process,
    IN PVOID Object,
    IN ACCESS_MASK GrantedAccess,
    IN ULONG HandleCount OPTIONAL
    )//摘自wdk的说明文档.

    一是前四个参数分析通过四个寄存器传递:RCX、RDX、R8、R9,如果还有更多的参数,才通过椎栈传递。
    二是调用者负责椎栈空间的分配与回收。

    外加一个返回地址留空间

    在Win2000和XP Vista系统下各个函数的参数有可能不一样,比如OpenProcedure 在2000下是8个参数,XP和Vista下是9个参数。

    根据反汇编:mov     rcx,qword ptr [rsp+28h]
    得出,至少有5个参数,再加会上默认的4个,所以至少有九个参数.
    */
{
    //KdBreakPoint();//DbgBreakPoint()
    KdPrint(("MyPspProcessOpen is called!\n"));

    /*
    在这里能做点啥呢?
    参数的类型代表的函数都不知道,只有分析汇编了.
    */
     
    return g_pPspProcessOpen(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);//如果参数个数过少会蓝屏的,arg10
}

VOID DriverUnload(PDRIVER_OBJECT DriverObject)
    /*
    恢复.
    */
{  
    unsigned __int64 x = 0;

    x = *(unsigned __int64 *)PsProcessType;

    x = (x + 0x40);

    x += 0x38;

    *(unsigned __int64 *)x = g_old;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    unsigned __int64 x = 0;
    unsigned __int64 * * Procedure[9];

    KdBreakPoint();//DbgBreakPoint()
    DriverObject->DriverUnload = DriverUnload;

    x = *(unsigned __int64 *)PsProcessType;

    x = (x + 0x40);

    g_old = *(unsigned __int64 *)(x + 0x38);

    x += 0x38;
    *(unsigned __int64 *)x = MyPspProcessOpen;

    g_pPspProcessOpen = g_old;

    return STATUS_SUCCESS;
}

/*
验证一下:
0: kd> dt _OBJECT_TYPE_INITIALIZER fffffa80`03c8fde0+40
nt!_OBJECT_TYPE_INITIALIZER
   +0x000 Length           : 0x70
   +0x002 ObjectTypeFlags  : 0x4a 'J'
   +0x002 CaseInsensitive  : 0y0
   +0x002 UnnamedObjectsOnly : 0y1
   +0x002 UseDefaultObject : 0y0
   +0x002 SecurityRequired : 0y1
   +0x002 MaintainHandleCount : 0y0
   +0x002 MaintainTypeList : 0y0
   +0x002 SupportsObjectCallbacks : 0y1
   +0x002 CacheAligned     : 0y0
   +0x004 ObjectTypeCode   : 0
   +0x008 InvalidAttributes : 0xb0
   +0x00c GenericMapping   : _GENERIC_MAPPING
   +0x01c ValidAccessMask  : 0x1fffff
   +0x020 RetainAccess     : 0x101000
   +0x024 PoolType         : 0 ( NonPagedPool )
   +0x028 DefaultPagedPoolCharge : 0x1000
   +0x02c DefaultNonPagedPoolCharge : 0x528
   +0x030 DumpProcedure    : (null)
   +0x038 OpenProcedure    : 0xfffff880`048010e0     long  test!MyPspProcessOpen+0
   +0x040 CloseProcedure   : 0xfffff800`01932fd0     void  nt!PspProcessClose+0
   +0x048 DeleteProcedure  : 0xfffff800`01932280     void  nt!PspProcessDelete+0
   +0x050 ParseProcedure   : (null)
   +0x058 SecurityProcedure : 0xfffff800`01963cd0     long  nt!SeDefaultObjectMethod+0
   +0x060 QueryNameProcedure : (null)
   +0x068 OkayToCloseProcedure : (null)

听说此方法可以过64位Windows的PG机制,可是在开启调试的机器上总是出现:Fatal System Error: 0x00000109.

made by correy
made at 2013.08.27
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com
*/

没有评论:

发表评论