Windows内核驱动验证C#桌面客户端完整性的防盗版方案问询
内核驱动端验证C#桌面客户端真实性的实用方案
一、可靠锁定合法客户端进程
先解决IOCTL请求中进程身份伪造的问题,完全避开未公开的EPROCESS结构:
- 首次通信绑定+多维度校验:客户端启动后第一次发IOCTL时,主动传自己的
ProcessId,同时带一个预约定的加密一次性令牌(比如用双方共享的密钥加密「进程ID+当前时间戳」)。驱动收到后走以下流程:- 用
PsLookupProcessByProcessId拿到进程对象,避免直接依赖PID(防止PID复用攻击); - 调用
ZwQueryInformationProcess(指定ProcessImageFileName)获取进程完整路径,校验是否在你指定的官方安装目录下; - 用
PsGetProcessImageFileName获取短文件名,确认是你的客户端exe; - 可选:通过
ProcessTimes获取进程创建时间,和客户端上报的启动时间比对,进一步排除伪造PID的恶意进程。
- 用
- 绑定进程对象:验证通过后,用
ObReferenceObjectByHandle保存该进程的引用句柄,后续所有IOCTL直接校验发起进程是否为这个绑定的对象,不用每次重新查询PID。
二、内核端拦截篡改后的客户端
针对DnSpy篡改生成的恶意exe,两种核心验证方案都能在核内实现:
1. 数字签名验证(最省心的方案)
核内可以调用WinVerifyTrust验证客户端exe的签名,确保是你发布的原版:
- 构造
WINTRUST_FILE_INFO结构,填入客户端exe的完整路径; - 指定验证类型为
WTD_CHOICE_FILE,动作设为WTD_ACTION_VERIFY; - 额外校验证书的指纹或主题信息,防止攻击者用其他合法证书签名篡改后的文件。
注意:核内调用需要确保驱动加载了
crypt32.sys和wintrust.sys,且要在合适的进程上下文(比如系统进程)调用,避免权限问题。
2. PE关键区域哈希校验
直接读取客户端exe的关键部分计算哈希,和驱动内预存的合法值比对:
- 安全读取文件:用
ZwCreateFile打开客户端exe(权限设FILE_READ_DATA | FILE_READ_ATTRIBUTES),绕开用户态可能被篡改的文件句柄; - 精准计算哈希:优先计算PE的
.text段和CLI元数据段的SHA256哈希——C#程序被DnSpy篡改时,主要修改的是IL代码和元数据,对应PE的这两个区域,只算关键区域比全文件哈希更高效; - 哈希加密存储:把合法哈希用驱动内置的密钥加密后嵌入,别存明文;如果要支持版本更新,让客户端启动时用共享密钥加密最新哈希传给驱动,驱动解密后更新校验值。
三、额外加固手段
- IOCTL数据加密:所有IOCTL传输的内容用AES加密,密钥由客户端和驱动首次通信时动态协商,防止请求被篡改或伪造;
- 核内反调试/反挂钩:用
PsIsProcessBeingDebugged检测客户端是否被调试,或者扫描进程内存页属性、导入表,排查异常的用户态挂钩; - 定时重校验:驱动每隔几分钟自动触发一次客户端完整性校验,防止程序运行中被动态篡改;
- 驱动自身防护:给驱动加代码混淆、反逆向处理,避免驱动被破解后直接绕过校验逻辑。
内容的提问来源于stack exchange,提问作者UnSure
相关产品推荐
相关产品推荐

