首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
逆向工程
发新帖
4
6
[原创]火绒剑驱动逆向
发表于: 2026-3-13 17:05
3422
[原创]火绒剑驱动逆向
mb_byqgltsb
2026-3-13 17:05
3422
原本想在win10环境中通过Ring3程序调用火绒剑驱动实现关闭进程的实验,但以失败告终,火绒剑在驱动的安全保护上确实下了功夫,对驱动打开时的进程进行了验证。虽未成功实现调用驱动关闭进程的功能,但在逆向中还是学到了很多知识,总结以下,供大家批评指正。 # 1、ZwTerminateProcess 在Ring0层关闭进程的API是ZwTerminateProcess,逆向就从这里开始。查看官方文档,调用ZwTerminateProcess函数需要两个参数,一个是进程句柄ProcessHandle,另一个是退出状态码ExitStatus。  IDA中打开驱动sysdiag_win10.sys,并在导入表Imports中查找ZwTerminateProcess。  使用交叉引用查看调用该api的情况。  # 2、定位用于终止进程的函数 定位到TerminateProcessById(sub_140029870)函数,功能是通过进程ID来终止进程。  继续交叉引用查看,直到找到处理DeviceIoControl的函数。  定位sub_14000C460->DispatchDeviceControl #3、驱动的派遣函数 DispatchDeviceControl(sub_14000D0C0)函数是一个Windows内核驱动程序的派遣函数(Dispatch Routine),用于处理来自不同设备对象的IRP(I/O请求包)。其主要目的是根据传入的设备对象和IRP的主功能代码(MajorFunction)进行路由,执行相应的操作,如进程监控、设备控制、数据读写等,并最终完成IRP请求。Ring0与Ring3层的交互方式,一般用DeviceIoControl来控制,所以该函数就是处理驱动IO关键函数。  通过sub_14000C460可以逆向出调用终止进程功能的IO控制码为**0x2200B8**,驱动名称为“\\.\HR::ActMon”  编写如下程序测试调用驱动,结果发现打开驱动失败。 ```c++ BOOL TerminateProcessByPid(DWORD targetPid) { wchar_t logMsg[128]; _snwprintf_s(logMsg, _countof(logMsg), _TRUNCATE, L"Attempting to terminate process with PID: %lu", targetPid); WriteLog(logMsg); // Correct device symbolic link (from reverse engineering) LPCWSTR devicePath = L"\\\\.\\HR::ActMon"; HANDLE hDevice = CreateFileW( devicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDevice == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); _snwprintf_s(logMsg, _countof(logMsg), _TRUNCATE, L"Failed to open device, error code: %lu", err); WriteLog(logMsg); return FALSE; } WriteLog(L"Device opened successfully"); // Prepare buffer (16 bytes) BYTE buffer[16] = {0}; DWORD64 pid64 = (DWORD64)targetPid; memcpy(buffer, &pid64, sizeof(pid64)); // First 8 bytes for PID DWORD bytesReturned; BOOL result = DeviceIoControl( hDevice, SYSDIAG_IOCTL_TERMINATE_PROCESS, buffer, sizeof(buffer), buffer, sizeof(buffer), &bytesReturned, NULL); if (!result) { DWORD err = GetLastError(); _snwprintf_s(logMsg, _countof(logMsg), _TRUNCATE, L"DeviceIoControl failed, error code: %lu", err); WriteLog(logMsg); CloseHandle(hDevice); return FALSE; } WriteLog(L"DeviceIoControl called successfully"); // Read return value (offset 8) NTSTATUS status = *(DWORD*)(buffer + 8); _snwprintf_s(logMsg, _countof(logMsg), _TRUNCATE, L"DeviceIoControl returned NTSTATUS: 0x%08lX", status); WriteLog(logMsg); CloseHandle(hDevice); WriteLog(L"Device handle closed"); BOOL finalResult = result && (status == 0); if (finalResult) { WriteLog(L"Termination operation successful (result TRUE and status 0)"); } else { WriteLog(L"Termination operation failed"); } return finalResult; } ``` 失败的原因出在用CreateFileW打开“\\.\HR::ActMon”时,驱动程序内部进行了判断。  程序通过函数FindAndReferenceNodeByKey(sub_1400297A0)查询数据,返回的**结构体V10+1360**的位置必须为0,否则就会返回错误码STATUS_ACCESS_DENIED(0xC0000022),所以接下来的逆向思路就是如何找到**修改**该地址存储数据的代码。 # 4、追踪结构体 驱动中结构体偏移1360(0x550)何时为0,可以通过IDA**搜索立即数**(Immediate value)的方式来定位。  虽然调用该偏移的位置很多,但大多指令是**读数据**,只有两条数据是向该偏移地址**写数据**,其中一条为写入eax的值,另外一条写入固定值0FFFFFFFFh。我们将重点放在第一条**RVA:0x13F38**,观察eax何时为0。 下图是RVA:0x13F38所在函数InitializeProcessPathInfo(sub_140013D00)引用图表,第一次分析代码头绪是比较乱的。  此时换用动态调试,用windbg调试并下端点,很快就在关键位置上中断下来。观察发现,大部分情况eax的值是0xffffffff,只有打开HRSword.exe时,eax的值为0,调用栈分析如下。  # 5、监控进程的回调函数 找到系统调用该驱动RVA为**0xbae0**和**0x10350**,用WPeChat插件辅助分析。 发现MyCreateProcessNotifyEx(sub_14000BAE0)是驱动注册的监控进程的回调函数。  ProcessLifecycleEventHandler(sub_140010300)函数负责具体处理回调,它是一个进程/线程生命周期事件处理器,主要用于处理与**进程创建或终止**相关的事件。根据IsCreationEvent参数的值,函数会执行不同的逻辑分支:当IsCreationEvent为真时处理进程创建事件,为假时处理进程终止事件。  继续分析标志位设置的条件,发现RVA:0x13F38上面的OpenAndValidatePEFile(sub_1400368B0)是关键验证函数。  OpenAndValidatePEFile函数通过检查文件扩展名是否为“.exe”(不区分大小写)来设置特定标志,然后调用系统API打开文件,最后调用AnalyzeAndValidatePEFile(sub_140036260)进行PE文件的分析与验证。  到此,梳理一下逻辑。只要有进程创建,驱动会打开该进程对应的exe,然后进行分析验证,如果条件符合,就会给**结构体偏移1360**处赋值0。 # 6、验证逻辑分析 主要逻辑判断分析如下: ## (1)文件大小判断 获取文件大小,并检查其是否在0x40 到64MB(0x4000000 字节)范围内。  ## (2)PE文件头验证 检查文件内容是否符合PE文件格式(如DOS头签名"MZ"、PE头签名"PE"),并验证特定字段(如可选头大小)。  其中一段是验证否为VB程序,但只影响文件标志,不对主判断有影响,无关紧要.  ## (3) 节表遍历与找到最后一个节 计算每个节的大小+地址偏移,最终结果肯定是最后一个节最大(偏移地址最大)。  程序设计似乎有点繁复,计算每个节的大小+地址偏移,最终结果肯定是最后一个节最大(偏移地址最大)。  ## (4)数据解密与验证 在最后一个节的倒数132字节出处进行**异或XOR**解密操作,使用硬编码密钥**0x900D900D**进行异或解密。  然后验证解密后的数据是否匹配特定魔数("HRBR"和"HROH")。  ## (5)哈希计算与匹配 如果解密数据验证通过,则使用SHA1算法计算文件(文件头到最后一个节的的倒数132字节)的哈希值,并与全局表中的哈希值进行比对。   函数ExtractPaddedData(sub_140007350)实现了校验和哈希算法,通过全局二维私钥数组CurrentHashEntry和倒数132字节解密后的字节计算后得出用于比较的哈希。  最后,如果匹配成功,就会将**匹配的下标**赋值给**结构体偏移1360**。所以要让结构体偏移1360为0,就必须第一个HASH数组就匹配成功。 这样看下来,想破解这个算法很难,由于哈希算法是单向的,真要凑出一个能通过验证的值需要大量计算,所以果断跳车,希望本文能给大家带来启发和帮助。
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
#调试逆向
#软件保护
#加密算法
收藏
・
4
点赞
・
6
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
wx_晨梦
谢谢你的细致分析,受益匪浅!
2026-7-16 05:31
mb_iirigsjr
感谢你的积极参与,期待更多精彩内容!
2026-6-29 20:31
huangmo
你的帖子非常有用,感谢分享!
2026-4-30 09:44
DeDream
谢谢你的细致分析,受益匪浅!
2026-3-25 18:33
我的小拇指啊
期待更多优质内容的分享,论坛有你更精彩!
2026-3-17 15:53
新气象
非常支持你的观点!
2026-3-14 10:17
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
3
)
YoungBai
雪 币:
1289
活跃值:
(1630)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
144
粉丝
1
关注
私信
YoungBai
2
楼
感谢分享思路.
2026-4-18 10:43
0
mb_gmajzygm
雪 币:
20
能力值:
( LV1,RANK:0 )
在线值:
发帖
4
回帖
37
粉丝
1
关注
私信
mb_gmajzygm
3
楼
这是在干啥ya
2026-5-12 16:44
0
nice667
雪 币:
10
能力值:
( LV1,RANK:0 )
在线值:
发帖
2
回帖
20
粉丝
2
关注
私信
nice667
4
楼
分析了半天才发现 无法绕过它的打开句柄验证
2026-5-23 17:31
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
mb_byqgltsb
1
发帖
3
回帖
10
RANK
关注
私信
他的文章
[原创]火绒剑驱动逆向
3422
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部