-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
114 lines (54 loc) · 43.8 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>给 Windows Server 2025 配置 Windows Hello 指纹解锁</title>
<link href="/2024/fingerprint-unlocking-for-windows-server-2025/"/>
<url>/2024/fingerprint-unlocking-for-windows-server-2025/</url>
<content type="html"><![CDATA[<p>Windows Server 2025 发布了,不过我在升级后发现 Windows Hello 仍然是用不了的,甚至在登录选项中只有 <strong>密码登录</strong> 一项,连 Windows Hello 相关的选项本身都消失了:</p><p><img src="0.webp" class="lazyload" data-srcset="0.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>尝试按照 <a href="/2021/fingerprint-unlocking-for-windows-server-2022">上一篇博客</a> 的流程进行配置时发现相关登录选项并没有被加回来,无奈只好拖出 IDA 重新研究一下。</p><h3 id="初步分析"><a href="#初步分析" class="headerlink" title="初步分析"></a>初步分析</h3><p>由于这次连相关登录选项都被隐藏了,首先在 AllSystemSettings 定义里面简单翻了翻,寻找这些选项相关的页面。</p><p>通过这个 XML 可以发现,密码、PIN、指纹等设置对应的页面为 <code>SettingsPageSignInOptions</code>:</p><p><img src="1.webp" class="lazyload" data-srcset="1.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>结合之前的逆向经验,这次就直奔 <strong>SettingsHandlers_Authentication.dll</strong> 进行分析。</p><p>直接把这个 Handler 拖进 IDA 搜这个页面 ID 对应的函数,在 <code>SystemSettings::DataModel::CSignInOptionsForDeviceList</code> 可以看到指纹、密码等选项在构建时都被加进 List 了:</p><p><img src="2.webp" class="lazyload" data-srcset="2.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>这样就排除了相关选项被删除的可能性,只能是对应的选项被隐藏了。如果相关选项直接被删除了就比较麻烦,可能得直接研究怎么在文件系统里写一份 PIN 和指纹的注册资料。</p><p>由于我们的重点还是放在 PIN 注册而不是生物识别上,这里再搜索 PinSetting 进行检查。转了一圈发现在 <code>get_IsApplicable</code> 函数中有一个名字就相当可疑的 <code>BugFix_HidingWindowsHelloInServerSku</code> Feature 检查:</p><p><img src="3.webp" class="lazyload" data-srcset="3.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>通过挂调试器直接修改 <code>get_IsApplicable</code> 的返回可以恢复显示相关选项,所以可以确认就是这部分逻辑隐藏的。</p><p>从这个名字的字面意思看,微软大概是认为 Windows Server 里显示普通 Windows Hello 登录选项属于一个 BUG,所以在 Server 2025 系统中直接把对应选项隐藏掉了。继续往下追可以发现这个 Feature 的 ID 是 <code>49406258</code>:</p><p><img src="4.webp" class="lazyload" data-srcset="4.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>遗憾的是,我尝试直接通过 ViveTool 覆盖掉这个 Feature 并不能让相关选项显示出来。从代码逻辑上看,这个 Feature 更像是测试时用来隐藏这些选项看效果的,并不是字面意思上的 “启用后在 Server 系统里隐藏”。</p><p>后面我也尝试过注入 DLL 挂 <code>IsOS</code> 的钩子绕过这个检查,但不知道为什么在 Server 2022 测试成功的钩子放到 2025 后就无法触发了,不管我是挂 <code>SHCore</code> 还是挂 <code>api-ms-win-shcore-sysinfo-l1-1-0</code> 都不行,遂放弃此方案:</p><p><img src="5.webp" class="lazyload" data-srcset="5.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>本来想尽可能减小对系统文件的修改,但是搞了一整天还是没解决,只好回到最原始的方案,直接 Patch 掉相关逻辑:</p><p><img src="6.webp" class="lazyload" data-srcset="6.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>对另外几个设置项的函数 (<code>FaceSetting</code>、<code>FingerprintSetting</code>) 如法炮制,再替换一下文件就可以正常看到相关选项了:</p><p><img src="7.webp" class="lazyload" data-srcset="7.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>当然问题没有这么简单,因为选项仍然显示 <code>该设备不符合你组织关于 Windows Hello 的要求</code> 并且不能配置。我们只是回到了 2022 时代的开头。</p><h3 id="又是凭据注册管理器?"><a href="#又是凭据注册管理器?" class="headerlink" title="又是凭据注册管理器?"></a>又是凭据注册管理器?</h3><p>先把设置 UI 放一边不管。根据之前的经验,我们应该先 Patch 一下凭据注册管理器,直接找到 <code>PinEnrollment::SetDisablePinPolicyReason</code> 进行一个 <code>jnz</code> 的改:</p><p><img src="8.webp" class="lazyload" data-srcset="8.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>然后再参考最初找到那篇 Server 2019 的博客把 <code>PinEnrollmentHelper.dll</code> 和 <code>PinEnrollmentBroker.exe</code> 从一个 Windows 11 24H2 系统里拷进系统并设置相关注册表项,再打开那篇博客提供的 PinEnroller 进行注册,就可以看到熟悉的验证密码弹窗:</p><p><img src="9.webp" class="lazyload" data-srcset="9.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>能用了么?并不能,输入密码点确定后这个弹窗就消失了,然后什么都没发生。看来 2025 的问题比之前还复杂,只好继续掏出 IDA,这次加载 <code>PinEnrollmentHelper.dll</code> 挂到这个 PinEnroller 程序上调试。</p><p>用 dnSpyEx 看了一下一下这个程序调的是 <code>EnrollPin</code> 函数,而这个函数里面只有一个跳转,所以我们直接到 <code>EnrollPinHelper</code> 里面下断点往下追,发现追到 <code>AddLocalPin</code> 的 <code>NgcLocalAddCredential</code> 时扔了一个 <code>0x80090010</code> 异常:</p><p><img src="10.webp" class="lazyload" data-srcset="10.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>这是什么?对着 MS 文档一阵翻,发现这个错误码是 <code>NTE_PERM</code>,显然是一个权限问题:</p><p><img src="11.webp" class="lazyload" data-srcset="11.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>权限问题是骗人的,折腾了半天发现是因为我用 RDP 连到机器上进行调试,但通过 RDP 是不能配置 PIN 和指纹等登录选项的,会扔这个异常。</p><p>遂搬来显示器,直接到机器上调试,这回换了个错误码,大 ★ 成 ★ 功:</p><p><img src="12.webp" class="lazyload" data-srcset="12.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><h3 id="是微软-Passport-Container-哒"><a href="#是微软-Passport-Container-哒" class="headerlink" title="是微软 Passport Container 哒"></a>是微软 Passport Container 哒</h3><p>因为另外几个 dll 没有符号,追到这里就不太能调试下去了,只能重新加载 <code>ngclocal.dll</code> 下 <code>I_NgcLocalAddCredential</code> 断点继续,发现异常是调用 <code>NgcCreateContainer</code> 时出现的:</p><p><img src="13.webp" class="lazyload" data-srcset="13.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>再重新加载 <code>cryptngc.dll</code> 下 <code>I_c_NgcRpcCreateContainer</code> 断点,结果发现异常居然是 <code>NdrClientCall3</code> 丢的,真让人摸不着头脑:</p><p><img src="14.webp" class="lazyload" data-srcset="14.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>又对着 MS 文档一阵翻,发现 <code>0x80073B01</code> <del>是 Windows Update 出错</del> 是 <code>ERROR_MUI_FILE_NOT_LOADED</code>,但是这和我们的 RPC 失败有什么关系?</p><p>百思不得其解,总之先看看调用的是哪个 RPC 服务好了,如此这般如此这般找到了我们的 <code>RpcInterfaceInformation</code> 结构体:</p><p><img src="15.webp" class="lazyload" data-srcset="15.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>再如此这般找到了 RPC 接口的 GUID,肉眼识别可得 <code>30034843-029d-46ec-8fff-5d12987f85c4</code>:</p><p><img src="16.webp" class="lazyload" data-srcset="16.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>那么这个 GUID 对应的是什么接口呢?到注册表里简单搜一下就发现是 <code>NgcCtnrSvc</code> 了:</p><p><img src="17.webp" class="lazyload" data-srcset="17.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>当然简单搜一下也是骗人的,真实情况是我把系统的 RPC Endpoint 翻了个底朝天也没找到,最后把整个注册表导出来把服务一个一个看过去才发现的。</p><p>总之让我们看看这个服务有什么毛病吧,乍一看好像挺正常的,他甚至正在运行:</p><p><img src="18.webp" class="lazyload" data-srcset="18.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>到这里我更搞不懂了,因为看起来所有东西都是正常的,<code>sc</code> 查询服务状态和控制服务都没有问题。前前后后又折腾了半天,RPC 调用还是同样的报错。</p><h3 id="服务装了,但没完全装"><a href="#服务装了,但没完全装" class="headerlink" title="服务装了,但没完全装"></a>服务装了,但没完全装</h3><p>在我放弃之前打开 <code>services.msc</code> 看了一眼,发现服务的描述符居然没加载出来,并且提示错误代码 <code>15100</code> (<code>ERROR_MUI_FILE_NOT_FOUND</code>),居然又是 MUI 文件的问题:</p><p><img src="19.webp" class="lazyload" data-srcset="19.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>这下我才意识到可能在 Windows Server 2025 里可能对应的 MUI 文件真的没被 MS 放进来,系统里可能只装了 Ngc 服务的注册表和可执行文件,但没装资源文件。</p><p>打开 Windows 11 24H2 一对比果然缺了好多 Ngc 相关的 MUI 文件:</p><p><img src="20.webp" class="lazyload" data-srcset="20.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>把这些文件也进行一个移花接木,再重启 <code>NgcCtnrSvc</code> 服务,运行 PinEnroller,终于可以正常注册 PIN 了:</p><p><img src="21.webp" class="lazyload" data-srcset="21.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>注册 PIN 后到设置里检查,果然添加指纹和面部识别的选项也都可以正常工作(我没有 Windows Hello 摄像头,所以这里只添加了指纹):</p><p><img src="22.webp" class="lazyload" data-srcset="22.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>总之,这样一来在 Windows Server 2025 上也可以愉快的使用 Windows Hello 进行登录了。</p><p>虽然修改了两个系统文件导致 sfc 或系统更新后可能需要再次修改,但是这是目前我能找到的最好的解决方案。</p><p>配置完成后即使这两个文件被 Windows 更新换回来,也不影响已配置的指纹和 PIN 正常用于解锁。</p><p>理论上,如果能通过注入 DLL 的方式动态的去 Hook 相关函数,可以减小对系统的侵入并避免更新后需要重复 Patch 的问题。</p><p>不过因为 Hook <code>IsOS</code> 函数失败,直接 Hook 检查函数的话又涉及到从 MS 服务器加载符号、解析等诸多问题,我就暂时不打算继续研究了。</p><h3 id="修改好的文件"><a href="#修改好的文件" class="headerlink" title="修改好的文件"></a>修改好的文件</h3><p>按照惯例,如果你手上没有 IDA 或者不想自己动手,我也在这里附上修改后的 <strong>CredentialEnrollmentManager.exe</strong> 和 <strong>SettingsHandlers_Authentication.dll</strong>:</p><span class='btn large'><a class="button" href='WindowsServer2025_Hello_20241203.zip' title='点击下载 (2024-12-03)'><i class='fa fa-download'></i>点击下载 (2024-12-03)</a></span><p>我不能保证这个文件一定能工作,也不能保证它不会损坏你的计算机,你将需要自行承担可能存在的风险。如果你同意承担此风险,我会告诉你解压密码是小写的 <code>xwtf</code>。</p><div class="note warning"><p><strong>注意事项</strong></p><p>和之前一样,Windows Server 的内建 Administrator 账户并不支持配置指纹解锁。需要创建一个单独的用户进行配置,如果需要管理员权限请将这个用户加入 Administrators 组。</p><p>覆盖文件的过程中可能会碰到权限问题,可以通过 <a href="https://github.com/M2Team/NSudo">NSudo</a> 拉起一个 <strong>TrustedInstaller</strong> 权限的命令提示符完成覆盖操作。NSudo 在 Windows 11 24H2 下不工作,但是在 Windows Server 2025 是可以正常提权的。</p><p>同样,为了确保操作系统的安全性不受破坏,你应该使用 <code>icacls /save</code> 命令来备份被覆盖的文件并在替换完成后使用 <code>icacls /restore</code> 进行还原。对于新添加的文件最好也如此操作。</p></div>]]></content>
<tags>
<tag> Windows Server </tag>
<tag> Windows Hello </tag>
<tag> 指纹解锁 </tag>
</tags>
</entry>
<entry>
<title>将 BW-16D1H-U 改装为 BW-16D1HT 并启用 LibreDrive</title>
<link href="/2023/asus-bw16d1h-u-modding/"/>
<url>/2023/asus-bw16d1h-u-modding/</url>
<content type="html"><![CDATA[<p>华硕的 BW-16D1H-U USB 蓝光光驱是 ITX/mATX 用户播放、刻录蓝光光盘的优秀桌面解决方案之一,数年使用下来体验都不错。</p><p>不过,BW-16D1H-U 并不能读取 UHD 碟片,甚至无法读取 BDXL 格式的蓝光。为了解决这些读取需求,同时继续使用 BW-16D1H-U 这个不错的外壳,我决定使用 BW-16D1HT 对其进行升级。</p><p>这里记述的操作均为我的个人经验,不保证操作可以成功,我也不对这些操作可能造成的任何损失负责,你需要自行承担相关风险。</p><h3 id="替换光驱硬件"><a href="#替换光驱硬件" class="headerlink" title="替换光驱硬件"></a>替换光驱硬件</h3><p>BW-16D1H-U 的拆解十分简单,首先卸掉图中脚垫下方的 2 个螺丝:</p><p><img src="1.webp" class="lazyload" data-srcset="1.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>然后向上稍微抬起上层外壳,并向两侧用力,最后向上提起就能拆下外壳了。图中标出了三个卡扣的位置,供参考:</p><p><img src="2.webp" class="lazyload" data-srcset="2.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>拆除屏蔽罩后可以看出,这是一个 USB 转 SATA 的胶水方案。需要注意的是红框处的排线由双面胶固定,拆解时要特别小心,避免损伤排线:</p><p><img src="3.webp" class="lazyload" data-srcset="3.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>可以看到,内置的光驱实际上是 <code>Pioneer BDR-209MBK</code>:</p><p><img src="4.webp" class="lazyload" data-srcset="4.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>拆除固定光驱的三颗螺丝(右侧两颗,左侧一颗)后,就可以将光驱取出了,小心的取下 SATA 连接线:</p><p><img src="5.webp" class="lazyload" data-srcset="5.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p><img src="6.webp" class="lazyload" data-srcset="6.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>最后,将 BW-16D1HT 装进去,组装好外壳就大功告成了。</p><h3 id="启用-LibreDrive"><a href="#启用-LibreDrive" class="headerlink" title="启用 LibreDrive"></a>启用 LibreDrive</h3><p>自 2017 下旬起出厂的 BW-16D1HT 基本都是 <code>3.03</code> 或以上版本的固件,封堵了 LibreDrive 利用的漏洞。</p><p>为了重新启用 LibreDrive,我们需要刷入自定义固件或对固件进行降级。我更推荐刷入来自 MakeMKV 的自定义固件,这里使用的版本是 <code>ASUS-BW-16D1HT-3.10-WM01601-211901041014.bin</code>。</p><p>对 ASUS 光驱的烧录操作非常简单,使用来自 MakeMKV 论坛的 <a href="https://forum.makemkv.com/forum/viewtopic.php?f=16&t=18933">ASUS ODD FW Changer (Modified)</a> 即可。</p><p>如果你无法访问上述链接,或者无法获取相关固件,也可以下载我当前使用的版本。该版本已经过 <a href="https://www.virustotal.com/gui/file/6b5c3ec48dba799af5b9015fd8f9bdd7343331bdc8fab9c5f6bf836d26f3764f">VirusTotal 扫描</a> 和 dnSpy 审计:</p><span class='btn large'><a class="button" href='ASUS-BW-16D1HT-3.10.7z' title='点击下载 (2023-05-13)'><i class='fa fa-download'></i>点击下载 (2023-05-13)</a></span><p>固件更新过程非常简单,使用 <strong>管理员身份</strong> 运行 FW Changer 后选中固件文件,然后点击 <strong>START</strong> 即可:</p><div galleryFlag itemscope itemtype="http://schema.org/ImageGallery" class="gallery " data-group='default'><div class='fancybox'><a class='fancybox' pjax-fancybox itemscope itemtype="http://schema.org/ImageObject" itemprop="url" href='7.webp' data-fancybox='default' data-caption='undefined'><img fancybox itemprop="contentUrl" src="7.webp" class="lazyload" data-srcset="7.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></a><span></span></div><br><div class='fancybox'><a class='fancybox' pjax-fancybox itemscope itemtype="http://schema.org/ImageObject" itemprop="url" href='8.webp' data-fancybox='default' data-caption='undefined'><img fancybox itemprop="contentUrl" src="8.webp" class="lazyload" data-srcset="8.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></a><span></span></div><br><div class='fancybox'><a class='fancybox' pjax-fancybox itemscope itemtype="http://schema.org/ImageObject" itemprop="url" href='9.webp' data-fancybox='default' data-caption='undefined'><img fancybox itemprop="contentUrl" src="9.webp" class="lazyload" data-srcset="9.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></a><span></span></div></div><p>光驱会在开始固件更新时弹出,并在更新结束后收回。中断固件更新过程通常会造成软件损伤,在固件更新过程中请不要移动光驱或断开连接线,最好使用 UPS 对光驱进行供电。</p><p>最后,我们就得到一个长得像 BW-16D1H-U,但是可以抓取 UHD 碟片和 BDXL 的设备了:</p><p><img src="10.webp" class="lazyload" data-srcset="10.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><h3 id="降低读取速度"><a href="#降低读取速度" class="headerlink" title="降低读取速度"></a>降低读取速度</h3><p>由于 BW-16D1HT 倍速读取时会产生大量热量,且 BW-16D1H-U 的塑料外壳散热效率不佳,在进行改装后可能会由于过热而出现 <code>STATUS_DEVICE_DATA_ERROR</code> 的错误。</p><p>当然,这个错误也会在碟片表面有划痕、不干净或是硬件故障时出现。如果你确定这就是由于碟片过热造成的,可以通过修改注册表让 MakeMKV 降低读取速度,具体请参考 <a href="https://forum.makemkv.com/forum/viewtopic.php?t=22689">MakeMKV drive speed control</a>。</p><p>需要注意的是,固件更新后对应的设备标识符也会发生变化。你可以在 MakeMKV 中打开设置窗口并点击保存,使其自动生成新标识符对应的注册表项。</p>]]></content>
<tags>
<tag> Blu-ray </tag>
<tag> UHD </tag>
<tag> LibreDrive </tag>
</tags>
</entry>
<entry>
<title>给 Windows Server 移植 Xbox 手柄驱动</title>
<link href="/2021/xbox-gamepad-driver-for-windows-server/"/>
<url>/2021/xbox-gamepad-driver-for-windows-server/</url>
<content type="html"><![CDATA[<p>前段时间迁移到了 Windows Server 2022,使用体验还算不错。不过,最近又发现一个新问题:Xbox 手柄没有驱动。</p><p>究其原因,还是 Windows Server 缺少 Xbox 相关的一整套软件,包括 Xbox APP、在线游戏服务、驱动服务等。只要想办法将桌面 Windows 的驱动程序移植过来,就可以正常使用了。</p><p>在 Google 上找了一圈,未能找到可借鉴的资料。这里记述的操作完全基于我对 Windows 系统的理解,你需要自行承担这些操作可能带来的风险。</p><h3 id="有线连接"><a href="#有线连接" class="headerlink" title="有线连接"></a>有线连接</h3><p>以 Xbox One 手柄为例,使用 <strong>有线连接</strong> 会直接报没有驱动的错误:</p><p><img src="1.webp" class="lazyload" data-srcset="1.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>如果你能忍受有线连接,其实不必大费周折。只要 在 <strong>Microsoft Update Catalog</strong> 中 <a href="https://www.catalog.update.microsoft.com/Search.aspx?q=xbox">搜索 “xbox”</a> 就能找到 <a href="https://www.catalog.update.microsoft.com/ScopedViewInline.aspx?updateid=0396c92c-ca8c-486a-9674-e2cc4f401860">能用的驱动包</a>。</p><p>如果下载有困难,我也在此提供一个副本,你可以点击 <a href="20844731_e19c69388a4a59f2e752f92ebaacbf3cddf3e4fd.cab">这里</a> 下载。该副本已经过 Microsoft 数字签名,请先验证签名再使用。</p><p>直接解压 cab 文件,然后使用设备管理器安装驱动即可。虽然是 <strong>Xbox Peripherals (legacy)</strong> 驱动,但它工作的很好。</p><p><img src="2.webp" class="lazyload" data-srcset="2.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><h3 id="无线连接?"><a href="#无线连接?" class="headerlink" title="无线连接?"></a>无线连接?</h3><p>我不喜欢有线连接。目前,Xbox 手柄的无线连接方式有两种:蓝牙或专用的 Xbox Wireless 接收器。</p><p>在本文中我只解决了蓝牙驱动问题,至于 Xbox Wireless 接收器,我只能说 “不太可能”,因为其中涉及太多的驱动和软件包了,几乎得将整套 Xbox 软件栈移植过来。如果你能移植成功,欢迎联系我共同交流。</p><div class="note info"><p>如果你不知道怎么通过蓝牙连接 Xbox 手柄,不妨 <a href="https://www.youtube.com/results?search_query=xbox+gamepad+bluetooth">问问 YouTube</a></p></div><p>如果采用 <strong>蓝牙连接</strong>,则配对成功后会出现一个名为 <strong>Xbox Bluetooth Gamepad</strong> 的 <strong>其他设备</strong>,虽然 “运转正常”,手柄却并不能正常工作。此时手柄的指示灯会继续闪烁。</p><p><img src="3.webp" class="lazyload" data-srcset="3.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>在桌面版中,负责蓝牙 Xbox 手柄驱动是 <code>xinputhid.inf</code>。而这个组件并不存在于 Server 中。让我们先看看桌面版系统中的驱动:</p><p><img src="4.webp" class="lazyload" data-srcset="4.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>很不幸,这里只有 <code>xinputhid.inf</code> 和 <code>xinputhid.sys</code> 两个文件,不仅没有 CAT,连 SYS 文件也没有独立签名。如果你熟悉 Windows 系统,就会马上意识到这种驱动是绝对无法在开着 SecureBoot 的环境下加载的。</p><p><img src="5.webp" class="lazyload" data-srcset="5.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>我也尝试过采用自己的证书和一些古旧的证书(2015年前)对驱动进行签名然后安装,但是这并不是一个优雅的方案。这里,我将提供一个手工移植驱动的 (相对优雅的) 方案。</p><h3 id="提取-XInputHID-驱动"><a href="#提取-XInputHID-驱动" class="headerlink" title="提取 XInputHID 驱动"></a>提取 XInputHID 驱动</h3><div class="note info"><p>这部分只是记录我的操作思路,如果你不想读,可以直接跳到后面的 “安装” 一节</p></div><p>首先,我们将桌面版的 <code>%WINDIR%\System32\DriverStore\FileRepository\xinputhid.inf_amd64_b01c6ccf7f1e23b6</code> 文件夹整个复制出来,这是驱动本体。</p><p>然后,我们要解决的最大的问题就是代码签名。这个驱动并没有单独的 Catalog 文件,而是和其他驱动共同打包在一个较大的 Catalog 中。</p><p>众所周知,Windows 的 Catalog 数据存在于两个地方:<code>%WINDIR%\System32\CatRoot</code> 和 <code>%WINDIR%\System32\catroot2</code>,前者存放原始 CAT 文件,后者存放的是包含所有 CAT 文件信息的 ESE 数据库。</p><p>要从 <code>CatRoot</code> 的上千个 CAT 文件中手动翻找 Hash 明显是不合理的,因此我们偷个懒采用 Velociraptor 的 <code>authenticode()</code> 函数直接查找 SYS 文件的签名:</p><p><img src="6.webp" class="lazyload" data-srcset="6.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>现在我们知道 <code>Microsoft-Windows-Client-Desktop-Required-Package~31bf3856ad364e35~amd64~~10.0.19041.1288.cat</code> 是需要的文件之一了。但是事情还没有结束,INF 文件和 SYS 文件的签名并没有被打包在同一个 CAT 中,我们还需要找到 INF 文件对应的 CAT。</p><p>由于 <code>authenticode()</code> 函数对 INF 文件是不工作的,这里我们再计算 INF 文件的 <code>SHA-1</code> 和 <code>SHA-256</code> 哈希值,打开 <code>catroot2</code> 下的 <code>catdb</code> 数据库,在 <code>HashCatNameTableSHA1</code> 和 <code>HashCatNameTableSHA256</code> 表中查找:</p><p><img src="7.webp" class="lazyload" data-srcset="7.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>然后将 <code>HashCatNameTable_CatNameCol</code> 的值转换为字符串,得到 <code>Microsoft-Windows-Client-Desktop-Required-Package~31bf3856ad364e35~amd64~~10.0.19041.1052.cat|Microsoft-Windows-Client-Desktop-Required-Package~31bf3856ad364e35~amd64~~10.0.19041.1288.cat|</code>,这样我们就拿到两个需要的 CAT 文件了。</p><p>接下来,由于我们要直接移植驱动,不走 PNP,还得导出这些注册表项:</p><ul><li>驱动配置:<code>HKLM\SYSTEM\DriverDatabase\DriverPackages\xinputhid.inf_amd64_b01c6ccf7f1e23b6</code></li><li>INF 注册:<code>HKLM\SYSTEM\DriverDatabase\DriverInfFiles\xinputhid.inf</code></li></ul><p>并且还要查看 INF 中注册的 VID、PID,从 <code>HKLM\SYSTEM\DriverDatabase\DeviceIds\</code> 导出对应的注册信息,以便操作系统能识别这些设备。</p><p><img src="8.webp" class="lazyload" data-srcset="8.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>最后,顺便将 <code>%WINDIR%\INF\xinputhid.PNF</code> 也复制出来 (BTW,它不需要数字签名),这样我们就准备好需要的所有文件了:</p><p><img src="9.webp" class="lazyload" data-srcset="9.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><h3 id="安装-XInputHID-驱动"><a href="#安装-XInputHID-驱动" class="headerlink" title="安装 XInputHID 驱动"></a>安装 XInputHID 驱动</h3><p>如果你不想自己提取,可以用我从 Windows 10 21H1 (19043.1052) 中提取的驱动文件。</p><span class='btn large'><a class="button" href='xinputhid.zip' title='点击下载 (2021-12-15)'><i class='fa fa-download'></i>点击下载 (2021-12-15)</a></span><p>我不能保证这个文件一定能工作,也不能保证它不会损坏你的计算机,你将需要自行承担可能存在的风险。如果你同意承担此风险,我会告诉你解压密码是小写的 <code>xwtf</code>。</p><p>首先,我们需要安装 Catalog 文件。使用 <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/signtool">SignTool</a> 进行安装 (BTW,你需要有管理员权限):</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">signtool catdb /v <span class="string">"Microsoft-Windows-Client-Desktop-Required-Package~31bf3856ad364e35~amd64~~10.0.19041.1052.cat"</span></span><br><span class="line">signtool catdb /v <span class="string">"Microsoft-Windows-Client-Desktop-Required-Package~31bf3856ad364e35~amd64~~10.0.19041.1288.cat"</span></span><br></pre></td></tr></table></figure><p><img src="10.webp" class="lazyload" data-srcset="10.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>然后,使用 <a href="https://github.com/M2Team/NSudo">NSudo</a> 或 <a href="https://docs.microsoft.com/en-us/sysinternals/downloads/psexec">PSExec</a> 或者其他你喜欢的工具拉起一个 <strong>TrustedInstaller</strong> 或更高权限的命令提示符,复制这些文件:</p><ul><li><code>xinputhid.inf_amd64_b01c6ccf7f1e23b6/</code> -> <code>C:\Windows\System32\DriverStore\FileRepository</code></li><li><code>xinputhid.PNF</code> -> <code>C:\Windows\INF</code></li><li><code>xinputhid.inf_amd64_b01c6ccf7f1e23b6/xinputhid.inf</code> -> <code>C:\Windows\INF</code></li><li><code>xinputhid.inf_amd64_b01c6ccf7f1e23b6/xinputhid.sys</code> -> <code>C:\Windows\System32\drivers</code></li></ul><p>最后,使用同样的高权限用户导入 <code>xinputhid.reg</code> 文件,这样就算安装完成了。</p><p><img src="11.webp" class="lazyload" data-srcset="11.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>通过蓝牙连接你的 Xbox 手柄,此时你应该会看到一个 <code>Bluetooth XINPUT compatible input device</code> 设备,并且 Xbox 手柄上的灯变为常亮。现在,可以开始游戏了 :)</p><p><img src="12.webp" class="lazyload" data-srcset="12.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p>]]></content>
<tags>
<tag> Windows Server </tag>
<tag> Xbox </tag>
<tag> Bluetooth </tag>
<tag> Driver </tag>
</tags>
</entry>
<entry>
<title>给 Windows Server 2022 配置 Windows Hello 指纹解锁</title>
<link href="/2021/fingerprint-unlocking-for-windows-server-2022/"/>
<url>/2021/fingerprint-unlocking-for-windows-server-2022/</url>
<content type="html"><![CDATA[<p>最近从 Windows 10 迁移到了 Windows Server 2022,不过我在设置指纹解锁时发现添加按钮是灰色的,并且系统显示了错误提示 <strong>“Windows Hello 在 Windows Server 上不可用”</strong>。</p><p><img src="1.webp" class="lazyload" data-srcset="1.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>在 Google 上找了一圈并没有找到一个可行的方案,<a href="https://blog.berd.moe/archives/windows-server-2019-setup-pin-and-biometric-login/">这篇 Windows Server 2019 的博客</a> 给出的工具在 2022 中可以加上 PIN,但加上 PIN 后添加指纹的按钮依然是提示不可用的。看来得自己研究一下了。</p><h3 id="初步分析"><a href="#初步分析" class="headerlink" title="初步分析"></a>初步分析</h3><p>根据前面提到那篇博客给出的思路,我大致翻了一下 <strong>SettingsHandlers_User.dll</strong>,但是并没有找到和指纹解锁 / Windows Hello 有关的东西,猜测 Microsoft 对这块设置进行了重构。</p><p>我并不想去研究整个 UWP APP 的逻辑,于是打开火绒剑观察进程模块。很快就发现进入 <em>登录选项</em> 这个标签时会加载 <strong>SettingsHandlers_Authentication.dll</strong>,相关逻辑应该就藏在这里了。</p><p><img src="2.webp" class="lazyload" data-srcset="2.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>放进 IDA 一看,这个 DLL 中确实有不少和 Windows Hello 相关的逻辑,然而点进函数我却发现这个 DLL 除了包含大量遥测、日志代码,还用了 <strong>eXtended Flow Guard</strong>,这直接让部分逻辑的静态分析变得几乎不可能。</p><p>碰到 <code>_guard_xfg_dispatch_icall_fptr()</code> 的时候,如果是调用 GUID 还可以去注册表翻一翻 CLSID,但碰到参数是几个寄存器的时候就只能傻眼了。</p><p><img src="3.webp" class="lazyload" data-srcset="3.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>没办法直接从 UI 逻辑下手,我试图从导入表中找到 WBF 相关内容然后反向追回去,但是却发现这个 DLL 没有 WBF 相关的导入。猜测微软的设计模式和之前那篇分析 2019 的博客中提到的相同,还是把相关的注册组件拆成了一个独立组件。</p><p>除此之外,根据这个 DLL 的逻辑粗略分析,按钮的 <code>SetupOrAddFingerprintSetting::get_IsApplicable()</code> 只是简单的从一个变量里读取了这些信息然后直接返回,而 <code>SetupOrAddFingerprintSetting::get_IsEnabled()</code> 等函数是通过 XFG 动态计算的值。猜测 Windows Server 的相关检测也放到了前文提到的独立组件中,或者在进入设置页面的时候就已经全部计算好了。无论如何,我决定先放弃这个文件,看看能不能找到那个 “独立组件”。</p><h3 id="凭据注册管理器"><a href="#凭据注册管理器" class="headerlink" title="凭据注册管理器"></a>凭据注册管理器</h3><p>花了一点时间把 System32 下带 Enrollment 字样的 DLL/EXE 文件全部翻了一遍,最后我定位到了 <strong>CredentialEnrollmentManager.exe</strong> 这个文件上。</p><p>这个 EXE 的标题为 <strong>凭据注册管理器</strong>,关联到服务 <strong>CredentialEnrollmentManagerUserSvc</strong>,并且它在我们进入 <em>登录选项</em> 标签时会被自动启动。加之导入表中有 <code>WinBio</code> 相关的一系列函数以及之前那篇分析 2019 的博客提到的 <code>EnrollPin</code> 函数,我猜测实际的注册逻辑和判断逻辑都在这里。</p><p><img src="4.webp" class="lazyload" data-srcset="4.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p><img src="5.webp" class="lazyload" data-srcset="5.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><h3 id="PIN-注册判断"><a href="#PIN-注册判断" class="headerlink" title="PIN 注册判断"></a>PIN 注册判断</h3><p>从之前在普通 Windows 10 中配置指纹的经验来看,还是必须有 PIN 才能设置指纹,所以这里先研究 PIN 的注册判断逻辑 (事实证明这个决定非常正确)。</p><p>根据函数名一个一个看,排除掉 <code>PinEnrollment::v_IsSupported()</code> 后很快我们就看到了 <code>PinEnrollment::v_CanEnroll()</code> 这个很明显是某种判断的函数。调试一下,很容易发现前面两个对自身变量的判断是通过了的,而在 <code>PinEnrollment::CanAddPin()</code> 这里返回了 <code>false</code> 导致我们不能添加 PIN“:</p><p><img src="6.webp" class="lazyload" data-srcset="6.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>追进 <code>PinEnrollment::CanAddPin()</code>,很容易发现第一个判断 <code>this->byteE8</code> 就没有通过:</p><p><img src="7.webp" class="lazyload" data-srcset="7.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>再花一点时间找寻找写这个内存的地方,最后找到了 <code>PinEnrollment::RefreshPolicy()</code> 这个函数。仔细一看,上面大多是一些读取用户配置、组策略配置之类的内容,而往下翻我们很快就看到了一个重要的判断 <code>!IsOS(0x1Du)</code>:</p><p><img src="8.webp" class="lazyload" data-srcset="8.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>这个 <code>IsOS</code> 是什么东西呢?让我们看看 <a href="https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-isos">Win32 API 文档</a>:</p><details blue quote><summary> IsOS function (shlwapi.h) </summary> <div class='content'> <p>Checks for specified operating systems and operating system features.</p><p><strong>dwOS</strong>: A value that specifies which operating system or operating system feature to check for. One of the following values (you cannot combine values).</p><p><strong>Return value</strong>: Returns a nonzero value if the specified operating system or operating system feature is detected, otherwise FALSE.</p><p><img src="10.webp" class="lazyload" data-srcset="10.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p> </div> </details><p>再结合这里传入的 <code>0x1D</code> 分析,很明显这就是我们要找的判断了。</p><h3 id="打补丁"><a href="#打补丁" class="headerlink" title="打补丁"></a>打补丁</h3><p>用 IDA 打一个简单的补丁 (如果你喜欢,这里换成 jnz 也行):</p><p><img src="11.webp" class="lazyload" data-srcset="11.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>然后我们覆盖一下文件并杀掉之前的进程,重新进入 <em>登录选项</em> 标签,添加 PIN 的按钮就可以正常使用了。除此之外,添加指纹的组件也可以正常工作,看起来这个 Policy 判断是针对 Windows Hello 而不是单纯针对 PIN 的。</p><p><img src="12.webp" class="lazyload" data-srcset="12.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><div class="note "><p><strong>注意事项:文件权限</strong></p><p>覆盖文件的过程中可能会碰到权限问题,你可以通过 <a href="https://github.com/M2Team/NSudo">NSudo</a> 拉起一个 <strong>TrustedInstaller</strong> 权限的命令提示符完成覆盖操作。</p><p>为了确保操作系统的安全性不受破坏,你应该使用 <code>icacls /save</code> 命令来备份 <strong>CredentialEnrollmentManager.exe</strong> 的 ACL 并在替换完成后使用 <code>icacls /restore</code> 进行还原。</p><p>当然,你也可以选择手动设置 ACL,条条大路通罗马。</p></div><h3 id="修改好的文件"><a href="#修改好的文件" class="headerlink" title="修改好的文件"></a>修改好的文件</h3><p>如果你手上没有 IDA 或者不想自己动手,也可以直接使用我修改好的 <strong>CredentialEnrollmentManager.exe</strong>:</p><span class='btn large'><a class="button" href='CredentialEnrollmentManager_patched_10.0.20348.1194.zip' title='点击下载 (2022-12-06)'><i class='fa fa-download'></i>点击下载 (2022-12-06)</a></span><p>我不能保证这个文件一定能工作,也不能保证它不会损坏你的计算机,你将需要自行承担可能存在的风险。如果你同意承担此风险,我会告诉你解压密码是小写的 <code>xwtf</code>。</p><div class="note warning"><p><strong>注意事项:管理员账户</strong></p><p>Windows Server 的内建 Administrator 账户并不支持配置指纹解锁。如果你尝试进行配置,就会碰到这样的错误:</p><p><img src="13.webp" class="lazyload" data-srcset="13.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p><p>日常使用 Administrator 账户也不是一个好习惯,建立一个独立的 <em>User + Administrators</em> 组账户就可以使用指纹解锁了。</p><p><img src="14.webp" class="lazyload" data-srcset="14.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p></div>]]></content>
<tags>
<tag> Windows Server </tag>
<tag> Windows Hello </tag>
<tag> 指纹解锁 </tag>
</tags>
</entry>
<entry>
<title>Hello World</title>
<link href="/2021/hello-world/"/>
<url>/2021/hello-world/</url>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]></content>
</entry>
</search>