标题：BLOWFISH
软件信息
BlowFish2000V3.1
软件大小：1.39MB
软件语言：英文
软件类别：国外软件/共享软件/加密工具.
应用平台：Win9x/WinNT/Win2000/WinXP/
BlowFish2000v3.0.............
软件大小：1.39MB
软件语言：英文
软件类型：国外软件-安全相关-加密工具
授权方式：共享软件
运行环境：Win9X/Win2000/WinXP/Win2003/
更新时间：/2005-5-2513:46:28
BlowFish2000v3.0Final.正式版
软件大小:1.7MB/
软件语言：英文
软件授权:共享软件
软件类型：国外软件-安全相关-加密工具
系统支持:Win2003,WinXP,Win2000
更新日期:2005年10月03日/
详细信息
BlowfishAdvancedCS是一个新的文件加密工具，它支持七种以上的算法，能将数据有效的压缩，而且使用安全的金钥来把守防止数据被破解，同时加密之后文件不会露出蛛丝马迹，不容易用各种软件找到破解线索，并且能与Windows文件总管做整合，设定每日自动档案加密工作。
BlowfishAdvancedCS软件支持的功能主要有加密(Encrypt)、解密(Decrypt)、消除数据(Wipe)，在档案加密的同时可以设定开启密码，也能压缩数据，或者更改文件名，更改之后的档名通常以无意义的随机数文件名为主，若不更改文件名则加密之后会改以扩展名bfa来储存，因此不容易被人察觉，要解密时只要输入密码并且使用本软件选择相同的算法即可。
算法说明
加密信息BlowFish算法用来加密64Bit长度的字符串。
BlowFish算法使用两个“盒”——unsignedlongpbox[18]和unsignedlongsbox[4,256]。
BlowFish算法中，有一个核心加密函数:BF_En(后文详细介绍）。该函数输入64位信息，运算后，以64位密文的形式输出。用BlowFish算法加密信息，需要两个过程：
1.密钥预处理
2.信息加密
分别说明如下：
密钥预处理：
BlowFish算法的源密钥——pbox和sbox是固定的。我们要加密一个信息，需要自己选择一个key，用这个key对pbox和sbox进行变换，得到下一步信息加密所要用的key_pbox和key_sbox。具体的变化算法如下：
1)用sbox填充key_sbox
2)用自己选择的key8个一组地去异或pbox，用异或的结果填充key_pbox。key可以循环使用。
比如说：选的key是"abcdefghijklmn"。则异或过程为：
key_pbox[0]=pbox[0]^abcdefgh
key_pbox[1]=pbox[1]^ijklmnab
…………
…………
如此循环，直到key_pbox填充完毕。
3)用BF_En加密一个全0的64位信息，用输出的结果替换key_pbox[0]和key_pbox[1]。i=0
4)用BF_En加密替换后的key_pbox,key_pbox[i+1],用输出替代key_pbox[i+2]和key_pbox[i+3]
5)i+2，继续第4步，直到key_pbox全部被替换
6)用key_pbox[16]和key_pbox[17]做首次输入（相当于上面的全0的输入），用类似的方法，替换key_sbox信息加密。信息加密就是用函数把待加密信息x分成32位的两部分:xL,xRBF_En对输入信息进行变换，BF_En函数详细过程如下：
对于i=1至16
xL=xL^Pi
xR=F(xL)^xR
交换xL和xR(最后一轮取消该运算)  blowfish算法xR=xR^P17
xL=xL^P18
重新合并xL和xR
函数F见下图:
8位32位
|-----------S盒1-----------
||加
|8位32位|----
|-----------S盒2-----------|
||
||异或----
32位-|||
|8位32位||
|-----------S盒3---------------|加
||-----------------32位
||
||
|8位32位|
|-----------S盒4-----------------------
把xL分成4个8位分组:a,b,c和d
输出为：F(xL)=((((S[1,a]+S[2,b])MOD4294967296)^s[3,c])+S[4,d])MOD4294967296
(2的32次方)(2的32次方)
重新合并后输出的结果就是我们需要的密文。
算法解密用BlowFish算法解密，同样也需要两个过程。
1.密钥预处理
2.信息解密
密钥预处理的过程与加密时完全相同
信息解密的过程就是把信息加密过程的key_pbox逆序使用即可。
可以看出，选择不同的key，用BlowFish算法加密同样的信息，可以得出不同的结果。
要破解BlowFish算法，就是要得到BlowFish算法的key。所以，使用BlowFish算法进行加密，最重要的也就是key的选择以及key的保密。其中key的选择可以使用bf_sdk中的_WeakKey函数进行检验。以下是该函数的说明：
源文：
---------------------------------------------------------------------------------------
_WeakKey
Function:TestifthegeneratedBoxesareweak
Argument:none
Return:AX=Status(1=weak,0=good)
Affects:AX,BX,CX,DX,SI,DI,directionFlag
Description:After"_InitCrypt"youshouldtesttheBoxeswiththisfunction.
Iftheyprovideaweaknesswhichacryptoanalystcoulduseto
breaktheciphera"1"isreturned.Inthiscaseyoushould
reloadtheoriginalboxesandlettheuserchooseadifferent
password.
---------------------------------------------------------------------------------------
译文：
---------------------------------------------------------------------------------------
_WeakKey
功能：测试产生的box是否安全
参数：无
返回：AX=1不安全；AX=0安全
影响：AX,BX,CX,DX,SI,DI,方向标志
描述：使用"_InitCrypt"函数产生用于加密的Boxes后，你应该用这个函数测试产生的Boxes是否安全，如果该key产生的Boxes不安全——可以被密码分析者通过分析Boxes得到key，那么，你应该采用另外一个key产生一个安全的Boxes用来加密。
---------------------------------------------------------------------------------------
BlowFish's 分析
由于该CrackMe主要是测试你的密码学知识，所以没有在其他方面设关卡。为了减小文件体积，缩短大家下载的时间，用upx加了壳，直接用Trw2000的"PNewSec+Makepe"很方便地就能脱掉壳。
用常规的方法，很快找到下面关键比较处：
:004015D951pushecx
:004015DA52pushedx
:004015DB6880894000push00408980
:004015E0E8EBFAFFFFcall004010D0//BF_De(sn)
:004015E58B442464moveax,dwordptr[esp+64]
:004015E98B0DF0994000movecx,dwordptr[004099F0]
:004015EF83C41Caddesp,0000001C
:004015F23BC1cmpeax,ecx//比较
:004015F47529jne0040161F
:004015F68B4C244Cmovecx,dwordptr[esp+4C]
:004015FAA1EC994000moveax,dwordptr[004099EC]
:004015FF3BC8cmpecx,eax//比较
:00401601751Cjne0040161F
:004016036A30push00000030
由于BlowFish算法加密，解密输出的信息都是64Bit的，所以要进行两次比较。
我们既然知道了他对我们的sn进行的变换是BF_De，那么，很显然，我们要找到程序初始化key_pbox和key_sbox的地方。跟进4015E0的Call，找到key_pbox在408980处，下bpm，然后跟踪，分析，找到程序初始化key_pbox和key_sbox的地方，如下：
:004016C050pusheax
*PossibleStringDataReffromDataObj->"CrackingForFun"
|
:004016C16844804000push00408044
:004016C66880894000push00408980
:004016CBE860FAFFFFcall00401130//初始化Boxes
由此我们知道了BF_De(sn)的key是"CrackingForFun"。
问题的一半已经解决了。下面我们来看用来比较的另外的64Bit的数是从何而来。
bpm4099ECw
跟踪分析后，发现这个用来比较的数是由BF_En(ComputerID,key="ChinaCrackingGroup")生成。
至此，我们可以写出注册机的算法：
sn=BF_En((BF_En(ComputerID,key="ChinaCrackingGroup"),key="CrackingForFun")
只要你编程够强，密码学也还过得去，写出这个东西的注册机就不是困难的事情了。
附：
ComputerID的产生
如果你对这个CrackMe很有兴趣，还想研究一下他的ComputerID是如何产生的，也可以继续跟踪，分析，在这里，我给处我分析的结果：
ComputerID=BF_En(0776f6c62h,068736966h,key=PW_1)
其中，PW_1就是你的Windows版本号，可以在“系统属性”里头看到，也就是注册表中的
H_L_M\Software\Microsoft\Windows\CurrentVersion中的ProductId项。在我的机器上是：
"25001-OEM-0080247-46673"
注册机源码里头有一些语句没有派上用场，用“;”屏蔽了，如果你有兴趣，可以把前面的;号去掉然后把.data段里头的PW_1换成你机器的ComputerID,再按照程序中的说明自己修改一下源程序，用Masm32V6重新编译，直接按Generate，也能得到正确的序列号。