1. 前言
Buy 新电脑后安装了 Windows 11,这个系统总给我一种在 UI 方面进行了过度优化的感觉。右键菜单部分 can’t stand。还好遇到了 StartAllBack,这款软件,在此特别感谢。
As a poor student,白嫖怪,看到该软件的注册机制后我就 try to crack 它,以后 earn my fortune 后一定补票。
2. 注册机制
2.1 注册流程
这里先说结论:StartAllBack 的注册机制分为两步:
- 将输入的注册码发送给 服务器,服务器经过认证后会返回一个 Base64 编码的二进制数据,在 HKCU\Software\StartIsBack\License 下创建 Key:ActivationData,将接收的数据写入其中。
- StartAllBackCfg.exe 进程会去查询 ActivationData 中的键值,进行本地认证。
2.2 从 Active 出发
2.2.1 准备工作
When 我们安装 StartAllBack 而未激活时,就会出现这样的窗口。我们首先需要填入 12345678-1234-1234-1234-123456789ABC 使得 Activate 按钮能够处于激活状态。
接着我们确定 Activate 对应的窗口 Handle 是哪个,使用 spy++ 来进行查找 which is a auxiliary tool 当你安装 Visual Studio 时,can be found in Microsoft Visual Studio\2022\Community\Common7\Tools。
- In spy++,按下 Ctrl + F 打开窗口寻找,将其中的靶心拖动到对应的窗口上。
这时可以得到窗口的句柄为:0x604E8。
- In x64dbg,按下Alt + A 打开 append 窗口,挂载 StartAllBackCfg.exe
- In x64dbg,找到 句柄 窗口,按下 F5 刷新,寻找之前通过 spy++ 找到的句柄 604E8,在该窗口设置 WM_LBUTTONDOW 鼠标左键按下的消息断点。
- 当一次遇到条件断点时,按F9继续运行,弹出了一个 TaskDialog,点击 OK 时又会断下,此时的观察调用栈。
2.2.2 分析调用栈
在 2.2.1 中我们得到了一个调用栈,此时我们将进行回溯,即在每个返回地址所属函数的开头设置断点,然后观察参数中是否含有指向我们刚才输入的字符串 12345678-1234-1234-1234-123456789ABC。
- 0x494024,IDA 中跳转到该地址按 Alt + P 打开函数编辑,可以看到该地址所属函数的起始位置,然后在 x64 的对应位置设置断点,重新运行程序。并将之前的消息断点禁用。
参数中没有我们想要的东西,下一个。
- 0x52C3DD,同样的操作。
参数中没有我们想要的东西,下一个。
- 0x52C91A,同样的操作。
参数中没有我们想要的东西,下一个。
- 0x52C8E4
- 0x5D0ECF
出现了,出现了,出现了。12345678-1234-1234-1234-123456789ABC 在 rcx 中出现了。那么这个函数就是我们分析的重点了。
2.2.3 sub_5D0C20
根据调用栈回溯到函数 sub_5D0C20 中,根据字符串可以看到这里的 if-else
语句应该就是激活成功和失败时运行的不同控制流了。
从头看该函数的功能,重点关注一下 0x5D0A60 和 0x5AD250 这两处被调用的函数。而中间的 sub_40C140 显然是构造 http 请求字符串的。
- function at 0x5D0A60,该函数的字符串显示表明它将从事与 注册表 相关的操作,不太 want 细究其中每个函数都是干什么的,我们直接动态调试观察其中的结果。
打开 Process Monitor 在其中设置两条规则 进程名中包含 StartAllBack 和 路径中包含 HKCU\Software\StartIsBack\License 进行监听,查看 x96 动态步过该函数后会发生 what。
监听结果中可以看到其将我们输入的 Key 写入到了注册表中,我们通过 regedit 查看对应的位置确实完成了相应的操作。
- sub_406D50 与 StartAllBackX64_103,我们步过产看这两个函数的功能。这里先说结论:sub_406D50 初始化缓冲区;StartAllBackX64_103 计算 hash 值写入到缓冲区。
运行 sub_406D50 后前后的内存区域的对比如下图所示:
运行 StartAllBackX64_103 后该内存区域存放了这样一串字符。
而在 Process Monitor 中观察到的行为是将之前写入的 Key 进行了删除,同时设置了 LicenseHash 这个键的值。
- 而运行到
call 0x5AD250
这个函数前,在 sub_40C140 中已经构造好了 http 请求,所以我们通过 burpsuite 代理本地服务来查看发送的请求以及返回的结果。准备好后单步步过该函数,可以得到如下截图:
- 由于我们希望运行 if 语句而不是下面的 else 语句,所以需要对于程序的控制流进行改写 in x64dbg 中。而其中的关键就是函数对于引用结果 vars98 变量的值。
运行后其存放的是指向字符串 “ERROR: INCORRECT LICENSE KEY” 的地址。
而在函数 sub_5D0750 中对于传入的 vars98 调用 CryptStringToBinaryA 函数进行了 Base64 解码。
而在 sub_5D0850 中则要求传入的参数至少有 128 个字节。
所以我们可以构造一个 Base64 编码的数据让程序跑到相应位置。通过 DevToys 这个工具将一个 128 字节的字符串进行 Base64 编码。
改写内存数据,将字符串 “ERROR: INCORRECT LICENSE KEY” 更改为上面得到的 Base64 编码字符。同时将长度信息更新到合适位置。这样就可以顺利的进入 if 分支了。
- sub_5D0750 函数会完成对于传入字符串的解 Base64 操作。
- sub_5D0850 函数则会将这个以 REG_BINARY 的类型写入到键 ActivationData 中。
2.3 本地认证过程
虽然前面的线索断了,但是我们知道其在 HKCU\Software\StartIsBack\License 中创建了一个名为 ActivationData 的 key。
那么在本地一定会有查询这个键值的过程用来进行本地认证,从而达到激活了效果。所以我们的思路就变为了找到 When and Who 查询了这个值。
Like 这种 condition,应该去 x96 中给相应的 API 函数下条件断点,但是 there is a simple way,fishwheel 使用 Process Monitor 来进行这个过程 because it’s a 注册表活动,可以 very 轻松的被监控。
2.3.1 Process Monitor 立大功
先前使用的规则可以继续用,如果 Path 中 contains HKCU\Software\StartIsBack\License 就将其包含进来。
过滤后可以看到 StartAllBackCfg.exe 进程查询了 HKCU\Software\StartIsBack\License\ActivationData 这个键值。
双击打开查看详细信息,这里重点关注其中的 Stack 部分。可以看到 RegQueryValueExA 是被 StartAllBackX64.dll 中 ordinal 为 102 的函数调用,而这个 API 则在 0x5d1af4 处被调用。这样我们的线索又回来了。
2.3.2 本地认证逻辑
在 IDA 中跳转到 0x5d1af4 处。当 fishwheel 跳转到这时,心情十分激动。终于、finally,最後の 我找到认证逻辑所在的位置了!!!。
那么 if 想要执行到 “Your license is activated” 这个位置,只需要 #102 这个导入函数返回值和引用传参结果为 1 就可以了。
使用 IDA 打开 StartAllBackX64.dll,在 export 中找到 #102 函数。这个函数十分的简单,从中我们可以看到当查询键 ActivationData 成功后,会将 查询到的数据 Data 和 接收指针 a1 传入 sub_180001EBC 函数中。
sub_180001EBC 中应该是进行本地的认证算法,比较复杂,fishwheel 不太 want 看。
3. 破解方案
3.1 Patch dll
前面说了只需要 StartAllBackX64.dll 的 #102 函数返回 true,并且传入的指针指向的内存空间被 assigned to 1 就可以了。
而在 sub_180001EBC 中有一个完美的跳转地址,只要我在进入这个函数时跳转到这,就能够得到认证成功所需要的返回信息。
上述反编译代码对应的反汇编代码如下,所以只需要在 sub_180001EBC 开头的某个位置跳转到 loc_1800020A2 这个位置就可以了。
从 sub_180001EBC 开头寻找合适的 patch 位置,看到 mov rdi, r8
这条汇编代码后,其后是一个 patch 的绝佳位置,将 a3 保存到了 rdi 中,这正是后续赋值用的寄存器。使用 keypatch 进行 patch,输入 jmp loc_1800020A3
。
完成 patch 后,反编译代码就成了我们期望的样子了。
patch 完毕后将结果写入到文件中,这样就大功告成了。
3.2 最后操作
那么整个过程是这样的:
- 先向 HKCU\Software\StartIsBack\License 写入 ActivationData = ???。
- 接着由于 StartAllBackX64.dll 被其他进程使用,无法被替换,需要将 explorer 和 StartAllBackCfg 这两个进程杀死。
- 最后将 patched StartAllBackX64.dll 复制到 C:\Program Files\StartAllBack 中。
下面是上面操作的 run.bat 文件。复制过来,然后 使用管理员权限运行。
:: add the ActivationData key in the License
reg add HKCU\Software\StartIsBack\License /y /v ActivationData /t REG_BINARY /d 12345678
:: kill the processes which are using StartAllBackX64.dll
taskkill /f /im explorer.exe
taskkill /f /im ShellHost.exe
taskkill /f /im StartAllBackCfg.exe
:: replace the StartAllBackX64.dll with patched one
copy /Y .\StartAllBackX64.dll "C:\Program Files\StartAllBack"
:: restart explorer.exe
explorer.exe
pause
Attention: 如果你遇到 Dll 正在被使用而导致无法成功覆盖,可以使用 ListDlls 来查看该 Dll 被 which process 使用。