1. bp ObRegisterCallbacks, 下段后,在函数入口处断下,此时查看返回地址。
Breakpoint 0 hit
nt!ObRegisterCallbacks:
fffff800`042d05a0 488bc4 mov rax,rsp
*** ERROR: Module load completed but symbols could not be loaded for win7.sys
2: kd> dq rsp
fffff880`047d47d8 fffff880`03a7e24a ffffffff`8000074c //fffff880`03a7e24a 是返回地址
fffff880`047d47e8 00000000`00000001 00000000`0000000e
fffff880`047d47f8 fffffa80`614eb000 fffff800`040cb020
fffff880`047d4808 00000000`00000001 fffff880`03a7e330
fffff880`047d4818 00000000`00000000 00000000`00010100
fffff880`047d4828 00000000`000a0008 fffff880`03a7e670
fffff880`047d4838 00000000`00000000 fffff880`047d4800
fffff880`047d4848 fffff880`047d49c0 00000000`00000000
2: kd> u fffff880`03a7e24a
win7+0x124a:
fffff880`03a7e24a 8bd8 mov ebx,eax
fffff880`03a7e24c b8010000c0 mov eax,0C0000001h
fffff880`03a7e251 85db test ebx,ebx
fffff880`03a7e253 0f48d8 cmovs ebx,eax
fffff880`03a7e256 e811000000 call win7+0x126c (fffff880`03a7e26c)
fffff880`03a7e25b 8bc3 mov eax,ebx
fffff880`03a7e25d 488b9c2480000000 mov rbx,qword ptr [rsp+80h]
fffff880`03a7e265 4883c470 add rsp,70h
根据上述代码,对照win7.sys函数反编译源码: 我们看到尾部的偏移一致。
.text:0000000140001244 call cs:ObRegisterCallbacks
.text:000000014000124A mov ebx, eax
.text:000000014000124C mov eax, 0C0000001h
.text:0000000140001251 test ebx, ebx
.text:0000000140001253 cmovs ebx, eax
.text:0000000140001256 call sub_14000126C
.text:000000014000125B mov eax, ebx
.text:000000014000125D mov rbx, [rsp+78h+arg_0]
.text:0000000140001265 add rsp, 70h
.text:0000000140001269 pop rbp
.text:000000014000126A retn
根据注册回调函数的用法:ObRegisterCallbacks(&obReg, &obHandle);
再看rsp+8,若用堆栈传递参数,这个就应该是第一参数arg0。
2: kd> dq ffffffff`8000074c
ffffffff`8000074c ????????`???????? ????????`????????
ffffffff`8000075c ????????`???????? ????????`????????
ffffffff`8000076c ????????`???????? ????????`????????
ffffffff`8000077c ????????`???????? ????????`????????
ffffffff`8000078c ????????`???????? ????????`????????
ffffffff`8000079c ????????`???????? ????????`????????
ffffffff`800007ac ????????`???????? ????????`????????
ffffffff`800007bc ????????`???????? ????????`????????
这说明不是采用堆栈传递参数。而是采用寄存器传递参数。ecx,edx
2: kd> dq ecx
fffff880`047d4820 00000000`00010100 00000000`000a0008
fffff880`047d4830 fffff880`03a7e670 00000000`00000000
fffff880`047d4840 fffff880`047d4800 fffff880`047d49c0
fffff880`047d4850 00000000`00000000 fffff800`0428c9c6
fffff880`047d4860 fffffa80`6192ac60 fffffa80`6192ac60
fffff880`047d4870 ffffffff`80000744 00000000`000007ff
fffff880`047d4880 fffff880`047d49c0 00000000`00000000
fffff880`047d4890 00000000`00000000 00000000`00000000
我们知道其参数第一参数arg0 是一个结构体, 这里面有我们需要的回调函数位置。
typedef struct _OB_CALLBACK_REGISTRATION {
USHORT Version;
USHORT OperationRegistrationCount;
UNICODE_STRING Altitude;
PVOID RegistrationContext;
OB_OPERATION_REGISTRATION *OperationRegistration; ///指向下面的结构
}
OB_CALLBACK_REGISTRATION, *POB_CALLBACK_REGISTRATION;
00000000`00010100 : 前面的00000000 是填充,用于结构体对齐。 后面的高位 0001 表示OperationRegistrationCount, 低位 0100 表示Version。
00000000`000a0008 : 前面的00000000 是填充,用于结构体对齐。 后面的高位 000a 表示unicode_string中的MaximumLength, 低位 0008 表示Length。
2: kd> dw fffff880`03a7e670 //这个里面存储的是unicode_string中的string。 目前存储的是“2111”
fffff880`03a7e670 0032 0031 0031 0031 0000 0000 0000 0000
fffff880`03a7e680 0000 0000 0000 0000 0000 0000 0000 0000
fffff880`03a7e690 0000 0000 0000 0000 0000 0000 0000 0000
fffff880`03a7e6a0 0000 0000 0000 0000 0000 0000 0000 0000
fffff880`03a7e6b0 0000 0000 0000 0000 0000 0000 0000 0000
fffff880`03a7e6c0 0000 0000 0000 0000 0000 0000 0000 0000
fffff880`03a7e6d0 0000 0000 0000 0000 0000 0000 0000 0000
fffff880`03a7e6e0 0000 0000 0000 0000 0000 0000 0000 0000
字符串内容与源码对应:
.text:00000001400011BC mov [rsp+arg_0], rbx
.text:00000001400011C1 push rbp
.text:00000001400011C2 mov rbp, rsp
.text:00000001400011C5 sub rsp, 70h
.text:00000001400011C9 mov rax, [rcx+28h]
.text:00000001400011CD xor edx, edx
.text:00000001400011CF lea rcx, [rbp-30h]
.text:00000001400011D3 or dword ptr [rax+68h], 20h
.text:00000001400011D7 lea r8d, [rdx+28h]
.text:00000001400011DB call sub_1400010A0
.text:00000001400011E0 call cs:ObGetFilterVersion
.text:00000001400011E6 and qword ptr [rbp-18h], 0
.text:00000001400011EB lea rdx, SourceString ; "2111" /////字符串
.text:00000001400011F2 lea rcx, [rbp-28h] ; DestinationString
.text:00000001400011F6 mov ebx, 1
.text:00000001400011FB mov [rbp-30h], ax
.text:00000001400011FF mov [rbp-2Eh], bx
.text:0000000140001203 call cs:RtlInitUnicodeString
00000000`00000000 对应着RegistrationContext
fffff880`047d4800 对应着OperationRegistration 指向下面的结构体:
typedef struct _OB_OPERATION_REGISTRATION {
POBJECT_TYPE *ObjectType;
OB_OPERATION Operations;
POB_PRE_OPERATION_CALLBACK PreOperation; ///指向回调函数。
POB_POST_OPERATION_CALLBACK PostOperation;
} OB_OPERATION_REGISTRATION, *POB_OPERATION_REGISTRATION;
2: kd> dq fffff880`047d4800
fffff880`047d4800 fffff800`040cb020 00000000`00000001
fffff880`047d4810 fffff880`03a7e330 00000000`00000000
fffff880`047d4820 00000000`00010100 00000000`000a0008
fffff880`047d4830 fffff880`03a7e670 00000000`00000000
fffff880`047d4840 fffff880`047d4800 fffff880`047d49c0
fffff880`047d4850 00000000`00000000 fffff800`0428c9c6
fffff880`047d4860 fffffa80`6192ac60 fffffa80`6192ac60
fffff880`047d4870 ffffffff`80000744 00000000`000007ff
对照结构体,我们看到:
fffff800`040cb020 对应着 ObjectType
00000000`00000001 对应着 Operations OB_OPERATION_HANDLE_CREATE
fffff880`03a7e330 对应着 PreOperation
00000000`00000000 对应着 PostOperation
2: kd> u fffff880`03a7e330
win7+0x1330:
fffff880`03a7e330 48895c2408 mov qword ptr [rsp+8],rbx
fffff880`03a7e335 48896c2418 mov qword ptr [rsp+18h],rbp
fffff880`03a7e33a 4889742420 mov qword ptr [rsp+20h],rsi
fffff880`03a7e33f 57 push rdi
fffff880`03a7e340 4883ec40 sub rsp,40h
fffff880`03a7e344 488b05b51c0000 mov rax,qword ptr [win7+0x3000 (fffff880`03a80000)]
fffff880`03a7e34b 4833c4 xor rax,rsp
fffff880`03a7e34e 4889442430 mov qword ptr [rsp+30h],rax
再看进程回调函数
.text:0000000140001330 PreProcessCall proc near ; DATA XREF: sub_140001190+A2�o
.text:0000000140001330 ; .pdata:0000000140004054�o
.text:0000000140001330
.text:0000000140001330 Str1 = byte ptr -28h
.text:0000000140001330 var_18 = qword ptr -18h
.text:0000000140001330 arg_0 = qword ptr 8
.text:0000000140001330 arg_10 = qword ptr 18h
.text:0000000140001330 arg_18 = qword ptr 20h
.text:0000000140001330
.text:0000000140001330 mov [rsp+arg_0], rbx
.text:0000000140001335 mov [rsp+arg_10], rbp
.text:000000014000133A mov [rsp+arg_18], rsi
.text:000000014000133F push rdi
.text:0000000140001340 sub rsp, 40h
.text:0000000140001344 mov rax, cs:__security_cookie
.text:000000014000134B xor rax, rsp
.text:000000014000134E mov [rsp+48h+var_18], rax
两者确认,完全一致。