首页
社区
课程
招聘
[旧帖] [原创]windows安全驱动开发(基于框架的HOOK) 0.00雪花
发表于: 2012-2-20 16:21 4818

[旧帖] [原创]windows安全驱动开发(基于框架的HOOK) 0.00雪花

2012-2-20 16:21
4818
题外话:搞安全驱动也有些日子了,从当年XP下肆无忌惮的HOOK,到现今win7 64位系统的微软的种种限制,忽然发觉我们的自由被严重的束缚。我们是做安全产品的,很显然是不会采取某种措施关闭掉微软的这些所谓的为了“安全”而做出的限制。好在,微软还是手下留情了,提供了另外一种HOOK的方式----基于微软规范的框架。
    今天,我们就来一起探讨下win7下这让人又爱又恨的框架。
    据我所知,现在很多公司都开始或者已经针对内网安全领域开发自己的产品,作为产品,那么稳定性是第一位的,而追求更加的底层就显得不是那么的重要了。因此越来越多的公司选择了基于微软框架的开发方式---保证高稳定性。
    现今的内网安全涉及以下几个:进程,文件,注册表,网络
    现在我就基于微软框架,详细的介绍下:
  1,进程
    在XP时代,你完全可以HOOK  NtOpenProcess 甚至inline其内部的一些对象函数,比如    NtReferenceObjectByName。而现在,我们必须使用ObRegisterCallbacks函数来注册一个进程操作的回调。这和HOOK NtOpenProcess是等效的。同时,微软还会传递给你一堆的信息让你来判断。 (注册的步骤,下面奉上)
   2,注册表
    在XP时代,注册表的监控和保护需要HOOK N多个函数,而现在就不要那么麻烦了。只要有注册表的操作,微软都会乖乖的告诉你触发了什么样的操作等一堆的信息。这是你就可以基于这些信息来判断。当然,前提是你必须注册注册表回调,使用ObUnRegisterCallbacks。
   下面是进程,注册表回调的总代码:
NTSTATUS register_process_register_protect(PDRIVER_OBJECT pdriverobj) //注册进程,注册表 保护回调
{
        NTSTATUS status=STATUS_SUCCESS;

        OB_CALLBACK_REGISTRATION    CallBackRegistration;
        UNICODE_STRING              Altitude;
        OB_OPERATION_REGISTRATION   OperationRegistration;
        PROCESS_CONTEXT             ProcessContextStruct;
   
        USHORT FilterVersion=ObGetFilterVersion();

        RtlInitUnicodeString(&Altitude,L"ProcessCallBack");
        RtlInitUnicodeString(&(process_register_hook.Altitude2),L"RegisterCallBack");

        memset(&CallBackRegistration,0,sizeof(OB_CALLBACK_REGISTRATION));
        memset(&OperationRegistration,0,sizeof(OB_OPERATION_REGISTRATION));
        memset(&ProcessContextStruct,0,sizeof(PROCESS_CONTEXT));

        ProcessContextStruct.ulindex=1;
        ProcessContextStruct.Version=120;

        if (FilterVersion == OB_FLT_REGISTRATION_VERSION)
        {
                CallBackRegistration.Version=OB_FLT_REGISTRATION_VERSION;
                CallBackRegistration.OperationRegistrationCount = ProcessCallBackEntry;
                CallBackRegistration.Altitude=Altitude;
                CallBackRegistration.RegistrationContext=&ProcessContextStruct;

                OperationRegistration.ObjectType=PsProcessType;
                OperationRegistration.Operations=OB_OPERATION_HANDLE_CREATE;
                OperationRegistration.PreOperation=ProcessPreCallBackX;
                OperationRegistration.PostOperation=ProcessPostCallBackX;

                CallBackRegistration.OperationRegistration=&OperationRegistration;

                status=ObRegisterCallbacks(&CallBackRegistration,&(process_register_hook.RegistrationProcessHandle));

                if (status==STATUS_SUCCESS) //如果进程注册成功,那么继续注册注册表保护回调。此驱动必须保证进程通知,进程保护,注册表保护3个回调全部成功,则加载才会成功
                {
                        process_register_hook.RegProcessCallBackOrNot = TRUE;
                        status=CmRegisterCallbackEx((PEX_CALLBACK_FUNCTION)RegistryCallback,&(process_register_hook.Altitude2),pdriverobj,NULL,&(process_register_hook.RegistrationRegisterCookie),NULL);
                        if (!NT_SUCCESS(status)){
                                process_register_hook.RegRegisterCallBackOrNot = FALSE;
                                ObUnRegisterCallbacks(process_register_hook.RegistrationProcessHandle); //如果注册表注册失败,则同时反注册进程保护回调
                                return STATUS_UNSUCCESSFUL;
                        }else{
                                process_register_hook.RegRegisterCallBackOrNot = TRUE;  //此时,注册表保护回调也已经注册成功
                        }
                }
        }else
        {
                status  = STATUS_UNSUCCESSFUL;
        }
        return status;
}

其中ProcessPreCallBackX 为进程相关回调函数(你自己提供的函数,函数类型请MSDN上找)
其中RegistryCallback为注册表回调函数,同上,自己找函数类型定义

///以上就是注册表,进程的HOOK框架///
3,文件相关
   在以往,文件方面要么HOOK ntoskrnl里的文件函数外就是基于文件系统过滤框架的驱动了。网上也有非常全面的源码,里面涉及到设备的挂载等一系列的名词,至少需要一定基础的人研究一段时间才能够开发出稳定的产品。关于常规的HOOK文件内核函数的做法,只能够做到基本的文件保护功能,也不够的底层。如果涉及到文件的透明加解密,那么还是要选择基于文件系统过滤框架来做。正如上面所说,比较复杂,开发周期比较长。微软似乎也感觉到这个问题,因此微软就发明了一个框架--文件系统微过滤框架。
    你在使用之前也必须注册:(代码如下)
            status = FltRegisterFilter(pDriverObject,&FilterRegistration,&gFilterHandle);  //此函数调用成功的前提必须使用正确的INF配置
        if (NT_SUCCESS(status))
        {
                status = FltStartFiltering( gFilterHandle );
                if (!NT_SUCCESS( status )){
                        FltUnregisterFilter( gFilterHandle );
                }
        }else{
                return status;
        }
        注册倒是不难,寒江独钓这本书讲的再清楚不过。但是,在使用的时候,MSDN上写得就不够清楚了,让我着实郁闷了几天。下面我就说下关于文件的读和写方面的保护。
    当有文件读写操作的时候,你的回调函数就会被触发。其中第一个参数:Data非常的关键。它里面有3个地方描述了这此HOOK截获到的操作类型,分别是:
   Data->Iopb->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess
                                Data->Iopb->Parameters.Create.SecurityContext->AccessState->OriginalDesiredAccess
                                Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess
   加入,HOOK到的对文件的操作是读写,而你只打算写(拒绝读文件)。那么你必须3个一起“去读操作”。代码如下:
                                   Data->Iopb->Parameters.Create.SecurityContext->AccessState->OriginalDesiredAccess &=~ FILE_READ_DATA;
                                Data->Iopb->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess &=~ FILE_READ_DATA;
                                Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &=~ FILE_READ_DATA;
   没错,效果达到了。而在拒绝文件写入的时候,就必须注意了。除了按常规除去FILE_WRITE_DATA,还必须同时除去FILE_APPEND_DATA。不然,文件的写保护是起不了效果的。就这事,郁闷了我几天。
                                Data->Iopb->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess &=~ FILE_WRITE_DATA;
                                Data->Iopb->Parameters.Create.SecurityContext->AccessState->OriginalDesiredAccess &=~ FILE_WRITE_DATA;
                                Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &=~ FILE_WRITE_DATA;

                                Data->Iopb->Parameters.Create.SecurityContext->AccessState->OriginalDesiredAccess &=~ FILE_APPEND_DATA;
                                Data->Iopb->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess &=~ FILE_APPEND_DATA;
                                Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &=~ FILE_APPEND_DATA;
其他的没什么好说的。仔细研究MSDN

需要说明的是,以上3个回调的注册操作,前提是你的驱动必须带有数字签名。如不然,你需要一些操作才可以避免注册失败。经过逆向分析。我们需要在DriverEntry函数里加上:
        PLDR_DATA_TABLE_ENTRY pldr = NULL
          DriverSection = pDriverObject->DriverSection;
        pldr = (PLDR_DATA_TABLE_ENTRY)DriverSection;
        pldr->Flags |= 0x20;
这样一来,回调函数的注册就不会失败了。这点很重要。

4,网络
   网络过滤框架有TDI,WFP,NDIS这3类框架,其中TDI属于要淘汰的产品,不晓得win7上还能不用使用,所以作为产品级的软件,肯定不能选用。代替而来的就是WFP,相关代码在WDK文档里有源码,由于篇幅的问题,就不介绍了。自己去研究代码。
   NDIS。NDIS框架由来已早,像市面上的sniffer,还有个很多软件都需要绑定的那个网络插件(忘记什么名字了,N多抓包软件都提示要安装)他们都基于NDIS框架。其中呢,这个框架分一下几类:NDIS协议驱动,NDIS过滤驱动,NDIS小端口驱动
    分别说下作用:
   NDIS协议驱动,和TCP/IP协议一个道理,你可以自由的封包,可以直接受应用层的控制。基于这样的原理,你可以开发自己的一套协议,从安全角度来讲,即使黑客截获到你的包,那么也需要很长时间来分析你的包的结构。NDIS协议驱动构建完包后,就可以通过NDIS内部函数进行发包操作,此时整个数据报将会交给NDIS小端口驱动来进行最终的发送
   NDIS过滤驱动,介于协议驱动和小端口驱动之间,其实他就是个过滤层驱动,整个驱动需要提供2套接口,一套接口是向上面协议驱动公开的,另一套接口向下层的小端口驱动公开的。学习过滤驱动的时候最好先学习协议驱动和小端口驱动。重点是他们之间配合的流程。
   NDIS小端口驱动。时间比较长了,具体忘记了。所以就不多说什么。他的应用其实很广。有兴趣的朋友可以自己找下相关资料
   在企业应用方面,WFP涉及到比如监听,外连,连入等操作的控制。而NDIS大都涉及到网络数据的透明加解密技术还有数据报的截获。后者是基于端口,IP这些裸信息的。而前者相对比较高层,可以截获某某进程对某某IP地址+端口的某某操作。应用不同,则按需选择。

好了,说了这一大堆,希望给做企业级产品的朋友带来帮助。同时,恳请发给我邀请码。谢谢~~

[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

收藏
免费
支持
分享
最新回复 (23)
雪    币: 114
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
没研究win7,不能inline HOOK,也就是说不能更改机器码的,用windbg无法调试驱动?在驱动里无法 *(byte *)0x8543210=0xE9???
2012-2-20 16:39
0
雪    币: 103
活跃值: (66)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
写的不错,但是有些错别字,影响阅读
2012-2-21 13:01
0
雪    币: 2562
活跃值: (4293)
能力值: ( LV13,RANK:540 )
在线值:
发帖
回帖
粉丝
4
嘿嘿~~处女贴啦~~
2012-2-21 13:05
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
是哈,一直潜水,感觉多交流能帮助更多的人呢
2012-2-21 13:18
0
雪    币: 114
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
那为什么不回答我的问题呢?
2012-2-21 13:41
0
雪    币: 1898
活跃值: (1905)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
7
坐等版主射精。。。。。
2012-2-21 13:44
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
是的,在win7 64位下  普通的修改内存的HOOK已经无法使用
2012-2-21 13:49
0
雪    币: 114
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
也就是说代码保护了,代码段的内存无法修改是否可以越过内存保护直接暴力修改呢?
2012-2-21 14:50
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
具体可以百度搜索下,网上已经有相关的介绍了。但是,这个帖子面向的是做安全产品的程序员,因此破坏现有的微软保护是不科学的。
具体的,我也没有深入研究。~~
2012-2-21 21:48
0
雪    币: 244
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
尤其是该死的 64 位,很多都做不了了
2012-2-21 21:49
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
哈哈,窝已经诅咒微软N此了。有利有弊吧。人家微软也是想缩短企业产品的开发周期。倒是我们搞技术的人比较迷茫了。知其然不知其所以然的日子过起来不爽啊。框架这个东西屏蔽了很多很多,有如父母把饭嚼碎了喂给你,哎。
2012-2-21 22:06
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
好东西学习了,加油
2012-2-22 09:53
0
雪    币: 1644
活跃值: (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
学习。。。。
2012-2-26 23:25
0
雪    币: 585
活跃值: (578)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
15
A miniport driver calls the NdisMRegisterMiniportDriver function to register MiniportXxx entry points with NDIS as the first step in initialization.

NDIS_STATUS
  NdisMRegisterMiniportDriver(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING  RegistryPath,
    IN NDIS_HANDLE  MiniportDriverContext,
    IN PNDIS_MINIPORT_DRIVER_CHARACTERISTICS  MiniportDriverCharacteristics,
    OUT PNDIS_HANDLE  NdisMiniportDriverHandle
    );
2012-4-19 12:00
0
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
学习学习。。。。
2012-4-19 16:14
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
请问下楼主,这个限定只有win7 64位才有吗
win7 32位有没有

另外这个框架是只能在win7 64位下用吗 其他系统呢
2012-4-19 20:20
0
雪    币: 266
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
mark之 有空再看
2012-4-20 17:28
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
学习了学习了.
2012-4-21 07:58
0
雪    币: 186
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
楼主能否将自己研究WFP的经验共享一下,
现在一直苦苦挣扎在这个上面的,先谢了
2012-7-15 11:45
0
雪    币: 558
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21

没错,效果达到了。而在拒绝文件写入的时候,就必须注意了。除了按常规除去FILE_WRITE_DATA,还必须同时除去FILE_APPEND_DATA。不然,文件的写保护是起不了效果的。就这事,郁闷了我几天。
Data->Iopb->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess &=~ FILE_WRITE_DATA;
Data->Iopb->Parameters.Create.SecurityContext->AccessState->OriginalDesiredAccess &=~ FILE_WRITE_DATA;
Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &=~ FILE_WRITE_DATA;

Data->Iopb->Parameters.Create.SecurityContext->AccessState->OriginalDesiredAccess &=~ FILE_APPEND_DATA;
Data->Iopb->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess &=~ FILE_APPEND_DATA;
Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &=~ FILE_APPEND_DATA;


这个刚才还专门去试了一下,对于.txt格式的文件倒是可以实现,但是对于.doc这种写操作在临时文件中来说,判断起来比较麻烦,还必须把临时文件也给禁止了

不过,我原来采用了一个微软的漏洞来实现文件的“只读”功能,这里利用到了一些系统保留的标志位,如果保留位被置1,则系统会将文件以“只读”权限打开(这里只是我个人的猜测,欢迎各位大侠给出更合理的解释)
Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess |=0x1000;
2012-7-16 10:52
0
雪    币: 18
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
强大学习了!!
2012-7-16 11:36
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
学习了 不过微软限制还是太多了 确实很烦
2012-7-23 11:01
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
在WIN64下面怎么办呢?
2012-7-24 02:38
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册