从狂风汉化百宝箱XP的破解看VB注册(二)(算法分析及注册机)
                      ——手把手系列之五
一些诸如“简介”的废话就不重申了,上次我们做了这个程序的内存注册机,也简单地看了一下爆破地址,有的坛友说这有点简单,况且这也决不应是我们的目的。解决OverNimble LocPlus这个难题后(该分析见系列之四),就回头又把狂风汉化百宝箱看了一遍,追出了其注册算法,现分享给各位。

【破解作者】jackily
【作者主页】http://estudy.ys168.com
【破解声明】 本破解纯属以学习为目的,偶得一点心得,愿与大家分享:) 
--------------------------------------------------------------------------------
【破解内容】
    
    通过上次的分析,我们知道本程序是典型的常用串(string) 明码比较,用到的函数是_vbastrcomp,内存地址是00462C3D。下断后,发现在mov eax,dword ptr ds:[esi+54]中,[esi+54]是真码的地址,我们只要追出其从何而来即可找到算法。但经研究,发现一个很有意思的现象,即此程序在启动时就算出了真码,然后放到[esi+54]。因此想追算法过程得在启动时下断。该程序的注册方式也是个重启验证型,和OverNimble LocPlus 1.04以前版本有些相像,这也难怪,因为两个程序的开发者都来自同一工作室。废话少说,于是有人问了,“你怎知该程序是重启验证型?”我想这是大多数人所关心的。还记得上次我们是如何下断的吗?对了,当时断在函数_vbastrcomp上,而且当时提到了程序有四处调用了该函数,我们全部下断,而上次只是在其中之一的地方停了下来。这次重启程序后,并没有新增断点,却在00464472处停了下来。于是沿着代码向上分析,发现00464419中push eax里的eax值是486cca,也就是"4746442"的HEX值。那么“4746442”又是什么呢?忘了吧,它不是我的机器码吗?该语句下一行0046441b这个call有问题,跟进后是jmp 00467120,再跟发现正是算法调用。

    代码分析如下:
00464220    > \55         push ebp
00464221    .  8BEC       mov ebp,esp
00464223    .  83EC 0C    sub esp,0C
00464226    .  68 F613400>push <jmp.&MSVBVM60.__vbaExceptHandler>;  SE handler installation
0046422B    .  64:A1 0000>mov eax,dword ptr fs:[0]
00464231    .  50         push eax
00464232    .  64:8925 00>mov dword ptr fs:[0],esp
00464239    .  81EC B0000>sub esp,0B0

...........此处代码省略

00464405    .  53         push ebx
00464406    .  50         push eax
00464407    .  FF15 64104>call dword ptr ds:[<&MSVBVM60.__vbaHre>;  MSVBVM60.__vbaHresultCheckObj
0046440D    >  8B55 D8    mov edx,dword ptr ss:[ebp-28]
00464410    .  8B1E       mov ebx,dword ptr ds:[esi]
00464412    .  52         push edx
00464413    .  FF15 8C114>call dword ptr ds:[<&MSVBVM60.__vbaI4S>;  MSVBVM60.__vbaI4Str
00464419    .  50         push eax                  ;eax=486cca,“4746442”的HEX值
0046441A    .  56         push esi
0046441B    .  FF93 00070>call dword ptr ds:[ebx+700] ;[ebx+700]=00458c30,跟进,算法调用
00464421    .  85C0       test eax,eax
00464423    .  7D 12      jge short _狂风汉?00464437
00464425    .  68 0007000>push 700
0046442A    .  68 9457450>push _狂风汉?00455794
0046442F    .  56         push esi
00464430    .  50         push eax
00464431    .  FF15 64104>call dword ptr ds:[<&MSVBVM60.__vbaHre>;  MSVBVM60.__vbaHresultCheckObj
00464437    >  8D4D D8    lea ecx,dword ptr ss:[ebp-28]
0046443A    .  FF15 14124>call dword ptr ds:[<&MSVBVM60.__vbaFre>;  MSVBVM60.__vbaFreeStr
00464440    .  8D4D C8    lea ecx,dword ptr ss:[ebp-38]
00464443    .  FF15 10124>call dword ptr ds:[<&MSVBVM60.__vbaFre>;  MSVBVM60.__vbaFreeObj
00464449    .  8B06       mov eax,dword ptr ds:[esi]
0046444B    .  56         push esi
0046444C    .  FF90 08070>call dword ptr ds:[eax+708]
00464452    .  85C0       test eax,eax
00464454    .  7D 12      jge short _狂风汉?00464468
00464456    .  68 0807000>push 708
0046445B    .  68 9457450>push _狂风汉?00455794
00464460    .  56         push esi
00464461    .  50         push eax
00464462    .  FF15 64104>call dword ptr ds:[<&MSVBVM60.__vbaHre>;  MSVBVM60.__vbaHresultCheckObj
00464468    >  8B4E 60    mov ecx,dword ptr ds:[esi+60]   假码地址
0046446B    .  8B56 54    mov edx,dword ptr ds:[esi+54]   真码地址
0046446E    .  51         push ecx                        ;unicode"123456" 我输入的假码
0046446F    .  52         push edx                        ;unicode"MNMNKMI" 真码
00464470    .  6A 01      push 1
[color]00464472    .  FF15 CC114>call dword ptr ds:[<&MSVBVM60.__vbaStrcomp>;关键比较 [/color]
00464478    .  66:85C0    test ax,ax
0046447B    .  0F85 36010>jnz _狂风汉?004645B7             ;跳走就失败,此处才是爆破点,


------------------------------------------------------------------------------
由0046441B跟进,此处是关键,注册算法在此。

00467120    > \55         push ebp
00467121    .  8BEC       mov ebp,esp
00467123    .  83EC 0C    sub esp,0C
00467126    .  68 F613400>push <jmp.&MSVBVM60.__vbaExceptHandler>   ;  SE handler installation
0046712B    .  64:A1 0000>mov eax,dword ptr fs:[0]
00467131    .  50         push eax
00467132    .  64:8925 00>mov dword ptr fs:[0],esp
00467139    .  81EC F4000>sub esp,0F4
0046713F    .  53         push ebx
00467140    .  56         push esi
00467141    .  57         push edi
00467142    .  8965 F4    mov dword ptr ss:[ebp-C],esp
00467145    .  C745 F8 B0>mov dword ptr ss:[ebp-8],_狂风汉?004013B0
0046714C    .  33F6       xor esi,esi
0046714E    .  8975 FC    mov dword ptr ss:[ebp-4],esi
00467151    .  8B45 08    mov eax,dword ptr ss:[ebp+8]
00467154    .  50         push eax
00467155    .  8B08       mov ecx,dword ptr ds:[eax]
00467157    .  FF51 04    call dword ptr ds:[ecx+4]   ;call zombie_addref
0046715A    .  B8 0200000>mov eax,2
0046715F    .  89B5 64FFF>mov dword ptr ss:[ebp-9C],esi
00467165    .  89B5 54FFF>mov dword ptr ss:[ebp-AC],esi
0046716B    .  89B5 44FFF>mov dword ptr ss:[ebp-BC],esi
00467171    .  8985 64FFF>mov dword ptr ss:[ebp-9C],eax
00467177    .  8985 54FFF>mov dword ptr ss:[ebp-AC],eax
0046717D    .  8985 44FFF>mov dword ptr ss:[ebp-BC],eax
00467183    .  8D95 64FFF>lea edx,dword ptr ss:[ebp-9C]
00467189    .  8D85 54FFF>lea eax,dword ptr ss:[ebp-AC]
0046718F    .  52         push edx
00467190    .  8D8D 44FFF>lea ecx,dword ptr ss:[ebp-BC]
00467196    .  50         push eax
00467197    .  8D95 04FFF>lea edx,dword ptr ss:[ebp-FC]
0046719D    .  51         push ecx
0046719E    .  8D85 14FFF>lea eax,dword ptr ss:[ebp-EC]
004671A4    .  52         push edx
004671A5    .  8D4D DC    lea ecx,dword ptr ss:[ebp-24]
004671A8    .  50         push eax
004671A9    .  51         push ecx
004671AA    .  8975 DC    mov dword ptr ss:[ebp-24],esi
004671AD    .  8975 D8    mov dword ptr ss:[ebp-28],esi
004671B0    .  8975 D4    mov dword ptr ss:[ebp-2C],esi
004671B3    .  8975 C4    mov dword ptr ss:[ebp-3C],esi
004671B6    .  8975 B4    mov dword ptr ss:[ebp-4C],esi
004671B9    .  8975 A4    mov dword ptr ss:[ebp-5C],esi
004671BC    .  8975 94    mov dword ptr ss:[ebp-6C],esi
004671BF    .  8975 84    mov dword ptr ss:[ebp-7C],esi
004671C2    .  89B5 74FFF>mov dword ptr ss:[ebp-8C],esi
004671C8    .  89B5 34FFF>mov dword ptr ss:[ebp-CC],esi
004671CE    .  89B5 24FFF>mov dword ptr ss:[ebp-DC],esi
004671D4    .  89B5 14FFF>mov dword ptr ss:[ebp-EC],esi
004671DA    .  89B5 04FFF>mov dword ptr ss:[ebp-FC],esi
004671E0    .  C785 6CFFF>mov dword ptr ss:[ebp-94],-1
004671EA    .  C785 5CFFF>mov dword ptr ss:[ebp-A4],1  ;步长为1
004671F4    .  C785 4CFFF>mov dword ptr ss:[ebp-B4],7  ;循环7次 
004671FE    .  FF15 78104>call dword ptr ds:[<&MSVBVM60.__vbaVarForInit>;和_vbaVarForNext联合使用,相当于for的循环语句
00467204    .  8B3D B8114>mov edi,dword ptr ds:[<&MSVBVM60.__vbaI4V>;  MSVBVM60.__vbaI4Var
0046720A    .  8B1D C0114>mov ebx,dword ptr ds:[<&MSVBVM60.__vbaVar>;  MSVBVM60.__vbaVarAdd
00467210    >  3BC6       cmp eax,esi
00467212    .  0F84 43010>je _狂风汉?0046735B
00467218    .  8B55 08    mov edx,dword ptr ss:[ebp+8]
0046721B    .  8D4D 0C    lea ecx,dword ptr ss:[ebp+C]    ;“4746442”的地址
0046721E    .  C785 24FFF>mov dword ptr ss:[ebp-DC],8
00467228    .  C745 CC 01>mov dword ptr ss:[ebp-34],1
0046722F    .  8B42 54    mov eax,dword ptr ds:[edx+54]
00467232    .  8D72 54    lea esi,dword ptr ds:[edx+54]
00467235    .  8985 2CFFF>mov dword ptr ss:[ebp-D4],eax
0046723B    .  8D55 C4    lea edx,dword ptr ss:[ebp-3C]
0046723E    .  8D45 DC    lea eax,dword ptr ss:[ebp-24]
00467241    .  52         push edx
00467242    .  50         push eax
00467243    .  C745 C4 02>mov dword ptr ss:[ebp-3C],2
0046724A    .  898D 6CFFF>mov dword ptr ss:[ebp-94],ecx
00467250    .  C785 64FFF>mov dword ptr ss:[ebp-9C],4003
0046725A    .  FFD7       call edi                       ;为MSVBVM60.__vbaI4Var
0046725C    .  8D8D 64FFF>lea ecx,dword ptr ss:[ebp-9C]  ;call之后,eax依次为0x7,0x6,...,0x1
00467262    .  50         push eax
00467263    .  8D55 B4    lea edx,dword ptr ss:[ebp-4C]
00467266    .  51         push ecx
00467267    .  52         push edx
00467268    .  FF15 B0104>call dword ptr ds:[<&MSVBVM60.#632>] ; MSVBVM60.rtcMidCharVar,取第eax值的字符
0046726E    .  8D45 B4    lea eax,dword ptr ss:[ebp-4C]
00467271    .  8D4D D8    lea ecx,dword ptr ss:[ebp-28]
00467274    .  50         push eax
00467275    .  51         push ecx
00467276    .  FF15 4C114>call dword ptr ds:[<&MSVBVM60.__vbaStrVar>;  MSVBVM60.__vbaStrVarVal
0046727C    .  50         push eax
0046727D    .  FF15 4C104>call dword ptr ds:[<&MSVBVM60.#516>] ; MSVBVM60.rtcAnsiValueBstr,变ASCII值,放ax里
00467283    .  66:8985 4C>mov word ptr ss:[ebp-B4],ax   ;依次是32,34,34,...,37,34
0046728A    .  B8 0200000>mov eax,2
0046728F    .  8985 44FFF>mov dword ptr ss:[ebp-BC],eax
00467295    .  8985 34FFF>mov dword ptr ss:[ebp-CC],eax
0046729B    .  8D95 44FFF>lea edx,dword ptr ss:[ebp-BC]
004672A1    .  8D45 DC    lea eax,dword ptr ss:[ebp-24]
004672A4    .  52         push edx
004672A5    .  8D4D A4    lea ecx,dword ptr ss:[ebp-5C]
004672A8    .  50         push eax
004672A9    .  51         push ecx                      ;ecx为0046725c语句里的ecx值
004672AA    .  C785 3CFFF>mov dword ptr ss:[ebp-C4],14  ;一个常量,0x14
004672B4    .  FFD3       call ebx                      ;_vbaVaradd,ax+ecx
004672B6    .  50         push eax                      ;
004672B7    .  8D95 34FFF>lea edx,dword ptr ss:[ebp-CC]
004672BD    .  8D45 94    lea eax,dword ptr ss:[ebp-6C]
004672C0    .  52         push edx
004672C1    .  50         push eax
004672C2    .  FFD3       call ebx                      ;_vbaVaradd,ax+ecx的值再加0x14
004672C4    .  50         push eax
004672C5    .  FFD7       call edi
004672C7    .  8D4D 84    lea ecx,dword ptr ss:[ebp-7C]
004672CA    .  50         push eax
004672CB    .  51         push ecx
004672CC    .  FF15 34114>call dword ptr ds:[<&MSVBVM60.#608>] ; rtcVarBstrFromAnsi,转整形数值,eax为存放地址
004672D2    .  8D95 24FFF>lea edx,dword ptr ss:[ebp-DC]
004672D8    .  8D45 84    lea eax,dword ptr ss:[ebp-7C]
004672DB    .  52         push edx
004672DC    .  8D8D 74FFF>lea ecx,dword ptr ss:[ebp-8C]
004672E2    .  50         push eax
004672E3    .  51         push ecx
004672E4    .  FF15 50114>call dword ptr ds:[<&MSVBVM60.__vbaVarCat>;  结果连接在一起
004672EA    .  50         push eax
004672EB    .  FF15 20104>call dword ptr ds:[<&MSVBVM60.__vbaStrVar>;  MSVBVM60.__vbaStrVarMove
004672F1    .  8BD0       mov edx,eax
004672F3    .  8D4D D4    lea ecx,dword ptr ss:[ebp-2C]
004672F6    .  FF15 E0114>call dword ptr ds:[<&MSVBVM60.__vbaStrMov>;  MSVBVM60.__vbaStrMove
004672FC    .  8BD0       mov edx,eax
004672FE    .  8BCE       mov ecx,esi
00467300    .  FF15 88114>call dword ptr ds:[<&MSVBVM60.__vbaStrCop>;  MSVBVM60.__vbaStrCopy
00467306    .  8D55 D4    lea edx,dword ptr ss:[ebp-2C]
00467309    .  8D45 D8    lea eax,dword ptr ss:[ebp-28]
0046730C    .  52         push edx
0046730D    .  50         push eax
0046730E    .  6A 02      push 2
00467310    .  FF15 90114>call dword ptr ds:[<&MSVBVM60.__vbaFreeSt>;  MSVBVM60.__vbaFreeStrList
00467316    .  8D8D 74FFF>lea ecx,dword ptr ss:[ebp-8C]
0046731C    .  8D55 84    lea edx,dword ptr ss:[ebp-7C]
0046731F    .  51         push ecx
00467320    .  8D45 94    lea eax,dword ptr ss:[ebp-6C]
00467323    .  52         push edx
00467324    .  8D4D A4    lea ecx,dword ptr ss:[ebp-5C]
00467327    .  50         push eax
00467328    .  51         push ecx
00467329    .  8D55 B4    lea edx,dword ptr ss:[ebp-4C]
0046732C    .  8D45 C4    lea eax,dword ptr ss:[ebp-3C]
0046732F    .  52         push edx
00467330    .  50         push eax
00467331    .  6A 06      push 6
00467333    .  FF15 30104>call dword ptr ds:[<&MSVBVM60.__vbaFreeVa>;  MSVBVM60.__vbaFreeVarList
00467339    .  83C4 28    add esp,28
0046733C    .  8D8D 04FFF>lea ecx,dword ptr ss:[ebp-FC]
00467342    .  8D95 14FFF>lea edx,dword ptr ss:[ebp-EC]
00467348    .  8D45 DC    lea eax,dword ptr ss:[ebp-24]
0046734B    .  51         push ecx
0046734C    .  52         push edx
0046734D    .  50         push eax
0046734E    .  FF15 04124>call dword ptr ds:[<&MSVBVM60.__vbaVarForNext>;和_vbaVarForInit一并使用
00467354    .  33F6       xor esi,esi
00467356    .^ E9 B5FEFFF>jmp _狂风汉?00467210
0046735B    >  68 BC73460>push _狂风汉?004673BC
00467360    .  EB 37      jmp short _狂风汉?00467399
00467362    .  8D4D D4    lea ecx,dword ptr ss:[ebp-2C]
00467365    .  8D55 D8    lea edx,dword ptr ss:[ebp-28]
00467368    .  51         push ecx
00467369    .  52         push edx
0046736A    .  6A 02      push 2
0046736C    .  FF15 90114>call dword ptr ds:[<&MSVBVM60.__vbaFreeSt>;  MSVBVM60.__vbaFreeStrList
00467372    .  8D85 74FFF>lea eax,dword ptr ss:[ebp-8C]
00467378    .  8D4D 84    lea ecx,dword ptr ss:[ebp-7C]
0046737B    .  50         push eax
0046737C    .  8D55 94    lea edx,dword ptr ss:[ebp-6C]
0046737F    .  51         push ecx
00467380    .  8D45 A4    lea eax,dword ptr ss:[ebp-5C]
00467383    .  52         push edx
00467384    .  8D4D B4    lea ecx,dword ptr ss:[ebp-4C]
00467387    .  50         push eax
00467388    .  8D55 C4    lea edx,dword ptr ss:[ebp-3C]
0046738B    .  51         push ecx
0046738C    .  52         push edx
0046738D    .  6A 06      push 6
0046738F    .  FF15 30104>call dword ptr ds:[<&MSVBVM60.__vbaFreeVa>;  MSVBVM60.__vbaFreeVarList
00467395    .  83C4 28    add esp,28
00467398    .  C3         retn
00467399    >  8D85 04FFF>lea eax,dword ptr ss:[ebp-FC]
0046739F    .  8D8D 14FFF>lea ecx,dword ptr ss:[ebp-EC]
004673A5    .  50         push eax
004673A6    .  51         push ecx
004673A7    .  6A 02      push 2
004673A9    .  FF15 30104>call dword ptr ds:[<&MSVBVM60.__vbaFreeVa>;  MSVBVM60.__vbaFreeVarList
004673AF    .  83C4 0C    add esp,0C
004673B2    .  8D4D DC    lea ecx,dword ptr ss:[ebp-24]
004673B5    .  FF15 18104>call dword ptr ds:[<&MSVBVM60.__vbaFreeVa>;  MSVBVM60.__vbaFreeVar
004673BB    .  C3         retn

--------------------------------------------------------------------------------
【破解总结】
  
  注册码一共七位。从机器码的最后一位开始倒着取ASCII值,结果分别加其位数,再加0x14,最后将所有的数相连即可,输出类型是字符。  
--------------------------------------------------------------------------------
【算法注册机】
/* KuangFeng Chinese c语言注册机 */
/* 在Turboc 2.0 下调试通过  */
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
main()
{
char name[100]={0} ,s[10];
int i,j;
long unsigned code;

  printf("KuangFeng Chinese KeyGen by jackily 2005-1-18\n");
  printf("Email:jackily_zhang@msn.com or jackily_zhang@yahoo.com.cn\n");
  printf("please input name:");
  scanf("%s",name);
  printf("please input computer code:");
  scanf("%s",s);
  printf("\nYour serial number is:");
    for (i=7;i>0;i--)
 { code=s[i-1]+i;code+=0x14;
   printf("%c",code);
    }
}
--------------------------------------------------------------------------------

最新发现,用户名虽不参与注册的运算,但机器码是由用户名计算出来的。然而机器码已由程序给出,所以用户名不过是个摆设而已。因此结论是:VB的运算很“有趣”的哟!
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢! 
2005-1-26