首页
社区
课程
招聘
[求助]编写驱动的问题 第二次调用MmGetSystemRoutineAddress会反回0
发表于: 2008-4-17 15:41 7092

[求助]编写驱动的问题 第二次调用MmGetSystemRoutineAddress会反回0

2008-4-17 15:41
7092
编写驱动的问题调用MmGetSystemRoutineAddress会反回0
以下是驱动的源码。
.386
.model flat, stdcall
option casemap:none
       
        ;**************************************************************************************************
        include w2k\ntstatus.inc
        include w2k\ntddk.inc
        include w2k\ntoskrnl.inc
        includelib c:\radasm\masm32\lib\w2k\ntoskrnl.lib
        includelib d:\ntoskrnl.lib
        include c:\radasm\masm32\Macros\Strings.mac
       
        ;**************************************************************************************************

m2m MACRO M1, M2
        push M2
        pop  M1
ENDM

IOCTL_GET_ZwOpenProcess        equ        CTL_CODE(FILE_DEVICE_UNKNOWN, 10h, METHOD_BUFFERED, FILE_READ_ACCESS+FILE_WRITE_ACCESS)
IOCTL_GET_ZwProtectVirtualMemory        equ        CTL_CODE(FILE_DEVICE_UNKNOWN, 11h, METHOD_BUFFERED, FILE_READ_ACCESS+FILE_WRITE_ACCESS)
IOCTL_GET_ZwReadVirtualMemory        equ        CTL_CODE(FILE_DEVICE_UNKNOWN, 12h, METHOD_BUFFERED, FILE_READ_ACCESS+FILE_WRITE_ACCESS)
IOCTL_GET_ZwWriteVirtualMemory        equ        CTL_CODE(FILE_DEVICE_UNKNOWN, 13h, METHOD_BUFFERED, FILE_READ_ACCESS+FILE_WRITE_ACCESS)

.data
        ;保存地址
        dwOldNtLoadDriver   dd            ?
        dwAddr              dd            ?
        dwDriverName        ANSI_STRING  <>
        dwOldNtOpenProcess dd ?
        dwOldNtProtectVirtualMemory dd ?
        dwOldNtReadVirtualMemory dd ?
        dwOldNtWriteVirtualMemory dd ?
        buffer db 256 dup(?)
.const
        CCOUNTED_UNICODE_STRING "\\Device\\devHookApi", g_usDeviceName, 4
        CCOUNTED_UNICODE_STRING "\\??\\slHookApi", g_usSymbolicLinkName, 4
        CCOUNTED_UNICODE_STRING "ZwLoadDriver", g_ZwLoadDriver, 4
        CCOUNTED_UNICODE_STRING "ZwOpenProcess", g_NtOpenProcess, 4
        CCOUNTED_UNICODE_STRING "ZwProtectVirtualMemory", g_NtProtectVirtualMemory, 4
        CCOUNTED_UNICODE_STRING "ZwReadVirtualMemory", g_NtReadVirtualMemory, 4
        CCOUNTED_UNICODE_STRING "ZwWriteVirtualMemory", g_NtWriteVirtualMemory, 4
       
       
        ;        要还原的函数
        ;        NtOpenProcess
        ;        NtProtectVirtualMemory
        ;        NtReadVirtualMemory
        ;        NtWriteVirtualMemory
        ;        NtUserSendInput
        ;**************************************************************************************************
.code
        ;让这个函数在NtLoadDriver的调用时被执行以实现监视
NewNtLoadDriver     proc  lpDriverName:PUNICODE_STRING
       
        pushad
        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
        ;下面是用KeServiceDescriptorTabled导出符号获得数组的基地址,这个数组中包含有NtXXXX函数的入口地址。
        mov eax, KeServiceDescriptorTable
        mov esi, [eax]
        mov esi, [esi]
        ;用MmGetSystemRoutineAddress来获得函数ZwLoadDriver的地址。并从这个函数地址后面的第2个字节中取得服务号。从而
        ;获得以服务号为下标的数组元素。
        invoke MmGetSystemRoutineAddress,addr g_ZwLoadDriver
        inc eax
        movzx ecx,byte ptr[eax]
        sal ecx,2                  
        add esi,ecx
        mov dwAddr,esi
        mov edi,dword ptr[esi]
        ;保存旧的函数地址。
        mov dwOldNtLoadDriver,edi
        invoke DbgPrint, $CTA0("dwOldNtLoadDriver:%08X"),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
        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
GetServiceDescriptorTableShadowAddress proc uses esi edi ebx

local dwThreadId:DWORD

        xor ebx, ebx                                ; = NULL. Assume ServiceDescriptorTableShadow will be not found

        mov eax, KeServiceDescriptorTable
        mov esi, [eax]

        ; Find KTHREAD.ServiceTable field
        ; For non-GUI threads this field == KeServiceDescriptorTable
        ; and it points to ServiceDescriptorTable
        ; For GUI threads
        ; ServiceDescriptorTableShadow

        invoke KeGetCurrentThread
        mov edi, 200h-4
        .while edi
                .break .if dword ptr [eax][edi] == esi
                dec edi
        .endw

        .if edi != 0
                ; edi = offset to ServiceTable field in KTHREAD structure
                mov dwThreadId, 080h
                .while dwThreadId < 400h
                        push eax                                        ; reserve DWORD on stack
                        invoke PsLookupThreadByThreadId, dwThreadId, esp
                        pop ecx                                                ; -> ETHREAD/KTHREAD
                        .if eax == STATUS_SUCCESS
                                push dword ptr [ecx][edi]
                                fastcall ObfDereferenceObject, ecx
                                pop eax
                                .if eax != esi
                                        mov edx, MmSystemRangeStart
                                        mov edx, [edx]
                                        mov edx, [edx]
                                        .if eax > edx                ; some stupid error checking
                                                mov ebx, eax
                                                .break
                                        .endif
                                .endif
                        .endif
                        add dwThreadId, 4
                .endw
        .endif

        mov eax, ebx
        ret

GetServiceDescriptorTableShadowAddress endp
_DispatchControl proc uses esi edi ebx,pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
        LOCAL        status : NTSTATUS
        LOCAL        dwBytesReturned
       
        and        dwBytesReturned, 0
        mov        status, STATUS_UNSUCCESSFUL
        mov        esi, pIrp
        assume        esi : ptr _IRP
       
        IoGetCurrentIrpStackLocation esi
        mov        edi, eax
        assume        edi : ptr IO_STACK_LOCATION
       
        mov        eax, [edi].Parameters.DeviceIoControl.IoControlCode
        push        edi
        int 3
        .if eax==IOCTL_GET_ZwOpenProcess
                invoke getsysFunction,addr g_NtOpenProcess,dwOldNtOpenProcess

此处调用返回正常。

        .elseif  eax==IOCTL_GET_ZwProtectVirtualMemory
                invoke getsysFunction,addr g_NtProtectVirtualMemory,dwOldNtProtectVirtualMemory

此处调用getsysfunction时MmGetSystemRoutineAddress会返回0

        .elseif  eax==IOCTL_GET_ZwReadVirtualMemory
                invoke getsysFunction,addr g_NtReadVirtualMemory,dwOldNtReadVirtualMemory
        .elseif  eax==IOCTL_GET_ZwWriteVirtualMemory
                invoke getsysFunction,addr g_NtWriteVirtualMemory,dwOldNtWriteVirtualMemory
        .endif
        pop        edi
        assume        edi : ptr IO_STACK_LOCATION
        mov        esi, pIrp
        assume        esi : ptr _IRP
       
        m2m        [esi].IoStatus.Status, status
        m2m        [esi].IoStatus.Information, dwBytesReturned

        assume        esi : nothing
        assume        edi : nothing

        invoke        IoCompleteRequest, pIrp, IO_NO_INCREMENT

        mov eax, status
        ret

_DispatchControl endp
       
getsysFunction proc funcname:dword,saveaddr:dword
        pushad
        mov eax, KeServiceDescriptorTable
        mov esi, [eax]
        mov esi, [esi]
        ;获得以服务号为下标的数组元素。
        invoke MmGetSystemRoutineAddress,funcname
        inc eax
        movzx ecx,byte ptr[eax]
        sal ecx,2                  
        add esi,ecx
        mov edi,dword ptr[esi]
        ;保存旧的函数地址。
        mov saveaddr,edi
        invoke DbgPrint, $CTA0("%08X"),edi
        popad
        ret
getsysFunction endp       

        ;**************************************************************************************************
DriverEntry         proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
local status:NTSTATUS
local pDeviceObject:PDEVICE_OBJECT
        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
                        mov        [eax].MajorFunction[IRP_MJ_DEVICE_CONTROL*(sizeof PVOID)],        offset _DispatchControl
                        assume eax:nothing
                        invoke GetServiceDescriptorTableShadowAddress
                        .if eax != NULL
                                invoke DbgPrint, $CTA0("ServiceDescriptorTableShadow at address: %08X\n"), eax
                        .endif
                        invoke HookFunction
                        mov status, STATUS_SUCCESS
                .else
                        invoke IoDeleteDevice, pDeviceObject
                .endif
        .endif
        mov eax, status

        ret
       
DriverEntry         endp
       
end DriverEntry

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
2
原因是ZwProtectVirtualMemory这个函数没有在ntoskrnl.exe中导出,如果在ntoskrnl的导出表中有,MmGetSystemRoutineAddress就能返回。如果没有,返回0
2008-4-17 22:33
0
雪    币: 157
活跃值: (416)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
明白了。   呵呵
2008-4-18 09:29
0
游客
登录 | 注册 方可回帖
返回
//