软件名称:易触得翻书系统v3.4.2
下载地址:http://www.crsky.com/soft/34451.html
主程序是Bookshow.exe,注册码是在BookSet.exe里面输入,首先查壳两个都是vb6无壳。
首先看BookSet.exe,
直接打开点注册是这样子,是重启验证
vb的程序用VB Decompiler 反编译看一下,可以看到有MD5和AES算法
frmReg是程序注册的窗口,但是启动的时候就已经显示了“您的软件未注册”几个字,说明验证是在启动的时候,
所以从frmStart -> Form_Load_47D304里面找,
单纯静态分析逆算法不容易,我们用OD来调试,
vb PCODE的调试跟native的有些不一样
47CBAB下内存访问断点(p-code只能下内存断点,因为代码是在vb虚拟机里运行的),,
按F9运行,断在了47CBA9(ESI是实际运行的代码)
大概猜测这里是从reg.db里面读取了注册码并且用clsBlowfish.DecryptFileAsStr算法解密的,
继续追踪,在frmStart -> Form_Load_47D304里面可以找到
loc_47D127: Set var_210 = Nothing
loc_47D139: MemVar_4920E4 = Proc_19_1_467B14(0, 0) '计算硬盘序列号 modDiskInfo.Proc_467B14
loc_47D140: MemVar_4920E0 = MemVar_4920E4 '这里赋值
loc_47D15D: var_F4 = 16
从4920e0下硬件写入断点,F9 2次,直到4920e0的数据变化,可以看到MemVar_4920E所指向的数据,[[4920E0]]=[545D7C]="ST1000DM003-1ER162,W4Y5R3FH",这个是电脑的硬盘型号
断在的地方ESI为47D144
然后再来看Bookshow.exe,同样先反编译
在frmStart.FormLoad里面可以找到
后面还有
可以知道有一些字符串运算,到底算的是什么,一一下断点调试太费时,
我们可以用smart check软件看一下比较方便,
可以看到是用|间隔的一串字符串,我们之前输入的序列号就保存在其中,
这样很快定位到了关键代码
[Asm] 纯文本查看 复制代码
loc_43714B: MsgBox("找不到数据文件!", &H30, "提示", var_140, var_160)
loc_43715B: End
loc_43715D: Exit Sub
loc_43715E: End If
loc_43716D: MemVar_4450A0 = Proc_10_1_42F524(0, 0) '读取硬盘序列号
loc_437174: MemVar_44509C = MemVar_4450A0
loc_437191: var_140 = 16
loc_43719C: Proc_12_14_43CBD8(var_160, Ucase(CVar(MemVar_4450A0 & MemVar_4450A8 & "eacde")), var_140) ’计算MD5(硬盘序列号EACDESOFT+"eacde") ST1000DM003-1ER162,W4Y5R3FHEACDESOFTEACDE 就是序列号+EACDESOFT+EACDE MD5为 57b1428ee2e49088
loc_4371A7: var_198 = Ucase(var_160) '转化大写 57B1428EE2E49088 这个是机器码
loc_4371B0: MemVar_4450A0 = CStr(var_198)
loc_4371CF: var_164 = Proc_11_3_42DD78(MemVar_4450A0, MemVar_4450A4) ’ AES(机器码,eacdesofttbk) 取32位 AES算法,MemVar_4450A4是key
|
0018F894 00548A9C UNICODE "eacdesofttbk" 密钥
0018F894 00616AEC UNICODE "F008D7A07648EAB5F983F9151D843391" 这个是加密结果
MD5可以在线验证,
手工验证一下这个aes,有个网站
http://www.seacha.com/tools/aes.html
结果跟OD调试的结果F008D7A07648EAB5F983F9151D843391是一样的
[Asm] 纯文本查看 复制代码
loc_4371E0: Proc_12_14_43CBD8(var_140, CVar(var_164), 32) //MD5 32位 MD532(ToUpper(AES(机器码,eacdesofttbk)))
0018F67C 02D502BC UNICODE "0A516B737C3FBF185C1B1DA99F1D9CED"
MD5("F008D7A07648EAB5F983F9151D843391",32)=0a516b737c3fbf185c1b1da99f1d9ced
loc_4371E5: var_160 = 16
loc_4371F0: Proc_12_14_43CBD8(var_198, var_140, var_160) //MD5 16位 MD516(MD532(ToUpper(AES(机器码,eacdesofttbk))))
MD5("0a516b737c3fbf185c1b1da99f1d9ced",16)=2a59468b454a2d05
loc_437226: var_120 = 32
loc_437238: Proc_12_14_43CBD8(var_140, CVar(CStr(Ucase(CStr(var_198))) & MemVar_4450A4), var_120)//再MD5 MD532(ToUpper(MD516(MD532(ToUpper(AES(机器码,eacdesofttbk)))))+eacdesofttbk)
|
算法就逆出来了,
有点乱,先整理一下主要步骤,MD5有两种,一种是16字节的,一种是32字节的,
步骤1 AES eacdesofttbk ToUpper
步骤2 MD532
步骤3 MD516 ToUpper
步骤4 MD532 eacdesofttbk
步骤5 MD516
0018F67C 02D502BC UNICODE "44CFDDA7226A8AF5227D0931817D399B"
0018F88C 00328A9C UNICODE "eacdesofttbk" MemVar_4450A4
MD5("2A59468B454A2D05"+eacdesofttbk,32)=44cfdda7226a8af5227d0931817d399b
[Asm] 纯文本查看 复制代码
loc_43724F: MemVar_4450B0 = 0
loc_437262: Proc_12_14_43CBD8(var_120, CStr(var_140), 16) 'MD516(MD532(ToUpper(MD516(MD532(ToUpper(AES(机器码,eacdesofttbk)))))+eacdesofttbk))MD5("44cfdda7226a8af5227d0931817d399b",16)=baf849ceaffd1606 这个是序列号=MD516(MD532(MD5()+eacdesofttbk))
loc_437267: var_140 = 16
loc_437272: Proc_12_14_43CBD8(var_160, var_120, var_140) 'MD5(baf849ceaffd1606,16)=be555d3d4e16025c
loc_437287: Proc_12_14_43CBD8(var_208, MemVar_4450AC, 16)
0032FCA4 22222222222222222222 MemVar_4450AC
MD5(22222222222222222222 ,16)=8bbb9d0bcc5c0d0f
loc_437297: Proc_12_14_43CBD8(var_1C8, var_160, 32)
MD5(be555d3d4e16025c,32)=323279f73adb2c39cb6916e611d0c356
loc_4372AA: Proc_12_14_43CBD8(var_234, var_208, 32, var_1C8)
MD5(8bbb9d0bcc5c0d0f,32)= f12b3549ffe313a1f6aa0a14eb0791bf
loc_4372CB: If (MemVar_4450B0 = var_234) Then
loc_4372D0: MemVar_4450B0 = &HFF
loc_4372D6: MemVar_4450F4 = MemVar_4450EC
loc_4372DC: Else
loc_4372DE: MemVar_4450B0 = 0
loc_4372E4: MemVar_4450F4 = MemVar_4450E8
loc_4372E7: End If
loc_4372F3: Me.tm.Enabled = True
loc_4372FB: Exit Sub
loc_4372FC: ' Referenced from: 436514
loc_437304: Set var_88 = Err()
loc_43730A: Call {A4C466B8-499F-101B-BB7800AA00383CBB}.Method_arg_2C (var_164, MemVar_4450F4, MemVar_4450B0, MemVar_4450F4)
loc_43732F: MsgBox(CVar("系统启动失败!" & var_164), &H10, "错误", var_140, var_160)
loc_437345: End
|
注册算法就分析完了
下面是修改资源,修改文字和图片等资源不难,可是BookSet.exe修改后运行程序闪退,有校验
一处是CRC
frmStart.FormLoad里面
[Asm] 纯文本查看 复制代码
loc_47C817: If (MemVar_492020 = Proc_2_18_4658D0(Proc_2_17_462E40(MemVar_4920F6, MemVar_492020))) Then
loc_47C81C: MemVar_4920F6 = 0
loc_47C822: Else
loc_47C824: MemVar_4920F6 = &HFF
loc_47C827: End If
|
47C82A的1C改成1D就过了CRC校验,这里是判断退出程序的地方
改完运行弹窗提示: 系统启动失败!Incorrect size descriptor in BFD
从FormLoad里面依次下断点缩小范围,看运行到哪里开始弹窗的
47CB84 大了
47CB7F 小了
最后定位到
[Asm] 纯文本查看 复制代码
loc_47CB58: Call frmStart.global_4289336Set(New clsBlowfish)
loc_47CBAB: var_D4 = Split(frmStart.global_4289336Get().DecryptFileAsStr(MemVar_492020 & MemVar_4920F8, MemVar_49210C), "|", -1, 0)
|
跟进去,在
clsBlowfish.DecryptFileAsStr
[Asm] 纯文本查看 复制代码
Public Function DecryptFileAsStr(SourceFile, Key) '462350
'Data Table: 4169E4
Dim var_8A As Integer
loc_462288: Call Proc_30_17_45CA68(SourceFile)
loc_462291: If Not(var_92) Then
loc_4622B2: Set var_118 = Err()
loc_4622B8: Call {A4C466B8-499F-101B-BB7800AA00383CBB}.Method_DecryptFileAsStr4 (-2147221504, var_B4, "Error in Skipjack EncryptFile procedure (Source file does not exist).")
loc_4622CB: DecryptFileAsStr = var_F4
loc_4622D1: End If
loc_4622D9: var_8A = FreeFile(var_B4)
loc_4622E7: Open SourceFile For Binary As var_8A Len = &HFF
loc_462301: ReDim var_90(0 To (LOF(var_8A) - 1))
loc_462311: Get var_8A, , var_90
loc_462318: Close var_8A
loc_462320: Call DecryptByte(var_90, Key) '在这一行弹窗出错
loc_462343: var_88 = CStr(StrConv(var_90, &H40, 0))
loc_462349: DecryptFileAsStr = var_8A
End Function
|
跟进去clsBlowfish.DecryptByte
就是46A0E7处的IF语句判断的,1C改成1D即可.
至于为什么是这么改,我们可以切换到Disassembler界面,BranchF就是1C,改成1D就是BranchT,就类似于我们win32下把jnz改成了jz
修改这个要用OD,在OD里面找到46A0E7的1C
然后改成1D,点右键-->复制到可执行文件-->所有修改
最后是注册机算法,C#写的
class Crypt
{
public static String bin2str(byte[] b, int length = -1)
{
var builder = new StringBuilder();
int len = (length == -1) ?16:b.Length;
for (int i = 0; i < len; i++)
{
builder.Append(b.ToString("x2"));
}
return builder.ToString();
}
public static byte[] encryptStringToBytes_AES(string plainText, byte[] Key)//, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
// Declare the stream used to encrypt to an in memory
// array of bytes.
MemoryStream msEncrypt = null;
// Declare the RijndaelManaged object
// used to encrypt the data.
RijndaelManaged aesAlg = null;
try
{
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = new RijndaelManaged();
aesAlg.KeySize = 128;
aesAlg.Key = Key;
aesAlg.Mode = CipherMode.ECB;
aesAlg.Padding = PaddingMode.Zeros;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
msEncrypt = new MemoryStream();
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
}
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
// Return the encrypted bytes from the memory stream.
return msEncrypt.ToArray();
}
public static string MD532(string str)
{
byte[] buf=MD5.Create().ComputeHash(Encoding.Default.GetBytes(str));
return bin2str(buf, 32);
}
public static string MD516(string str)
{
byte[] buf = MD5.Create().ComputeHash(Encoding.Default.GetBytes(str));
return bin2str(buf, 32).Substring(8, 16);
}
public static string encrypt(string str)
{
string tmpstr;
byte[] key = { 0x65, 0x61, 0x63, 0x64, 0x65, 0x73, 0x6f, 0x66, 0x74, 0x74, 0x62, 0x6b, 0, 0, 0, 0 };
tmpstr=bin2str( encryptStringToBytes_AES(str, key)).ToUpper();
tmpstr=MD532(tmpstr);
tmpstr=MD516(tmpstr).ToUpper();
tmpstr=MD532(tmpstr+"eacdesofttbk");
tmpstr=MD516(tmpstr);
return tmpstr;
}
}
附上源码vs工程文件和主程序的exe
翻书v3.4.2注册机源码.rar (125.53 KB, 下载次数: 103)
|