正确获得同益起名大师v337 的注册号――解读 moon 帮主的妙文6 s8 u& u2 o, z N `: [
【作者】gzgzlxg
|0 z! B) W$ r9 |0 U7 I【声明】只是好奇,没有别的目的,如有,我就把注册机发表了(已经写好了),不要发信向我要注册机,我不会发表的,这也是看雪老大的要求,其实我觉得这篇文章已经很过分。按这篇文章,你100%可以得到正确的注册码。
" O \# W1 b( _' E) C* ^/ ?【工具】IDA,OllyDBG
( A( H: L+ I( h) J& A【软件】使用我在【ACProtect 1.41 -- 同益起名大师 v3.36、v3.37、vp3.33(专业版)完美脱壳】中所完美脱壳后的 GoodName.Exe v3.37版。使用脱壳版,跟踪比较容易,当然你也可以直接使用原版,但会困难一些。
: k2 W6 l# N) O `http://bbs.pediy.com/showthread. ... &threadid=16204
' @. B8 o8 M) g0 v \% g【注】读此文前,请先读 moon 帮主的【谜----同益起名大师3.36注册算法分析】,7 h1 _, |) `5 w% `* x) [
http://bbs.pediy.com/showthread. ... &threadid=14716 凡是和moon 相同的部分我就不再多废笔墨。
$ u0 E* r' a$ {: [! x8 e本文同时发表在看雪论坛和DFCG,转载时请保持完整,版主如果觉得不合适可以删除。
- Q' R: |+ R6 _+ [$ p前言:
) Y; T) q9 S0 Q5 s' m同益起名的注册码验证遍布全程序,在主窗体建立,子窗口建立,按键操作,对注册码和注册申请码的验证无所不在,而且计算方法来回重复,例如获取注册申请码就有三个完全相同的过程,DES 算法也有完整的两套。我们用来分析注册码取的是注册操作部分,其实在主窗口建立、子窗口建立的过程中都可以进行,因为他们是完全相同的。
: F3 `* O7 P) C- g这是注册窗口(Tfxhm)VMT表中的方法表部分,(全表太长)。这些代码都是在 IDA 中分析得到的。
, u2 Y( S/ `1 O0 I复制内容到剪贴板
) O3 z" W* d% E R, N代码:......8 w1 ^/ B1 z$ M& }3 |$ P
0055647F TfxhmMethodTable dw 6
0 [' J* O2 {6 Y1 E$ v+ _* V: j00556481 dw 16h( |) Z4 W; S" j, y
00556483 dd offset Tfxhm@suiButton2Click ;退出按键
; }1 n$ Q, P$ ^2 M( V8 u5 `& |00556487 aSuibutton2click db 0Fh,'suiButton2Click'# S) ^' Z8 G8 g y" r3 [$ Q
00556497 dw 10h, H% T/ @* \9 r0 H( @
00556499 dd offset Tfxhm@FormClose ;关闭窗口
' q" p. u, [( M$ `0055649D aFormclose_0 db 9,'FormClose'
; x+ ^" P9 B0 M3 x, Q, O4 a! w005564A7 dw 11h
( S+ D5 u& z+ Q, n: x9 |005564A9 dd offset Tfxhm@FormCreate ;建立窗口2 y* z- u$ n6 k! z4 k* M9 Z
005564AD aFormcreate_0 db 0Ah
: B5 Y; `# g& f2 i% P005564AD db 'FormCreate'
% N5 m- m' c0 p4 a, Q- ^005564B8 dw 16h
+ k; M8 K+ z- a6 _4 L6 _# Z* V005564BA dd offset Tfxhm@suiButton1Click ;注册按键& h. _4 ~3 z% H* k7 L+ E- H
005564BE aSuibutton1cli ck db 0Fh,'suiButton1Click'( F6 @1 p0 G. V* U F }
005564CE dw 0Fh X i; h- c4 }- v! w0 G/ s
005564D0 dd offset Tfxhm@get_text ;suiButton1Click 调用的校验注册申请码6 s4 T/ m' `7 E- |+ j& D' K1 j0 F! \
;和注册码并注册的子过程
; ~/ j. c+ D$ ~5 Y005564D4 aGet_text db 8,'get_text'/ U, Q' [/ r6 _/ ^/ Y
005564DD dw 0Fh
! z, W# p8 z1 H7 M005564DF dd offset Tfxhm@FormShow ;显示窗口: w& l! S/ E, J3 h
005564E3 aFormshow_0 db 8,'FormShow'3 c$ q1 O0 d3 J0 D) w
005564EC Tfxhm db 5,'Tfxhm' ;类名; O: V% Y# `/ d5 } ~
005564F2 word_5564F2 dw 5
* G2 {* H. |+ O6 R+ {005564F4 dd offset TsuiForm@VMT@Prt ;父辈 TsuiForm 的 VMT 表指针地址4 V: `& ]5 |$ l9 @$ s( g0 Q
......我们分析的所有代码都是属于 Tfxhm@get_text 过程和它的子过程的。 Tfxhm@get_text 起始地址: 0055986C: x" b- N+ @4 \- F, G0 D& l6 D) {( T
一、 获取注册码第28位
0 B0 M" [ k3 N, D* y% x确定你想注册姓氏的正确笔划数(必须和同益数据库中 slzik 所查到的相同,以繁体字笔画数为准,同益库中有些字的笔画数并不正确,这时你可以在同益起名的姓名分析中获得姓氏的笔画数)。在下面的字符串中从左到右查寻,得到第 28 位注册码:例如,吕:繁体字为 7 划。(从0开始数)
. d5 }' ^+ W, _2 V" T# U$ n0123456 7 89012345678901234567890
$ c& V: ?5 U8 S& U1 U0AH6CD3 B EF4TRS2PUV5K1MN78YZ9GIJ6 b& h. m5 h/ p6 a' J
得到的字母为 B,这样我们的注册码有如下形式:(31 位)下面是我们的起始注册码
& m s v- `2 I123456789012345678901234567 8 901
3 q4 Y5 G6 ]6 Y7 Y4 _- z123456789ABCDEFGHIJKLMNOPQR S TUV
, h+ A; L- Q% C加入第 28 个字母 B,得如下注册码:: } D, ~, Y- J0 w5 V1 o
123456789ABCDEFGHIJKLMNOPQR B TUV
% j- t8 |" J, n& [ F# | ~根据 moon 提出的换位法(4*i+1位和4*(i+1)位互换,i=0,1,2,...,末尾不足4位时,最后两位互换),2528位对调,这个B应该在第25 位
% c* v, l$ x* ?5 v7 D: z. s为了便于调位,写了几句Delphi的小程序来完成:(这种操作,还是汇编容易,所以实际还是汇编写的)
/ B" `( Z& O- W/ u, F复制内容到剪贴板
% @- X: e' Z' b p, S代码:procedure TForm1.Button2Click(Sender: TObject);
& H+ e2 B# F, Evar
5 {7 W8 t. d9 X; E/ Y' c% `' P. M Str: String;
, d# O- _. p9 k- Jbegin
3 X$ T5 x2 L4 [9 S1 }' o- b0 O$ N Str := Edit1.Text;6 d0 s8 r; Z" G" p' G" r5 R6 Q& ~
asm" `& g9 _+ _3 g) E* M
PushA
. U! `1 g# O/ D' ^) \5 B Xor Edx, Edx: ], A X+ h/ ~- D) l. E$ K7 r
Mov Esi, Str8 N0 j& H; O" i% w) q8 X3 L
Mov Ecx, 7
- \- A) m& k: q @1:$ l9 o% ^1 D- A* j. r
Mov Al, [Esi + Edx]7 B' C3 T! C8 O2 i$ P
Xchg Al, [Esi + Edx + 3]( N& M' q+ c, K" r! y: [ y
Xchg Al, [Esi + Edx]7 f. c1 v0 s ^ b3 E+ r3 i1 i
Dec Ecx
, p# y0 w! i% D5 N! n Add Edx, 4
5 j6 W3 H# L" _, } Cmp Ecx, 0
4 W% U0 m/ H! @4 W. G6 B Jnz @1
. I" F, v2 y/ N! A4 Q. w Mov Al, [Esi + Edx + 1]
3 Q; h* _# _' t* d4 w Xchg Al, [Esi + Edx + 2]
3 P+ v4 t" a8 _6 @* b. [ Xchg Al, [Esi + Edx + 1]* X" N1 ^% S* `9 r) i# c' i1 y
PopA
" D6 ?$ B! ]; u6 n' F end;
- X; @/ y, o, o7 N: { Edit2.Text := Str;
/ E. m& S" V" k: Q. x( z8 Pend;在 Edit1 中输入 123456789ABCDEFGHIJKLMNOPQRBTUV,按 Button2 键得到下面的新注册码:. q$ x, i4 f, B1 r) J+ {& u
新注册码为:
: ~0 y8 S. d" z' h123456789012345678901234 5 678901
& U: e3 V- L! f6 D42318675CAB9GEFDKIJHOMNL B QRPTVU7 z, Z) B8 l9 v$ R& h
具体分析请看 moon 的解释。
$ m& Q; B9 o* o6 g; M+ v二、 获取注册码 23~27 位注册码5 Y( z3 z- \$ `
用OD载如 UNGDN.exe (脱壳后的程序)
6 K Z$ o6 R8 {2 y! z5 D复制内容到剪贴板
9 j( a- \5 ?8 B& j代码:Tfxhm@get_text+ _9 Q, Q" D8 {$ o) m# _+ S
......3 |0 J. V$ f& y& m' m
......: \6 X5 e$ C3 w+ X1 l
0055CF7E mov eax, ds:AppIDAndName_CryHex@Prt ;注册申请号加姓氏和1FH 异或得到的结果9 r$ _/ d7 S8 d* |' ?
0055CF83 mov eax, [eax]
: A3 x" y: q' R' ?0055CF85 call sub_4FED88 ;EncodeFunction1
* V2 L# M' d- u2 f. d5 F6 ]7 U! D0055CF8A lea eax, [ebp+var_94] ;这里断下获取计算23-27位的三个字符
, ]2 H/ A) d! L' K: ]. U& p) \0055CF8A ;按照 moon帮主的给出的算法可以获得/ X: l- G. e; x' R% i* a
0055CF90 pus eax
* Z* E0 Q/ i5 V6 M! j8 ?0055CF91 lea edx, [ebp+var_98]
3 s( ?) u9 { J1 j0055CF97 mov eax, ds:Serial_CryHex@Prt ;注册号和 1FH 异或得到的结果
k4 l2 h) {& w4 j+ e- @# C& h* s0055CF9C mov eax, [eax]
0 L( ^: K) _! ]( I3 W& H7 O' N+ m0055CF9E call CycleConversionStr ;经过 1FH 异或,即还原9 N/ P6 o1 \4 ~( i$ J; t
0055CFA3 mov eax, [ebp+var_98] t4 P; U6 M' U, E, P" n# W
0055CFA9 mov ecx, 5; V' i' ?5 s; } U" d
0055CFAE mov edx, 17h6 C3 [: A0 b E& z
0055CFB3 call LStrCopy ;取第 23~27位
8 O+ @ ]. y: c0055CFB8 mov eax, [ebp+var_94]
( h3 D# y A4 w1 q4 X# h0 ~6 s0055CFBE lea edx, [ebp+var_90]
1 d" D) l" E& P, O0 A" _0055CFC4 call sub_4F0048 ;进行计算得到三个字符,如果和上面计算得到的三个字符相同,则过) Z) c- q. X, J3 Z
0055CFC9 mov edx, [ebp+var_90] Q- L* T3 W8 K1 D4 L
0055CFCF mov eax, [ebp+var_C]4 {8 j3 H5 Q6 p! q" g) ? L9 b
0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符
% D: i1 O5 ^; @$ j$ B0055CFD7 jnz loc_55D1575 o. [: \' G( }
0055CFDD lea eax, [ebp+var_A0]* @5 i6 v5 f8 u& g( \
0055CFE3 push eax
/ R! F) j2 I8 ^* g( p+ h0055CFE4 lea edx, [ebp+var_A4]
2 ?* ^' J0 ? L8 C" e0055CFEA mov eax, ds:Serial_CryHex@Prt
* `( s5 Q0 b, `1 r0 e! Z0055CFEF mov eax, [eax]
J* h G# }8 N- D0 \0055CFF1 call CycleConversionStr
1 B1 M4 I1 R: h7 h' `. T0055CFF6 mov eax, [ebp+var_A4]$ Z" ]* |/ Z6 ?8 L- [9 J
0055CFFC mov ecx, 5! U- q$ @) \! U3 B8 f% |% g- W/ f
0055D001 mov edx, 17h ;取注册号23~27" ]/ c: Q2 j1 t4 } R
0055D006 call LStrCopy
/ [$ O, a3 B+ }4 i; [0055D00B mov eax, [ebp+var_A0]
, y, o- n; F3 }% P: t" q# W& ~0055D011 lea edx, [ebp+var_9C]
- d9 m% `* p h3 |; j/ K+ C9 _* G; V0055D017 call sub_4F00484 R) U6 a' b1 D1 j$ y( }! q
0055D01C mov edx, [ebp+var_9C]
* k1 u2 M @! J+ W0055D022 mov eax, [ebp+var_C] i8 ^$ Z; H1 A( X
0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同
; r' g# b" b% y8 g* p+ k1 a0055D02A jnz loc_55D0EA8 a% q9 ]3 x& ~+ K; X! ^
0055D030 lea eax, [ebp+var_A8]
" S5 h! \# T0 x; T1 k* i6 C0055D036 push eax. C) A3 V7 k% a v2 @
0055D037 lea edx, [ebp+var_AC]! @% O4 f7 \7 m) ?) ]: k- |
0055D03D mov eax, ds:Serial_CryHex@Prt3 R- q: A# a5 j9 ~% `* t
0055D042 mov eax, [eax]8 i* {! k9 a0 Q" p# q
0055D044 call CycleConversionStr. P$ \% `$ y+ W3 i* |# K; W
0055D049 mov eax, [ebp+var_AC]- d( U0 Z# o5 ?0 a( v, Z
0055D04F mov ecx, 3
- c6 e* N% J5 T) y, K0055D054 mov edx, 1Dh ;取注册号 29~31 位
z7 v# n& r* q0055D059 call LStrCopy2 ^! \4 M) J5 F9 e$ |9 w
0055D05E mov eax, [ebp+var_A8]
% B1 c0 L& s7 d/ c0055D064 call 31decimalToHex ;对29~31位注册码进行31进制到十六进制的转换
% C4 c( r. f/ [1 W. c0055D069 mov ebx, eax5 e0 V4 E) L* G; A, I) u' J
0055D06B lea eax, [ebp+var_B0]' |) p# w$ P3 G! I' G
0055D071 push eax% K# w+ d/ v5 U; o5 n+ }
0055D072 lea edx, [ebp+var_B4]' L$ O1 g; m. Y Y! K0 ~, H- ]- d
0055D078 mov eax, ds:Serial_CryHex@Prt ;取注册号(经过1FH异或处理)
" q/ v% u& f- A6 |( U3 J0055D07D mov eax, [eax]: Z V, a1 X6 Q
0055D07F call CycleConversionStr ;经过相同的过程还原
) P7 k! c5 M) ], I, G# `0055D084 mov eax, [ebp+var_B4]
& q5 j5 V7 N# s) j1 R% C& |0055D08A mov ecx, 1Ch
- W' V( D$ q; g9 a+ y' q" s; b0055D08F mov edx, 1 ;取注册号 1~28 位. z1 M* }1 n9 G/ ?3 }$ y
0055D094 call LStrCopy( v! O8 r, y0 Z. D
0055D099 mov eax, [ebp+var_B0]9 y) W2 e `; _5 o
0055D09F call SumSerial_1to28 ;做 1~28 位累加(中间还有判断是否大于27000,见moon帮主的解释)
2 l/ N/ D+ {$ v0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点
- H7 M) a, J3 |5 X0 F0 [5 h L' J- @0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉
# x" `, U9 @0 x" s! z# P0055D0AC mov eax, offset a111_2 ; "111"0 U9 r" F, c7 @) }6 n9 \* {& a
0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口- q0 t' e+ a, Z: U1 t
0055D0B6 mov [ebp+var_1], al
" T' E- @5 z- K$ x! ~! {0055D0B9 cmp [ebp+var_1], 09 u5 W2 ~7 I0 A7 O) E. ?0 e3 e+ }) k
0055D0BD jz short loc_55D0CC
y" l! m) @) R2 h$ D6 T0055D0BF lea eax, [ebp+var_C]- F, P; K- @: q* V
0055D0C2 mov edx, offset a111_2 ;"111"7 T6 b- I+ E5 c1 `& ?4 C. S
0055D0C7 call LStrLAsg! S3 B* G% Z8 Q5 H E3 A& @4 w
0055D0CC
6 j' i$ d! h( _/ q0055D0CC loc_55D0CC:
7 Y) X6 A- _$ g' t8 a% Z, ^# D0055D0CC cmp [ebp+var_1], 0
' a( O n. Z' e0055D0D0 jz loc_55D157- @2 F: K! d7 H, w# x
0055D0D6 mov eax, [ebp+var_C]
1 b- A" E" b2 b# s0055D0D9 mov edx, offset a111_2 ;"111"2 b* Q; e6 a$ ^
0055D0DE call LStrCmp2 c% J$ J( v# M7 s7 A3 B
0055D0E3 jnz short loc_55D0EA* o' o6 g3 r) d3 `% N! M) }
0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口在0055CF8A 处下断点,F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',注册申请码是不能修改的,由你的机器的 CPU 和硬盘的参数变化而来。在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的 123456789ABCDEFGHIJKLMNOBWRSTUV 注册码拷贝到输入窗口。按【注册】键,中断在 0055CF8A ,清除断点(或关闭),由 [ebp - c] 中的内容,得到三个字符 VRB,记录下这三个字符,用moon帮主给出的方法:
" w" `7 C- w% i% ? Q8 ]/ j# {1 ], z% J! [: n
求逆方法:
% ^! ~4 g1 c$ D5 E0 y+ a, w1. 执行到00559D0A,然后下:d [ebp-c],记下数据区显示的正确值x,y,z;
2 B' ]+ s6 w/ U- Z; m) Y" \, X2 n2. 对3个字节的正确值进行调位,得到5个字节a,b,c,d,e,调位方法为:
8 V3 H; [% Q4 \2 b0,0,0,x7,x6,x5,x4,x34 t2 y0 G/ {: E
0,0,0,x2,x1,x0,y5,y4
$ H& Y; u9 y' Y0,0,0,0 ,y3,y2,y1,y0* F- c% V0 m" L$ f
0,0,0,y7,y6,z7,z6,z5
6 y. W: u( Q% n: ~0,0,0,z4,z3,z2,z1,z0
5 K- Z# S( {+ c5 H' q( V: r# R3. 根据5个字节查表"0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX",得到5位注册码即为23~27位。
0 w5 e4 B$ ^; V" u- ?9 v--摘自 moon 帮主文7 d) Y' z; ~' F: D
: g z, C, B( g' r8 `4 [' j+ ~6 I
我用Delphi写了几句小程序完成这个转换,程序如下:
% r, j# I* j. K, M$ x4 W/ y; Z复制内容到剪贴板 c, C+ P9 V& M! m
代码:procedure TForm1.Button1Click(Sender: TObject);
! ?' N o% H( ?+ w( S& O$ tconst6 ^+ x j b0 ` E# c7 q& b
Str = '0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX';3 a/ `' a6 B! M; `$ [
var' W* N" B8 l5 L; [1 X+ t2 w! ~/ J
X1, X2: Integer;
. U1 c! s m C) _* D1 @ x, y, z: Char;# n* O5 N3 h" C, O. n0 o8 s0 I
a, b, c, d, e: string;
% N2 E& c9 H1 M Pin: string;' P& i$ K; T: ^* `) Q5 ^* {& D
begin
9 N n m& S; M0 } Pin := Edit1.Text;, K0 ], [, W' Z- ^/ O& Q W
x := Pin[1];: n3 x) ~' O/ n g9 s B8 A+ o
y := Pin[2];
& p$ z: @7 u; G* |; a z := Pin[3];
! q8 d. G" L5 w) y3 [4 A0 V. m# | x1 := (Byte(x) shr 3) and $1F;
; A, E+ g+ W2 ]4 J7 O( H3 ] a := Copy(Str, x1 + 1, 1);$ z0 U2 ~2 U) W0 m. K6 _
x1 := ((Byte(x) shl 2) and $1C) or ((Byte(y) shr 4) and $03);0 E+ L b1 g$ d/ R/ [ p
b := Copy(Str, x1 + 1, 1);/ E& y5 }! v: S6 N9 d" i M
x1 := Byte(y) and $0F;3 G$ z. [6 o E: ^
c := Copy(Str, x1 + 1, 1);/ @0 l& [* p. f4 l
x1 := ((Byte(y) shr 3) and $18) + ((Byte(z) shr 5) and $07);
# r5 O5 y3 w2 I& t* { d := Copy(Str, x1 + 1, 1);" C6 D0 M& d" l
x1 := (Byte(z) and $1F);# K8 L2 L* d& \. v, ^0 {
e := Copy(Str, x1 + 1, 1);
! I. A# N" ^* Z) b4 H4 G Edit2.Text := a + b + c + d + e;6 ?+ Z1 U. m1 M/ K
end;在 Edit1 输入 VRB 按 Button1 键,在 Edit2 窗口中给出我们要的结果 B8MBM 。现在来继续完善我们的注册码。将得到的字符串替换原注册码中第 23~27 位:' t; Q* n6 |# U* x: _% ]( J; t
1234567890123456789012 34567 8 901
$ q" c- f x+ g7 K+ k123456789ABCDEFGHIJKLM B8MBM B TUV8 u" u& h1 }; _ ^+ ~
用前面的小程序进行调位,得新注册码如下:
/ W* B9 ~, d7 Y& f$ {1234567890123456789012345678901% C# [% f+ z/ \4 o3 f
42318675CAB9GEFDKIJH8MBLBBMMTVU
3 N7 I3 J0 \% G三、 获得的 17~22 位注册码:
! T' J5 F) b# p7 K在OD中按 Ctrl-F2组合键,重新运行程序,将 0055D0A6 的 jnz loc_55D157 Nop 掉 1 z9 `6 C; X9 a) Q4 n
复制内容到剪贴板
8 Z! Q i* q; R, G: m; v$ |代码:0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉
, o k4 w! X' `+ @- x4 D; z" X0055D0AC mov eax, offset a111_2 ;"111"
8 c9 E& l! J3 h# U' @0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口
, |+ f' Z3 d& ?) O0 [6 O跟进 0055D0B1 call CheckSerial_17to22& x: h! [) ^6 {2 [* @
......% X' _- c9 P+ T2 O! ?$ }' K: s' e5 N
...... 省略
* [7 v* q. E3 R3 r- L0050C705 mov edx, [ebp+var_20]
. x& o( B; e+ M' W! A0050C708 mov eax, [ebp+var_1C]1 K$ U$ G, b% o; L
0050C70B call DES_EncryStr ;在这里进行 DES 的 EncryStr 加密运算,运算结果再经过8 P' ?% @. d) O
0050C70B ;另一过程处理,这个子过程我们后面还要用到
. {0 {* C; [ S% y0050C710 mov edx, [ebp+var_60] ;moon 文中提到在这个位置获取 17~22 位注册码,可能; r W7 ^$ N1 i- ?8 ~6 E
0050C710 ;是帮主写文章时粗心了,正确的位置应该在下面删除第5位
# ]4 p! } W1 j B: K0050C710 ;相同字母后才取结果。, z" D! g0 z4 {. C
0050C713 lea eax, [ebp+var_20]+ Z( \, E4 `5 ^6 R$ t6 k
0050C716 call LStrLAsg4 @* u( N: F. Z% i( J
0050C71B lea ecx, [ebp+var_64]
# y1 V6 ^9 a" o7 M" } m9 ~0 P0050C71E mov eax, [ebp+var_20]
; e% X- n6 [7 U4 h0 L3 N# |$ H0050C721 mov dl, [eax+5] ;取出 EncryStr 运算结果的字符串的第 5 位
$ y- R2 R; e3 f( r) ?$ s3 t: C0050C724 mov eax, [ebp+var_20]
. t4 [8 z9 N' c* [1 i1 `% _0050C727 call DelChr ;将 EncryStr 运算结果中凡是和第5位相同的字母删除
$ q# s+ F; C9 N0 d( y0050C72C mov edx, [ebp+var_64]% G U. D: n5 O1 b# [9 U, d
0050C72F lea eax, [ebp+var_20] ;这里下断点,从Edx中取前6位,即我们要的第 17-22 位
, e3 y( T) p) |4 R }, h/ ?$ r......
- W& C% R) a% t. ?2 |/ ]......省略在 0050C72C 处下断点,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDKIJH8MBLBBMMTVU)拷贝过去。点击【注册】按键。中断在 0050C72F,在Edx 返回一个长度为30的字符串(这个字符串的长度是不一定为30的,要看删除相同字符的数目而定),取前 6 为,即为我们要的注册码的第 17~22位,在我们的例子中得到的字符串是:DEDAHI。现在我们来修改我们的注册码:4 W) `: K% Q" T) L1 M
1234567890123456 789012 34567 8 901+ r0 m( r9 q' p) o |
123456789ABCDEFG DEDAHI B8MBM B TUV
2 t6 `0 S( |( \7 @用前面的小程序调位后得新注册码:: K; _$ z- `2 B$ N' l
1234567890123456789012345678901
$ s! z; C8 B5 k; L, P6 X2 O$ l42318675CAB9GEFDAEDD8IBHBBMMTVU
# ~4 |' a5 \, D6 @9 X {四、 获取 1~16 位注册码) ]* H( J' b# ?; o5 ? Z
我们首先来看看程序的代码,从前面列出的程序最后一句:
2 p) Z( `. h) d' Y6 N复制内容到剪贴板
! ~8 C& U3 U8 B. U代码:0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口. g1 v7 ~% z0 [ Z- u% P$ v e7 L
跟进 call CheckSerial_1to16* o& P* ^% R& w0 U. [6 O" y+ a
......3 W( K* M+ y% }5 e3 z. I
......省略
! x/ \5 S% @8 J0 p, t) z6 G1 Z00508EEB lea edx, [ebp+var_18]
" f) P5 a0 V3 F3 e( n00508EEE mov eax, ds:AppIDAndName_CryHex@Prt
/ t4 e. L! C0 w6 E00508EF3 mov eax, [eax]$ `" l4 t8 h6 |3 v
00508EF5 call ConversionHex10To16. `' A* B+ z+ u9 a9 O ?0 C
00508EFA lea eax, [ebp+var_18]5 H; ?1 G9 }- N
00508EFD lea edx, [ebp+var_8]' {4 a9 x- |% s' i9 ~' Q" e% c o6 y
00508F00 call ConversionHexAndFNameToStr* q2 y! F8 s+ I. \# n
00508F05 lea eax, [ebp+var_20]; r- p% C: O$ C1 C5 c# o% U
00508F08 push eax& M* F5 m' s% ]6 E
00508F09 lea edx, [ebp+var_24]
& a& ^- |. L7 L) Z; _3 z00508F0C mov eax, ds:Serial_CryHex@Prt
/ G1 @3 h: L7 L00508F11 mov eax, [eax]! C* T/ A ^ n8 I, Q. m
00508F13 call CycleConversionStr
- _, k5 T5 ~2 x00508F18 mov eax, [ebp+var_24]
3 H6 O4 @8 m, {( S6 N+ Y00508F1B mov ecx, 10h
0 X$ {) m2 E3 ?( m U00508F20 mov edx, 1 ;取注册号 1~16 位
v3 P+ {; t0 C6 [$ A1 g0 A1 w! h* O00508F25 call LStrCopy# R, W# g) ~+ _
00508F2A mov eax, [ebp+var_20]3 Y& _$ {, g' ]9 E" J, c) e
00508F2D lea ecx, [ebp+var_1C]
9 C0 I0 [2 g# L00508F30 mov edx, [ebp+var_8]5 \& ^5 C8 U' ?9 k% N
00508F33 call DES_DecryStr ;这是 DES 的逆运算,我们再跟进
. l, h% D/ v5 s1 ~00508F38 mov eax, [ebp+var_1C]
$ K" K7 T) d! x& n$ A5 T6 ?00508F3B lea edx, [ebp+var_18]
, ^) b& J( W; T" n V00508F3E call ConversionHex10To165 v8 F6 q1 V: z+ h
00508F43 lea eax, [ebp+var_18]
( G( {* n5 u% Y6 n. l00508F46 push eax* D/ a' D% ], P1 T$ B; _2 k
00508F47 lea edx, [ebp+var_38]( E" \5 s) A# C2 P+ L
00508F4A mov eax, ds:AppIDAndName_CryHex@Prt2 n/ t* @" p8 p% d" u, {7 l& i( c
00508F4F mov eax, [eax]6 g/ u' _9 Q( j+ Q
00508F51 call sub_4FBA70! `$ q8 o! C, o+ F) X e% u3 X
00508F56 mov eax, [ebp+var_38]
; w8 G7 |1 O& c1 ?2 v* B0 _00508F59 lea edx, [ebp+var_34] ;这里是我们要下断点的地方+ J s& d z( K' U( {# O: }5 j1 G& K
......- c9 F. E& K; p! n1 p. Z
...... 省略
5 F! Y, ~- [& x }1 `& }6 k1 J5 E跟进 call DES_DecryStr
- I* M. L7 |6 T9 n; I4 F......0 v% O" D6 q5 J& k, i4 g
......省略8 f: D& e" d( H0 @% e/ z
004F788E lea edx, [ebp+var_C]
1 F' R* m. W+ |( w' b004F7891 mov eax, [ebp+var_4]
8 |9 e4 D3 Z, t004F7894 call sub_4E97BC
" L! D8 H, k3 s! S0 ]& C1 I004F7899 mov ecx, ebx I/ W# u- ^/ H
004F789B mov edx, [ebp+var_8]
$ h \8 U: h/ k! Q, h+ t004F789E mov eax, [ebp+var_C]& ]5 t/ j$ E$ [9 ]3 b/ \) a8 V
004F78A1 call DecryStr ;DES 逆运算
2 Z3 {( n8 e z! a004F78A6 xor eax, eax ;这里是 moon 帮主提出下断点处,还有一些其他相应的做法
" {9 ?& F: d5 S. ]* X ;请看 moon 原文。
* _/ |: }- N& v% N, } J......
/ z8 d" Z4 x, H( T2 |3 O8 v0 G# \......省略在OD中按 Ctrl-F2,重新启动,在00508F59下断点,同上,将 0055D0A6 的 jnz loc_55D157 Nop 掉,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 00508F59,下面是堆栈内容:
8 W& Z" ^8 i$ f复制内容到剪贴板
+ P* i0 e& Y: w5 v8 {+ M+ T5 D: Y代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"
1 N0 S" F; E0 I0 }0 yEBP-34 0012F914 00000000
$ P0 l+ E1 s/ q) }, @: i( y$ ^& J6 dEBP-30 0012F918 00000000* M( M: s' Z3 J. V5 O, k- a: ^
EBP-2C 0012F91C 00000000
/ L# f0 H. U1 T/ ` OEBP-28 0012F920 00000000/ e8 {2 M6 y* b& o- q- x4 V" h
EBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"
0 i/ A$ c6 x& h/ P/ g0 P+ AEBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"
) h6 S/ G5 z) o8 W. bEBP-1C 0012F92C 00F3009C2 o: Z8 \+ A% w' f
EBP-18 0012F930 C338FAD3
+ m1 m9 T# E( ^5 S7 }6 dEBP-14 0012F934 DD5CB3D0
; c3 g, T; |8 g0 S7 {EBP-10 0012F938 D5D42656
, C. R1 z3 @+ @- `EBP-C 0012F93C A2BB6C94: V: Q; \+ V+ x# H: F9 ~" R9 g* w
EBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"
, j3 m* P( y+ |: @& WEBP-4 0012F944 00000000注意: EBP-38 0 00F2A130 ASCII "5FF51115" 这是我们要的 DES 加密的明文。
" m, G5 ?9 e. o; K2 c, Y# ^ EBP-8 0> 00F2FFE4 ASCII "M9BJBBRIDE88TNP4" 这是 Key。
0 l' @# f& N) @1 U8 f按 moon 帮主的方法,修改两句代码,进行逆运算,但我经过努力,总是没有成功,可能是对 moon 的方法不能深刻的理解,于是决定改用其他的方法。我们注意到如下代码: # l0 L% A: `$ q) v; m; f
复制内容到剪贴板
K n1 y& }5 Q2 i- j4 W# h* X代码:004F788E lea edx, [ebp+var_C]
& o3 N3 a3 O3 m$ P" L) h8 e) q004F7891 mov eax, [ebp+var_4]. a& A( r! y: C: `
004F7894 call sub_4E97BC
7 x; ?% D v# G x" F: }- |! J1 V004F7899 mov ecx, ebx" M1 ]0 a8 f+ M" P+ l$ L
004F789B mov edx, [ebp+var_8]
) @0 J) K# g$ e. i' {& B& } o004F789E mov eax, [ebp+var_C]
7 E6 M0 c6 c) F3 B# }. N- h6 t# P004F78A1 call DecryStr ;DES 逆运算在最后一句 Call DecryStr 做的其实是DES的逆运算,前面还有一个辅助的运算,我认为,同益的代码中一定有一个DES的正向运算,即EncryStr,所以我找了一下,其实就在上面第三节--【获得的 17~22 位注册码】中出现过,下面我们跟进这个Call: ! T6 Y+ s- r7 ~' A' X8 B
复制内容到剪贴板 " j8 w2 Y. n% X! d: h( ~
代码:0050C70B call DES_EncryStr
8 z; I; _. G3 k, j$ K# k0 c7 |跟进) O. D; c. u- X
......3 _8 w! b4 e/ X$ z. o# W4 h4 p
......省略4 b- B: C% k+ V
004F781A lea ecx, [ebp+var_C] ; 返回地址 R4 I( S7 `% w3 g
004F781D mov edx, [ebp+var_8] ; Key = M9BJBBRIDE88TNP4
, A' k; J [9 P, @! ~& X0 E2 G$ @004F7820 mov eax, [ebp+var_4] ; Str = 5FF51115
( d8 y, y' V9 v4 o# K4 f5 V004F7823 call EncryStr# g. z! `: v m9 b8 {" H
004F7828 mov edx, ebx0 [$ X' b, Z% h9 v+ b( S
004F782A mov eax, [ebp+var_C]
9 J; _ J! L3 E004F782D call sub_4E63F42 \) a/ N9 J7 b* Z
004F7832 xor eax, eax ;这里下断点
+ n/ m0 J& S. L1 h2 ?....../ K) Y! l; n/ V8 |2 o; n- b, J
......省略可以看出,它和上面的代码正好相反,我们用下面的方法来获得 1~16 位的代码。' C7 i( F% C: Q: |7 y; z( @) b" ]- f
接前面,我们中断在
2 @+ X$ T/ Y+ j3 e* y4 X复制内容到剪贴板 # [( e; E" F+ e/ B# z
代码:00508F59 lea edx, [ebp+var_34]在代码窗口中按 Ctrl-G,输入004F781A,转移到 004F781A。按 Ctrl-*,将Eip地址改到 004F781A。9 ?! B+ |" F) \0 ], `! n
我们要做的工作其实就是修改堆栈的地址,下面是具体操作。
) C8 p1 ]1 i2 o" _/ C6 C9 n复制内容到剪贴板
4 }! o0 D3 i/ H; f代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115", e* ~/ G4 @- Q
EBP-34 0012F914 000000002 t" |7 \1 v2 N* O9 v
EBP-30 0012F918 00000000
! X' f' e- T+ I m' tEBP-2C 0012F91C 00000000
$ g4 M2 w- `; g R+ A8 o2 IEBP-28 0012F920 00000000
& A9 c4 L/ B) q- E5 FEBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"; \* A" g! o3 r& G a6 r) y E) y6 c
EBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG" a) {% |5 n) W- {4 {! i& A8 z7 T" K
EBP-1C 0012F92C 00F3009C! I7 v& L- ?9 K0 N4 w5 t. f
EBP-18 0012F930 C338FAD3
& R$ G0 z( S$ c- s. X6 [/ G* D( ~EBP-14 0012F934 DD5CB3D0
) L8 c$ m, i z% jEBP-10 0012F938 D5D42656
5 f& }" L/ P7 J4 f/ Q w0 TEBP-C 0012F93C A2BB6C94 结果返回地址,这里改为 0,程序运行时会自行分配新的内存
* P) L% x+ c: l% tEBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"
, |2 ]0 b7 G- e6 w* dEBP-4 0012F944 00000000 这里是 Str 所以将这里改为 00F303D0,也就是[EBP-38] 指向的地址。另外,最终返回结果在 Ebx 中,而Ebx 是由上一级的过程传递过来的参数,已经由入口程序做过初始化,所以,必须分配一个有效的返回地址,这点和 [EBP-C] 不同,需要要注意,这里我们将 [EBP-24] 的堆栈地址分配给 Ebx, 也就是Ebx = 0012F924
" B9 _& k7 I0 a2 @# K& B0 \, F改完后堆栈如下:
5 `8 r/ C" ^) U; ^( i5 b, B复制内容到剪贴板 - V3 s- j' g1 s. U4 W
代码:EBP-C 0> 00000000
' t, A5 r. T2 r* ]2 Q4 ?% p! pEBP-8 0> 00F2FFF8 ASCII "M9BJBBRIDE88TNP4" Key
' _6 B! s& `' R* M( K$ u; GEBP-4 0> 00F303D0 ASCII "5FF51115" Str
1 L: l( U j6 B4 K% Q在将 Ebx 的内容改为 EBP-24 的堆栈地址,即 Ebx = 0012F924 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"在 004F7832 下断点,F9 运行,d [Ebx], [Ebx] =0VBMHYAMA260CSD1 第 1~16 位的注册码
: u$ ?+ t( y& L3 |! _+ l% H现在我们来修改我们的注册码:
1 F; ?4 `' n1 x8 l/ g& Z1234567890123456 789012 34567 8 901# b% {4 u9 L5 u" o
0VBMHYAMA260CSD1 DEDAHI B8MBM B TUV
2 J# ^) ?1 _+ Q4 ?" b2 v# |用前面的小程序调位后得新注册码:% Z o J) J; X7 R" F5 x+ r
12345678901234567890123456789011 w! C+ L0 a; u' U! ?
MVB0MYAH026A1SDCAEDD8IBHBBMMTVU6 ~0 l: Z2 M5 x$ M. L/ G( Z
五、 获取最后 29~31 位注册码% \$ N/ p# h. \5 _
打开注册表编辑器:将Serial中的内容清除:4 L4 M X0 S. `
[HKEY_LOCAL_MACHINE\SOFTWARE\GoodSoft\GoodName]! Q2 |2 t& J3 l0 T+ X
"Appid"=dword:059c0935
" o: @* N; F& F4 }"Serial"="MVB0MYAH026A1SDCAEDD8IBHBBMMTVU"' r* q3 v4 j, {" y V$ m
"Serial"="0"
1 A8 J, @) L# p3 ~) y0 ^. ~在OD 中按 Ctrl-F2 重新启动,将下面两处 Nop 掉。 7 { L& n2 w3 L0 [& K0 ]$ D+ z% w
复制内容到剪贴板
2 ^& r& O; _2 e8 V代码:0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符( q0 K, D$ t, K7 F: _0 `/ q4 O# D
0055CFD7 jnz loc_55D157 ;Nop 这里& T- |& T' h) Q8 f/ C: I
0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同
3 w! h) P( I- N0055D02A jnz loc_55D0EA ;Nop这里
I: V% x# N l: b0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点在上面 0055D0A4 处下断点,F9运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(MVB0MYAH026A1SDCAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 0055D0A4,记录下Eax寄存器的内容,我这里是 2C3AH,换算成十进制数为 11322
' }# t" }! j$ S根据 moon 帮主的文章:
2 J) d; Q g( O$ x# u; t: F3 z0 L
9 @) o7 a) S b) v% F8 ^求逆方法:* M* e4 ~4 n6 S4 d( d7 l
1. 执行到00559E24,记下eax中的值x,或按照上面的方法计算出这个值;1 k" D% b3 a+ Q5 d# x! G6 w1 ?
2. x除以31,用余数查表"0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ",所得字符作为第31位;% t0 r& S- u2 T( ?+ U0 E
3. 第2步的商除以31,用余数查表,作为第30位;/ ~; s! t# o8 w- _, H
4. 第3步的商查表,作为第29位。, i# G5 O6 I* C5 w
--摘自 moon 帮主的文章
' V, r7 B9 B) W, g
5 r- [/ Q; a7 Y写如下Delphi 的小程序计算最后3位注册码。 ' L. Q2 H% @6 G! R! m
复制内容到剪贴板
: \/ i2 m1 }. {9 V1 j5 Z& W代码:procedure TForm1.Button3Click(Sender: TObject);
. j& V' b) v& N( C( kconst) t1 `) e2 ]! n* O9 K& I4 A5 F; ^3 P" m0 m
Str = '0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ';9 `+ e8 \0 F' f" J ^
var
! _& d: s/ E7 A+ k! n x1, x2: Integer;
: `2 F, E, {! Q S1, S2: String;3 n6 N6 ~' M; k. w6 ^; D/ g
begin0 Q; j7 P- }1 E4 L% s- W
x2 := StrToInt(Edit1.Text);, n* K2 D/ `: x$ f1 A) L( C
x1 := x2 mod 31;. @1 M d; h" e9 ~; ~2 L
S1 := Copy(Str, x1 + 1, 1);* w, g C) t! s& [
x1 := (x2 div 31) mod 31;8 u: L% D' R- @# [4 k0 k) y
S2 := Copy(Str, x1 + 1, 1);8 C$ A* R2 F3 Z/ x4 V
S1 := S2 + S1;
' k2 _& V! m' j/ o# O; l x1 := (x2 div 31) div 31;9 W. ~( B$ N) z' ]
S2 := Copy(Str, x1 + 1, 1);/ i0 B; }9 x( }. l: c4 L! W/ m
Edit2.Text := S2 + S1;
- {% b* L' _ j/ W) Pend;在 Edit1 中输入 11322,按 Button3 键,在 Edit2 中给出结果 T8B
0 i5 W0 u5 A: L( e, o+ \/ V现在我们将获得最终的注册号:7 t8 k& Z. a6 K4 F
1234567890123456 789012 34567 8 9019 C+ P! k' C$ ` g$ d
0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B
. K9 X. G- u6 ^2 p) I用前面的小程序调位后得新注册码:
2 `/ E H) Y' r- O5 {1 [7 U4 T) A1234567890123456789012345678901
4 ]7 q; ?1 R* e& N- AMVB0MYAH026A1SDCAEDD8IBHBBMMTB8
" ~8 j' E! m# z* h9 Y. U在我的机器上,注册号为 MVB0MYAH026A1SDCAEDD8IBHBBMMTB8 ,用未脱壳的原版注册后所有功能完全正常,公司后缀的分析类似,有兴趣的朋友可以自己试。
" _& X6 j( W/ e2 Q- J8 R2 V* l另外,对于Delphi的小程序,什么版本都可以,但编译开关 Huge String 要勾上,我使用的是 Delphi 7。 P& {8 [( h/ \) _& d0 \" i
说明:
) R$ g+ h; B- ~0 R w. n' x- O8 j) S: [8 b. j/ e) C
1、对于调位操作,字符串长度必须是 31 位(不算空格),可以带空格输入,这样比较方便直接拷贝,如可以直接输入:
2 a: D- }! _( `- d. \$ R0 n"0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B"
: x- M: u* D) J" ?- D/ j: b9 B2、对于计算最后的第 29~31 位,可以直接输入十六进制数,不过要加 '$' 前缀,例如在我们这个例子中,可以直接输入 $2C3A (不分大小写)。; h5 \8 r( M7 {. [4 _
|