黑客X档案官方论坛's Archiver

610548422 发表于 2008-8-30 11:39

兵刃部分功能实现

兵刃想必大家都知道吧。一个不错的ROOTKIT和病毒检测工具。它的自身保护比较简单,就是INLINE HOOK了两个函数。
1.NtOpenProcess
2.NtTerminateProcess

我这天没事情干,就看了看兵刃,发现它的SSDT HOOK检测不错。于是就想自己来实现。实现它要几个方便的技术
1.        如何获取原始地址表
2.        怎么知道谁HOOD的
3.        如何将服务号于具体函数对应

反正只是一个练习,没技术含量。高手就别BS了。
其中大部分是R3的,只有获取内存中SSDT表的部分是R0,也只是一小部分
代码写的很垃圾,寄存器乱用了。也没注释

第一点:如何获取原始地址表

先用ZwQuerySystemInformation查看内核文件

然后静态分析内核文件,得到KeServiceDescriptorTable,然后通过重定位表来确定KiServiceTable,然后就可以得到原始表了(其中涉及到PE文件方面的内容)
找KiServiceTable网上已经开源了,但是那是C的,由于我的C和我的英语一样,单词认识,句子就…………,所以就用汇编写了个,给和我一样对C不熟悉的用。

[code]
FindKiServiceTable        proc        uses ebx esi edi _hKernel,_dwRVAKsdt
        mov        esi,_hKernel
        assume        esi:ptr IMAGE_DOS_HEADER
        mov        edi,[esi].e_lfanew
        add        edi,_hKernel
        assume        edi:ptr IMAGE_NT_HEADERS
        .if        [edi].OptionalHeader.DataDirectory[8*5].VirtualAddress
                mov        esi,[edi].OptionalHeader.DataDirectory[8*5].VirtualAddress
                add        esi,_hKernel
                assume        esi:ptr IMAGE_BASE_RELOCATION
                .while        [esi].VirtualAddress
                        cld
                        lodsd                                ;eax=[esi].VirtualAddress
                        mov        ebx,eax
                        lodsd                                ;eax=[esi].sizeofblock
                        sub        eax,sizeof IMAGE_BASE_RELOCATION
                        shr        eax,1
                        mov        ecx,eax                        ;eax=重定位数量
                        xor        edi,edi
                        .repeat
                                push        ecx                 
                                push        ebx
                                lodsw                        ;取重定位项
                                mov        cx,ax
                                and        cx,0f000h        ;取高四位,为3时候表示32位需要重定位
                                .if        cx==03000h
                                        and        ax,0fffh        ;取低12位
                                        movzx        eax,ax
                                        add        eax,ebx
                                        add        eax,_hKernel
                                        mov        ebx,eax                ;ebx=eax,是现在重定位位置
                                        mov        eax,[eax]        ;eax,要重定位的数据
                                        mov        edi,_hKernel
                                        assume        edi:ptr IMAGE_DOS_HEADER
                                        add        edi,[edi].e_lfanew
                                        assume        edi:ptr IMAGE_NT_HEADERS
                                        sub        eax,[edi].OptionalHeader.ImageBase
                                        .if        eax==_dwRVAKsdt
                                                mov        ax,[ebx-2]
                                                .if        ax==05c7h
                                                        mov        ebx,[ebx+4]
                                                        sub        ebx,[edi].OptionalHeader.ImageBase                ; EBX=KiServiceTable的RVA
                                                        mov        eax,ebx
                                                        ret
                                                .endif
                                        .endif
                                .else
                                        mov        eax,-1
                                .endif
                                pop        ebx
                                pop        ecx
                        .untilcxz
                .endw
        .endif
        mov        eax,FALSE
        ret

FindKiServiceTable endp [/code]

下面讲讲第二点,

如何知道被HOOK,其实很简单,比较原始表和内存中的表就可以了。所以写了个根据服务号得到函数地址。

这个是驱动部分

[code]
GetSSDTByIndex                proc        index:dword
                        
                        mov        eax,KeServiceDescriptorTable
                        mov        eax,[eax]
                        push        eax
                        mov        eax,4
                        mul        index
                        pop        ecx
                        add        eax,ecx
                        mov        eax,[eax]
                        ret
GetSSDTByIndex                 endp
[/code]

可以发送IOCTL_GETSSDT控制号就可以得到实际函数地址,然后和得到原始地址比较就可以了

在发现被HOOK的情况下,怎么样得到被谁HOOK呢?这要借助ZwQuerySystemInforamtion这个函数的SystemModuleInformation来枚举系统加载的模块,然后根据基地址和大小来判断

[code]
CheckByAddress        proc        uses ebx esi edi Address:dword,lpszBuffer:dword
         
        LOCAL        @cb,@p,@dwNumOfModule
        invoke        NtQuerySystemInformation,SystemModuleInformation,addr @p,0,addr @cb
        .if        !@cb
                invoke        MessageBox,0,$CTA0("无法枚举"),0,MB_ICONERROR
                mov        eax,FALSE
                ret
        .endif
        invoke        GlobalAlloc,GPTR,@cb
        .if        !eax
                invoke        MessageBox,NULL,$CTA0("分配内存出错"),0,MB_ICONERROR
                mov        eax,FALSE
                ret
        .endif
        mov        @p,eax
        invoke        NtQuerySystemInformation,SystemModuleInformation,@p,@cb,addr @cb
        .if        eax!=STATUS_SUCCESS
                invoke        MessageBox,0,$CTA0("无法枚举"),0,MB_ICONERROR
                invoke        GlobalFree,@p
                mov        eax,FALSE
                ret
        .endif
        mov        esi,@p
        mov        ecx,[esi]
        add        esi,4
        assume        esi:ptr SYSTEM_MODULE_INFORMATION
        mov        eax,Address
        .repeat
                push        ecx
                mov        ebx,[esi].Base
                add        ebx,[esi]._Size
                .if        eax>=[esi].Base && eax<ebx
                        lea        edi,[esi].ImageName
                        invoke        lstrlen,edi
                        invoke        RtlMoveMemory,lpszBuffer,edi,eax
                        mov        eax,TRUE
                        pop        ecx
                        ret
                .endif
                pop        ecx
                add        esi,sizeof SYSTEM_MODULE_INFORMATION
        .untilcxz
        invoke        GlobalFree,@p
        mov        eax,FALSE
        ret

CheckByAddress endp [/code]

就可以检测是谁HOOK的了。

下面将将第三个功能:

我用查看ntdll.dll这个DLL的导出表来找ZW开头的函数,在反汇编就可以得到函数名于服务号对应了。


直接贴出代码,PE导出表方面的内容就不说了

[code]
LookByIndex        proc        uses esi edi index:dword,_lpsz
        LOCAL        hModule,dwNum,lpsz
        invoke        LoadLibraryEx,$CTA0("ntdll.dll"),0,DONT_RESOLVE_DLL_REFERENCES
        mov        hModule,eax
        mov        esi,eax
        assume        esi:ptr IMAGE_DOS_HEADER
        add        esi,[esi].e_lfanew
        assume        esi:ptr IMAGE_NT_HEADERS
        MOV        edi,[esi].OptionalHeader.DataDirectory.VirtualAddress
        add        edi,hModule
        assume        edi:ptr IMAGE_EXPORT_DIRECTORY
        mov        ecx,[edi].NumberOfNames
        mov        dwNum,0
        mov        esi,[edi].AddressOfNames
        add        esi,hModule
        .repeat
                push        ecx
                mov        eax,4
                mul        dwNum
                add        eax,esi
                mov        eax,[eax]
                add        eax,hModule
                push        eax
                pop        lpsz
                mov        ax,[eax]
                .if        ax=='wZ'
                        mov        eax,[edi].AddressOfFunctions
                        add        eax,hModule
                        push        eax
                        mov        eax,4
                        mul        dwNum
                        pop        ecx
                        add        eax,ecx
                        mov        eax,[eax]
                        add        eax,hModule
                        mov        eax,[eax+1]
                        .if        eax==index
                                POP        ecx
                                invoke        lstrlen,lpsz
                                invoke        RtlMoveMemory,_lpsz,lpsz,eax
                                mov        eax,TRUE
                                ret
                        .endif
                .endif
                pop        ecx
                add        dwNum,1
        .untilcxz
        mov        eax,FALSE
        ret

LookByIndex endp [/code]

代码写的都不怎么简洁,也没注释,寄存器都乱用了。高手就别笑了。

peter08 发表于 2008-8-30 12:01

对汇编不熟悉,不过是不错得东西,支持了。

夜魔血影 发表于 2008-8-30 12:26

呵呵,兵刃是inline hook 你的是ssdt hook

610548422 发表于 2008-9-2 18:49

我HOOK SSDT了吗。

我的是检测SSDT HOOK,而不是HOOK SSDT

夜魔血影 发表于 2008-9-2 20:37

[quote]原帖由 [i]610548422[/i] 于 2008-9-2 06:49 PM 发表 [url=http://bbs.hackerxfiles.net/redirect.php?goto=findpost&pid=891983&ptid=118059][img]http://bbs.hackerxfiles.net/images/common/back.gif[/img][/url]
我HOOK SSDT了吗。

我的是检测SSDT HOOK,而不是HOOK SSDT [/quote]


呵呵,没细看(其实是不会汇编#_#),看见NtOpenProcess 我还以为,是hook ZwOpenProcess 呢?失误失误啊!

[[i] 本帖最后由 夜魔血影 于 2008-9-2 20:38 编辑 [/i]]

i9420 发表于 2008-9-2 22:11

看着头就大。只学过C语言。。::08:: ::08::

找不到北 发表于 2008-9-9 00:21

不懂,不懂,看来还是要好好学习的了!

上尉 发表于 2008-9-9 21:05

回复 1# 的帖子

本人低手,::02::

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.