欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

SmartCheck 6.03的InstallShield序列号破解(上)——好久没研究了。 (7千字)

SmartCheck 6.03的InstallShield序列号破解(上)——好久没研究了。 (7千字)

SmartCheck 6.03的InstallShield序列号破解。
Passion
2001.8.20
SmartCheck 6.03对于破解者来说不但是对付VB的利器,而且它自个儿也算是典型的InstallShield安装的破解范例。Numega的产品的检验过程似乎都类似。我以前不完全地破过SoftICE,因为不全,感觉总不对,这次拿SmartCheck重新来一次,希望过程还算完整。
先拿Windows instalshield decompiler也就是wisdec反setup.ins,反出来一大段。有过一点破Sice的经验,也不浪费时间查找字符串“The Serial Number……”了,反正找不到。看看它导入了什么DLL文件,也就是看MISC菜单下的DLL import,有俩比较特别,是UTILITY.DLL和NMINST32.DLL,其中UTILITY.DLL有个导出的函数叫DigitCheck,一个参数还是STRING,似乎专门就是检验序列号的,这么容易?
在反编译后的文本中找字串UTILITY.DLL,很容易就找到一段:
StrLocal[0007] = SUPPORTDIR ^ "UTILITY.dll"
00004C96: 0128  IF (UseDLL (StrLocal[0007]) = 00000000) THEN
00004CB6: 00B4        NumLocal[0001] = UTILITY.DigitCheck (StrLocal[0002])
00004CC6: 00B3        UnUseDLL (StrLocal[0007])
00004CC7: 0000  ENDIF
——这是典型的动态加载UTILITY.DLL,检验序列号再释放该DLL的过程。
动态加载好办,至少可以断LoadLibraryA。
好,现在开始动态跟踪。启动SmartCheck的setup.exe,下一步下一步,嗯?怎么序列号没填就通过了?——对了,SmartCheck安装的时候会检验注册表里是否有现存的NUmega的同种产品,有的话就自动读出序列号来填到序列号框里去,真是体贴人哇。——咱们这群人谁没装Numega的东西?^_^
算了算了,按上一步回到序列号填写的界面。Ctrl+D切入Sice,下断bpx loadlibrarya do "d esp->4"
回来按下一步,断了,正是加载utility.dll。
且慢,这是正确的序列号,倘若乱填的呢?——真的乱填一气,按下一步,糟!直接出来序列号错误的消息框了。
看来序列号有两步检验过程,第一步通过后才loadlibraryA来加载UTILITY.DLL来进行第二次检验。怎么办?
断messageboxa的话也有效,断后返回nminst32.dll的领空(在我的机子上call messageboxa的地址是2491cf9,mod nmi命令可看见NMINST32.DLL的基址是2490000),只是只能跳过检验,不能帮我们弄出正确的序列号来。
看来是nminst32.dll在弄鬼,再静态的反反看,用Win32Dasm反一下nminst32.dll,10001cf9处果然是Call MessageBoxa,往上看,一大段REPNE SCANSB加MOVSB的,也不知道在干什么。
往上面找个断点,既不能太远进不来,也不能太近(怕已经出错了)。——这段过程好像是用SendDlgItemmessagea来获取文本框内容并且进行第一步检验,对了就EndDialog。前后找找看就知道了。
选个断点1A70,也就是2491a70,是输出函数的开始:
:10001A70 8B442408                mov eax, dword ptr [esp+08]
:10001A74 81EC64020000            sub esp, 00000264
:10001A7A 83E810                  sub eax, 00000010
:10001A7D 53                      push ebx
:10001A7E 55                      push ebp
:10001A7F 56                      push esi
:10001A80 57                      push edi
:10001A81 0F8490050000            je 10002017
:10001A87 2D00010000              sub eax, 00000100
:10001A8C 0F841C040000            je 10001EAE
:10001A92 48                      dec eax
:10001A93 0F858E050000            jne 10002027
:10001A99 8B842480020000          mov eax, dword ptr [esp+00000280]
:10001AA0 25FFFF0000              and eax, 0000FFFF
:10001AA5 83F80C                  cmp eax, 0000000C
:10001AA8 0F8F76030000            jg 10001E24
:10001AAE 0F8461030000            je 10001E15
:10001AB4 48                      dec eax
:10001AB5 7416                    je 10001ACD
:10001AB7 48                      dec eax
:10001AB8 0F8569050000            jne 10002027
其实这个断点没啥效果,程序没事就进来(这段输出函数是对话框的过程,随便动点什么东西都会进来)。
不过跟了几次后觉得前面的是检查点击了什么按钮的,看看这儿1AB5处的跳
:10001AB5 7416                    je 10001ACD
其他几个跳都很远(差不多就是直接退出对话框过程),而且这个跳指向的地方附近就有SendDlgItemMessagea函数引用。估计这里跳的话可能有文章,于是下断2491acd
(不知怎的,setup界面中直接CTRL+D切入再下断的话大多数不成功,不是没效果就是Invalid address,难道填序列号的时候nminsl32.dll还没装进来?不管它,填满后先断hmemcpy进来,回Nminst32领空再来下断bpx 2491acd,注意得清掉hmemcpy的断点。)
好,断了!F10往下走:
* Reference To: USER32.SendDlgItemMessageA, Ord:01D8h
                                  |
:10001AD4 8B1D30230210            mov ebx, dword ptr [10022330]
  …………
 
:10001AEC FFD3                    call ebx
 
  …………
 
:10001B00 FFD3                    call ebx
 
  …………
 
:10001B11 FFD3                    call ebx
连续三次Call USER32.SendDlgItemMessageA,目的八成就是获得三个序列号框中的内容。
:10001B1A 33C0                    xor eax, eax
:10001B1C F2                      repnz        //这里看看EDI,就是输入的序列号的前四个字符。
:10001B1D AE                      scasb
跟下来一大段REPNE MOVSB SCANSB之类的,不容易弄明白什么功能,直到下面这里:
:10001C52 8D442410                lea eax, dword ptr [esp+10]
    
    //这里EAX看看,是序列号第一部分的前三个字符,于是可以明白,前面是取三个字符。^_^
    
:10001C56 33F6                    xor esi, esi
:10001C58 50                      push eax
:10001C59 68608F0110              push 10018F60
:10001C5E E8DD860000              call 1000A340        //对这前三个字符进行检验。
10001C5E这里来个d *esp,看见什么了?一大堆数字:640 641 480 481 490 491 510 511 520 521
跟进去看看,原来:10001C5E处的这个Call是检验输入的序列号的前三位数字是不是这一堆中的,不是?不是当然就不行!
:10001C66 85C0                    test eax, eax
:10001C68 7542                    jne 10001CAC
    //属于这一堆的话,返回那个符合的地址,否则返回0,不跳就完了。
稍微改改数据,接着跳:
    
:10001CAC 6820A60110              push 1001A620
:10001CB1 E85A810000              call 10009E10     //这里是第二步检验。
:10001CB6 83C404                  add esp, 00000004
:10001CB9 8BF0                    mov esi, eax
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001CAA(C)
|
:10001CBB 85F6                    test esi, esi
:10001CBD 7552                    jne 10001D11        //这里不跳也完蛋。
现在,序列号判断的流程都清楚了。——如果从:10001CB1处的CALL进去,里面会来个Loadlibrarya,这才真正的装入utility.dll文件。接着GetProcAddress,传参数
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10009E75(C)
|
:10009E80 6890A20110              push 1001A290            //含utility.dll路径的字串
* Reference To: KERNEL32.LoadLibraryA, Ord:0190h
                                  |
:10009E85 FF1518220210            Call dword ptr [10022218]    //装utility.dll
:10009E8B 8BF0                    mov esi, eax
:10009E8D 85F6                    test esi, esi            //esi返回DLL的句柄。
:10009E8F 7539                    jne 10009ECA            //成功则跳。
接着GetProcAddress,传参数调用
* Possible StringData Ref from Data Obj ->"DigitCheck"
                                  |
:10009ECA 68C0520110              push 100152C0
:10009ECF 56                      push esi
* Reference To: KERNEL32.GetProcAddress, Ord:0116h
                                  |
:10009ED0 FF151C220210            Call dword ptr [1002221C]    //取DigitCheck函数的地址
:10009ED6 85C0                    test eax, eax
:10009ED8 740E                    je 10009EE8
:10009EDA 8D4C240C                lea ecx, dword ptr [esp+0C]    
    //ECX指向我们输入的序列号,已经去掉了“-”号的,
:10009EDE 51                      push ecx
:10009EDF FFD0                    call eax            //调用,
:10009EE1 83C404                  add esp, 00000004
:10009EE4 8BD8                    mov ebx, eax
:10009EE6 EB2D                    jmp 10009F15
10009EDF处以刚刚推入堆栈的序列号的地址为参数调用utility.DigitCheck,是应该跟进去的时候了。

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功