2013年8月30日星期五

揪出驱动卸载而没有释放的内存

因为以前在工程中解决过,在实际中经常发生,所以有此文,以备终结和以后使用.

先来一个示例的工程,代码如下:
#include <ntifs.h>

#define TAG 'tset' //本驱动在内存中的标志,即test.

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{  

}

#pragma INITCODE
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
    NTSTATUS status = STATUS_SUCCESS ;
    PVOID p = 0;

    KdBreakPoint();// == DbgBreakPoint()        

    p = ExAllocatePoolWithTag(NonPagedPool, 9, TAG);
    if (p == NULL) {
        status = STATUS_UNSUCCESSFUL;
    }  

    DriverObject->DriverUnload = Unload;  
   
    return status;
}

上面的代码很简单,相信大家都能看出来,如果加载成功将会出现本文的话题.
可是实际上的工程很复杂,可能有几十个文件,每个文件几千行代码.

现在要做的是:即使有代码,先无视代码,或者把代码看的很复杂.

1.加载驱动.
2.启动和配置驱动程序验证程序管理器,这一步一定要配置池跟踪选项,
  详细的可以参考:http://bbs.pediy.com/showthread.php?t=156804
3.重启计算机,重启之前可以查看一下自己刚才的配置.
4.再次加载驱动.
5.如果加载成功,就开始卸载.这时最好双击调试链接上.
  卸载完毕,即Unload函数的代码运行完毕之后,出现蓝屏.以下分析估计也可以适用于内存转储文件.
  蓝屏内容如下:
0: kd> g

*** Fatal System Error: 0x000000c4
                       (0x0000000000000062,0xFFFFFA80059C5C88,0xFFFFFA8004F5A010,0x0000000000000001)

Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.

Connected to Windows 7 7601 x64 target at (Sat Jul 13 10:17:30.820 2013 (UTC + 8:00)), ptr64 TRUE
Loading Kernel Symbols
...............................................................
...................................

Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long.
Run !sym noisy before .reload to track down problems loading symbols.

.............................
........
Loading User Symbols
.................................
Loading unloaded module list
.....Unable to enumerate user-mode unloaded modules, Win32 error 0n30
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

Use !analyze -v to get detailed debugging information.

BugCheck C4, {62, fffffa80059c5c88, fffffa8004f5a010, 1}

Probably caused by : test.sys

Followup: MachineOwner
---------

nt!DbgBreakPointWithStatus:
fffff800`0167bb90 cc              int     3


按照提示运行!analyze -v命令.
0: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_VERIFIER_DETECTED_VIOLATION (c4)
A device driver attempting to corrupt the system has been caught.  This is
because the driver was specified in the registry as being suspect (by the
administrator) and the kernel has enabled substantial checking of this driver.
If the driver attempts to corrupt the system, bugchecks 0xC4, 0xC1 and 0xA will
be among the most commonly seen crashes.
Arguments:
Arg1: 0000000000000062, A driver has forgotten to free its pool allocations prior to unloading.
Arg2: fffffa80059c5c88, name of the driver having the issue.
Arg3: fffffa8004f5a010, verifier internal structure with driver information.
Arg4: 0000000000000001, total # of (paged+nonpaged) allocations that weren't freed.
  Type !verifier 3 drivername.sys for info on the allocations
  that were leaked that caused the bugcheck.

Debugging Details:
------------------


BUGCHECK_STR:  0xc4_62

IMAGE_NAME:  test.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  51e0b488

MODULE_NAME: test

FAULTING_MODULE: fffff88004c72000 test

VERIFIER_DRIVER_ENTRY: dt nt!_MI_VERIFIER_DRIVER_ENTRY fffffa8004f5a010
Symbol nt!_MI_VERIFIER_DRIVER_ENTRY not found.

DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT

PROCESS_NAME:  services.exe

CURRENT_IRQL:  2

LAST_CONTROL_TRANSFER:  from fffff8000176e212 to fffff8000167bb90

STACK_TEXT:
fffff880`03f31c98 fffff800`0176e212 : 00000000`00000062 fffffa80`054d28f0 00000000`00000065 fffff800`016beb78 : nt!DbgBreakPointWithStatus
fffff880`03f31ca0 fffff800`0176effe : fffffa80`00000003 00000000`00000000 fffff800`016bf3d0 00000000`000000c4 : nt!KiBugCheckDebugBreak+0x12
fffff880`03f31d00 fffff800`01683e44 : 00000000`00000000 fffff880`04c79000 00000000`00000003 00000000`00000000 : nt!KeBugCheck2+0x71e
fffff880`03f323d0 fffff800`01b0c3dc : 00000000`000000c4 00000000`00000062 fffffa80`059c5c88 fffffa80`04f5a010 : nt!KeBugCheckEx+0x104
fffff880`03f32410 fffff800`01b1b54a : 00000000`00000001 00000000`00000000 fffff880`04c72000 00000000`00000001 : nt!VerifierBugCheckIfAppropriate+0x3c
fffff880`03f32450 fffff800`0176fa70 : 00000000`00000000 00000000`00000000 fffff800`017f8e80 00000000`00000000 : nt!VfPoolCheckForLeaks+0x4a
fffff880`03f32490 fffff800`01a352de : fffffa80`059c5bd0 00000000`00000000 00000000`00000000 00000000`00000000 : nt!VfTargetDriversRemove+0x160
fffff880`03f32530 fffff800`01a59d33 : 00000000`00000000 00000000`000e0082 00000000`00000000 00000000`00000001 : nt!VfDriverUnloadImage+0x2e
fffff880`03f32560 fffff800`01a5a1ad : 00000000`00000000 fffffa80`059c5bd0 00000000`00000000 00000000`00010200 : nt!MiUnloadSystemImage+0x283
fffff880`03f325d0 fffff800`01afb6e1 : 00000000`00000000 fffff880`03f328f0 fffffa80`03cfb180 00000000`00000018 : nt!MmUnloadSystemImage+0x4d
fffff880`03f32610 fffff800`0168d004 : 00000000`00000000 fffff880`03f328f0 fffffa80`03cfb180 fffff880`03f328f0 : nt!IopDeleteDriver+0x41
fffff880`03f32640 fffff800`01a6ba3e : fffff880`03f328f0 00000000`00000000 00000000`c0000001 fffff800`00000000 : nt!ObfDereferenceObject+0xd4
fffff880`03f326a0 fffff800`01682fd3 : fffffa80`054d28f0 fffff880`03f328c0 00000000`00000001 fffff980`01450000 : nt!IopUnloadDriver+0x45c
fffff880`03f32870 fffff800`0167f570 : fffff800`01a6b737 00000000`0104e820 00000000`00000001 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
fffff880`03f32a08 fffff800`01a6b737 : 00000000`0104e820 00000000`00000001 00000000`00000000 00000000`00cb8f20 : nt!KiServiceLinkage
fffff880`03f32a10 fffff800`01682fd3 : fffffa80`054d28f0 fffff880`03f32c60 00000000`00000000 00000000`00000000 : nt!IopUnloadDriver+0x155
fffff880`03f32be0 00000000`779a2b8a : 00000000`ffb75879 00000000`00341460 00000000`00341460 00000000`00000334 : nt!KiSystemServiceCopyEnd+0x13
00000000`0104e7f8 00000000`ffb75879 : 00000000`00341460 00000000`00341460 00000000`00000334 00000000`0000000a : ntdll!NtUnloadDriver+0xa
00000000`0104e800 00000000`ffb7575a : 00000000`0000000a 00000000`00000000 00000000`0104e970 00000000`00000334 : services!ScUnloadDriver+0xa9
00000000`0104e840 00000000`ffb6118b : 00000000`00000000 00000000`00000020 00000000`00000001 00000000`00240022 : services!ScControlDriver+0x112
00000000`0104e870 00000000`ffb4907b : 00000000`00000001 00000000`0104ede0 00000000`00000000 000007fe`00000000 : services!ScControlService+0x192
00000000`0104e940 000007fe`ff5a23d5 : 00000000`00000003 00000000`0104edf8 00000000`0104ef40 000007fe`ff5a2396 : services!RControlService+0x4b
00000000`0104e9b0 000007fe`ff5969b2 : 00000000`0104ede0 00000000`ffb80192 00000000`00000020 00000000`ffb7ed54 : RPCRT4!Invoke+0x65
00000000`0104ea10 000007fe`ff59338d : 00000000`0104f120 00000000`00000000 00000000`00000000 00000000`00000000 : RPCRT4!NdrStubCall2+0x32a
00000000`0104f030 000007fe`ff5950f4 : 00000000`00000000 00000000`00000001 00000000`00000000 00000000`003ea9c0 : RPCRT4!NdrServerCall2+0x1d
00000000`0104f060 000007fe`ff594f56 : 00000000`00000000 00000000`003e1680 00000000`0104f210 00000000`003d2090 : RPCRT4!DispatchToStubInCNoAvrf+0x14
00000000`0104f090 000007fe`ff595679 : 00000000`00361878 000007fe`ff58a9df 00000000`00000308 00000000`003ea870 : RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x146
00000000`0104f1b0 000007fe`ff59532d : 00000000`00369a00 00000000`0125e8d0 000007fe`ff570000 00000000`0034e920 : RPCRT4!LRPC_SCALL::DispatchRequest+0x149
00000000`0104f290 000007fe`ff5b2e7f : 00000000`00000000 00000000`0034a820 00000000`00000000 00000000`00000001 : RPCRT4!LRPC_SCALL::HandleRequest+0x20d
00000000`0104f3c0 000007fe`ff5b2a35 : 00000000`ffb57f48 00000000`00000000 00000000`0034a920 00000000`00000000 : RPCRT4!LRPC_ADDRESS::ProcessIO+0x3bf
00000000`0104f500 00000000`7796b68b : 00000000`00000048 00000000`00000001 00000000`00000000 00000000`00000000 : RPCRT4!LrpcIoComplete+0xa5
00000000`0104f590 00000000`7796feff : 00000000`00000000 00000000`00000000 00000000`0000ffff 00000000`00000000 : ntdll!TppAlpcpExecuteCallback+0x26b
00000000`0104f620 00000000`7774652d : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!TppWorkerThread+0x3f8
00000000`0104f920 00000000`7797c521 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
00000000`0104f950 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d


STACK_COMMAND:  kb

FOLLOWUP_NAME:  MachineOwner

FAILURE_BUCKET_ID:  X64_0xc4_62_VRF_LEAKED_POOL_IMAGE_test.sys

BUCKET_ID:  X64_0xc4_62_VRF_LEAKED_POOL_IMAGE_test.sys

Followup: MachineOwner
---------

上面说:
Arg2: fffffa80059c5c88, name of the driver having the issue.
输入:db fffffa80059c5c88
0: kd> db fffffa80059c5c88
fffffa80`059c5c88  74 00 65 00 73 00 74 00-2e 00 73 00 79 00 73 00  t.e.s.t...s.y.s.
fffffa80`059c5c98  00 00 00 00 00 00 00 00-0e 00 36 02 43 63 56 70  ..........6.CcVp
fffffa80`059c5ca8  60 5b 9c 05 80 fa ff ff-a0 b2 cb 03 80 fa ff ff  `[..............
fffffa80`059c5cb8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
fffffa80`059c5cc8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
fffffa80`059c5cd8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
fffffa80`059c5ce8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
fffffa80`059c5cf8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
果然不错.

再看:Arg3: fffffa8004f5a010, verifier internal structure with driver information.
估计这是一个结构,啥结构暂时没有深入查看.
不过windbg帮助文档说这个参数:Reserved.

再看:Arg4: 0000000000000001, total # of (paged+nonpaged) allocations that weren't freed.
这个是申请而没有释放的次数(包含分页的和不分页的),不是内存大小.

接下来就是乖乖的运行:
Type !verifier 3 drivername.sys for info on the allocations
  that were leaked that caused the bugcheck.
的提示.
0: kd> !verifier 3 test.sys

Verify Level fbf ... enabled options are:
  Special pool
  Special irql
  Inject random low-resource API failures
  All pool allocations checked on unload
  Io subsystem checking enabled
  Deadlock detection enabled
  DMA checking enabled
  Security checks enabled
  Force pending I/O requests
  IRP Logging
  Miscellaneous checks enabled

Summary of All Verifier Statistics

RaiseIrqls                             0x0
AcquireSpinLocks                       0x0
Synch Executions                       0x0
Trims                                  0x24d9

Pool Allocations Attempted             0x2757b
Pool Allocations Succeeded             0x2757b
Pool Allocations Succeeded SpecialPool 0x2757b
Pool Allocations With NO TAG           0x0
Pool Allocations Failed                0x0
Resource Allocations Failed Deliberately   0x0

Current paged pool allocations         0x0 for 00000000 bytes
Peak paged pool allocations            0x0 for 00000000 bytes
Current nonpaged pool allocations      0x1 for 0000000C bytes
Peak nonpaged pool allocations         0x1 for 0000000C bytes

Driver Verification List

Entry     State           NonPagedPool   PagedPool   Module

fffffa8003c2f740 Loaded           0000000c       00000000    test.sys

Current Pool Allocations  00000001    00000000
Current Pool Bytes        0000000c    00000000
Peak Pool Allocations     00000001    00000000
Peak Pool Bytes           0000000c    00000000

PoolAddress  SizeInBytes    Tag       CallersAddress
fffff9800933eff0     0x0000000c     test      fffff88004c73043


可以看到:
Peak Pool Allocations     00000001    00000000
Peak Pool Bytes           0000000c    00000000

PoolAddress  SizeInBytes    Tag       CallersAddress
fffff9800933eff0     0x0000000c     test      fffff88004c73043

关于内存标志的提示:
有的标志本驱动没有定义,却出现在本驱动中,这些标志是系统定义的,使用不当造成的.
例如:RtlConvertSidToUnicodeString,RtlAnsiStringToUnicodeString,RtlUnicodeStringToAnsiString等.
不过这些内存的标记,我忘记了.

这里只做非分页的内存泄漏,没有做分页内存的演示.
有一次没有释放,申请的内存的大小是12.

看一下:
0: kd> db fffff9800933eff0
fffff980`0933eff0  d7 d7 d7 d7 d7 d7 d7 d7-d7 d7 d7 d7 d7 d7 d7 d7  ................
fffff980`0933f000  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
fffff980`0933f010  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
fffff980`0933f020  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
fffff980`0933f030  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
fffff980`0933f040  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
fffff980`0933f050  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
fffff980`0933f060  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
好像是16个字节.

0: kd> u fffff88004c73043
test!DriverEntry+0x33 [e:\driver\test\test.c @ 20]:
fffff880`04c73043 4889442428      mov     qword ptr [rsp+28h],rax
fffff880`04c73048 48837c242800    cmp     qword ptr [rsp+28h],0
fffff880`04c7304e 7508            jne     test!DriverEntry+0x48 (fffff880`04c73058)
fffff880`04c73050 c7442420010000c0 mov     dword ptr [rsp+20h],0C0000001h
fffff880`04c73058 488b442440      mov     rax,qword ptr [rsp+40h]
fffff880`04c7305d 488d0d1c000000  lea     rcx,[test!Unload (fffff880`04c73080)]
fffff880`04c73064 48894868        mov     qword ptr [rax+68h],rcx
fffff880`04c73068 8b442420        mov     eax,dword ptr [rsp+20h]

注意这一步要正确的加载符号文件.
看到了吧!
就是e:\driver\test\test.c文件的第20行申请的内存没有释放.

至此分析完毕,具体的解决办法我就不说了,相信你是知道的.

总结和心得:
解决问题,需要思路和方法,方法和思路是动脑子想出来的,我无人可问,其次是查询和搜索.
如果没有思路和方法,无头苍蝇的乱转,转了很长时间是没有收获和进展的.
如果你会了,其实这也很简单的.

关于没有源码的驱动卸载后仍在系统中的内存另论.
关于运行过程中的内核的内存泄漏,可以参考:http://bbs.pediy.com/showthread.php?t=154015


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

书于匆忙之中,如果不当之处,敬请指出.


2013.11.19补充:
权威的参照:
http://msdn.microsoft.com/en-us/library/windows/hardware/dn457995(v=vs.85).aspx
也就是多两个命令:
对调用的地址运行:ln 0xXXXXXXXXXXX
对申请到的内存地址运行:!verifier 0x80 0xXXXXXXXXXXX
建议:如果不会用!verifier 0x80命令,不要对ExAllocatePoolWithTag函数进行封装.
             会用!verifier 0x80命令,可以对ExAllocatePoolWithTag函数进行封装.

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
*/

2013年8月24日星期六

枚举命名的内核对象的类型

#include <ntifs.h>

/*
功能:枚举命名的内核对象的类型.
说明:本代码只适宜于windows server 2008 r2 64位版本.
*/

/*
0: 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`0164d000 PsLoadedModuleList = 0xfffff800`018906d0
Debug session time: Fri Aug 23 14:58:58.968 2013 (UTC + 8:00)
System Uptime: 0 days 20:30:10.037
0: kd> dt _OBJECT_DIRECTORY
nt!_OBJECT_DIRECTORY
+0x000 HashBuckets      : [37] Ptr64 _OBJECT_DIRECTORY_ENTRY
+0x128 Lock             : _EX_PUSH_LOCK
+0x130 DeviceMap        : Ptr64 _DEVICE_MAP
+0x138 SessionId        : Uint4B
+0x140 NamespaceEntry   : Ptr64 Void
+0x148 Flags            : Uint4B
0: kd> dt _OBJECT_DIRECTORY_ENTRY
nt!_OBJECT_DIRECTORY_ENTRY
+0x000 ChainLink        : Ptr64 _OBJECT_DIRECTORY_ENTRY
+0x008 Object           : Ptr64 Void
+0x010 HashValue        : Uint4B
1: kd> dt _OBJECT_TYPE
nt!_OBJECT_TYPE
+0x000 TypeList         : _LIST_ENTRY
+0x010 Name             : _UNICODE_STRING
+0x020 DefaultObject    : Ptr64 Void
+0x028 Index            : UChar
+0x02c TotalNumberOfObjects : Uint4B
+0x030 TotalNumberOfHandles : Uint4B
+0x034 HighWaterNumberOfObjects : Uint4B
+0x038 HighWaterNumberOfHandles : Uint4B
+0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
+0x0b0 TypeLock         : _EX_PUSH_LOCK
+0x0b8 Key              : Uint4B
+0x0c0 CallbackList     : _LIST_ENTRY
*/

#define TAG 'tset' //test

typedef struct _OBJECT_DIRECTORY_ENTRY {
    struct _OBJECT_DIRECTORY_ENTRY * ChainLink;
    void * Object;
    int HashValue;
} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;

typedef struct _OBJECT_DIRECTORY {
    struct _OBJECT_DIRECTORY_ENTRY *HashBuckets[37];
    struct _OBJECT_DIRECTORY_ENTRY **Lock;
    void * DeviceMap;
    USHORT SessionId;
    void * NamespaceEntry;
    int Flags;
} OBJECT_DIRECTORY, *POBJECT_DIRECTORY;

typedef struct _OBJECT_TYPE {
    LIST_ENTRY TypeList;
    UNICODE_STRING Name;
    //.......
} OBJECT_TYPE;

//一个导出但没有公开的函数
typedef OBJECT_TYPE * (*ObGetObjectType)(IN PVOID pObject);
ObGetObjectType g_pObGetObjectType;

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
    UNICODE_STRING ObjectTypes;
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE Handle = NULL;
    POBJECT_DIRECTORY ObjectTypes_Directory = NULL;
    int i = 0;
    UNICODE_STRING usObGetObjectType;
    OBJECT_TYPE * pot;
    PUNICODE_STRING pu;
    ULONG  Length = 512;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    OBJECT_DIRECTORY_ENTRY * p = 0;

    KdBreakPoint();//DbgBreakPoint()

    RtlInitUnicodeString( &usObGetObjectType, L"ObGetObjectType" );
    g_pObGetObjectType = MmGetSystemRoutineAddress(&usObGetObjectType);
    if (g_pObGetObjectType == NULL)
    {
        return STATUS_UNSUCCESSFUL;
    }

    RtlInitUnicodeString(&ObjectTypes,L"\\ObjectTypes");//这里也可以直接填写对象空间的根目录,及L"\\".试试看看效果.肯定是不正确的.
    InitializeObjectAttributes(&ObjectAttributes,&ObjectTypes,0,0,0);

    status = ZwOpenDirectoryObject(&Handle, DIRECTORY_QUERY, &ObjectAttributes);
    if (NT_SUCCESS (status))
    {
        status = ObReferenceObjectByHandle(Handle, FILE_READ_ACCESS, NULL, KernelMode, (PVOID *)&ObjectTypes_Directory, NULL);
        if (NT_SUCCESS (status))
        {
            for ( ; i<37 ;i++)
            {
                //__try
                //{
                //    WCHAR w = *(WCHAR *)(ObjectTypes_Directory->HashBuckets[i]->Object);//试探内存是否可访问.MmIsAddressValid要非分页,ProbeForRead 是用户模式.
                //}
                //__except (EXCEPTION_EXECUTE_HANDLER)
                //{
                //    continue;
                //}  

                if (ObjectTypes_Directory->HashBuckets[i] == NULL)
                {
                    continue;
                }

                p = ObjectTypes_Directory->HashBuckets[i];
                for ( ; ; )
                {
                    pot = g_pObGetObjectType(ObjectTypes_Directory->HashBuckets[i]->Object);
                    //KdPrint(("文件路径为:%wZ\n",&(pot->Name)));//这种情况下,得到的值永远是Type.

                    pu = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, Length, TAG);
                    if (pu == 0) {
                        return STATUS_UNSUCCESSFUL;
                    }
                    RtlZeroMemory(pu, Length);

                    status = ObQueryNameString(p->Object, (POBJECT_NAME_INFORMATION)pu, Length, &Length);//""
                    if (status != STATUS_SUCCESS )//#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS)0xC0000004L)
                    {
                        //KdPrint(("ObQueryNameString fail 0x%08x",status));
                        ExFreePoolWithTag(pu, TAG);
                        continue;
                    }

                    //估计也可以根据\ObjectTypes\Process这个名字,打开这个对象.

                    KdPrint(("Hash:%d\tAddress:0x%p\tType:%wZ\tName:%wZ\n",i,p->Object,&(pot->Name),pu));
                    ExFreePoolWithTag(pu, TAG);//这两行搞反了是要蓝屏的.

                    if (p->ChainLink == NULL)
                    {
                        break;
                    }

                    p = p->ChainLink;
                }
            }

            ObDereferenceObject(ObjectTypes_Directory);
        }
        ZwClose(Handle);
    }

    return STATUS_UNSUCCESSFUL;
}


看看效果吧!
0: kd> g
Hash:0 Address:0xFFFFFA8003CDC1D0 Type:Type Name:\ObjectTypes\TmTm
Hash:1 Address:0xFFFFFA8003CDB250 Type:Type Name:\ObjectTypes\Desktop
Hash:1 Address:0xFFFFFA8003C8FDE0 Type:Type Name:\ObjectTypes\Process
Hash:3 Address:0xFFFFFA8003C8F8A0 Type:Type Name:\ObjectTypes\DebugObject
Hash:4 Address:0xFFFFFA8003CDC080 Type:Type Name:\ObjectTypes\TpWorkerFactory
Hash:5 Address:0xFFFFFA8003CDCF30 Type:Type Name:\ObjectTypes\Adapter
Hash:5 Address:0xFFFFFA8003C6AAA0 Type:Type Name:\ObjectTypes\Token
Hash:8 Address:0xFFFFFA8003CD08F0 Type:Type Name:\ObjectTypes\EventPair
Hash:9 Address:0xFFFFFA8003FA8200 Type:Type Name:\ObjectTypes\PcwObject
Hash:9 Address:0xFFFFFA8003CF83A0 Type:Type Name:\ObjectTypes\WmiGuid
Hash:11 Address:0xFFFFFA8003CF93A0 Type:Type Name:\ObjectTypes\EtwRegistration
Hash:12 Address:0xFFFFFA8003CDD590 Type:Type Name:\ObjectTypes\Session
Hash:12 Address:0xFFFFFA8003CDB790 Type:Type Name:\ObjectTypes\Timer
Hash:13 Address:0xFFFFFA8003CDB080 Type:Type Name:\ObjectTypes\Mutant
Hash:16 Address:0xFFFFFA8003CDC9F0 Type:Type Name:\ObjectTypes\IoCompletion
Hash:17 Address:0xFFFFFA8003CDB3A0 Type:Type Name:\ObjectTypes\WindowStation
Hash:17 Address:0xFFFFFA8003CDB640 Type:Type Name:\ObjectTypes\Profile
Hash:18 Address:0xFFFFFA8003CDC8A0 Type:Type Name:\ObjectTypes\File
Hash:21 Address:0xFFFFFA8003CDB8E0 Type:Type Name:\ObjectTypes\Semaphore
Hash:23 Address:0xFFFFFA8003CFA3A0 Type:Type Name:\ObjectTypes\EtwConsumer
Hash:25 Address:0xFFFFFA8003CDDF30 Type:Type Name:\ObjectTypes\TmTx
Hash:25 Address:0xFFFFFA8003C6AC90 Type:Type Name:\ObjectTypes\SymbolicLink
Hash:26 Address:0xFFFFFA8003F35880 Type:Type Name:\ObjectTypes\FilterConnectionPort
Hash:26 Address:0xFFFFFA8003CB37A0 Type:Type Name:\ObjectTypes\Key
Hash:26 Address:0xFFFFFA8003CDB4F0 Type:Type Name:\ObjectTypes\KeyedEvent
Hash:26 Address:0xFFFFFA8003CDBF30 Type:Type Name:\ObjectTypes\Callback
Hash:28 Address:0xFFFFFA8003C8FB40 Type:Type Name:\ObjectTypes\UserApcReserve
Hash:28 Address:0xFFFFFA8003C8FF30 Type:Type Name:\ObjectTypes\Job
Hash:29 Address:0xFFFFFA8003CDCDE0 Type:Type Name:\ObjectTypes\Controller
Hash:29 Address:0xFFFFFA8003C8F9F0 Type:Type Name:\ObjectTypes\IoCompletionReserve
Hash:30 Address:0xFFFFFA8003CDCC90 Type:Type Name:\ObjectTypes\Device
Hash:30 Address:0xFFFFFA8003C6ADE0 Type:Type Name:\ObjectTypes\Directory
Hash:31 Address:0xFFFFFA8003CDD6E0 Type:Type Name:\ObjectTypes\Section
Hash:31 Address:0xFFFFFA8003CDDC90 Type:Type Name:\ObjectTypes\TmEn
Hash:31 Address:0xFFFFFA8003C8FC90 Type:Type Name:\ObjectTypes\Thread
Hash:32 Address:0xFFFFFA8003C6AF30 Type:Type Name:\ObjectTypes\Type
Hash:33 Address:0xFFFFFA8003F5FF30 Type:Type Name:\ObjectTypes\FilterCommunicationPort
Hash:33 Address:0xFFFFFA8003CBC7F0 Type:Type Name:\ObjectTypes\PowerRequest
Hash:35 Address:0xFFFFFA8003CDDDE0 Type:Type Name:\ObjectTypes\TmRm
Hash:35 Address:0xFFFFFA8003CD0A40 Type:Type Name:\ObjectTypes\Event
Hash:36 Address:0xFFFFFA8003CB7AC0 Type:Type Name:\ObjectTypes\ALPC Port
Hash:36 Address:0xFFFFFA8003CDCB40 Type:Type Name:\ObjectTypes\Driver

验证一下:
0: kd> !object \ObjectTypes
Object: fffff8a000006930  Type: (fffffa8003c6ade0) Directory
    ObjectHeader: fffff8a000006900 (new version)
    HandleCount: 0  PointerCount: 44
    Directory Object: fffff8a000004c90  Name: ObjectTypes

    Hash Address          Type          Name
    ---- -------          ----          ----
     00  fffffa8003cdc1d0 Type          TmTm
     01  fffffa8003cdb250 Type          Desktop
         fffffa8003c8fde0 Type          Process
     03  fffffa8003c8f8a0 Type          DebugObject
     04  fffffa8003cdc080 Type          TpWorkerFactory
     05  fffffa8003cdcf30 Type          Adapter
         fffffa8003c6aaa0 Type          Token
     08  fffffa8003cd08f0 Type          EventPair
     09  fffffa8003fa8200 Type          PcwObject
         fffffa8003cf83a0 Type          WmiGuid
     11  fffffa8003cf93a0 Type          EtwRegistration
     12  fffffa8003cdd590 Type          Session
         fffffa8003cdb790 Type          Timer
     13  fffffa8003cdb080 Type          Mutant
     16  fffffa8003cdc9f0 Type          IoCompletion
     17  fffffa8003cdb3a0 Type          WindowStation
         fffffa8003cdb640 Type          Profile
     18  fffffa8003cdc8a0 Type          File
     21  fffffa8003cdb8e0 Type          Semaphore
     23  fffffa8003cfa3a0 Type          EtwConsumer
     25  fffffa8003cddf30 Type          TmTx
         fffffa8003c6ac90 Type          SymbolicLink
     26  fffffa8003f35880 Type          FilterConnectionPort
         fffffa8003cb37a0 Type          Key
         fffffa8003cdb4f0 Type          KeyedEvent
         fffffa8003cdbf30 Type          Callback
     28  fffffa8003c8fb40 Type          UserApcReserve
         fffffa8003c8ff30 Type          Job
     29  fffffa8003cdcde0 Type          Controller
         fffffa8003c8f9f0 Type          IoCompletionReserve
     30  fffffa8003cdcc90 Type          Device
         fffffa8003c6ade0 Type          Directory
     31  fffffa8003cdd6e0 Type          Section
         fffffa8003cddc90 Type          TmEn
         fffffa8003c8fc90 Type          Thread
     32  fffffa8003c6af30 Type          Type
     33  fffffa8003f5ff30 Type          FilterCommunicationPort
         fffffa8003cbc7f0 Type          PowerRequest
     35  fffffa8003cddde0 Type          TmRm
         fffffa8003cd0a40 Type          Event
     36  fffffa8003cb7ac0 Type          ALPC Port
         fffffa8003cdcb40 Type          Driver

还可以对照:Winobj(EX).exe或者其他工具查看对比.

made by correy
made at 2013.08.23
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com
不足之处,敬请指出.


一下代码需要改进,不完善:
#include <ntifs.h>

/*
功能:枚举以\为根的整个命名空间的对象.运行的时间长些,需要几分钟.可能有重复,需改进.
说明:本代码只适宜于windows server 2008 r2 64位版本.
*/

#define TAG 'tset' //test

typedef struct _OBJECT_DIRECTORY_ENTRY {
    struct _OBJECT_DIRECTORY_ENTRY * ChainLink;
    void * Object;
    int HashValue;
} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;

typedef struct _OBJECT_DIRECTORY {
    struct _OBJECT_DIRECTORY_ENTRY *HashBuckets[37];
    struct _OBJECT_DIRECTORY_ENTRY **Lock;
    void * DeviceMap;
    USHORT SessionId;
    void * NamespaceEntry;
    int Flags;
} OBJECT_DIRECTORY, *POBJECT_DIRECTORY;

typedef struct _OBJECT_TYPE {
    LIST_ENTRY TypeList;
    UNICODE_STRING Name;
    //.......
} OBJECT_TYPE;

//一个导出但没有公开的函数
typedef OBJECT_TYPE * (*ObGetObjectType)(IN PVOID pObject);
ObGetObjectType g_pObGetObjectType;

UNICODE_STRING us_Directory;

NTSTATUS enum_object(UNICODE_STRING * pus,int n)
{  
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE Handle = NULL;
    POBJECT_DIRECTORY ObjectTypes_Directory = NULL;
    int i = 0;  
    OBJECT_TYPE * pot;
    PUNICODE_STRING pu;
    ULONG  Length = 512;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    OBJECT_DIRECTORY_ENTRY * p = 0;

    InitializeObjectAttributes(&ObjectAttributes,pus,0,0,0);
    status = ZwOpenDirectoryObject(&Handle, DIRECTORY_QUERY, &ObjectAttributes);
    if (NT_SUCCESS (status))
    {
        status = ObReferenceObjectByHandle(Handle, FILE_READ_ACCESS, NULL, KernelMode, (PVOID *)&ObjectTypes_Directory, NULL);
        if (NT_SUCCESS (status))
        {
            for ( ; i<37 ;i++)
            {
                if (ObjectTypes_Directory->HashBuckets[i] == NULL)
                {
                    continue;
                }

                p = ObjectTypes_Directory->HashBuckets[i];
                for ( ; ; )
                {
                    pot = g_pObGetObjectType(ObjectTypes_Directory->HashBuckets[i]->Object);

                    pu = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool, Length, TAG);
                    if (pu == 0) {
                        return STATUS_UNSUCCESSFUL;
                    }
                    RtlZeroMemory(pu, Length);

                    status = ObQueryNameString(p->Object, (POBJECT_NAME_INFORMATION)pu, Length, &Length);//""
                    if (status != STATUS_SUCCESS )//#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS)0xC0000004L)
                    {
                        //KdPrint(("ObQueryNameString fail 0x%08x",status));
                        ExFreePoolWithTag(pu, TAG);
                        continue;
                    }

                    //不准重复.
                    // if (RtlEqualUnicodeString(pu,pus,TRUE))
                    // {
                    // break;
                    // }

                    //如果是目录,进行递归的调用.
                    if (RtlEqualUnicodeString(&us_Directory,&(pot->Name),TRUE))
                    {
                        enum_object(pu,n);
                    }

                    // {
                    // int j = 0;
                    // for ( ;j < n; j++)
                    // {
                    // KdPrint(("\t"));
                    // }
                    // }

                    KdPrint(("Address:0x%p\tType:%wZ\tName:%wZ\n",p->Object,&(pot->Name),pu));
                    ExFreePoolWithTag(pu, TAG);//这两行搞反了是要蓝屏的.

                    if (p->ChainLink == NULL)
                    {
                        break;
                    }

                    p = p->ChainLink;
                }
            }

            ObDereferenceObject(ObjectTypes_Directory);
        }
        ZwClose(Handle);
    }

    i++;

    return status;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
    UNICODE_STRING usObGetObjectType;
    UNICODE_STRING ObjectTypes;
    int n = 0;

    KdBreakPoint();//DbgBreakPoint()

    RtlInitUnicodeString( &usObGetObjectType, L"ObGetObjectType" );
    g_pObGetObjectType = MmGetSystemRoutineAddress(&usObGetObjectType);
    if (g_pObGetObjectType == NULL)
    {
        return STATUS_UNSUCCESSFUL;
    }

    RtlInitUnicodeString(&us_Directory, L"Directory");
    RtlInitUnicodeString(&ObjectTypes,L"\\");

    enum_object(&ObjectTypes,n);

    return STATUS_UNSUCCESSFUL;
}

2013年8月22日星期四

手工查询内核对象的处理函数

手工查询内核对象的处理函数.

方法一:从\ObjectTypes中获取.

首先确保符号文件已经加载.

0: kd> vertarget
Windows 7 Kernel Version 7601 (Service Pack 1) MP (2 procs) Free x64
Product: Server, suite: Enterprise TerminalServer SingleUserTS
Built by: 7601.18113.amd64fre.win7sp1_gdr.130318-1533
Machine Name:
Kernel base = 0xfffff800`01661000 PsLoadedModuleList = 0xfffff800`018a46d0
Debug session time: Thu Aug 22 10:59:24.528 2013 (UTC + 8:00)
System Uptime: 0 days 0:04:06.230

0: kd> !object \ObjectTypes
Object: fffff8a000004650  Type: (fffffa8003c8aa90) Directory
    ObjectHeader: fffff8a000004620 (new version)
    HandleCount: 0  PointerCount: 44
    Directory Object: fffff8a000004c30  Name: ObjectTypes

    Hash Address          Type          Name
    ---- -------          ----          ----
     00  fffffa8003cfc500 Type          TmTm
     01  fffffa8003cfb8a0 Type          Desktop
         fffffa8003c8baa0 Type          Process
     03  fffffa8003ce4f30 Type          DebugObject
     04  fffffa8003cfb750 Type          TpWorkerFactory
     05  fffffa8003cfb600 Type          Adapter
         fffffa8003c8be10 Type          Token
     08  fffffa8003cef8f0 Type          EventPair
     09  fffffa8004e0c3b0 Type          PcwObject
         fffffa8003d10350 Type          WmiGuid
     11  fffffa8003d11350 Type          EtwRegistration
     12  fffffa8003cfd7a0 Type          Session
         fffffa8003cfbde0 Type          Timer
     13  fffffa8003cea740 Type          Mutant
     16  fffffa8003cfcc90 Type          IoCompletion
     17  fffffa8003cfb9f0 Type          WindowStation
         fffffa8003cfbc90 Type          Profile
     18  fffffa8003cfcb40 Type          File
     21  fffffa8003cfbf30 Type          Semaphore
     23  fffffa8003d12350 Type          EtwConsumer
     25  fffffa8003cfc3b0 Type          TmTx
         fffffa8003c8a940 Type          SymbolicLink
     26  fffffa8004dc3f30 Type          FilterConnectionPort
         fffffa8003cd48f0 Type          Key
         fffffa8003cfbb40 Type          KeyedEvent
         fffffa8003cea5f0 Type          Callback
     28  fffffa8003cb0f30 Type          UserApcReserve
         fffffa8003c8bbf0 Type          Job
     29  fffffa8003cfc080 Type          Controller
         fffffa8003cb0de0 Type          IoCompletionReserve
     30  fffffa8003cfcf30 Type          Device
         fffffa8003c8aa90 Type          Directory
     31  fffffa8003cfd8f0 Type          Section
         fffffa8003cfdf30 Type          TmEn
         fffffa8003c8b950 Type          Thread
     32  fffffa8003c8abe0 Type          Type
     33  fffffa8004dc3de0 Type          FilterCommunicationPort
         fffffa8003cd81c0 Type          PowerRequest
     35  fffffa8003cfc260 Type          TmRm
         fffffa8003cefa40 Type          Event
     36  fffffa8003cd8e40 Type          ALPC Port
         fffffa8003cfcde0 Type          Driver

;拿进程来做实验.
0: kd> !object fffffa8003c8baa0
Object: fffffa8003c8baa0  Type: (fffffa8003c8abe0) Type
    ObjectHeader: fffffa8003c8ba70 (new version)
    HandleCount: 0  PointerCount: 2
    Directory Object: fffff8a000004650  Name: Process

有类型和地址了,拿来直接用.
0: kd> dt _object_type fffffa8003c8baa0
nt!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`03c8baa0 - 0xfffffa80`03c8baa0 ]
   +0x010 Name             : _UNICODE_STRING "Process"
   +0x020 DefaultObject    : (null)
   +0x028 Index            : 0x7 ''
   +0x02c TotalNumberOfObjects : 0x24
   +0x030 TotalNumberOfHandles : 0xb9
   +0x034 HighWaterNumberOfObjects : 0x28
   +0x038 HighWaterNumberOfHandles : 0xc1
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x636f7250
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffff8a0`082d4190 - 0xfffff8a0`08da5830 ]
0: kd> dt _OBJECT_TYPE_INITIALIZER fffffa8003c8bae0
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`019a9ca0     long  nt!PspProcessOpen+0
   +0x040 CloseProcedure   : 0xfffff800`01990fd0     void  nt!PspProcessClose+0
   +0x048 DeleteProcedure  : 0xfffff800`01990280     void  nt!PspProcessDelete+0
   +0x050 ParseProcedure   : (null)
   +0x058 SecurityProcedure : 0xfffff800`019c1cd0     long  nt!SeDefaultObjectMethod+0
   +0x060 QueryNameProcedure : (null)
   +0x068 OkayToCloseProcedure : (null)
0: kd> u nt!PspProcessOpen
nt!PspProcessOpen:
fffff800`019a9ca0 488b4c2428      mov     rcx,qword ptr [rsp+28h]
fffff800`019a9ca5 80fa01          cmp     dl,1
fffff800`019a9ca8 7516            jne     nt!PspProcessOpen+0x20 (fffff800`019a9cc0)
fffff800`019a9caa 410fbaa03c0400000b bt    dword ptr [r8+43Ch],0Bh
fffff800`019a9cb3 720b            jb      nt!PspProcessOpen+0x20 (fffff800`019a9cc0)
fffff800`019a9cb5 410fbaa13c0400000b bt    dword ptr [r9+43Ch],0Bh
fffff800`019a9cbe 7211            jb      nt!PspProcessOpen+0x31 (fffff800`019a9cd1)
fffff800`019a9cc0 8b01            mov     eax,dword ptr [rcx]

关于函数的类型,已有的可以用IDA分析(64位),32位的直接分析出了.没有的是不是可以随意写?



方法二:拿当前进程对象做实验.
0: kd> !process
PROCESS fffffa8003cb0890
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00187000  ObjectTable: fffff8a0000019b0  HandleCount: 553.
    Image: System
    VadRoot fffffa8004ed04e0 Vads 5 Clone 0 Private 8. Modified 3214605. Locked 0.
    DeviceMap fffff8a000007eb0
    Token                             fffff8a000004040
    ElapsedTime                       00:03:32.487
    UserTime                          00:00:00.000
    KernelTime                        00:00:02.199
    QuotaPoolUsage[PagedPool]         0
    QuotaPoolUsage[NonPagedPool]      0
    Working Set Sizes (now,min,max)  (91, 0, 0) (364KB, 0KB, 0KB)
    PeakWorkingSetSize                1412
    VirtualSize                       3 Mb
    PeakVirtualSize                   8 Mb
    PageFaultCount                    25105
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      28

......显示的内容省略.


0: kd> !object fffffa8003cb0890
Object: fffffa8003cb0890  Type: (fffffa8003c8baa0) Process
    ObjectHeader: fffffa8003cb0860 (new version)
    HandleCount: 3  PointerCount: 167
0: kd> dt _object_type fffffa8003c8baa0
nt!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`03c8baa0 - 0xfffffa80`03c8baa0 ]
   +0x010 Name             : _UNICODE_STRING "Process"
   +0x020 DefaultObject    : (null)
   +0x028 Index            : 0x7 ''
   +0x02c TotalNumberOfObjects : 0x24
   +0x030 TotalNumberOfHandles : 0xb9
   +0x034 HighWaterNumberOfObjects : 0x28
   +0x038 HighWaterNumberOfHandles : 0xc1
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x636f7250
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffff8a0`082d4190 - 0xfffff8a0`08da5830 ]
0: kd> dt _OBJECT_TYPE_INITIALIZER fffffa8003c8baa0+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`019a9ca0     long  nt!PspProcessOpen+0
   +0x040 CloseProcedure   : 0xfffff800`01990fd0     void  nt!PspProcessClose+0
   +0x048 DeleteProcedure  : 0xfffff800`01990280     void  nt!PspProcessDelete+0
   +0x050 ParseProcedure   : (null)
   +0x058 SecurityProcedure : 0xfffff800`019c1cd0     long  nt!SeDefaultObjectMethod+0
   +0x060 QueryNameProcedure : (null)
   +0x068 OkayToCloseProcedure : (null)





方法三:
跟据上面的进程对象的对象体,减去下面的结构的大小.
0: kd> dt _object_header  fffffa8003cb0860
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 0n167
   +0x008 HandleCount      : 0n3
   +0x008 NextToFree       : 0x00000000`00000003 Void
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : 0x7 ''
   +0x019 TraceFlags       : 0 ''
   +0x01a InfoMask         : 0 ''
   +0x01b Flags            : 0x2 ''
   +0x020 ObjectCreateInfo : 0xfffff800`01864940 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : 0xfffff800`01864940 Void
   +0x028 SecurityDescriptor : 0xfffff8a0`00004e49 Void
   +0x030 Body             : _QUAD

发现_object_header结构里面没有Type成员,但是有一个TypeIndex.
0: kd> dq nt!obTypeIndexTable
fffff800`01874b80  00000000`00000000 00000000`bad0b0b0
fffff800`01874b90  fffffa80`03c8abe0 fffffa80`03c8aa90
fffff800`01874ba0  fffffa80`03c8a940 fffffa80`03c8be10
fffff800`01874bb0  fffffa80`03c8bbf0 fffffa80`03c8baa0
fffff800`01874bc0  fffffa80`03c8b950 fffffa80`03cb0f30
fffff800`01874bd0  fffffa80`03cb0de0 fffffa80`03ce4f30
fffff800`01874be0  fffffa80`03cefa40 fffffa80`03cef8f0
fffff800`01874bf0  fffffa80`03cea740 fffffa80`03cea5f0

索引从零开始,从这里找到了_OBJECT_TYPE,进而_OBJECT_TYPE_INITIALIZER获取函数的位置.
注意:obTypeIndexTable,这个变量没有导出.


如果要编程获取,还得费一些小周折.






方法四:
例如ObOpenObjectByPointer函数的说明中有一段话:
ObjectType
Pointer to the object type.
If the value of AccessMode is KernelMode, this parameter is optional and can be NULL.
Otherwise, it must be either *ExEventObjectType, *ExSemaphoreObjectType, *IoFileObjectType, *PsThreadType or *SeTokenObjectType.
Note  The SeTokenObjectType object type is supported in Windows XP and later operating systems.

这是啥东西呢?继续探索,再看看定义:
extern POBJECT_TYPE *CmKeyObjectType;
extern POBJECT_TYPE *IoFileObjectType;
extern POBJECT_TYPE *ExEventObjectType;
extern POBJECT_TYPE *ExSemaphoreObjectType;
extern POBJECT_TYPE *TmTransactionManagerObjectType;
extern POBJECT_TYPE *TmResourceManagerObjectType;
extern POBJECT_TYPE *TmEnlistmentObjectType;
extern POBJECT_TYPE *TmTransactionObjectType;
extern POBJECT_TYPE *PsProcessType;
extern POBJECT_TYPE *PsThreadType;
extern POBJECT_TYPE *SeTokenObjectType;

其实远不止这些,再看看:
1: kd> x /v /z nt!*type
pub func   fffff800`0183a3d8    8 nt!ExDesktopObjectType (<no parameter info>)
pub func   fffff800`01842f98    8 nt!TmTransactionManagerObjectType (<no parameter info>)
pub func   fffff800`01842fc0    8 nt!TmTransactionObjectType (<no parameter info>)
pub func   fffff800`018cc048    8 nt!IoFileObjectType (<no parameter info>)
pub func   fffff800`018cc1a8    b nt!IoDriverObjectType (<no parameter info>)
pub func   fffff800`018cc020   10 nt!PsProcessType (<no parameter info>)
pub func   fffff800`018cc128   11 nt!MmSectionObjectType (<no parameter info>)
pub func   fffff800`01842fa0   20 nt!TmResourceManagerObjectType (<no parameter info>)
pub func   fffff800`019466a0   20 nt!ObGetObjectType (<no parameter info>)
pub func   fffff800`01b61050   20 nt!CmKeyObjectType (<no parameter info>)
pub func   fffff800`018cc0b0   50 nt!ExEventObjectType (<no parameter info>)
pub func   fffff800`018cc050   60 nt!PsThreadType (<no parameter info>)
pub func   fffff800`016b65a8   70 nt!RtlFindAceByType (<no parameter info>)
pub func   fffff800`01b61070   c0 nt!SeTokenObjectType (<no parameter info>)
pub func   fffff800`018cc938   f0 nt!IoAdapterObjectType (<no parameter info>)
pub func   fffff800`018cc2e8  140 nt!PsJobType (<no parameter info>)
pub func   fffff800`0188f068  158 nt!LpcPortObjectType (<no parameter info>)
pub func   fffff800`018cc428  1e0 nt!ExSemaphoreObjectType (<no parameter info>)
pub func   fffff800`016b6324  284 nt!SeComputeAutoInheritByObjectType (<no parameter info>)
pub func   fffff800`018cc608  330 nt!IoDeviceObjectType (<no parameter info>)
pub func   fffff800`01aa4920  4f0 nt!ObCreateObjectType (<no parameter info>)
pub func   fffff800`019473d8  5e4 nt!SeTokenType (<no parameter info>)
pub func   fffff800`018ccc38  ee8 nt!IoDeviceHandlerObjectType (<no parameter info>)
pub func   fffff800`0183a3e0 8bb8 nt!ExWindowStationObjectType (<no parameter info>)
pub func   fffff800`01842fc8 4c0a0 nt!TmEnlistmentObjectType (<no parameter info>)


说明:这些变量或者函数是导出的,可喜的是这些东西可以直接在代码中直接使用,不必再获取了.
根据这些变量或者函数,获取对象的处理函数的2个示例及验证如下:
1: kd> dq MmSectionObjectType
fffff800`018cc128  fffffa80`03cdd6e0 00000000`00000000
fffff800`018cc138  00d5ade9`1100020f 00007530`00000000
fffff800`018cc148  00000000`00000000 fffffa80`03d1e4e0
fffff800`018cc158  00000000`00000000 fffff880`00961000
fffff800`018cc168  00000000`00000000 fffffa80`03cdd850
fffff800`018cc178  00000000`000037ba fffff800`016c1890
fffff800`018cc188  00000000`00000000 00000000`00002710
fffff800`018cc198  00010100`00000064 fffff8bf`ffffffff
1: kd> !object \ObjectTypes
Object: fffff8a000006930  Type: (fffffa8003c6ade0) Directory
    ObjectHeader: fffff8a000006900 (new version)
    HandleCount: 0  PointerCount: 44
    Directory Object: fffff8a000004c90  Name: ObjectTypes

    Hash Address          Type          Name
    ---- -------          ----          ----
     00  fffffa8003cdc1d0 Type          TmTm
     01  fffffa8003cdb250 Type          Desktop
         fffffa8003c8fde0 Type          Process
     03  fffffa8003c8f8a0 Type          DebugObject
     04  fffffa8003cdc080 Type          TpWorkerFactory
     05  fffffa8003cdcf30 Type          Adapter
         fffffa8003c6aaa0 Type          Token
     08  fffffa8003cd08f0 Type          EventPair
     09  fffffa8003fa9210 Type          PcwObject
         fffffa8003d173a0 Type          WmiGuid
     11  fffffa8003d18330 Type          EtwRegistration
     12  fffffa8003cdd590 Type          Session
         fffffa8003cdb790 Type          Timer
     13  fffffa8003cdb080 Type          Mutant
     16  fffffa8003cdc9f0 Type          IoCompletion
     17  fffffa8003cdb3a0 Type          WindowStation
         fffffa8003cdb640 Type          Profile
     18  fffffa8003cdc8a0 Type          File
     21  fffffa8003cdb8e0 Type          Semaphore
     23  fffffa8003d193a0 Type          EtwConsumer
     25  fffffa8003cddf30 Type          TmTx
         fffffa8003c6ac90 Type          SymbolicLink
     26  fffffa8003f30880 Type          FilterConnectionPort
         fffffa8003cb37a0 Type          Key
         fffffa8003cdb4f0 Type          KeyedEvent
         fffffa8003cdbf30 Type          Callback
     28  fffffa8003c8fb40 Type          UserApcReserve
         fffffa8003c8ff30 Type          Job
     29  fffffa8003cdcde0 Type          Controller
         fffffa8003c8f9f0 Type          IoCompletionReserve
     30  fffffa8003cdcc90 Type          Device
         fffffa8003c6ade0 Type          Directory
     31  fffffa8003cdd6e0 Type          Section
         fffffa8003cddc90 Type          TmEn
         fffffa8003c8fc90 Type          Thread
     32  fffffa8003c6af30 Type          Type
     33  fffffa8003f36aa0 Type          FilterCommunicationPort
         fffffa8003cc2900 Type          PowerRequest
     35  fffffa8003cddde0 Type          TmRm
         fffffa8003cd0a40 Type          Event
     36  fffffa8003cb7ac0 Type          ALPC Port
         fffffa8003cdcb40 Type          Driver
1: kd> dq nt!LpcPortObjectType
fffff800`0188f068  fffffa80`03cb7ac0 00000000`00000288
fffff800`0188f078  00000000`00000000 00000002`00000000
fffff800`0188f088  00000000`00000000 00000000`00000000
fffff800`0188f098  00000000`00000000 00000000`00000c00
fffff800`0188f0a8  00000000`00000d08 00000000`00000000
fffff800`0188f0b8  00000c02`00000106 fffffa80`03ccb500
fffff800`0188f0c8  fffffa80`03cc9500 00000000`00000000
fffff800`0188f0d8  00000000`00000000 00000000`00000000

0: kd> dt _object_type fffffa80`03cdd6e0
nt!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`03cdd6e0 - 0xfffffa80`03cdd6e0 ]
   +0x010 Name             : _UNICODE_STRING "Section"
   +0x020 DefaultObject    : 0xfffff800`01845220 Void
   +0x028 Index            : 0x21 '!'
   +0x02c TotalNumberOfObjects : 0x3dd
   +0x030 TotalNumberOfHandles : 0x1b7
   +0x034 HighWaterNumberOfObjects : 0x3e5
   +0x038 HighWaterNumberOfHandles : 0x1c3
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x74636553
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffffa80`03cdd7a0 - 0xfffffa80`03cdd7a0 ]
0: kd> dt _OBJECT_TYPE_INITIALIZER fffffa80`03cdd6e0+40
nt!_OBJECT_TYPE_INITIALIZER
   +0x000 Length           : 0x70
   +0x002 ObjectTypeFlags  : 0x4 ''
   +0x002 CaseInsensitive  : 0y0
   +0x002 UnnamedObjectsOnly : 0y0
   +0x002 UseDefaultObject : 0y1
   +0x002 SecurityRequired : 0y0
   +0x002 MaintainHandleCount : 0y0
   +0x002 MaintainTypeList : 0y0
   +0x002 SupportsObjectCallbacks : 0y0
   +0x002 CacheAligned     : 0y0
   +0x004 ObjectTypeCode   : 0
   +0x008 InvalidAttributes : 0x100
   +0x00c GenericMapping   : _GENERIC_MAPPING
   +0x01c ValidAccessMask  : 0x1f001f
   +0x020 RetainAccess     : 0
   +0x024 PoolType         : 1 ( PagedPool )
   +0x028 DefaultPagedPoolCharge : 0x98
   +0x02c DefaultNonPagedPoolCharge : 0
   +0x030 DumpProcedure    : (null)
   +0x038 OpenProcedure    : (null)
   +0x040 CloseProcedure   : (null)
   +0x048 DeleteProcedure  : 0xfffff800`019b4558     void  nt!MiSectionDelete+0
   +0x050 ParseProcedure   : (null)
   +0x058 SecurityProcedure : 0xfffff800`0197fcd0     long  nt!SeDefaultObjectMethod+0
   +0x060 QueryNameProcedure : (null)
   +0x068 OkayToCloseProcedure : (null)


0: kd> dt _object_type fffffa80`03cb7ac0
nt!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`03cb7ac0 - 0xfffffa80`03cb7ac0 ]
   +0x010 Name             : _UNICODE_STRING "ALPC Port"
   +0x020 DefaultObject    : 0x00000000`000000c9 Void
   +0x028 Index            : 0x24 '$'
   +0x02c TotalNumberOfObjects : 0x261
   +0x030 TotalNumberOfHandles : 0x260
   +0x034 HighWaterNumberOfObjects : 0x30c
   +0x038 HighWaterNumberOfHandles : 0x30a
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x43504c41
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffffa80`03cb7b80 - 0xfffffa80`03cb7b80 ]
0: kd> dt _OBJECT_TYPE_INITIALIZER fffffa80`03cb7ac0+40
nt!_OBJECT_TYPE_INITIALIZER
   +0x000 Length           : 0x70
   +0x002 ObjectTypeFlags  : 0x10 ''
   +0x002 CaseInsensitive  : 0y0
   +0x002 UnnamedObjectsOnly : 0y0
   +0x002 UseDefaultObject : 0y0
   +0x002 SecurityRequired : 0y0
   +0x002 MaintainHandleCount : 0y1
   +0x002 MaintainTypeList : 0y0
   +0x002 SupportsObjectCallbacks : 0y0
   +0x002 CacheAligned     : 0y0
   +0x004 ObjectTypeCode   : 0
   +0x008 InvalidAttributes : 0x80
   +0x00c GenericMapping   : _GENERIC_MAPPING
   +0x01c ValidAccessMask  : 0x1f0001
   +0x020 RetainAccess     : 0
   +0x024 PoolType         : 0 ( NonPagedPool )
   +0x028 DefaultPagedPoolCharge : 0
   +0x02c DefaultNonPagedPoolCharge : 0x228
   +0x030 DumpProcedure    : (null)
   +0x038 OpenProcedure    : 0xfffff800`01973430     long  nt!AlpcpOpenPort+0
   +0x040 CloseProcedure   : 0xfffff800`0193abf8     void  nt!AlpcpClosePort+0
   +0x048 DeleteProcedure  : 0xfffff800`01939730     void  nt!AlpcpDeletePort+0
   +0x050 ParseProcedure   : (null)
   +0x058 SecurityProcedure : 0xfffff800`0197fcd0     long  nt!SeDefaultObjectMethod+0
   +0x060 QueryNameProcedure : (null)
   +0x068 OkayToCloseProcedure : (null)


made by correy
made at 2013.08.22

2013年8月13日星期二

Minifilter禁止写操作

/*
禁止写操作。
暂时只禁止一个卷。
前操作实现。
注意普通的删除操作也会被拦截。

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

#include <fltKernel.h>

PFLT_FILTER gFilterHandle;

FLT_PREOP_CALLBACK_STATUS WritePreOPeration(__inout PFLT_CALLBACK_DATA Cbd, __in PCFLT_RELATED_OBJECTS FltObjects, __out PVOID *CompletionContext)
{
    PFLT_FILE_NAME_INFORMATION    pfni;
    NTSTATUS                      status;
    UNICODE_STRING temp;

    status = FltGetFileNameInformation( Cbd, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &pfni);    
    if (!NT_SUCCESS( status )) 
    {
        /*
        Note  If the minifilter driver's preoperation callback routine returns FLT_PREOP_SUCCESS_WITH_CALLBACK but the minifilter driver has not registered a postoperation callback routine for the operation, the system asserts on a checked build. 
        注释:在XP上会蓝屏,在WIN 7上不会蓝屏。
        */
        return FLT_PREOP_SUCCESS_WITH_CALLBACK;
    }

    status = FltParseFileNameInformation(pfni);
    if (!NT_SUCCESS( status )) 
    {
        FltReleaseFileNameInformation(pfni); 
        return FLT_PREOP_SUCCESS_WITH_CALLBACK;
    }

    RtlInitUnicodeString(&temp,L"\\Device\\HarddiskVolume2");
    if (RtlEqualUnicodeString(&temp,&pfni->Volume,TRUE))
    {
        Cbd->IoStatus.Status = STATUS_ACCESS_DENIED;
        Cbd->IoStatus.Information = 0;
        return FLT_PREOP_COMPLETE;
    }

    FltReleaseFileNameInformation(pfni);    

    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}

CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
    { IRP_MJ_WRITE,  0, WritePreOPeration, 0},
    { IRP_MJ_OPERATION_END }
};

#pragma PAGEDCODE
NTSTATUS PtInstanceQueryTeardown (__in PCFLT_RELATED_OBJECTS FltObjects,__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{
    return STATUS_SUCCESS;
}

#pragma PAGEDCODE//#pragma alloc_text(PAGE, PtUnload)
NTSTATUS PtUnload (__in FLT_FILTER_UNLOAD_FLAGS Flags)
{
    FltUnregisterFilter( gFilterHandle );
    return STATUS_SUCCESS;
}

CONST FLT_REGISTRATION FilterRegistration = {
    sizeof( FLT_REGISTRATION ),         //  Size
    FLT_REGISTRATION_VERSION,           //  Version
    0,                                  //  Flags
    NULL,                               //  Context
    Callbacks,                          //  Operation callbacks
    PtUnload,                           //  MiniFilterUnload
    NULL,                               //  InstanceSetup
    PtInstanceQueryTeardown,            //  InstanceQueryTeardown
    NULL,                               //  InstanceTeardownStart
    NULL,                               //  InstanceTeardownComplete
    NULL,                               //  GenerateFileName
    NULL,                               //  GenerateDestinationFileName
    NULL                                //  NormalizeNameComponent
};

DRIVER_INITIALIZE DriverEntry;
#pragma alloc_text(INIT, DriverEntry)//#pragma INITCODE
NTSTATUS DriverEntry (_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
    NTSTATUS status;

    UNREFERENCED_PARAMETER( RegistryPath );

    KdBreakPoint();//DbgBreakPoint() 
    
    status = FltRegisterFilter( DriverObject, &FilterRegistration, &gFilterHandle );//Register with FltMgr to tell it our callback routines    
    if (NT_SUCCESS( status )) //FLT_ASSERT( NT_SUCCESS( status ) );
    {        
        status = FltStartFiltering( gFilterHandle );
        if (!NT_SUCCESS( status )) {
            FltUnregisterFilter( gFilterHandle );
        }
    }

    return status;
}