A盾的原理是在驱动加载时重载os内核,获取原始ssdt表的地址。

应用层点击查询的代码在文件A-ProtectView.cpp中,每种点击操作调用相应的

query查询函数,在query函数里 ReadFile。读操作的Handle是A盾自定义的操作码,

类似DeviceIoControl的控制码,比如handle 为LIST_SSDT,LIST_INLINEHOOK等。

驱动加载时hook 了NtReadFile,在hook函数里做应用层要求的操作,返回对应的结构buffer

给应用层。

    下面分两部分做分析。驱动加载的操作和加载和应用层交互完成具体功能部分。

    驱动加载的DriverEntry在SafeSystem.c中,驱动加载时主要完成 1.判断是否是系统刚刚启动。通过当前进程数大于三。2.创建注册表标识驱动运行起来,应用层启动成功删除,主要是判断是否启动成功。3.

判断是否是hook 了 KiFastCallEntry。主要是读取msr寄存器指向该函数的指针,inline 前五个字节到新内核。3.重载内核。重载内核的目的是获取原始ssdt表的地址,方便查询ssdt hook 和 自己调用函数时不经过其他软件的过滤。4.对服务做深度扫描。主要是在驱动里面枚举Services的注册表键值。

    加载驱动的核心操作在第3步重载内核ReLoadNtos函数中。函数中操作主要是1.获取已经加载的内核的信息,2.调用InitSafeOperationModule来peload一个ntos避免其它软件hook的过滤,peload的操作需要先获取内核文件大小,通过IRP_MJ_QUERY_INFORMATION自己构造IRP来获取。然后自己通过IRP_MJ_READ自己构造IRP把文件全部读入内存。然后读取dos,nt头和节表,获取模块基地址。然后修复导入表,重定位表。这么麻烦的操作主要是内存中的pe文件和硬盘中的文件会有字节对齐的差别,导致计算ssdt偏移时出错。重载os后,在导出表中搜寻KeServiceDescriptorTable,然后计算它和加载基址的偏移差。通过旧的ssdt偏移,新的os内核基址,旧的os内核基址,_KiServiceTable,计算出重载后的os的ssdt表的基址。得到基址后,修复对ssdt表的地址重定位。将重定位后的ssdt表保存到自己的全局变量中了。3.将导出表里面的函数地址信息保存到自己的结构中。

4.调用ReLoadNtosCALL通过刚才保存的结构从新内核中获取PsGetCurrentProcess,MmIsAddressValid的原始地址,方便后面调用。5.hook KiFastCallEntry开头5个字节跳转到新内核的KiFastCallEntry,再 hook dwReloadKiFastCallEntry,目的不是很清楚。6.初始化和应用层的通信,hook ZwReadFile ,通过handle和应用层通信。hook ZwTerminateProcess保护自己不被结束进程。hook ZwSetValueKey监控start,ImagePath,ServiceDll启动服务,加载驱动。hook ZwCreateSection监控进程启动,object hook,子进程创建,dll加载,dll劫持。7. hook PsCreateSystemThread监控系统线程的创建。8.hook NtReadFile获取csrss.exe的 

EPROCESS. Reload win32k根据对话框,判断是否是A盾发送的命令。

    和应用层交互完成具体功能部分。按菜单提供的功能从上到下分析。

    查询SSDT的hook,分为两种ssdt hook 和inline hook。通过reload os的操作,对比下系统的ssdt和reload os的ssdt就可以出来了。对于inline hook,依次遍历ssdt表的函数,在导出表中找到对应的函数名,然后二分法查找旧的函数和reload 的函数汇编代码,如果不同就是inline hook 了,然后根据call 指令还是jmp指令判断跳转类型。还有简单处理一下多级跳。

    查询Shadow SDT的hook,先附加CSRSS进程,查找方法同SSDT hook。

    查询内核钩子,对于win32k和ntos处理一样。先检查模块的eat导出表hook,对于导出的函数依次调用反汇编引擎,二分法查找每个函数内是否有hook 指令。它的反汇编引擎是libdasm 开源库。如果是扫描指定模块,方法同上面。

    查询Object Hook,对于FileObject,DeviceObject,DriverObject,CmpKeyObject分别进行检测。对于FileObject,检测FileCloseProcedure,IopProcedure,IopQueryName是否被inline hook,这个是文件对象的关闭函数,打开函数,查询函数。对于DeviceObject,检测IopDeleteDevice,IopParseDevice设备对象的删除,打开函数。对于DriverObject,检测IopDeleteDriver函数。对于CmpKeyObject,检测CmpCloseKeyObject,CmpDeleteKeyObject,CmpParseKey,CmpKeyObjectType函数。注册表的是openkey注册表,然后ObReferenceObjectByHandle,ObGetObjectType。

    检测驱动模块,检测分为链表检测和A盾运行后的驱动监控,暴力枚举驱动对象。链表检测主要是遍历DriverObject->DriverSection->InLoadOrderLinks。暴力枚举参考了sysnap的代码貌似,搜索MmNonPagedPoolStart开始的内存区,搜索0xf000000个字节,通过判断MajorFunction[28]来确定是不是驱动。

    检测内核中线程的创建,主要是hook PsCreateSystemThread监视线程的创建。

    检测内核中系统线程或者进程的线程,主要是检测硬编码偏移,eprocess的ThreadListHead 线程链表和ethread的ThreadListEntry。

    检测DPC定时器,系统有DPC和IO两种定时器。获取每个cpu的kpcr+0x34->KdVersionBlock->KiProcessorBlock结构,每个cpu有个KPRCB控制结构,里面有KTIMER_TABLE_ENTRY,即DPC定时器的地址。

    检测IO定时器,在IoInitializeTimer定时器初始化函数中,搜寻到nt!IopTimerQueueHead定时器链表

指针的偏移指令,然后枚举这个链表。

    检测系统回调,分别检测文件系统,创建进程,创建线程,loadImage,BugCheck,关机回调,LeaveSession注销回调。对于文件系统回调链表,在IoRegisterFsRegistrationChange函数搜索IopFsNotifyChangeQueueHead回调链表的地址。对于进程,是在PsSetCreateProcessNotifyRoutine搜索回调数组的指令偏移。对于线程,是在PsSetCreateThreadNotifyRoutine搜索回调数组的指令固定偏移。对于LoadImage是在PsSetLoadImageNotifyRoutine中搜索回调数组指令偏移。对于BugCheck,是搜索KeRegisterBugCheckCallback函数中的回调例程指令地址。关机回调是搜索IoRegisterShutdownNotification的固定偏移。对于注销回调,是搜索SeRegisterLogonSessionTerminatedRoutine中的固定偏移。

    检测工作队列线程。硬编码WorkSuspendThread检查。可以枚举ExWorkerQueue。

    检测过滤驱动,分别枚举\\FileSystem,\\Driver目录下的驱动。依次调用ZwOpenDirectoryObject,

ZwQueryDirectoryObject打开目录对象,查询目录对象,然后遍历设备栈看AttachedDevice附加设备。

    检测Ntfs驱动例程,Peload 驱动文件ntfs.sys,找到驱动入口点DriverEntry后,硬编码找到派遣例程,

重定位ntfs,然后找到各种irp_mj_xx的派遣例程地址。

    检测TcpIp驱动例程,Nsiproxy网络netBios驱动例程,KbdClass,Mouclass,Atapi。即网络,键盘,鼠标的驱动派遣例程。方式同ntfs。Atapi是Windows IDE/ATAPI 硬盘的小端口驱动程序。Nsiproxy是以前的

netio.sys驱动。

    检测系统进程,主要是遍历Eprocess中的ActiveProcessLinks进程链表。

    检测系统服务,分为普通检测和深度检测。普通检测就是驱动中枚举注册表CurrentControlSet\Services。深度检测就是在系统启动时在注册表刚初始化好时枚举依次,然后做一次对比。

    检测网络连接,主要是显示网络连接状态。先reload tcpip.sys和nsiproxy.sys,然后自己构建一个

IRP向Tcpip驱动发送IOCTL_TCP_QUERY_INFORMATION_EX查询,然后打印出来。

    检测被动防御,主要是向驱动查询日志信息,驱动启动后会记录日志信息,比如进程,线程创建等。

    本机所有数据的监控。这个是自己注册了一个Ndis协议驱动,监控所有发送出去的包。当开启监控时,

加载A-ProtectTcpSniffer.sys协议驱动,向该驱动发送控制码IOCTL_NDIS5PKT_BIND_ADAPTER绑定网卡,

发送IOCTL_NDIS5PKT_SET_OID_VALUE控制码设置网卡信息,然后创建A-Protect-TcpSniffer.txt记录文件

最后开启一个线程注册事件死循环等待ndis激活事件,事件激活后输出到记录文件中。向协议驱动发送读请求,然后驱动中把请求队列包中的一个包复制到输出缓冲区。驱动在ReceiveHandler中把包保存到接收队列里。

    检测启动项,主要是在驱动中读Winlogon,CurrentVersion,Installed Components,Print\Monitors,Print\Providers注册表项传给应用层。

    一键体检。主要是在应用层调用前面的检测方式输出到文件中。

    下面是手动配置中的功能,在文件ProtectSetting中。

    强制删除文件。就是把文件对象FileObject的SECTION_OBJECT_POINTERS结构的DataSectionObject和ImageSectionObject两个域清空,常规代码。

    禁止加载驱动。就是hook SeSinglePrivilegeCheck,在权限检查的时候都返回失败。

    强制环保重启就是KeBugCheck(POWER_FAILURE_SIMULATE),其实是HalReturnToFirmware。

    一键卸载360主要是PspTerminateThread结束360进程里面的所有线程。然后删除目录和注册表。

    禁止创建进程,禁止创建文件,进程服务回写,禁止内核线程,禁止全局钩子,关闭dll劫持防护在开源代码中目前还没有实现。

对A盾原理的小小总结,膜拜A神的更多相关文章

  1. YYLabel计算富文本高度-膜拜大神

    http://www.jianshu.com/p/07cd655fee7e YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:C ...

  2. ListView实现原理

    转载:http://blog.csdn.net/guolin_blog/article/details/44996879 在Android所有常用的原生控件当中,用法最复杂的应该就是ListView了 ...

  3. Android ListView工作原理完全解析,带你从源码的角度彻底理解

    版权声明:本文出自郭霖的博客,转载必须注明出处.   目录(?)[+] Adapter的作用 RecycleBin机制 第一次Layout 第二次Layout 滑动加载更多数据   转载请注明出处:h ...

  4. Android ListView工作原理完全解析(转自 郭霖老师博客)

    原文地址:http://blog.csdn.net/guolin_blog/article/details/44996879 在Android所有常用的原生控件当中,用法最复杂的应该就是ListVie ...

  5. Android ListView工作原理全然解析,带你从源代码的角度彻底理解

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/44996879 在Android全部经常使用的原生控件其中.使用方法最复杂的应该就是 ...

  6. 深入理解RunLoop

    网上看的一篇文章,写的真好,我得多看几次好好理解理解 膜拜大神,转载至此便于学习查看. 此处标明原文链接:http://blog.ibireme.com/2015/05/18/runloop/    ...

  7. 【CImg】霍夫变换——直线检测

    霍夫变换——直线检测 考古debug,其实很久之前就解决的bug......一直忘记过来改文章....欸 =============================原文================ ...

  8. JAVA学习博客---2015.5

    上一次的学习博客写的和流水账差不多,有点生硬的和背目录一样,所以既然学习的目的是程序,那么这个月的学习博客就用程序来说点东西吧.这个月看了一些C和JAVA的视频,开始看别人写的程序,能看的懂但是自己去 ...

  9. 《Xenogears》(异度装甲)隐含的原型与密码

    <Xenogears>(异度装甲)隐含的原型与密码 X 彩虹按:一种高次元的“生命体”,因“事故”被抓来当成“超能源”,其实那不只是“无限的能源”而已,“它”是有意志的!在我们眼里看来,这 ...

随机推荐

  1. 关于if else 和 三目运算符的效率问题-java

    1.从类型转换上看,因为三目运算符在做判断的时候需要考虑到类型转换的问题,而if else 不需要考虑类型转换. 所以 if else 效率高一点. 2.从总体上看 A:需要考虑到循环自身所占用的时间 ...

  2. 吉首大学校赛 I 滑稽树上滑稽果 (Lucas + 莫队)

    链接:https://ac.nowcoder.com/acm/contest/925/I来源:牛客网 题目描述 n个不同的滑稽果中,每个滑稽果可取可不取,从所有方案数中选取一种,求选取的方案中滑稽果个 ...

  3. django_websocket实现简单聊天室

    一.安装模块 pip install channels pip install channels-redis 二.代码 #websocket_v1/settings.py INSTALLED_APPS ...

  4. (转)即时通讯IM OpenFire源码学习之三:在Eclipse中构建源码

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43412617 源码搭建 下载地址: 地址:http://www.igniterealti ...

  5. STM32嵌入式开发学习笔记(一)

    本文中,笔者将介绍使用嵌入式开发工具Keil uVision5,使用C语言,对微处理器STM32F103C8进行嵌入式开发. 开发使用C语言,首先需要新建一个C语言文件,将其设为主函数的入口,因此,将 ...

  6. angularjs 中使用 service 在controller 之间 share 对象和数据

    在做angularjs 的UI 时,我们经常会遇到一个页面之间有几个controller,在controller 之间share 公共的一些数据和方法就变得比较困难,目前推荐的做法是创建一个servi ...

  7. HVM(Hardware-Assisted Virtualization)

    A set of extra instructions is added that can be used by a process in VMX rootmode. These instructio ...

  8. POJ3630-Phone List-Trie字典树模板题

    Given a list of phone numbers, determine if it is consistent in the sense that no number is the pref ...

  9. socket API CSocket CAsyncSocket 用法及区别

    要进行网络编程就要和Socket打交道,Socket有同步阻塞方式和异步非阻塞方式两种使用,事实上同步和异步在我们编程的生涯中可能遇到了很多,而Socket也没什么特别.虽然同步好用,不费劲,但不能满 ...

  10. JS Window对象 计时器setInterval() 在执行时,从载入页面后每隔指定的时间执行代码。

    计时器setInterval() 在执行时,从载入页面后每隔指定的时间执行代码. 语法: setInterval(代码,交互时间); 参数说明: 1. 代码:要调用的函数或要执行的代码串. 2. 交互 ...