前言
最近公司有需求, 要写这玩意儿, 经过九九八十一难终于写完, 并签上了elam的签名
适应范围
按照从开始到现在的研究成果, elam驱动属于引导型驱动的一种(start值为0, 组名是"Early-Launch");
但是启动的比其他引导型型驱动都早, 可以按照自定规则拦截其他引导型驱动启动(微软提供标准api来搞), 其他的用处, 暂没有发现;
生命周期也比较特别, 在boot型驱动之前启动, 所有boot型驱动启动完成后, 会收到通知, 然后, 系统会调用注册的unload函数, 结束驱动的运行
代码编写
elam的要求: https://docs.microsoft.com/en-us/windows-hardware/drivers/install/elam-driver-requirements
微软提供了一个简单的例子可以参考: https://github.com/Microsoft/Windows-driver-samples/tree/master/security/elam
提交微软进行签名(堪称整个过程最坑的地方)
1 提交帐号必须是微软的MVI成员
2 完成特定的HLK测试
3 用EV证书对HLK的测试报告文件(hlkx文件, 其实就是个zip文件, 不知道为啥非要起了这么个幺蛾子扩展名)进行签名
4 提交微软签名网站进行签名
5 不出意外的话, 等美国佬审核完了, 就会返回签好微软elam专用签名的驱动文件了
简单的参考微软官方文档就行, 下面说说遇到的大坑
1 搭这个幺蛾子HLK测试环境(以下仅说明在workgroup模式下搭建, 域环境仅供参考)
<1> 下载地址: https://docs.microsoft.com/en-us/windows-hardware/test/hlk/
<2> HLK这套系统, 分server与client, 而server端呢, 又包括controler与studio俩组件, 这俩组件可以装在同一台机器上, 客户端需要装在另一台机器上. 也就是说, 这个测试环境最少需要两台机器, 不测试某些性能测试的话, 可以用俩虚拟机
controler属于严格意义上的server端, studio属于server端的控制面板一类的东西, 负责控制测试的执行,并输出测试报告, 就是上面说的hlkx文件
<3> 首先说HLK的版本问题
经过各种姿势的折腾发现,
- controler对操作系统版本要求特别苛刻, 目前能用的最高版本系统是windows server2016, 且必须是英文界面, 区域是 美国.
- studio对服务器系统版本貌似没啥要求,但是需要跟客户端的系统版本对应上
- client版本必须与客户端系统的版本对应上, 除此以外没啥别的要求
微软网站上提供的HLK包包含以上三个组件, 根据客户端系统的版本选择hlk的版本, 安装时把controler跟studio安装到服务器系统上, 此时客户端的安装程序也复制到服务器机器上了, 然后在客户端系统上通过网络共享的形式(这个不需要自己操作, 服务端安装完, 共享自然就有了), 从服务器上安装
举个例子:
比如说 要用 Windows HLK for Windows 10, version 2004 这个版本吧, server端必须是 windows server2016, 客户端版本可以是win10 2004-21h2版本, 其他的版本不行
<4> 下面说具体的安装过程(以上面这个例子版本为例)
1 服务器跟客户端要在同一个局域网下, 相互之间能够访问而不需要通过网关; 服务器在安装完成后, 不要改名字, 貌似客户端是通过名字找到服务器的; 服务器配制成静态ip(可能不需要);
2 在服务器上安装HLKForWin10(2004), controler跟studio都选上, 然后开启guest账户, 关闭防火墙
3 在客户机上 执行 "bcdedit /set testsigning on", 然后重启, 关闭防火墙
4 在客户机上打开 服务器的网络共享, 找到 \\服务器主机名(或者ip)\HLKInstall\Client\Setupamd64.exe, 直接双击安装, 不需要下载下来再安装, 等待安装完成, 到这客户端就准备好了.
不要按照微软网站上执行后续的操作,
不要按照微软网站上执行后续的操作,
不要按照微软网站上执行后续的操作,
重要的事情说三遍, 后续的操作可能是早期版本的步骤, 新的不要再执行, 这是个天坑
5 下面回到服务器这边, 打开controler(就是hlk manager, 在开始菜单 windows kits下面), 选择 explorers菜单下的 "job monitor"命令, 在machine pool里面的 "default pool"里会看到刚才的客户端机器, 此时的状态一般是manual, 右键这机器把状态改为reset, 等待几秒钟, 点上面绿色的刷新按钮, 刚才的机器状态会变成ready状态, 变不过来的, 再等等, 等得不耐烦的自己去bing一下;
6 接着5的地方, 在左边新建一个 machine pool, 随便起个名字, 比如说 "hehe", 然后把刚才的机器拖进来, 这样 hehe这个机器池里就有一台可用的机器了, hlk这套测试环境干活的是以 machine pool为单位, 一个pool可以容纳好多机器, 按需重复4-6, 增加机器
2下面说 具体测试
7 承接上面, controler的工作就配置完了, 然后在相同的地方打开 hlk studio, 在project标签, 新建一个project, 名字随便起;
然后 在 selection标签选择 上面的 hehe机器池, 测试驱动的话, 页面左边选"software device", 右上角选择"driver", 然后在中间选择你要测试的驱动, 如果你安装的驱动不在当前的列表里面 --> 在客户机器安装上要测试的驱动后, 在control中把对应机器的状态重新设置成reset状态, 然后等待变成ready, 貌似就可以找到了(其他尝试的动作包括但不限于重装客户端, 更换机器池等等), 这里比较坑, 签了好几次每次都在这折腾好长时间, 每次还都不一样
接着在tests标签选择 要测试的项目, 点 run selected 测试就开始了, 这时就倒杯水, 接杯咖啡等着吧, 如果测试没过, 点开看看啥原因, 问题描述都在 系统的"事件查看器"里面, 在 "应用与服务logs"下面的 HLK-hardware lab kit里面, 描述的问题可能跟实际差十万八千里, 别问我是怎么知道的
8 结果测完了, 来到 package标签, 增加 驱动文件的文件夹, 跟pdb文件的文件夹, (即同一个驱动的编出来sys,inf放一个文件夹 pdb文件放另一个文件夹中) 然后 选择打包, 选不带签名, 然后选个位置, 等一会, 打包好的不带签名的报告就生成了
3 最后说签名部分
1 由于这个hlkx是个zip格式的, signtool不能签, 只能用hlk studio 签名, 签名可以在上步测试完了直接签上, 也可以先生成个不带签名的报告, 然后拿到另一台只安装hlk studio+EV证书的机器(这个机器的系统版本没啥要求, 只要安装的hlk studio不小于生成hlkx文件stduio版本小就行)上签
2 把ev签名的公钥导入到系统库的个人证书库底下, 然后打开 certmgr, 找到ev证书, 导出公钥到文件(cer扩展名)
3 用studio打开 未签名的hlkx, 在package标签下, 确认 驱动文件夹, 跟pdb文件夹有相应的文件, 然后 选择 创建包, 弹出的三个选项, 选择第三个(使用证书文件), 然后选择第2步中的evkey导出的cer文件, 选择目标hlkx位置, 不出意外的话, 会弹出输入evkey密码的框, 全部完成后, 就会生成签好名字的hlkx包了(这种方式的原理, 猜测是从公钥里找到代表证书的hash, 然后经过一系列查找, 找到对应的私钥, 弹出私钥的密码框)
4 提交
1 如果提交不签证书的包, 会提示提交的包格式不正确(这个是因为没有签名, hlkx文件内没有证书的那个package目录)
2 如果签的证书不是ev类型的, 会出其他的错误提示
3 inf文件除了常规的条目外, 还要增加下面的段(xxx.sys替换成你要签名的驱动文件),不加这段可能会签别的名
[SignatureAttributes]
xxx.sys=SignatureAttributes.Elam
[SignatureAttributes.Elam]
Elam=true
4 除了对包进行签名外, 驱动文件本身也要签名, 最后返回的包里, 驱动文件自己签的名会被微软的elam名给覆盖掉(貌似驱动文件本身不签也可以)
5 不知道是不是elam类型的缘故, 居然需要美国人民人工审核, 而且需要审核两个工作日(人工审核这步一天, 签名这步又一天)
6 还有由于4步骤的原因, 不要在周五这天提交, 因为中间隔着一个周末, 美国佬也是要休假的, 可能会因为这个导致签名超时失败
7 经过各种试错, 经过漫长的等待后, 漂亮国终于把签好elam名字的驱动包给返回了