-
-
[原创]黄玫瑰Bitlock系列加密盘中的秘密
-
发表于: 2025-11-30 23:34 1383
-
这篇文章是继KV300+密匙盘制作完成后,对90年代加密盘拯救保存计划的副产品,希望那些尘封的明珠,可以原汁原味的在一个字节都不动的情况下展现其原有的风采,KV300和KV300+的86Box模拟器中86f格式文件已经完成,可以在模拟器中模拟出加密软盘,成功测试所有存世版本。CCED 4.0的加密盘分析也已完成,制作方法将另文阐述。
Bitlock系列是雷军先生和王全国先生年轻时的作品,作为商业磁盘加密软件的半壁江山,除了Bitlock本身,金山的盘古,WPSNT,STHVCD等软件都采用其加密,在那个时代大放异彩。本文从其磁盘加密设计部分入手,在没有密匙原盘的情况下完成等效密匙盘。
我们以BLW2.04为例,这是BITLOCK for Windows的最后一个版本,很多盗版光盘都有收录,为HD-COPY的镜像,展开到磁盘后,可以发现BLW无法运行,需要用HD_INST安装,安装过程需要验证钥匙盘,从HD_INST可以看出BLW2.04是BitLOCK 2.03加密。有钥匙盘BLW也可以验证钥匙盘后运行。图为验证我们制作的等效盘后与取出磁盘的运行情况。

BitLock有反调试代码,TR和Soft-Ice都不能直接调试。最简单的办法是脱去最外层反跟踪代码后调试,因为与外壳有通信,脱壳后的程序不能直接运行,主要是用于分析其加密核心,用Ding-Boy的BW2.5脱去最外层反跟踪代码,BW2.5脱壳不在本文探讨,在第一次段跳跃后脱壳即可。
刘涛涛先生的调试神器TR载入,Bitlock系列通常会用INT 40读盘,BLW因为要在Windows下运行,使用了INT 13读盘,下断点 BPINT 13,然后一路G到读盘核心:

下断点后一路G

获取驱动器参数,继续G

重置软盘系统,准备读取关键扇区19FF(25磁道0面255号扇区,查看INT 1E,此时N值为3,将要在ES:BX读出1024字节数据)

读取数据成功,返回AH=10代表19FF是一个CRC扇区,下面验证数据。为什么我知道这是一个CRC扇区,一是BITLOCK系列大多都是这样,第二AX为10h才能进入正确流程。

AH=10h吗?
这个时候D SI 看一眼,很重要的数据都在这里了。AX取值来自[SI+6]

进入核心验证过程

BX是缓冲区首址,BX+200处为该扇区CRC,BX+202后既为扇区接缝数据。AX减去1FE个字节的累加和,此时AX应该为多少?

看看数据区

从38E4开始用AX连续减1FE字节

38E4-39AC这部分数据是计算出来的,后文将会提到。

AX减完如果为0,进入下一步验证:CX除以2,开始计算Word的累加和。

累加和应该是[si+8],至此核心数据验证完成,验证了25道255扇区的后1Feh的字节累加和和ffh word的字累加和。
你现在看到的数据是已经计算好的,如何计算呢?
}
这是数据模拟的核心函数,计算出数据并以BIN格式输出,取510h字节。祭出钟世通老师的SCS40,如下格式化:

格式化完成后读取19FF扇区数据存盘,将后510字节替换为我们计算出的数据,然后使用精确复制回写入该扇区。

至此0面复制完成,1面与0面完全一样,可以看作是0面的备份,如果0面数据出问题回去读1面数据。1面的累加和在[si+10]和[si+12]相同的方法完成1面,至此等效盘制作完成。BITLOCK后继版本包括3.0,3.1核心验证都是类似,同一方法可以制作出所有BITLOCK系列等效加密盘。
附:Bl2.01在很多光盘亦有收录破解版本,但缺失BLINST文件,该版本BLINST可以在李祥礼先生的LLGZ中找到,但是序列号不同,跟踪发现其使用INT 21的40号功能完成显示,BPM后看到其序列号只是简单的XOR 1993后存放于文件中,修改序列号后,该文件完全正常配套使用。
void generate_bytes(int A, int B, unsigned char *bytes_array) {// 所有变量定义移到函数开头int inv_255, D, O, E, k_e, r_e, k_o, r_o, j, i;// 步骤1: 计算 E 和 Oinv_255 = 65279; // 255^{-1} mod 65536D = (B - A) % 65536;if (D < 0) D += 65536;O = (D * inv_255) % 65536;E = (A - O) % 65536;if (E < 0) E += 65536;// 步骤2: 初始化1024字节数组for (i = 0; i < 1024; i++) { bytes_array[i] = 0;}// 步骤3: 设置偶数索引字节和为 Ek_e = E / 255;r_e = E % 255;for (j = 0; j < k_e; j++) { // 前 k_e 个偶数索引设为255 bytes_array[2 * j] = 255;}if (k_e < 512) { // 设置余数字节 bytes_array[2 * k_e] = r_e;}// 步骤4: 设置奇数索引字节和为 Ok_o = O / 255;r_o = O % 255;for (j = 0; j < k_o; j++) { // 前 k_o 个奇数索引设为255 bytes_array[2 * j + 1] = 255;}if (k_o < 512) { bytes_array[2 * k_o + 1] = r_o;}void generate_bytes(int A, int B, unsigned char *bytes_array) {// 所有变量定义移到函数开头int inv_255, D, O, E, k_e, r_e, k_o, r_o, j, i;// 步骤1: 计算 E 和 Oinv_255 = 65279; // 255^{-1} mod 65536D = (B - A) % 65536;if (D < 0) D += 65536;赞赏
- [原创]CCED4.0加密磁盘复制指南 1616
- [原创]黄玫瑰Bitlock系列加密盘中的秘密 1384
- [原创]KVXXX加密磁盘制作指南 37872
- [求助]PB中如何修改EDIT控件的内容? 6282
- [分享]新年快乐! 6464