正确获得同益起名大师v337 的注册号――解读 moon 帮主的妙文
【作者】gzgzlxg
【声明】只是好奇,没有别的目的,如有,我就把注册机发表了(已经写好了),不要发信向我要注册机,我不会发表的,这也是看雪老大的要求,其实我觉得这篇文章已经很过分。按这篇文章,你100%可以得到正确的注册码。
【工具】IDA,OllyDBG
【软件】使用我在【ACProtect 1.41 -- 同益起名大师 v3.36、v3.37、vp3.33(专业版)完美脱壳】中所完美脱壳后的 GoodName.Exe v3.37版。使用脱壳版,跟踪比较容易,当然你也可以直接使用原版,但会困难一些。
http://bbs.pediy.com/showthread.php?threadid=16204

【注】读此文前,请先读 moon 帮主的【谜----同益起名大师3.36注册算法分析】,
http://bbs.pediy.com/showthread.php?threadid=14716  凡是和moon 相同的部分我就不再多废笔墨。

本文同时发表在看雪论坛和DFCG,转载时请保持完整,版主如果觉得不合适可以删除。


前言:
同益起名的注册码验证遍布全程序,在主窗体建立,子窗口建立,按键操作,对注册码和注册申请码的验证无所不在,而且计算方法来回重复,例如获取注册申请码就有三个完全相同的过程,DES 算法也有完整的两套。我们用来分析注册码取的是注册操作部分,其实在主窗口建立、子窗口建立的过程中都可以进行,因为他们是完全相同的。
这是注册窗口(Tfxhm)VMT表中的方法表部分,(全表太长)。这些代码都是在 IDA 中分析得到的。

代码:
...... 0055647F TfxhmMethodTable dw 6 00556481                   dw 16h 00556483                   dd offset Tfxhm@suiButton2Click ;退出按键 00556487 aSuibutton2click  db 0Fh,'suiButton2Click' 00556497                   dw 10h 00556499                   dd offset Tfxhm@FormClose       ;关闭窗口 0055649D aFormclose_0      db 9,'FormClose' 005564A7                   dw 11h 005564A9                   dd offset Tfxhm@FormCreate      ;建立窗口 005564AD aFormcreate_0     db 0Ah 005564AD                   db 'FormCreate' 005564B8                   dw 16h 005564BA                   dd offset Tfxhm@suiButton1Click ;注册按键 005564BE aSuibutton1cli    ck db 0Fh,'suiButton1Click' 005564CE                   dw 0Fh 005564D0                   dd offset Tfxhm@get_text        ;suiButton1Click 调用的校验注册申请码                                                            ;和注册码并注册的子过程 005564D4 aGet_text         db 8,'get_text' 005564DD                   dw 0Fh 005564DF                   dd offset Tfxhm@FormShow        ;显示窗口 005564E3 aFormshow_0       db 8,'FormShow' 005564EC Tfxhm             db 5,'Tfxhm'                    ;类名 005564F2 word_5564F2       dw 5 005564F4                   dd offset TsuiForm@VMT@Prt      ;父辈 TsuiForm 的 VMT 表指针地址 ......


我们分析的所有代码都是属于 Tfxhm@get_text 过程和它的子过程的。 Tfxhm@get_text 起始地址: 0055986C

一、 获取注册码第28位
确定你想注册姓氏的正确笔划数(必须和同益数据库中 slzik 所查到的相同,以繁体字笔画数为准,同益库中有些字的笔画数并不正确,这时你可以在同益起名的姓名分析中获得姓氏的笔画数)。在下面的字符串中从左到右查寻,得到第 28 位注册码:例如,吕:繁体字为 7 划。(从0开始数)
0123456 7 89012345678901234567890
0AH6CD3 B EF4TRS2PUV5K1MN78YZ9GIJ
得到的字母为 B,这样我们的注册码有如下形式:(31 位)下面是我们的起始注册码
123456789012345678901234567 8 901
123456789ABCDEFGHIJKLMNOPQR S TUV
加入第 28 个字母 B,得如下注册码:
123456789ABCDEFGHIJKLMNOPQR B TUV
根据 moon 提出的换位法(4*i+1位和4*(i+1)位互换,i=0,1,2,...,末尾不足4位时,最后两位互换),25<->28位对调,这个B应该在第25 位
为了便于调位,写了几句Delphi的小程序来完成:(这种操作,还是汇编容易,所以实际还是汇编写的)

代码:
procedure TForm1.Button2Click(Sender: TObject); var     Str: String; begin     Str := Edit1.Text;     asm         PushA         Xor  Edx, Edx         Mov  Esi, Str         Mov  Ecx, 7     @1:         Mov  Al, [Esi + Edx]         Xchg Al, [Esi + Edx + 3]         Xchg Al, [Esi + Edx]         Dec  Ecx         Add  Edx, 4         Cmp  Ecx, 0         Jnz  @1         Mov  Al,    [Esi + Edx + 1]         Xchg Al, [Esi + Edx + 2]         Xchg Al, [Esi + Edx + 1]         PopA     end;     Edit2.Text := Str; end;


在 Edit1 中输入 123456789ABCDEFGHIJKLMNOPQRBTUV,按 Button2 键得到下面的新注册码:
新注册码为:
123456789012345678901234 5 678901
42318675CAB9GEFDKIJHOMNL B QRPTVU
具体分析请看 moon 的解释。

二、 获取注册码 23~27 位注册码
用OD载如 UNGDN.exe (脱壳后的程序)

代码:
Tfxhm@get_text ...... ...... 0055CF7E  mov eax, ds:AppIDAndName_CryHex@Prt ;注册申请号加姓氏和1FH 异或得到的结果 0055CF83  mov eax, [eax] 0055CF85  call sub_4FED88                 ;EncodeFunction1 0055CF8A  lea eax, [ebp+var_94]           ;这里断下获取计算23-27位的三个字符 0055CF8A                                  ;按照 moon帮主的给出的算法可以获得 0055CF90  pus  eax 0055CF91  lea  edx, [ebp+var_98] 0055CF97  mov  eax, ds:Serial_CryHex@Prt  ;注册号和 1FH 异或得到的结果 0055CF9C  mov  eax, [eax] 0055CF9E  call CycleConversionStr         ;经过 1FH 异或,即还原 0055CFA3  mov  eax, [ebp+var_98] 0055CFA9  mov  ecx, 5 0055CFAE  mov  edx, 17h 0055CFB3  call LStrCopy                   ;取第 23~27位 0055CFB8  mov  eax, [ebp+var_94] 0055CFBE  lea  edx, [ebp+var_90] 0055CFC4  call sub_4F0048                 ;进行计算得到三个字符,如果和上面计算得到的三个字符相同,则过 0055CFC9  mov  edx, [ebp+var_90] 0055CFCF  mov  eax, [ebp+var_C] 0055CFD2  call LStrCmp                    ;关键比较,比较两种方式和数据计算得到的三个字符 0055CFD7  jnz  loc_55D157 0055CFDD  lea  eax, [ebp+var_A0] 0055CFE3  push eax 0055CFE4  lea  edx, [ebp+var_A4] 0055CFEA  mov  eax, ds:Serial_CryHex@Prt 0055CFEF  mov  eax, [eax] 0055CFF1  call CycleConversionStr 0055CFF6  mov  eax, [ebp+var_A4] 0055CFFC  mov  ecx, 5 0055D001  mov  edx, 17h                   ;取注册号23~27 0055D006  call LStrCopy 0055D00B  mov  eax, [ebp+var_A0] 0055D011  lea  edx, [ebp+var_9C] 0055D017  call sub_4F0048 0055D01C  mov  edx, [ebp+var_9C] 0055D022  mov  eax, [ebp+var_C] 0055D025  call LStrCmp                    ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同 0055D02A  jnz  loc_55D0EA 0055D030  lea  eax, [ebp+var_A8] 0055D036  push eax 0055D037  lea  edx, [ebp+var_AC] 0055D03D  mov  eax, ds:Serial_CryHex@Prt 0055D042  mov  eax, [eax] 0055D044  call CycleConversionStr 0055D049  mov  eax, [ebp+var_AC] 0055D04F  mov  ecx, 3 0055D054  mov  edx, 1Dh                   ;取注册号 29~31 位 0055D059  call LStrCopy 0055D05E  mov  eax, [ebp+var_A8] 0055D064  call 31decimalToHex             ;对29~31位注册码进行31进制到十六进制的转换 0055D069  mov  ebx, eax 0055D06B  lea  eax, [ebp+var_B0] 0055D071  push eax 0055D072  lea  edx, [ebp+var_B4] 0055D078  mov  eax, ds:Serial_CryHex@Prt  ;取注册号(经过1FH异或处理) 0055D07D  mov  eax, [eax] 0055D07F  call CycleConversionStr         ;经过相同的过程还原 0055D084  mov  eax, [ebp+var_B4] 0055D08A  mov  ecx, 1Ch 0055D08F  mov  edx, 1                     ;取注册号 1~28 位 0055D094  call LStrCopy 0055D099  mov  eax, [ebp+var_B0] 0055D09F  call SumSerial_1to28            ;做 1~28 位累加(中间还有判断是否大于27000,见moon帮主的解释) 0055D0A4  cmp  ebx, eax                   ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点 0055D0A6  jnz  loc_55D157                 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉 0055D0AC  mov  eax, offset a111_2         ; "111" 0055D0B1  call CheckSerial_17to22         ;这里是获取 17~22 位注册码的入口 0055D0B6  mov  [ebp+var_1], al 0055D0B9  cmp  [ebp+var_1], 0 0055D0BD  jz   short  loc_55D0CC 0055D0BF  lea  eax, [ebp+var_C] 0055D0C2  mov  edx, offset a111_2         ;"111" 0055D0C7  call LStrLAsg 0055D0CC 0055D0CC loc_55D0CC: 0055D0CC  cmp  [ebp+var_1], 0 0055D0D0  jz   loc_55D157 0055D0D6  mov  eax, [ebp+var_C] 0055D0D9  mov  edx, offset a111_2         ;"111" 0055D0DE  call LStrCmp 0055D0E3  jnz  short  loc_55D0EA 0055D0E5  call CheckSerial_1to16          ;这里是获取 1~16 位注册码的入口


在0055CF8A 处下断点,F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',注册申请码是不能修改的,由你的机器的 CPU 和硬盘的参数变化而来。在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的 123456789ABCDEFGHIJKLMNOBWRSTUV 注册码拷贝到输入窗口。按【注册】键,中断在 0055CF8A ,清除断点(或关闭),由 [ebp - c] 中的内容,得到三个字符 VRB,记录下这三个字符,用moon帮主给出的方法:


求逆方法:
1. 执行到00559D0A,然后下:d [ebp-c],记下数据区显示的正确值x,y,z;
2. 对3个字节的正确值进行调位,得到5个字节a,b,c,d,e,调位方法为:
0,0,0,x7,x6,x5,x4,x3
0,0,0,x2,x1,x0,y5,y4
0,0,0,0 ,y3,y2,y1,y0
0,0,0,y7,y6,z7,z6,z5
0,0,0,z4,z3,z2,z1,z0
3. 根据5个字节查表"0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX",得到5位注册码即为23~27位。
--摘自 moon 帮主文


我用Delphi写了几句小程序完成这个转换,程序如下:

代码:
procedure TForm1.Button1Click(Sender: TObject); const     Str = '0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX'; var     X1, X2: Integer;     x, y, z: Char;     a, b, c, d, e: string;     Pin: string; begin     Pin := Edit1.Text;     x   := Pin[1];     y   := Pin[2];     z   := Pin[3];     x1  := (Byte(x) shr 3) and $1F;     a   := Copy(Str, x1 + 1, 1);     x1  := ((Byte(x) shl 2) and $1C) or ((Byte(y) shr 4) and $03);     b   := Copy(Str, x1 + 1, 1);     x1  := Byte(y)  and $0F;     c   := Copy(Str, x1 + 1, 1);     x1  := ((Byte(y) shr 3) and $18) + ((Byte(z) shr 5) and $07);     d   := Copy(Str, x1 + 1, 1);     x1  := (Byte(z) and $1F);     e   := Copy(Str, x1 + 1, 1);     Edit2.Text := a + b + c + d + e; end;


在 Edit1 输入 VRB 按 Button1 键,在 Edit2 窗口中给出我们要的结果 B8MBM 。现在来继续完善我们的注册码。将得到的字符串替换原注册码中第 23~27 位:
1234567890123456789012 34567 8 901
123456789ABCDEFGHIJKLM B8MBM B TUV

用前面的小程序进行调位,得新注册码如下:
1234567890123456789012345678901
42318675CAB9GEFDKIJH8MBLBBMMTVU

三、 获得的 17~22 位注册码:
在OD中按 Ctrl-F2组合键,重新运行程序,将 0055D0A6 的 jnz loc_55D157 Nop 掉

代码:
0055D0A6  jnz  loc_55D157             ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉 0055D0AC  mov  eax, offset a111_2     ;"111" 0055D0B1  call CheckSerial_17to22     ;这里是获取 17~22 位注册码的入口 跟进 0055D0B1  call CheckSerial_17to22 ...... ...... 省略 0050C705  mov  edx, [ebp+var_20] 0050C708  mov  eax, [ebp+var_1C] 0050C70B  call DES_EncryStr           ;在这里进行 DES 的 EncryStr 加密运算,运算结果再经过 0050C70B                              ;另一过程处理,这个子过程我们后面还要用到 0050C710  mov  edx, [ebp+var_60]      ;moon 文中提到在这个位置获取 17~22 位注册码,可能 0050C710                              ;是帮主写文章时粗心了,正确的位置应该在下面删除第5位 0050C710                              ;相同字母后才取结果。 0050C713  lea  eax, [ebp+var_20] 0050C716  call LStrLAsg 0050C71B  lea  ecx, [ebp+var_64] 0050C71E  mov  eax, [ebp+var_20] 0050C721  mov  dl, [eax+5]            ;取出 EncryStr 运算结果的字符串的第 5 位 0050C724  mov  eax, [ebp+var_20] 0050C727  call DelChr                 ;将 EncryStr 运算结果中凡是和第5位相同的字母删除 0050C72C  mov  edx, [ebp+var_64] 0050C72F  lea  eax, [ebp+var_20]      ;这里下断点,从Edx中取前6位,即我们要的第 17-22 位 ...... ......省略



在 0050C72C 处下断点,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDKIJH8MBLBBMMTVU)拷贝过去。点击【注册】按键。中断在 0050C72F,在Edx 返回一个长度为30的字符串(这个字符串的长度是不一定为30的,要看删除相同字符的数目而定),取前 6 为,即为我们要的注册码的第 17~22位,在我们的例子中得到的字符串是:DEDAHI。现在我们来修改我们的注册码:

1234567890123456 789012 34567 8 901
123456789ABCDEFG DEDAHI B8MBM B TUV
用前面的小程序调位后得新注册码:
1234567890123456789012345678901
42318675CAB9GEFDAEDD8IBHBBMMTVU


四、 获取 1~16 位注册码
我们首先来看看程序的代码,从前面列出的程序最后一句:

代码:
0055D0E5  call  CheckSerial_1to16     ;这里是获取 1~16 位注册码的入口 跟进 call CheckSerial_1to16 ...... ......省略 00508EEB  lea  edx, [ebp+var_18] 00508EEE  mov  eax, ds:AppIDAndName_CryHex@Prt 00508EF3  mov  eax, [eax] 00508EF5  call ConversionHex10To16 00508EFA  lea  eax, [ebp+var_18] 00508EFD  lea  edx, [ebp+var_8] 00508F00  call ConversionHexAndFNameToStr 00508F05  lea  eax, [ebp+var_20] 00508F08  push eax 00508F09  lea  edx, [ebp+var_24] 00508F0C  mov  eax, ds:Serial_CryHex@Prt 00508F11  mov  eax, [eax] 00508F13  call CycleConversionStr 00508F18  mov  eax, [ebp+var_24] 00508F1B  mov  ecx, 10h 00508F20  mov  edx, 1                     ;取注册号 1~16 位 00508F25  call LStrCopy 00508F2A  mov  eax, [ebp+var_20] 00508F2D  lea  ecx, [ebp+var_1C] 00508F30  mov  edx, [ebp+var_8] 00508F33  call DES_DecryStr               ;这是 DES 的逆运算,我们再跟进 00508F38  mov  eax, [ebp+var_1C] 00508F3B  lea  edx, [ebp+var_18] 00508F3E  call ConversionHex10To16 00508F43  lea  eax, [ebp+var_18] 00508F46  push eax 00508F47  lea  edx, [ebp+var_38] 00508F4A  mov  eax, ds:AppIDAndName_CryHex@Prt 00508F4F  mov  eax, [eax] 00508F51  call sub_4FBA70 00508F56  mov  eax, [ebp+var_38] 00508F59  lea  edx, [ebp+var_34]          ;这里是我们要下断点的地方 ...... ...... 省略 跟进 call  DES_DecryStr ...... ......省略 004F788E  lea  edx, [ebp+var_C] 004F7891  mov  eax, [ebp+var_4] 004F7894  call  sub_4E97BC 004F7899  mov  ecx, ebx 004F789B  mov  edx, [ebp+var_8] 004F789E  mov  eax, [ebp+var_C] 004F78A1  call DecryStr                   ;DES 逆运算 004F78A6  xor  eax, eax                   ;这里是 moon 帮主提出下断点处,还有一些其他相应的做法                                                             ;请看 moon 原文。 ...... ......省略



在OD中按 Ctrl-F2,重新启动,在00508F59下断点,同上,将 0055D0A6 的 jnz loc_55D157 Nop 掉,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 00508F59,下面是堆栈内容:

代码:
EBP-38  0012F910    00F303D0    ASCII "5FF51115" EBP-34  0012F914    00000000 EBP-30  0012F918    00000000 EBP-2C  0012F91C    00000000 EBP-28  0012F920    00000000 EBP-24  0012F924    00F30038    ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV" EBP-20  0012F928    00F29F5C    ASCII "123456789ABCDEFG" EBP-1C  0012F92C    00F3009C EBP-18  0012F930    C338FAD3 EBP-14  0012F934    DD5CB3D0 EBP-10  0012F938    D5D42656 EBP-C   0012F93C    A2BB6C94 EBP-8   0012F940    00F2FFF8    ASCII "M9BJBBRIDE88TNP4" EBP-4   0012F944    00000000


注意: EBP-38   0  00F2A130  ASCII "5FF51115"  这是我们要的 DES 加密的明文。
      EBP-8    0> 00F2FFE4    ASCII "M9BJBBRIDE88TNP4" 这是 Key。

按 moon 帮主的方法,修改两句代码,进行逆运算,但我经过努力,总是没有成功,可能是对 moon 的方法不能深刻的理解,于是决定改用其他的方法。我们注意到如下代码:

代码:
004F788E  lea  edx, [ebp+var_C] 004F7891  mov  eax, [ebp+var_4] 004F7894  call sub_4E97BC 004F7899  mov  ecx, ebx 004F789B  mov  edx, [ebp+var_8] 004F789E  mov  eax, [ebp+var_C] 004F78A1  call DecryStr                   ;DES 逆运算


在最后一句 Call DecryStr 做的其实是DES的逆运算,前面还有一个辅助的运算,我认为,同益的代码中一定有一个DES的正向运算,即EncryStr,所以我找了一下,其实就在上面第三节--【获得的 17~22 位注册码】中出现过,下面我们跟进这个Call:

代码:
0050C70B  call DES_EncryStr 跟进 ...... ......省略 004F781A  lea  ecx, [ebp+var_C]           ; 返回地址 004F781D  mov  edx, [ebp+var_8]           ; Key = M9BJBBRIDE88TNP4 004F7820  mov  eax, [ebp+var_4]           ; Str = 5FF51115 004F7823  call EncryStr 004F7828  mov  edx, ebx 004F782A  mov  eax, [ebp+var_C] 004F782D  call sub_4E63F4 004F7832  xor  eax, eax                   ;这里下断点 ...... ......省略


可以看出,它和上面的代码正好相反,我们用下面的方法来获得 1~16 位的代码。
接前面,我们中断在

代码:
00508F59  lea  edx, [ebp+var_34]


在代码窗口中按 Ctrl-G,输入004F781A,转移到 004F781A。按 Ctrl-*,将Eip地址改到 004F781A。
我们要做的工作其实就是修改堆栈的地址,下面是具体操作。

代码:
EBP-38  0012F910    00F303D0    ASCII "5FF51115" EBP-34  0012F914    00000000 EBP-30  0012F918    00000000 EBP-2C  0012F91C    00000000 EBP-28  0012F920    00000000 EBP-24  0012F924    00F30038    ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV" EBP-20  0012F928    00F29F5C    ASCII "123456789ABCDEFG" EBP-1C  0012F92C    00F3009C EBP-18  0012F930    C338FAD3 EBP-14  0012F934    DD5CB3D0 EBP-10  0012F938    D5D42656 EBP-C   0012F93C    A2BB6C94    结果返回地址,这里改为 0,程序运行时会自行分配新的内存 EBP-8   0012F940    00F2FFF8    ASCII "M9BJBBRIDE88TNP4" EBP-4   0012F944    00000000    这里是 Str 所以将这里改为 00F303D0,也就是[EBP-38] 指向的地址。


另外,最终返回结果在 Ebx 中,而Ebx 是由上一级的过程传递过来的参数,已经由入口程序做过初始化,所以,必须分配一个有效的返回地址,这点和 [EBP-C] 不同,需要要注意,这里我们将 [EBP-24] 的堆栈地址分配给 Ebx, 也就是Ebx = 0012F924

改完后堆栈如下:

代码:
EBP-C    0> 00000000 EBP-8    0> 00F2FFF8    ASCII "M9BJBBRIDE88TNP4"    Key EBP-4    0> 00F303D0    ASCII "5FF51115"            Str 在将 Ebx 的内容改为 EBP-24 的堆栈地址,即 Ebx = 0012F924   ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"


在 004F7832 下断点,F9 运行,d [Ebx], [Ebx] =0VBMHYAMA260CSD1  第 1~16 位的注册码

现在我们来修改我们的注册码:
1234567890123456 789012 34567 8 901
0VBMHYAMA260CSD1 DEDAHI B8MBM B TUV

用前面的小程序调位后得新注册码:
1234567890123456789012345678901
MVB0MYAH026A1SDCAEDD8IBHBBMMTVU

五、 获取最后 29~31 位注册码
打开注册表编辑器:将Serial中的内容清除:
[HKEY_LOCAL_MACHINE\SOFTWARE\GoodSoft\GoodName]
"Appid"=dword:059c0935
"Serial"="MVB0MYAH026A1SDCAEDD8IBHBBMMTVU"

"Serial"="0"

在OD 中按 Ctrl-F2 重新启动,将下面两处 Nop 掉。

代码:
0055CFD2  call LStrCmp            ;关键比较,比较两种方式和数据计算得到的三个字符 0055CFD7  jnz  loc_55D157         ;Nop 这里 0055D025  call LStrCmp            ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同 0055D02A  jnz  loc_55D0EA         ;Nop这里 0055D0A4  cmp  ebx, eax           ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点


在上面 0055D0A4 处下断点,F9运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(MVB0MYAH026A1SDCAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 0055D0A4,记录下Eax寄存器的内容,我这里是 2C3AH,换算成十进制数为 11322

根据 moon 帮主的文章:

求逆方法:
1. 执行到00559E24,记下eax中的值x,或按照上面的方法计算出这个值;
2. x除以31,用余数查表"0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ",所得字符作为第31位;
3. 第2步的商除以31,用余数查表,作为第30位;
4. 第3步的商查表,作为第29位。
--摘自 moon 帮主的文章


写如下Delphi 的小程序计算最后3位注册码。

代码:
procedure TForm1.Button3Click(Sender: TObject); const     Str = '0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ'; var     x1, x2: Integer;     S1, S2: String; begin     x2 := StrToInt(Edit1.Text);     x1 := x2 mod 31;     S1 := Copy(Str, x1 + 1, 1);     x1 := (x2 div 31) mod 31;     S2 := Copy(Str, x1 + 1, 1);     S1 := S2 + S1;     x1 := (x2 div 31) div 31;     S2 := Copy(Str, x1 + 1, 1);     Edit2.Text := S2 + S1; end;


在 Edit1 中输入 11322,按 Button3 键,在 Edit2 中给出结果 T8B

现在我们将获得最终的注册号:
1234567890123456 789012 34567 8 901
0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B

用前面的小程序调位后得新注册码:
1234567890123456789012345678901
MVB0MYAH026A1SDCAEDD8IBHBBMMTB8

在我的机器上,注册号为 MVB0MYAH026A1SDCAEDD8IBHBBMMTB8 ,用未脱壳的原版注册后所有功能完全正常,公司后缀的分析类似,有兴趣的朋友可以自己试。

另外,对于Delphi的小程序,什么版本都可以,但编译开关 Huge String 要勾上,我使用的是 Delphi 7。

说明:

1、对于调位操作,字符串长度必须是 31 位(不算空格),可以带空格输入,这样比较方便直接拷贝,如可以直接输入:
 "0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B"
2、对于计算最后的第 29~31 位,可以直接输入十六进制数,不过要加 '$' 前缀,例如在我们这个例子中,可以直接输入 $2C3A (不分大小写)。

  • 标 题: 答复
  • 作 者:gzgzlxg
  • 时 间:2005-11-29 20:33

说明:这样得到的注册号其实对过去几个版本如 v3.34、v3.35、v3.36都是实用的,但现在除了v3.37,其余的版本都无法使用了,原因是同益起名每一版都有时间限制,过了期限,就不能运行了,另外专业版的算法差不多,但两者不通用,只是差不多。专业版也有日期限制,比如vp3.33的有效期就在今年年底,明年就不能使用了。除非你爆破,将日期限制去掉(很容易,两分钟搞定)