首页
社区
课程
招聘
[原创]兵刃部分功能实现
发表于: 2008-8-30 11:32 5903

[原创]兵刃部分功能实现

2008-8-30 11:32
5903
兵刃想必大家都知道吧。一个不错的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不熟悉的用。

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 


下面讲讲第二点,

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

这个是驱动部分

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 



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

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

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 



就可以检测是谁HOOK的了。

下面将将第三个功能:

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

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


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 



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

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 301
活跃值: (300)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
2
收藏学习了。谢谢分享!
2008-8-30 11:40
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
3
又是SSDT,还和IS扯上关系。。。
太古老了。。。
2008-8-30 13:23
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
对于你们这些大牛是古老了,但是对于我这样的小菜就不老了
2008-8-30 13:32
0
雪    币: 581
活跃值: (149)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
5
IS过时了.....
2008-8-30 13:34
0
游客
登录 | 注册 方可回帖
返回
//