数字驱动分析笔记之HookPort

参考资料:

1、腾讯管家攻防驱动分析-TsFltMgr

2、发一个可编译,可替换的hookport代码 

3、为什么win32k.sys在System进程空间无法访问

4、明明白白自旋锁

5、那些年搞驱动的那些坑_欢迎补充

6、用DeviceIoControl实现应用程序与驱动程序通信

推荐使用的环境

备注

操作系统

Windows 7 SP3

简体中文版

虚拟机

VM

版本号:15

编译器

VS2013 + WDK8.1

调试

Windbg

sxe ld xxxx.sys

目录:

1、流程图文介绍

2、驱动入口点DriverEntry

3、驱动高低版本区别

4、驱动接口使用

5、HookPort_InitSDT

1、流程图文介绍

1、Hook前后的对比图

 2、HookPort的工作流程

HookPort负责构造一份空白的Hook模板(不负责编写对应的Fake函数,导出给SalfProtectionX用)

可以理解为老板(HookPort)小弟(SelfProtectionX)

 理论上我们是可以有无数个SelfProtectionX,但是大数字最大限制16个

Hook模板结构如下(单向链表结构):

 举个例子:

假设我们一共有SelfProtection1、SelfProtection2两个驱动设置了对应的Fake_CraeteProcess函数

 原始CreateProcess->KiFastCallEntry->Filter_CreateProcess代理函数->HookPort_DoFilter

循环将链表中所有Fake函数取出来并执行,直到链表下一个为零终止

必须全部所有Fake函数合法返回才算正确,其中一个返回错误都算错误

2、驱动入口点DriverEntry 

2、1 如何调试

首先输入:sxe ld xxxxx.sys         中断

然后输入:lmvm xxxxx               获取基地址,后面基地址+偏移

2、2 代码逻辑流程

1、获取系统版本信息,假设是win10将Global_Version_Win10_Flag变量置1

2、安全模式下禁止启动

3、创建\\Device\\***HookPort设备和\\DosDevices\\***HookPort符号链接

4、设备DeviceExtension驱动接口,为3600SelfProtection服务

5、注册IRP_MJ_CREATE、IRP_MJ_CLOSE、IRP_MJ_DEVICE_CONTROL

6、执行HookPort_InitSDT函数该函数实现功能如下:

6、1 设置内核API过滤函数

6、2 挂钩KiFastCallEntry

6、3 创建线程、进程、模块回调

6、4 IAT方式挂钩KeUserModeCallback,可以拦截DLL注入、键盘劫持等等。

7、初始化驱动导出接口

8、执行HookPort_19230函数(不知取什么名字好)

8、1 假设是Win2K(Int 2E)就挂钩KiSystemService

8、2 实现LoadImageNotifyRoutine对应的Fake函数

8、3 LoadImageNotifyRoutine的Fake函数是根据你打开个某个进程设置ZwDisplayString对应的Fake函数为空函数

 2、3 代码实现:

//************************************
// 函数名称: DriverEntry
// 函数说明:驱动程序入口
// 作 者:Mr.M
// 参考网址:
// 作成日期:2019/11/29
// 返 回 值: NTSTATUS
// 参 数: IN PDRIVER_OBJECT DriverObj
// 参 数: IN PUNICODE_STRING RegPath
//************************************
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject, //代表本驱动的驱动对象
IN PUNICODE_STRING RegPath //驱动的路径,在注册表中
)
{
NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
UNICODE_STRING SymbolicLinkName;
UNICODE_STRING DestinationString;
PDEVICE_OBJECT DeviceObject = NULL;
Global_DriverObject = (ULONG)DriverObject;
//1、获取版本信息
Status = HookPort_PsGetVersion();
if (!NT_SUCCESS(Status))
{
return Status;
}
//2、安全模式下不启动
if (*(ULONG*)InitSafeBootMode)
{
if (*(ULONG*)InitSafeBootMode == 1)
{
Status = RtlCheckRegistryKey(RTL_REGISTRY_CONTROL, HookPort_Minimal);
}
else
{
if (*(ULONG*)InitSafeBootMode <= 1u || *(ULONG*)InitSafeBootMode > 3u)
return STATUS_NOT_SAFE_MODE_DRIVER;
Status = RtlCheckRegistryKey(RTL_REGISTRY_CONTROL, HookPort_Network);
}
if (Status < 0)
return STATUS_NOT_SAFE_MODE_DRIVER;
}
//2、创建设备
RtlInitUnicodeString(&DestinationString, HookPort_DeviceName);
RtlInitUnicodeString(&SymbolicLinkName, HookPort_LinkName);
Status = IoCreateDevice(
DriverObject,
sizeof(HOOKPORT_EXTENSION), //扩展18u
&DestinationString,
FILE_DEVICE_UNKNOWN, //#define FILE_DEVICE_UNKNOWN 0x00000022
FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics ,#define FILE_DEVICE_SECURE_OPEN 0x00000100
FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status))
{

KdPrint(("HookPort: DriverEntry IoCreateDevice failed,err=%08x\n", Status));
return Status;
}

//3、给设备创建一个符号链接
Status = IoCreateSymbolicLink(&SymbolicLinkName, &DestinationString);
if (!NT_SUCCESS(Status)){
KdPrint(("HookPort: DriverEntry IoCreateSymbolicLink failed,err=%08x\n", Status));
IoDeleteDevice(DeviceObject);
return Status;
}

//4、DeviceControl都是些开启调试信息相关的直接无视
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)HookPort_Create;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)HookPort_Close;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)HookPort_DeviceControl;

//5、初始化部分各种hook、创建进程、线程回调等等
if (!NT_SUCCESS(HookPort_InitSDT()))
{
IoDeleteSymbolicLink(&SymbolicLinkName);
IoDeleteDevice(DeviceObject);
return STATUS_UNSUCCESSFUL;
}
//6、初始化导出接口函数
HookPort_InitDeviceExtInterface(DeviceObject);
//7、
//1、根据条件判断是否启用FakeKiSystemService的hook
//2、初始化扩展结构,导出给另外一个sys使用
HookPort_19230();
KdPrint(("360HookPort驱动加载成功\t\n"));
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}

3、驱动高低版本区别

1、高低版本HookPort代码区别

底:layerfsd作者发布的Hookport为蓝本作为低版本(2010年)

高:笔者逆向的Hookport高版本(2019年)

2、Hook代理函数优化

低版本

1、我们发现一个问题,就是有多少个fake函数定义多少个相同的代理函数

 2、我们发现代理函数逻辑基本相同,除了参数个数不一致

 高版本

1、除了个别感兴趣的其他都通用函数模板处理

 2、通用函数模板

 3、修复通用函数分为5个部分:

3、Hook方式(加密解密4已经有图文介绍了13章)

数字hook点:

// 保存特征指令之后的那个地址,即钩子处理之后的返回地址

//840541a4 2be1            sub     esp, ecx     此时address                                                     = 840541a4

//840541a6 c1e902        shr      ecx, 2         此时g_KiFastCallEntry_360HookPoint             = 840541a6

//840541a9 8bfc             mov    edi, esp     此时g_KiFastCallEntry_Fake_rtn_address         = 840541a9

hook方式有两种:

IdtHook4号中断

InlineHook

4、驱动接口使用

注意HookPort只是初始化接口,是导出给N个类似于SelfProtection的驱动使用

导出接口结构体定义如下:

/*

// sizeof(HOOKPORT_EXTENSION) = 0x18

设备扩展包含了添加规则的接口

1、其他驱动需要增加规则时只需要获取Hookport的驱动扩展访问里面的HookPort_FilterRule_Init初始化一条规则

2、HookPort_SetFilterSwitchFunction 设置规则过滤函数

3、HookPort_SetFilterRuleFlag 设置开关表示启动 or 关闭

State                                          启动标识

HookPort_FilterRule_Init                  初始化规则,新建规则会加到规则链中

HookPort_SetFilterSwitchFunction            设置规则过滤函数

HookPort_SetFilterRuleFlag                         设置规则开关

HookPort_SetFilterRuleName                      设置规则名字

Value3F1                                   该驱动版本

*/

typedef struct _HOOKPORT_EXTENSION

{

_DWORD State;

_DWORD HookPort_FilterRule_Init;

_DWORD HookPort_SetFilterSwitchFunction;

_DWORD HookPort_SetFilterRule;

_DWORD HookPort_SetFilterRuleName;

_DWORD Value3F1;

}HOOKPORT_EXTENSION, *PHOOKPORT_EXTENSION;

然后进行初始化操作

//初始化导出接口

ULONG NTAPI HookPort_InitDeviceExtInterface(IN PDEVICE_OBJECT DeviceObject)

{

PHOOKPORT_EXTENSION pHookPortExt;

pHookPortExt = DeviceObject->DeviceExtension;

pHookPortExt->State = (PULONG)3;

pHookPortExt->HookPort_FilterRule_Init = HookPort_AllocFilterRuleTable;                        //初始化规则

pHookPortExt->HookPort_SetFilterSwitchFunction = HookPort_SetFilterSwitchFunction;                //设置规则过滤函数

pHookPortExt->HookPort_SetFilterRule = HookPort_SetFilterRule;                                //设置规则开关

pHookPortExt->HookPort_SetFilterRuleName = HookPort_SetFilterRuleName;                        //设置规则名字

pHookPortExt->Value3F1 = 0x3F1;                                                                //版本

return pHookPortExt;

}

使用:

FakeServiceRoutine[X]

Fake_xxxxx

设置单独的Fake函数

FakeServiceRoutine[X]

1

设置单独的Fake函数开关

IsFilterFunFilledReady

1

设置总开关

关闭:

FakeServiceRoutine[X]

0

设置单独的Fake函数,随你清不清

FakeServiceRoutine[X]

0

设置单独的Fake函数开关,随你清不清 直接拉总闸省事

IsFilterFunFilledReady

0

设置总开关,嫌一个个关闭麻烦直接关这个(拉总闸直接GG)

5、HookPort_InitSDT 

1、获取SSDT和ShadowSSDT地址

SSDT表获取方法:

直接NT内核里面找KeServiceDescriptorTable,KeServiceDescriptorTable是导出的遍历下导出表

 ShadowSSDT表获取方法:

首先获取win32k基地址,然后再通过特征码查找代码如下

2、获取函数索引

1、通过导出表找到zwXXX的地址,然后再取对应的索引号B8+1就是索引号

 2、取B8后面4个字节就是索引号

 3、SSDT和ShadowSSDT区别

ShadowSSDT的索引号要-0x1000才是真正的索引

例如4419-4096=323

3、填写函数过滤数组

该数组一共有0x9E个

4、申请一块缓冲区专门存放过滤函数开关、代理函数等地址,大小是0x7D10

 1、接下来执行HookPort_InitProxyAddress函数填充该结构,感兴趣的自己单独写一个代理函数,不感兴趣的直接通用模板处理即可。

 2、注意我们要过滤掉以下几个函数,因为他们由HookPort实现Fake函数

5、KiFastCallEntry处理

1、通过修改SSDT表的ZwSetEvent来触发安装钩子

设置一个虚假的ZwSetEvent句柄来触发,注意保存原始函数地址后面要恢复

 5、1 Fake_ZwSetEvent处理部分

1、判断Hook方式,默认Global_IdtHook_Or_InlineHook置1,并且恢复SSDT钩子(ZwSetEvent)

修改:Jmpxxx             Global_IdtHook_Or_InlineHook == 0 

修改:Int 4                    Global_IdtHook_Or_InlineHook == 1

 2、sub_1567A实在没看懂,有明白的老哥告诉下

 3、栈回溯获取返回地址[EBP+4](这里指的是正常调用时返回到KiFastCallEntry中的地址),找到hook点

 4、多核Hook方法

假设是单核直接替换即可

 假设是多核就采用DPC方式处理即可

 暂停N一段时间处理hook

6、创建进程、线程、模块回调和IAT方式挂钩KeUserModeCallback

ClientLoadLibrary加载模块相关

ClientImmLoadLayout加载模块相关

fnHkOPTINLPEVENTMSG未知

fnHkINLPKBDLLHOOKSTRUCT拦截键盘消息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值