一个DLL的两种破解方法Biglnt.dll包含一个很好用的人整数类喜欢密码学的朋友可以方便地调用这个DLL来实现 一些密码学算法不过它是需要注册的一一未注册用户在调用DLL中的某些函数时会随机 地出现NAG窗11 (提示注册)o本人经过深入分析,终于破解了这个DLLo我从中也学到了不少知识现把破解过程写出 来与大家分享1.暴力破解作者提供了 DLL使用的示例代码在VC6卜•可以直接编译通过运行编译后的程序,发现: 在单击Buttonl时,会随机地出现NAG窗I丨在CMyDlg::OiiButtoiil()开始的地方设置断点, VC6 Debug 模式下单步跟踪发现在执行代码 cB3=cBl*cB2;和 cB3.GetBreakStiing(3, sz); 时会出现NAG窗I I (因为是随机出现的,所以•次测试可能不出现矛试几次就会发现了) 记下代码相应的虚拟地址(VC调试状态下切换到反汇编窗I I,就可以看到虚拟地址了)另一种定位关键代码的方法是:在OD中对MessageBoxA下断)下面使用OD来调试分析DLL中的关键代码在分析完多个DLL的导出函数后,发现: DLL内有一个全局的CRand对象(本文将其命名为CRand_obj),该对象的成员变量m_dSeed 控制NAG窗门的出现。
内存中的CRand_obj10021918 1001A380offset Biglnt.CRand::' vitable'1002191C00000000;填充4字节10021920FA8CAA01;m_dSeed100219243FD0F698(说明:由于字节对齐的因素,CRand.obj实际占用16个字节,偏移0x0处是虚表指针, 偏移0x8处是m.dSeedo关于字节对齐,可以参考 )在DLL的部分导出函数中会调用double CRand::GetRandO.该函数的代码如下:10007710 Biglnt.CRand: :GetRandfld qword ptr ds:[1001A490];l・010007716fsub qword ptr ds:[ecx+8]10007719finul qword ptr ds:[ecx+8]1000771Cfinul qword ptr ds:[1001A488];4.010007722fst qword ptr ds:[ecx+8]10007725retn用C语言表达就是:double CRaiid: :GetRand(){m_dSeed = 4.0 * m_dSeed * (1.0-m_dSeed); return m_dSeed;}/*题外话:混沌理论兀申=4£(1 一益)由初始值XoW(O」)开始迭代,得到序列心…是无规则的。
由该序列所统计岀的 概率密度p(x)在区间(0, 1)上分布为p(x)= ,图彖如下:龙 Jx(l - X)然后,将函数double CRaiid::GetRaiid()返回的浮点值(即当前的m.dSeed)与0.5进行比较 如果人于或等于0.5,则弹出NAG窗「I地址 I HEX ?1反忙编10001ADC8Bt9novebp,ecxmfifl-IADE57edi1OO01ADFB90^1000000IWUecx,a1OOO1AE4BF08190210novedi.oFFset 100MAE9BED817G21Gnnuesi,offset 10001AEEF3:A7repe-cnps dwurd plr es: f edi] ,dvjurd plr ds:[Ml] 1WU01fiF0 vZ20IB short BigInt.1B081B1D槓等则表不己经往册咸功JinooiAF?R91819G21GKt(lUecx,offset 耒注•叭 随机地押岀囲口10UWinF7E81M5C00O0call.Biglnt.CRand::GetRand1HMH1AFC0C10 28A4II11IIqword ptr ds:[10O1A428]M.51OO01B02DFEO-w ax10091804F6G4 01test:ahvi10G0-infi7 ,75-1UEEEshort BigInt.1flOfi1B1D叠跳走,则不会弹窗口1OO01B096A3030弹岀NAG亩口1UUU1UUB68BCU8B210Big Int.10628600looniRio48BigInt.1Qfi215D010001B1S60OUUFF15 3CA3II11IIcall| dixird ptr ds:[]USER32.MessagpBoxA1OO01B1D^8Ba5 0CIWVeaXyduurd ptr ss:[ebp*C]1UUU1B2033F6xoresi.esi10S&1B223BC6crapeaxresi1OO01B2a v7525REshort Biglnt.l0OOWhB1M&1B2680«C2^l 8UUMUUnovecx.duord ptr 55:[esp*89]mG01R2D48B8OO021GBigInt:.10(l20nB8如果爆破的话,一种简单的想法是修改条件跳转指令。
但是,在DLL中这样的跳转指令有 很多,逐个修改会很麻烦这里使用另一种方法一一修改与返回值比较的浮点数0.5由于 double CRaiid::GetRand()的返回值总是在0到1之间,这样只需要将0.5修改为1.0或者更人 的数即可具体做法如下:(1)将虚拟地址0X10001A428转换为文件偏移为0xlA428o⑵使用16进制工具定位到DLL文件偏移0X1A428处,该处的8个字节为00 00 00 00 00 00 E0 3F (表示浮点数 0.5), 将其修改为00 00 00 00 00 00 F0 3F (表示浮点数1.0),即只需要将E0修改为F02.写注册机爆破后的DLL已经可以自由使用下面来分析该DLL的注册算法按照提示,DLL使用16字节的注册码进行注册,注册函数为BOOL BigniCRegister(LPSTRpszRegCode)oBigIiit Register的部分反汇编代码如下:10001183call Biglnt.lOOOSCCO;初始化结构体变量C_AES_obj10001188lea eax,dwoid ptr ss:[esp+8]1000118Cpush 101000118Epush eax1000118Flea ecx,dword ptr ss:[esp+40]10001193mov dwoid ptr ss:[esp+298],01000119EcaU BigInt.l0008E70;密钥扩展100011A3lea ecx^dword ptr ss:[esp+38]100011A7caU BigInt.l0008FB0100011AClea ecx^dword ptr ss:[esp+18]100011B0push 10100011B2lea edxjwoid ptr ss:[esp+2C]100011B6push ecx100011B7push edx100011B8lea ecx^dword ptr ss:[esp+44]I00011BCcall BigInt.l0008FC0;AES-128 加密100011C1mov ecx,4100011C6lea edi^dword ptr ss:[esp+18]100011CAmov esi,offset ;str2 == byte[16],虚拟地址为 100217D8,:内容为 17 39 9B IB CA08 2F A2 B5 F3 25 24 8C E5 ED 99100011CFxor eax,eax100011D1repe cmps dword ptr es:[edi],dwoid ptr ds:[esi]I00011D3je short Biglnt. 10001202I00011D5lea ecx^dword ptr ss:[esp+38];注册失败100011D9mov dword ptr ss:[esp+290],-lI00011E4caU Biglnt. 10008D30100011E9pop edi100011EAxor eax.eax100011ECpop esiI00011EDmov ecx,dword ptr ss:[esp+280]100011F4mov dword ptr fs:[O],ecx100011FBadd esp,28C10001201retn10001202mov ecx^dword ptr ss:[esp+lC];注册成功10001206mov eax,dword ptr ss:[esp+18]1000120Amov edx.dword ptr ss:[esp+20]1000120Emov esi^dword ptr ss:[esp+24](只需要识别出算法是AES即可,AES的具体实现不必详细跟踪) 结构体变量C_AES_obj定义在栈中,其定义为stmct C_AES0x0Mabie ptr32虚表指针0x4s_box byte [256]AES的s盒0x238Nr dwoid加密轮数Nr=0xA0x23Ckey ptr32指向加密密钥=”zxf80531goodluck"0x248e_key ptr32指向扩展密钥}DLL验证注册码的算法为:AES_Enciypt(SeiiaL key=5,zxfB053 lgoodluck^) = sti2 ? 其中str2是犬小为16的字节数组,位于虚拟地址100217D8, 内容为 17 39 9B IB CA08 2F A2 B5 F3 25 24 8CE5ED99。
显然,Serial = AES_Deciypt(str2, key=”zxf8O531 goodluck”)计算得 Serial-5。