Hook API监视驱动的加载_ASM

来源:互联网 发布:知乎女神陈大花 编辑:程序博客网 时间:2024/05/21 05:37
;**************************************************************************************************
;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大侠的帮助 
原创粉丝点击