21:33 2007-9-20
今天发现了 syser debugger 的 SDbgMsg.sys。 这个驱动程序就是SERVICE_BOOT_START 类型的驱动程序, 在windows 启动后最新给出提示信息 "Press "ESC" to Cancel Load Syser Boot Module ",我想看看到底是怎样编程实现的:
打开 IDA 载入 SDbgMsg.sys 程序, 反汇编代码如下:
; int __stdcall start(PDEVICE_OBJECT DeviceObject)
public start
start proc near
SymbolicLinkName = UNICODE_STRING ptr -18h
DeviceName = UNICODE_STRING ptr -10h
SystemRoutineName = UNICODE_STRING ptr -8
DeviceObject = dword ptr 8
.text:00010850 push ebp
.text:00010851 mov ebp, esp ; 打开栈帧
.text:00010853 sub esp, 18h
.text:00010856 push ebx
.text:00010857 push esi
.text:00010858 mov esi, [ebp+DeviceObject]
.text:0001085B push edi
.text:0001085C push 1Bh
.text:0001085E lea edx, [esi+38h]
.text:00010861 pop ecx ; 给ecx赋值 1Bh
.text:00010862 mov eax, offset loc_10428
.text:00010867 mov edi, edx
.text:00010869 rep stosd
上面的反汇编代码可能有问题, DeviceObject 应该是 DirverObject。如果是 DeviceObject ,那偏移 38H 位置是
DeviceObject->Queue.Blink 或者是 DeviceObject->Queue.Wcb.WaitQueueEntry.Blink 。我想不出 DeviceObject 的这些成员怎么使用。一般情况下程序开始时就是设置 Dispatch 例程, 而 DriverObject 的 Dispatch 例程就是在 38H 偏移位置, 所以我可以认为这里的 DeviceObject 就是 DriverObject。
可见 loc_10428 例程就是通用的派遣例程.
下面是DeviceObject 的偏移为38H 位置的结构图
下面是 DriverObject 偏移为 38H 位置的结构图
.text:0001086B mov edi, ds:RtlInitUnicodeString
.text:00010871 push offset aDeviceSyserdbg ; "//Device//SyserDbgMsg"
.text:00010876 lea eax, [ebp+DeviceName]
.text:00010879 push eax ; DestinationString
; 设置 DirverObject->DriverUnload = sub_10702
.text:0001087A mov dword ptr [esi+34h], offset sub_10702
; 设置 DirverObject->MajorFunction[IRP_MJ_CREATE] = loc_103DC
.text:00010881 mov dword ptr [edx], offset loc_103DC
; 设置 DirverObject->MajorFunction[IRP_MJ_READ] = sub_10646
.text:00010887 mov dword ptr [esi+44h], offset sub_10646
; 设置 DirverObject->MajorFunction[IRP_MJ_CLOSE] = loc_103F8
.text:0001088E mov dword ptr [esi+40h], offset loc_103F8
; 设置 DirverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = loc_10442
.text:00010895 mov dword ptr [esi+70h], offset loc_10442
.text:0001089C call edi ; RtlInitUnicodeString
.text:0001089E lea eax, [ebp+DeviceObject]
.text:000108A1 push eax ; DeviceObject
.text:000108A2 xor ebx, ebx
.text:000108A4 push ebx ; Exclusive
.text:000108A5 push ebx ; DeviceCharacteristics
.text:000108A6 push 22h ; DeviceType
.text:000108A8 lea eax, [ebp+DeviceName]
.text:000108AB push eax ; DeviceName
.text:000108AC push ebx ; DeviceExtensionSize
.text:000108AD push esi ; DriverObject
.text:000108AE call ds:IoCreateDevice
.text:000108B4 test eax, eax
.text:000108B6 jl short loc_108E6
.text:000108B8 mov eax, 2000h
.text:000108BD push eax ; BugCheckParameter1
.text:000108BE mov dword_1221C, eax
.text:000108C3 mov dword_12220, ebx
.text:000108C9 call sub_10FD6
.text:000108CE cmp eax, ebx
.text:000108D0 pop ecx
.text:000108D1 mov dword_12224, eax
.text:000108D6 jnz short loc_108F0
.text:000108D8 push [ebp+DeviceObject] ; DeviceObject
.text:000108DB call ds:IoDeleteDevice
NTSTATUS NtStatus= IoCreateDevice( esi,
0,
"//Device//SyserDbgMsg", // UNICODE_STRING 类型的变量
22h, // FILE_DEVICE_UNKNOWN
0,
0,
DeviceObject );
if (STATUS_SUCCESS != NtStatus)
{
退出;
}
sub_10FD6 ( , 2000h);
.text:000108F0 mov eax, [ebp+DeviceObject]
.text:000108F3 or dword ptr [eax+1Ch], 4
.text:000108F7 mov eax, [ebp+DeviceObject]
.text:000108FA and byte ptr [eax+1Ch], 7Fh
.text:000108FE push offset a??Syserdbgms_0 ; "//??//SyserDbgMsg"
.text:00010903 lea eax, [ebp+SymbolicLinkName]
.text:00010906 push eax ; DestinationString
.text:00010907 call edi ; RtlInitUnicodeString
.text:00010909 lea eax, [ebp+DeviceName]
.text:0001090C push eax ; DeviceName
.text:0001090D lea eax, [ebp+SymbolicLinkName]
.text:00010910 push eax ; SymbolicLinkName
.text:00010911 call ds:IoCreateSymbolicLink
.text:00010917 push offset SpinLock ; SpinLock
.text:0001091C call ds:KeInitializeSpinLock
RtlInitUnicodeString (SymbolicLinkName , L"//??//SyserDbgMsg");
// SymbolicLinkName: "//??//SyserDbgMsg"
// DeviceName: "//Device//SyserDbgMsg"
IoCreateSymbolicLink( SymbolicLinkName , DeviceName) ;
.text:00010938 push offset aDbgsetdebugpri ; "DbgSetDebugPrintCallback"
.text:0001093D lea eax, [ebp+SystemRoutineName]
.text:00010940 push eax ; DestinationString
.text:00010941 call edi ; RtlInitUnicodeString
.text:00010943 mov esi, ds:MmGetSystemRoutineAddress
.text:00010949 lea eax, [ebp+SystemRoutineName]
.text:0001094C push eax ; SystemRoutineName
.text:0001094D call esi ; MmGetSystemRoutineAddress
.text:0001094F cmp eax, ebx
.text:00010951 mov dword_12000, eax
.text:00010956 jz short loc_109A3
.text:00010958 push 1
.text:0001095A push offset sub_10D8A
.text:0001095F call eax
.text:00010961 test eax, eax
.text:00010963 jl short loc_109A3
.text:00010965 push offset aDbgsetdebugfil ; "DbgSetDebugFilterState"
.text:0001096A lea eax, [ebp+SystemRoutineName]
.text:0001096D push eax ; DestinationString
.text:0001096E mov byte_11FFC, 1
.text:00010975 call edi ; RtlInitUnicodeString
.text:00010977 lea eax, [ebp+SystemRoutineName]
.text:0001097A push eax ; SystemRoutineName
.text:0001097B call esi ; MmGetSystemRoutineAddress
.text:0001097D cmp eax, ebx
.text:0001097F mov dword_12004, eax
.text:00010984 jz short loc_109A3
.text:00010986 xor edi, edi
RtlInitUnicodeString (uniSystemRoutineName, L"DbgSetDebugPrintCallback");
dword_12000 = MmGetSystemRoutineAddress(uniSystemRoutineName);
RtlInitUnicodeString (uniSystemRoutineName, L"DbgSetDebugFilterState");
dword_12004 = MmGetSystemRoutineAddress(uniSystemRoutineName);
if ( (dword_12000 == NULL) && (dword_12004 == NULL) )
{
.text:000109AB push ebx ; DeferredContext
.text:000109AC push offset DeferredRoutine ; DeferredRoutine
.text:000109B1 mov edi, offset Dpc
.text:000109B6 push edi ; Dpc
.text:000109B7 call ds:KeInitializeDpc
.text:000109BD mov esi, offset unk_11FB0
.text:000109C2 push esi ; Timer
.text:000109C3 call ds:KeInitializeTimer
.text:000109C9 push edi ; Dpc
.text:000109CA push 3E8h ; Period
.text:000109CF or ecx, 0FFFFFFFFh
.text:000109D2 push ecx
.text:000109D3 mov eax, 0FF676980h
.text:000109D8 push eax ; DueTime
.text:000109D9 push esi ; Timer
.text:000109DA call ds:KeSetTimerEx
.text:000109E0 jmp short loc_109F3
DeferredContext = 0;
KTIMER g_Timer ;
KeInitializeDpc( &g_Dpc , DeferredRoutine, 0);
KeInitializeTimer( &g_Timer );
KeSetTimerEx( &g_Timer, 0FF676980h, 3E8h, &g_Dpc );
.text:000109F3 loc_109F3: ; CODE XREF: start+159j
.text:000109F3 ; start+190j
.text:000109F3 xor eax, eax
.text:000109F5
.text:000109F5 loc_109F5: ; CODE XREF: start+9Bj
.text:000109F5 pop edi
.text:000109F6 pop esi
.text:000109F7 pop ebx
.text:000109F8 leave
.text:000109F9 retn 8
.text:000109F9 start endp
程序结束
}
下面是关于延迟过程调用和Timer的说明:
If the Dpc parameter is specified, a DPC object is associated with the timer object.
When the timer expires, the timer object is removed from the system timer queue and it is set to a signaled state.
If a DPC object was associated with the timer when it was set, the DPC object is inserted in the system DPC queue to be executed as soon as conditions permit after the timer interval expires.
总结:
(1)DeferredRoutine 是一个延迟过程调用, 在该例程中会做些什么呢? 我想可能是先前执行的某段代码由于执行时机的原因而没有成功, 在该例程中会重复执行直至成功为止.
(2)sub_10702: DriverUnload
loc_103DC: SDbgMsgCreate
sub_10646: SDbgMsgRead
loc_103F8: SDbgMsgClose
loc_10442: SDbgMsgDeviceIoControl
在 IDA 中分别选中这些函数名,然后 鼠标右键-->"rename" ,把这些函数替换为上面容易记忆的名字;
(3) 上面的 DirverEntry 例程中通过 MmGetSystemRoutineAddress 来得到 DbgSetDebugPrintCallback和 DbgSetDebugFilterState 系统例程, 并分别存在 dword_12000 和 dword_12004 内存位置.以后的代码中肯定使用这 2 个值(函数的地址), 我们可以在代码中找到 对dword_12000 和 dword_12004 访问的代码并把它改成具体的例程名 "DbgSetDebugPrintCallback" 和 "DbgSetDebugFilterState "
23:30 2007-9-20