轉自:http://blog.csdn.net/iiprogram/archive/2007/09/06/1774026.aspx
;**************************************************************************************************
;Author:dge/D哥
;Date :2006.7.20
;**************************************************************************************************
;@echo off
;goto make
.386
.model flat, stdcall
option casemap:none
;**************************************************************************************************
include d:/masm32/include/w2k/ntstatus.inc
include d:/masm32/include/w2k/ntddk.inc
include d:/masm32/include/w2k/ntoskrnl.inc
includelib d:/masm32/lib/w2k/ntoskrnl.lib
include d:/masm32/Macros/Strings.mac
;**************************************************************************************************
.data
;保存地址
dwOldNtLoadDriver dd ?
dwAddr dd ?
dwDriverName ANSI_STRING
.const
CCOUNTED_UNICODE_STRING "//Device//devHookApi", g_usDeviceName, 4
CCOUNTED_UNICODE_STRING "//??//slHookApi", g_usSymbolicLinkName, 4
CCOUNTED_UNICODE_STRING "ZwLoadDriver", g_usRoutineAddr, 4
;**************************************************************************************************
.code
;讓這個函數在NtLoadDriver的調用時被執行以實現監視
NewNtLoadDriver proc lpDriverName:PUNICODE_STRING
pushad
; int 3
; invoke DbgPrint, $CTA0("/nEntry into NEW/n")
invoke RtlUnicodeStringToAnsiString, addr dwDriverName, lpDriverName,TRUE
invoke DbgPrint, $CTA0("/nDriverName: %s.sys/n"), dwDriverName.Buffer
popad
;調用原函數
push lpDriverName
call dwOldNtLoadDriver
ret
NewNtLoadDriver endp
;**************************************************************************************************
HookFunction proc
pushad
; int 3
; invoke DbgPrint, $CTA0("/nEntry into hoookfunction/n")
;下面是用KeServiceDescriptorTabled導出符號獲得數組的基地址,這個數組中包含有NtXXXX函數的入口地址。
mov eax, KeServiceDescriptorTable
mov esi, [eax]
mov esi, [esi]
;用MmGetSystemRoutineAddress來獲得函數ZwLoadDriver的地址。並從這個函數地址後面的第2個字節中取得服務號。從而
;獲得以服務號爲下標的數組元素。
invoke MmGetSystemRoutineAddress,addr g_usRoutineAddr
inc eax
movzx ecx,byte ptr[eax]
sal ecx,2
add esi,ecx
mov dwAddr,esi
mov edi,dword ptr[esi]
;保存舊的函數地址。
mov dwOldNtLoadDriver,edi
mov edi,offset NewNtLoadDriver
;修改入口地址
cli
mov dword ptr[esi],edi
sti
popad
mov eax, STATUS_SUCCESS
ret
HookFunction endp
;**************************************************************************************************
DispatchCreateClose proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
mov eax, pIrp
assume eax:ptr _IRP
mov [eax].IoStatus.Status, STATUS_SUCCESS
and [eax].IoStatus.Information, 0
assume eax:nothing
invoke IoCompleteRequest, pIrp, IO_NO_INCREMENT
mov eax, STATUS_SUCCESS
ret
DispatchCreateClose endp
;**************************************************************************************************
DriverUnload proc pDriverObject:PDRIVER_OBJECT
;必須保存環境,否則後果很嚴重。在這個函數中恢復被修改的地址。
pushad
; int 3
; invoke DbgPrint, $CTA0("/nEntry into DriverUnload /n")
mov esi,dwAddr
mov eax,dwOldNtLoadDriver
cli
mov dword ptr[esi],eax
sti
invoke IoDeleteSymbolicLink, addr g_usSymbolicLinkName
mov eax,pDriverObject
invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject
popad
ret
DriverUnload endp
;**************************************************************************************************
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
local status:NTSTATUS
local pDeviceObject:PDEVICE_OBJECT
; int 3
; invoke DbgPrint, $CTA0("/nEntry into DriverEntry/n")
mov status, STATUS_DEVICE_CONFIGURATION_ERROR
invoke IoCreateDevice, pDriverObject, 0, addr g_usDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, addr pDeviceObject
.if eax == STATUS_SUCCESS
invoke IoCreateSymbolicLink, addr g_usSymbolicLinkName, addr g_usDeviceName
.if eax == STATUS_SUCCESS
mov eax, pDriverObject
assume eax:ptr DRIVER_OBJECT
mov [eax].DriverUnload, offset DriverUnload
mov [eax].MajorFunction[IRP_MJ_Create*(sizeof PVOID)], offset DispatchCreateClose
mov [eax].MajorFunction[IRP_MJ_CLOSE*(sizeof PVOID)], offset DispatchCreateClose
assume eax:nothing
invoke HookFunction
mov status, STATUS_SUCCESS
.else
invoke IoDeleteDevice, pDeviceObject
.endif
.endif
mov eax, status
ret
DriverEntry endp
end DriverEntry
;**************************************************************************************************
:make
set drv=HooKapi
d:/masm32/bin/ml /nologo /c /coff %drv%.bat
d:/masm32/bin/link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj
del %drv%.obj
echo.
pause
參考:Undocumented Windows NT
感謝:非常感謝cardmagic大俠的幫助