⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 反病毒引擎设计之实时监控篇.txt

📁 学习(编程技巧_编程知识_程序代码),是学习编程不可多得的学习精验
💻 TXT
📖 第 1 页 / 共 5 页
字号:
3.设备控制例程(IRP_MJ_DEVICE_CONTROL):它会从入口IRP当前堆栈单元中取得用户程序利用DeviceIoControl传送进来的IO控制代码(IoControlCode),以此判断用户程序的意图。和Hooksys.sys协同工作的ring3级客户程序guidll.dll会依次向Hooksys.sys发送IO控制请求来完成一系列工作,具体次序和代码含义如下: 

83003C2F:将guidll取得的驱动器类型值传给驱动(保存在DriverType变量中),根据此变量值的不同,设置不同的等待(KeWaitForSingleObject)超时值,因为非固定驱动器的读写时间会稍长些。 

83003C0F:保存guidll传送的用户指定的拦截文件的类型,其实这个类型过滤器在查毒模块中已存在,这里再设置显然是为了提高处理效率:它确保不会将非指定类型文件送到ring3级查毒模块,节省了通信的开销。经过解析的各文件类型过滤块指针将保存在_gaFileNameFilterArra数组中,同时更新过滤项个数_gNumOfFilters变量的值。 

83003C13:修改文件系统驱动程序对象调度例程入口,启动拦截文件操作的钩子函数的工作。 

83003C17:恢复文件系统驱动程序原调度例程入口,停止拦截文件操作的钩子函数工作。 

以上列出的IO控制代码的发出是固定,而当钩子函数启动后,还会发出一些随机的控制代码: 

83003C07:驱动将打开文件链表的头元素即最先的请求打开的文件删除并插入到等待链表尾部,同时将元素的用户空间地址传送至ring3级等待查杀打开文件的线程中处理。 

83003C0B:驱动将关闭文件链表的头元素即最先的请求关闭的文件删除并插入到备用链表尾部,同时将元素中的文件名串传送至ring3级等待查杀关闭文件的线程中处理 

83003C1F:当查得关闭文件是病毒时,更新历史记录链表。 

下面介绍钩子函数_HookCreateDispatch和guidll中等待查杀打开文件的线程协同工作流程,而关闭,清除,设置文件信息,和写入操作的处理与此大同小异: 

当文件请求进入钩子函数_HookCreateDispatch后,它首先从入口IRP中定位当前的堆栈单元并从中取得代表此次请求的文件对象。然后判断当前进程是否为我们自己,若是则必须放过去,因为查毒模块中要频繁的进行文件操作,所以拦截来自ravmon的文件请求将导致严重的系统死锁。接下来利用堆栈单元中的文件对象取得完整的文件路径名并确保文件不是:\PIPE\,\IPC。之后查找历史记录链表以确定该文件是否最近曾被检查并记录过,若在历史记录链表中找到关于该文件的记录并且记录未失效即其时间戳和当前系统时间之差不得大于1F4h,则可直接从记录中读取查毒结果。如历史链表中没有该文件的记录则利用保存的文件类型过滤阵列检查文件是否在被拦截的文件类型之列。至此才进入真正的检查打开文件函数_RAVCheckOpenFile,此函数入口处先从备用,等待或关闭链表头部摘得一空闲元素(_GetFreeEntry)并填充之,如文件路径名域等。接着将空闲元素加入打开文件链表尾部并释放Hookopen信号量唤醒ring3下等待检查打开文件的线程。然后调用KeWaitForSingleObject在空闲元素中保存的一个事件对象上等待ring3查毒的完成。当钩子函数挂起后,ring3查毒线程得到执行:它会向驱动发出一IO控制码为83003C07的请求以取得打开文件链表头元素即保存最先提交而未决的文件请求,驱动会将元素映射到用户空间中的偏移地址直接传给它。接着它调用RsEngine.dll中的fnScanOneFile函数进行查毒并在元素中设置查毒结果位,完毕后再对元素中保存的事件对象调用SetEvent唤醒在此事件上等待的钩子函数。被唤醒的钩子函数检查被ring3查毒代码设置的结果位以此决定该文件请求是被采纳即调用保存的原调度例程还是被取消即调用IofCompleteRequest直接返回,同时增加历史记录。 

以上只是钩子函数与ring3线程流程的一个简单介绍,其中省略了诸如判断固定驱动器,超时等内容,具体细节请参看guidll.dll和hooksys.sys的反汇编代码注释。 

4.关闭例程(IRP_MJ_CLOSE):停止钩子函数工作,恢复文件系统驱动程序原调度入口(_StopFilter)。解除到用户空间的内存映射。 

5.卸载例程(DriverUnload):停止钩子函数工作,恢复文件系统驱动程序原调度入口。删除设备和符号连接。删除初始化时创建的一组命名事件对象Hookxxxx,包括解除指针引用,关闭打开的句柄。释放为MDL(_pMdl),备用链表(_SysBufAddr),历史记录链表(_HistoryBuf)和过滤器分配的内存空间。删除为文件名过滤数组访问同步设置的资源变量(_FilterResource)。解除对系统全局命名内核区中Hookopen和Hookclose两个命名信号量的指针引用。 

3.4.3HOOKSYS.SYS逆向工程代码剖析 

3.4.3.1取得当前进程名称代码 

初始化例程中取得进程名在Eprocess中偏移 

00011889 call ds:__imp__IoGetCurrentProcess@0 ;
得到当前进程System的Eprocess指针
0001188F mov edi, eax ;Eprocess基地址
00011891 xor esi, esi ;初始化偏移为0
00011893 lea eax, [esi+edi] ;扫描指针
00011896 push 6 ;进程名长度
00011898 push eax ;扫描指针
00011899 push offset $SG8452 ; "System" ;进程名串
0001189E call ds:__imp__strncmp ;比较扫描指针处是否为进程名
000118A4 add esp, 0Ch ;恢复堆栈
000118A7 test eax, eax ;测试比较结果
000118A9 jz short loc_118B9 ;找到则跳出循环
000118AB inc esi ;增加偏移量
000118AC cmp esi, 3000h ;在12K范围中扫描
000118B2 jb short loc_11893 ;在范围之内则继续比较
钩子函数开始处取得当前进程名

00010D1E call ds:__imp__IoGetCurrentProcess@0 ;得到当前进程System的Eprocess指针
00010D24 mov ecx, _ProcessNameOffset ;取得保存的进程名偏移量
00010D2A add eax, ecx ;得到指向进程名的指针


3.4.3.2启动钩子函数工作代码 

000114F4 push 4 ;预先将文件系统驱动对象个数压栈
000114F6 mov esi, offset FsDriverObjectPtrList ;
取得文件系统驱动对象指针列表偏移地址
000114FB pop edi ;用EDI做记数器,初始值为4
000114FC mov eax, [esi] ;取得第一个驱动对象的指针 
000114FE test eax, eax ;测试是否合法
00011500 jz short loc_11548 ;不合法则继续下一个修改驱动对象
00011502 mov edx, offset _HookCreateDispatch@8 ;
取得自己的钩子函数的偏移地址
00011507 lea ecx, [eax+38h] ;取得对象中打开调度例程(IRP_MJ_CREATE)偏移
0001150A call @InterlockedExchange@8 ;
原子操作,替换驱动对象中打开调度例程的入口为钩子函数的偏移地址
0001150F mov [esi-10h], eax ;保存原打开调度例程的入口


3.4.3.3映射系统内存至用户空间代码 

0001068E push esi ;系统内存大小
0001068F push _SysBufAddr ;系统内存基地址
00010695 call ds:__imp__MmSizeOfMdl@8 ;计算描述系统内存所需内存描述符表(MDL)大小 
0001069B push 206B6444h ;调试用标签
000106A0 push eax ;MDL大小 
000106A1 push 0 ;在系统非分页内存池中分配
000106A3 call ds:__imp__ExAllocatePoolWithTag@12 ;为MDL分配内存
000106A9 push esi ;系统内存大小
000106AA mov _pMdl, eax ;保存MDL指针
000106AF push _SysBufAddr ;系统内存基地址 
000106B5 push eax ;MDL指针
000106B6 call ds:__imp__MmCreateMdl@12 ;初始化MDL
000106BC push eax ;MDL指针
000106BD mov _pMdl, eax ;保存MDL指针
000106C2 call ds:__imp__MmBuildMdlForNonPagedPool@4 
;填写MDL后物理页面数组
000106C8 push 1 ;访问模式
000106CA push _pMdl ;MDL指针
000106D0 call ds:__imp__MmMapLockedPages@8 ;映射MDL描述的物理内存页面
......
000106DB mov _UserBufAddr, eax ;保存映射后的用户空间地址 
_UserBufAddr 和_SysBufAddr映射到相同的物理地址。
 
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -