正确获得同益起名大师v337 的注册号――解读 moon 帮主的妙文
5 {/ t. w& L( j9 |8 q d U4 [8 m【作者】gzgzlxg& ~( S8 V. k1 u. @8 Q7 |0 Y
【声明】只是好奇,没有别的目的,如有,我就把注册机发表了(已经写好了),不要发信向我要注册机,我不会发表的,这也是看雪老大的要求,其实我觉得这篇文章已经很过分。按这篇文章,你100%可以得到正确的注册码。8 g7 }/ `6 t7 C! G
【工具】IDA,OllyDBG9 u) t# a: p3 G. q/ y0 h
【软件】使用我在【ACProtect 1.41 -- 同益起名大师 v3.36、v3.37、vp3.33(专业版)完美脱壳】中所完美脱壳后的 GoodName.Exe v3.37版。使用脱壳版,跟踪比较容易,当然你也可以直接使用原版,但会困难一些。
0 ^3 h X0 G. C8 _( H- `http://bbs.pediy.com/showthread. ... &threadid=16204
' f0 t0 C+ ]8 N, P$ G& w% i, M! C Q. b【注】读此文前,请先读 moon 帮主的【谜----同益起名大师3.36注册算法分析】,+ P8 K6 O+ c q$ c
http://bbs.pediy.com/showthread. ... &threadid=14716 凡是和moon 相同的部分我就不再多废笔墨。
# X+ P9 R) t( I5 ]本文同时发表在看雪论坛和DFCG,转载时请保持完整,版主如果觉得不合适可以删除。
+ n% m! u% W! m6 [$ b# F! h" t9 y前言:
+ N- H# C; c6 K: g; B+ N% L同益起名的注册码验证遍布全程序,在主窗体建立,子窗口建立,按键操作,对注册码和注册申请码的验证无所不在,而且计算方法来回重复,例如获取注册申请码就有三个完全相同的过程,DES 算法也有完整的两套。我们用来分析注册码取的是注册操作部分,其实在主窗口建立、子窗口建立的过程中都可以进行,因为他们是完全相同的。
& R- y1 G2 I! w" q2 N这是注册窗口(Tfxhm)VMT表中的方法表部分,(全表太长)。这些代码都是在 IDA 中分析得到的。
, S, T7 R2 P5 b4 M- o( n复制内容到剪贴板 4 }' y7 G1 h4 O
代码:......
0 F; L0 r5 x, W I1 m0055647F TfxhmMethodTable dw 6
# K% P+ G+ H; Q4 W00556481 dw 16h( Q5 N) F6 P8 ^* f: p0 L Z% W
00556483 dd offset Tfxhm@suiButton2Click ;退出按键
' H! p/ q# ?/ [7 x- ?00556487 aSuibutton2click db 0Fh,'suiButton2Click'
( K- |! x4 J- C7 V0 \' h$ Z00556497 dw 10h5 r% f' Y u: l7 v# z) i" M6 P
00556499 dd offset Tfxhm@FormClose ;关闭窗口" a( j4 B: }7 m& i
0055649D aFormclose_0 db 9,'FormClose'& s4 v7 t- l/ b) Z% A+ N& |" v
005564A7 dw 11h
5 v* [# i& h6 D005564A9 dd offset Tfxhm@FormCreate ;建立窗口
, f2 P1 y: t& w6 |2 E- ~005564AD aFormcreate_0 db 0Ah' W' O# @, W+ K5 o7 F* i' I
005564AD db 'FormCreate'# T: V2 Y( c `2 ?% B6 N6 m( B" C" g
005564B8 dw 16h
0 C" K! v9 C: F' E005564BA dd offset Tfxhm@suiButton1Click ;注册按键2 G6 Y0 r6 j0 }$ Z- r
005564BE aSuibutton1cli ck db 0Fh,'suiButton1Click'
3 Q, [1 a4 f9 K* W$ p005564CE dw 0Fh
1 [+ F! M2 K" z5 l005564D0 dd offset Tfxhm@get_text ;suiButton1Click 调用的校验注册申请码$ `" s7 G( I; Q# B7 f, E2 |
;和注册码并注册的子过程
! \1 [8 v" x( q9 \) K4 f005564D4 aGet_text db 8,'get_text'
) t6 W2 m# M3 ]1 h005564DD dw 0Fh; p- n2 P2 `* x" V% m
005564DF dd offset Tfxhm@FormShow ;显示窗口
0 C1 g! V2 o4 O; Z0 o, n2 m005564E3 aFormshow_0 db 8,'FormShow'
: e" L0 R; w0 D005564EC Tfxhm db 5,'Tfxhm' ;类名
( \" i' d4 C9 k005564F2 word_5564F2 dw 5
0 y v' O" p& M% z005564F4 dd offset TsuiForm@VMT@Prt ;父辈 TsuiForm 的 VMT 表指针地址/ c$ ^8 |/ {) e1 E
......我们分析的所有代码都是属于 Tfxhm@get_text 过程和它的子过程的。 Tfxhm@get_text 起始地址: 0055986C
! V6 q3 S- V$ K$ d一、 获取注册码第28位5 F; S* S$ k+ }7 u e f! z
确定你想注册姓氏的正确笔划数(必须和同益数据库中 slzik 所查到的相同,以繁体字笔画数为准,同益库中有些字的笔画数并不正确,这时你可以在同益起名的姓名分析中获得姓氏的笔画数)。在下面的字符串中从左到右查寻,得到第 28 位注册码:例如,吕:繁体字为 7 划。(从0开始数); q! U5 L5 g h: ?+ O
0123456 7 89012345678901234567890
* x) s0 B$ {& _# s: c- G# m) u0AH6CD3 B EF4TRS2PUV5K1MN78YZ9GIJ- ~3 R( u9 }# b( R
得到的字母为 B,这样我们的注册码有如下形式:(31 位)下面是我们的起始注册码
( P9 U7 P% q& n0 V, |; `5 c0 ^- n123456789012345678901234567 8 901
7 K" b8 ~+ d; {123456789ABCDEFGHIJKLMNOPQR S TUV+ C4 m8 H% m) G
加入第 28 个字母 B,得如下注册码:6 O0 s1 v/ h* `/ X3 l" e7 m% S W
123456789ABCDEFGHIJKLMNOPQR B TUV1 r) O6 {2 g# P; r" I
根据 moon 提出的换位法(4*i+1位和4*(i+1)位互换,i=0,1,2,...,末尾不足4位时,最后两位互换),2528位对调,这个B应该在第25 位$ _0 \: G8 T# ]( I1 b4 ?' n+ v8 \
为了便于调位,写了几句Delphi的小程序来完成:(这种操作,还是汇编容易,所以实际还是汇编写的) 0 H, i+ l" ~9 ]4 ?3 I' p+ i: g
复制内容到剪贴板 : n$ r' d6 Z, n
代码:procedure TForm1.Button2Click(Sender: TObject);
! l1 `. S: N& ^1 {* G" lvar }/ _& t, [: J2 a; s' P2 M4 r7 l
Str: String;( A; S( r( O" h @, M: f( D; e
begin4 D5 z g f1 w Q, ?
Str := Edit1.Text;9 ]; i3 K3 U0 L, V
asm
; C0 k+ }$ n- r# C, R PushA
9 _$ _% _4 k$ x! I- O5 i Xor Edx, Edx
, K+ L9 Y2 ]0 D Mov Esi, Str
6 h1 f7 r6 N; v1 y/ P Mov Ecx, 7
/ O9 O& H/ w) p1 e8 {: F" W @1:% U' _* x/ J8 f
Mov Al, [Esi + Edx]
; H' d! d$ x+ F& W9 { Xchg Al, [Esi + Edx + 3]
. L) Q* u' P( O8 S9 q. }& l" D3 g Xchg Al, [Esi + Edx]
; C4 X# D9 J% Y Dec Ecx
& [$ B5 i7 U( s( M: | Add Edx, 45 w/ R2 N% G; A% W# H5 D& w1 b
Cmp Ecx, 0
' a3 g* B, M- p- A Jnz @1
$ l& `3 n3 x! V8 D% @4 w6 f- ], } Mov Al, [Esi + Edx + 1]3 `; Q6 p. J8 D
Xchg Al, [Esi + Edx + 2]; m0 z1 C, o9 k+ M. Y$ e; C
Xchg Al, [Esi + Edx + 1]0 v7 r D. D" v6 M
PopA
, f0 `3 j& S# c2 N0 [ end;
$ A! W& Z, A( a6 [5 w8 Z* f Edit2.Text := Str;
$ w! M( Y. v# B1 R3 H2 Mend;在 Edit1 中输入 123456789ABCDEFGHIJKLMNOPQRBTUV,按 Button2 键得到下面的新注册码:( f h. ^0 k+ [
新注册码为:
" B9 W g* w/ `123456789012345678901234 5 678901! A; c0 i# _( d. C0 g
42318675CAB9GEFDKIJHOMNL B QRPTVU9 I& a& L0 |6 {8 f9 q1 P6 u
具体分析请看 moon 的解释。4 ]1 M6 y4 }5 s( ~8 Z% l/ R
二、 获取注册码 23~27 位注册码
6 x5 l8 I! r8 S用OD载如 UNGDN.exe (脱壳后的程序)
) C& g: d* \4 P7 `* h. V5 _复制内容到剪贴板 ; [$ V# @9 N0 ^! p% B( m
代码:Tfxhm@get_text4 n+ h- J, I- `# q8 o- ~) y) F
......
, r9 w( ~3 s& Y K* I3 Q4 E......
. [( ?' Z+ d/ v: j) z: Q0055CF7E mov eax, ds:AppIDAndName_CryHex@Prt ;注册申请号加姓氏和1FH 异或得到的结果
" H& W( e9 K6 G, z0055CF83 mov eax, [eax]8 f7 U$ g9 O( d8 }( R0 P* N: f
0055CF85 call sub_4FED88 ;EncodeFunction1
/ V( L# Q2 {6 c/ O) r9 n0 l0055CF8A lea eax, [ebp+var_94] ;这里断下获取计算23-27位的三个字符! z2 Z; r/ B0 Q# y- J- X
0055CF8A ;按照 moon帮主的给出的算法可以获得$ U# B) `( s1 T( ^9 Z* l
0055CF90 pus eax: n1 U" A, c5 u4 u
0055CF91 lea edx, [ebp+var_98]7 d# R% y0 B! H. Q/ N" i
0055CF97 mov eax, ds:Serial_CryHex@Prt ;注册号和 1FH 异或得到的结果/ ?" \& B% A5 p# e
0055CF9C mov eax, [eax]6 l9 c5 f( \- _. h6 ^8 ]/ W
0055CF9E call CycleConversionStr ;经过 1FH 异或,即还原6 E c5 g- s7 @! ^6 P$ Z# E* A
0055CFA3 mov eax, [ebp+var_98]2 ^/ _6 Q. O% A
0055CFA9 mov ecx, 5
j0 n+ k7 E6 b2 K0055CFAE mov edx, 17h
2 @8 e( y/ T. ^- N' c0055CFB3 call LStrCopy ;取第 23~27位
3 i' m6 A/ s4 D# j0055CFB8 mov eax, [ebp+var_94]3 q; B0 f- x. w/ Z+ ?
0055CFBE lea edx, [ebp+var_90]" s, c# B) d& i# {! c
0055CFC4 call sub_4F0048 ;进行计算得到三个字符,如果和上面计算得到的三个字符相同,则过
/ q& o+ F. q9 h: Q" A# Q/ I0055CFC9 mov edx, [ebp+var_90]: C! c# ^! n7 n8 n- I
0055CFCF mov eax, [ebp+var_C]
. D' i/ b0 p) {. }1 V4 F0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符
# B6 G. u% K! ?3 {2 E/ c0 Q3 @0055CFD7 jnz loc_55D157: i5 u! i8 [5 N
0055CFDD lea eax, [ebp+var_A0]
9 C4 F% J& q) W( U( S4 J; m, E: I0055CFE3 push eax, L7 k; @2 g5 \
0055CFE4 lea edx, [ebp+var_A4]
9 L. J! l6 n6 O- c$ A9 C0055CFEA mov eax, ds:Serial_CryHex@Prt' c( y# t2 R- h
0055CFEF mov eax, [eax]
! c" e# t* b% T; p0 B8 f3 ?: |0055CFF1 call CycleConversionStr- t' J3 i- V( g" _. c
0055CFF6 mov eax, [ebp+var_A4]
5 ?$ C7 a, [' C" P3 T+ z0055CFFC mov ecx, 5- `) H6 C9 z* N" ~& L
0055D001 mov edx, 17h ;取注册号23~27
2 B0 b4 _3 B" O3 H. n/ N' L9 V0055D006 call LStrCopy: ]$ i& _/ _* _
0055D00B mov eax, [ebp+var_A0]1 ~8 b5 [3 x. F' Z
0055D011 lea edx, [ebp+var_9C]
: F: G! u+ W6 k3 [% [0055D017 call sub_4F0048
! | [! u# Z! C/ p0055D01C mov edx, [ebp+var_9C]! }+ O' Q% B5 l0 ]6 X
0055D022 mov eax, [ebp+var_C]4 f h2 ?' q& U0 S5 b5 ]
0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同' _; q g/ J: t' x
0055D02A jnz loc_55D0EA7 h2 S& F: V! ]- {/ ^# Q
0055D030 lea eax, [ebp+var_A8]
/ Z+ ^! u% w8 n% ~0055D036 push eax5 v9 T5 [' f* [2 S! E
0055D037 lea edx, [ebp+var_AC]
) e0 |& S3 d# \0055D03D mov eax, ds:Serial_CryHex@Prt; Z& _( G4 f3 c2 F0 P
0055D042 mov eax, [eax]
$ s/ ]$ D5 |/ H* q% W: Z0055D044 call CycleConversionStr
5 s) Q, C1 d* K. M0055D049 mov eax, [ebp+var_AC]
, o8 n" f9 f# \9 z& Y0055D04F mov ecx, 3- |5 N9 S: q; e$ [2 T8 y
0055D054 mov edx, 1Dh ;取注册号 29~31 位* k0 k ]" V5 P# a6 \$ t" ?
0055D059 call LStrCopy8 e2 ^* `& j( l
0055D05E mov eax, [ebp+var_A8]: f1 Y6 T2 p. r" @: i, V
0055D064 call 31decimalToHex ;对29~31位注册码进行31进制到十六进制的转换' l- D9 V/ p' g) W$ L6 p
0055D069 mov ebx, eax
3 ~6 s. X) Q7 w0055D06B lea eax, [ebp+var_B0]
' e0 e$ j- M3 h% J% ]1 t3 p0055D071 push eax
9 R9 \) v1 q8 z) E/ V$ N; f/ e0055D072 lea edx, [ebp+var_B4]9 o& Q w* G3 j; N7 N: H
0055D078 mov eax, ds:Serial_CryHex@Prt ;取注册号(经过1FH异或处理)
: ]; I& b1 _* {" k+ E0055D07D mov eax, [eax]
/ J9 S& l" P9 x- f V% ?$ z0055D07F call CycleConversionStr ;经过相同的过程还原* ]/ Q, U" V- _" t, _, s( h
0055D084 mov eax, [ebp+var_B4]
* a9 I& _" ^: l0055D08A mov ecx, 1Ch
+ v" [# a7 ?* _: b1 B0055D08F mov edx, 1 ;取注册号 1~28 位; E: Q% N( w: B1 C, e9 x6 Y
0055D094 call LStrCopy
4 d' o' J, \% R3 h% t7 U3 V/ T* `' X2 q0055D099 mov eax, [ebp+var_B0]
! Q& o+ j2 E7 M/ t0055D09F call SumSerial_1to28 ;做 1~28 位累加(中间还有判断是否大于27000,见moon帮主的解释)
6 f2 m5 V1 v. }* X0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点' E$ {% D! y- k3 Q$ H- H
0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉
+ J5 ?: J4 P# j; `0055D0AC mov eax, offset a111_2 ; "111"
2 o0 s: K; U1 C \) A0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口4 y$ s. k- H0 o$ F6 G3 V
0055D0B6 mov [ebp+var_1], al* [3 _' \+ L ~1 ]0 X
0055D0B9 cmp [ebp+var_1], 0
! c2 D4 }4 n; q: C% I8 }0055D0BD jz short loc_55D0CC* n! o2 o z" ~0 w/ J
0055D0BF lea eax, [ebp+var_C]' Q$ H# q, K# H E" `+ a8 i
0055D0C2 mov edx, offset a111_2 ;"111"$ \/ Z& p4 @( V& v& @0 e
0055D0C7 call LStrLAsg: H! B& L9 B/ Y0 f5 y
0055D0CC
9 C: v+ O& u' X0055D0CC loc_55D0CC:
& a; V3 }% B' P7 Y, Q0055D0CC cmp [ebp+var_1], 0
/ E8 L& s+ x# j0055D0D0 jz loc_55D157
, V4 T5 l. o) a% ]. }0 r0055D0D6 mov eax, [ebp+var_C]+ b" p" y" W. V
0055D0D9 mov edx, offset a111_2 ;"111"
7 P S" ~& a7 a: f+ d$ T' X% k0055D0DE call LStrCmp6 M7 Q3 N- p6 e" h% E+ X
0055D0E3 jnz short loc_55D0EA$ g+ W" x* a7 G [) l# U
0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口在0055CF8A 处下断点,F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',注册申请码是不能修改的,由你的机器的 CPU 和硬盘的参数变化而来。在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的 123456789ABCDEFGHIJKLMNOBWRSTUV 注册码拷贝到输入窗口。按【注册】键,中断在 0055CF8A ,清除断点(或关闭),由 [ebp - c] 中的内容,得到三个字符 VRB,记录下这三个字符,用moon帮主给出的方法:
: A- }5 t. d8 Z$ c+ e
$ Z) D) G# c0 e0 V( o求逆方法:
& I, k- Z, B- _1. 执行到00559D0A,然后下:d [ebp-c],记下数据区显示的正确值x,y,z;1 s3 m3 r; F' Y
2. 对3个字节的正确值进行调位,得到5个字节a,b,c,d,e,调位方法为:
; l# B- Q2 F* A. s* H0,0,0,x7,x6,x5,x4,x3) Q# V+ I h5 r# d& A9 m
0,0,0,x2,x1,x0,y5,y4) U& V V0 a' t% P' I7 k7 L2 V
0,0,0,0 ,y3,y2,y1,y0
# v5 m: S. q; D0,0,0,y7,y6,z7,z6,z58 `3 R0 l! g( |1 Q6 {$ C: [
0,0,0,z4,z3,z2,z1,z0
, c1 H i. E$ R4 k+ k: C# o3. 根据5个字节查表"0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX",得到5位注册码即为23~27位。
" l3 M" d @3 W7 t--摘自 moon 帮主文
- { d, a- ^7 M, ^8 t) t
" E% _, b. ?& ~7 L% w我用Delphi写了几句小程序完成这个转换,程序如下: 2 b* X" @# z$ Z
复制内容到剪贴板
1 N. `' i( a8 @: ]2 b2 ~. i代码:procedure TForm1.Button1Click(Sender: TObject);
6 i2 @: `6 p$ H8 pconst/ j* P/ O7 j# \+ X! M
Str = '0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX';
$ ?; B0 V6 m7 Q) i8 W1 Bvar( s. E. @' h, b
X1, X2: Integer;! Z. r( z+ b; I" P( A3 z6 [
x, y, z: Char;
, I. M( J0 Q* W. a! ~- B a, b, c, d, e: string;; w& W5 A) G2 W: i! M
Pin: string;
9 l+ e3 H- F/ nbegin
p. k) h8 R3 ^5 U$ k Pin := Edit1.Text;$ d+ a. z* Z# l' p
x := Pin[1];4 F6 J% j8 X @ D' {# ~: U
y := Pin[2]; L( q2 ]' S# L9 g
z := Pin[3];
( J4 V9 h+ A+ G- o% Q( j/ \ z+ Y x1 := (Byte(x) shr 3) and $1F;
) |& f9 @+ H2 I7 j! f a := Copy(Str, x1 + 1, 1);: _, X) a. z9 f5 r2 E1 e2 z: o: P& ^
x1 := ((Byte(x) shl 2) and $1C) or ((Byte(y) shr 4) and $03);; F7 n0 s4 A+ T* E, S
b := Copy(Str, x1 + 1, 1);
$ l1 L/ K" K& b Y x1 := Byte(y) and $0F;
! _; l3 E! g+ H. a( ] c := Copy(Str, x1 + 1, 1);! j- Q, f7 [5 s2 B( K1 p2 ?% V9 b8 L
x1 := ((Byte(y) shr 3) and $18) + ((Byte(z) shr 5) and $07);
6 l* K# W( M6 r9 C" A" U* P d := Copy(Str, x1 + 1, 1);% z# S" B3 K" |- D8 U% r, e- O
x1 := (Byte(z) and $1F);; c5 n i9 f6 h. C$ Z
e := Copy(Str, x1 + 1, 1);
9 _. X: `1 n9 m" p Edit2.Text := a + b + c + d + e;
5 \& X. H" {- S9 W7 f+ u( Jend;在 Edit1 输入 VRB 按 Button1 键,在 Edit2 窗口中给出我们要的结果 B8MBM 。现在来继续完善我们的注册码。将得到的字符串替换原注册码中第 23~27 位:
& Z6 k' F2 y( x- z) b' F, ~1234567890123456789012 34567 8 901
; c8 h5 o1 J" W/ g" o A123456789ABCDEFGHIJKLM B8MBM B TUV
& y3 ?1 N9 E6 h* |! g0 ?3 u, y用前面的小程序进行调位,得新注册码如下:' C' Z/ K7 j# v
1234567890123456789012345678901& k1 L- M) g: w A+ k. I; F, O& } w
42318675CAB9GEFDKIJH8MBLBBMMTVU
3 }* R) F8 f$ n5 u三、 获得的 17~22 位注册码:
) j2 x: w- J# i, W4 s2 n在OD中按 Ctrl-F2组合键,重新运行程序,将 0055D0A6 的 jnz loc_55D157 Nop 掉 ; U: L% p9 J9 I. A T
复制内容到剪贴板
! F1 }4 g n s代码:0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉
$ a$ n' e; F; R$ D4 z) [8 G0055D0AC mov eax, offset a111_2 ;"111"- `6 [$ q$ A) k" N
0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口
, h( a- Y* V" | R; i, w跟进 0055D0B1 call CheckSerial_17to22* Q/ g5 n& L1 S) f- s2 \+ d6 u% i
......, E, T# o$ }1 A" D- `% Z( W
...... 省略8 k: R: c; T1 K% M% Z% `" P
0050C705 mov edx, [ebp+var_20]
# \1 q; J' R% i. O0050C708 mov eax, [ebp+var_1C]
' F! M1 w% n" d0 d7 ]" A' i0050C70B call DES_EncryStr ;在这里进行 DES 的 EncryStr 加密运算,运算结果再经过2 A+ ^- l" D5 n+ ^3 |3 W# q
0050C70B ;另一过程处理,这个子过程我们后面还要用到0 s1 ?' Q' d0 P* [( o8 \# E0 ~
0050C710 mov edx, [ebp+var_60] ;moon 文中提到在这个位置获取 17~22 位注册码,可能8 Z ^' p1 m- a% j! [- |
0050C710 ;是帮主写文章时粗心了,正确的位置应该在下面删除第5位0 o0 l# d" k7 x! \; O( B
0050C710 ;相同字母后才取结果。
3 L* v' E5 s3 \( q8 n2 E' |- M0050C713 lea eax, [ebp+var_20]
1 @/ V, h4 s$ k; X$ C: [% h0050C716 call LStrLAsg
4 _5 a9 p; u8 f2 B* c2 u3 D0050C71B lea ecx, [ebp+var_64]0 U* x" g& v' z1 H9 y
0050C71E mov eax, [ebp+var_20]5 P/ T* Q& ^ a5 C2 C0 Z
0050C721 mov dl, [eax+5] ;取出 EncryStr 运算结果的字符串的第 5 位
% X. L0 ^# z! t! X0050C724 mov eax, [ebp+var_20]: M7 Y3 a! T B; Q) O! s) f
0050C727 call DelChr ;将 EncryStr 运算结果中凡是和第5位相同的字母删除# _+ {& \0 q3 H5 `# E
0050C72C mov edx, [ebp+var_64]
: P0 j( H9 f# [, Y2 Q0050C72F lea eax, [ebp+var_20] ;这里下断点,从Edx中取前6位,即我们要的第 17-22 位* R" w: V8 q2 y5 V- E2 d& J* a
......9 N3 g- f2 E2 E% L( a) b
......省略在 0050C72C 处下断点,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDKIJH8MBLBBMMTVU)拷贝过去。点击【注册】按键。中断在 0050C72F,在Edx 返回一个长度为30的字符串(这个字符串的长度是不一定为30的,要看删除相同字符的数目而定),取前 6 为,即为我们要的注册码的第 17~22位,在我们的例子中得到的字符串是:DEDAHI。现在我们来修改我们的注册码:
; g1 Z2 w5 e u7 u I* c1234567890123456 789012 34567 8 901' |0 _( B, }; }6 n6 f8 L0 l. q* P
123456789ABCDEFG DEDAHI B8MBM B TUV
, t0 a& s( _! c用前面的小程序调位后得新注册码:% D# i, a8 Z$ h
1234567890123456789012345678901; P& O# u( d8 j! z
42318675CAB9GEFDAEDD8IBHBBMMTVU) P5 L1 |" w m% T0 z
四、 获取 1~16 位注册码
4 n( c, G3 k8 d. n+ t% e; A我们首先来看看程序的代码,从前面列出的程序最后一句: : m, Z' Q3 @3 |% z
复制内容到剪贴板
& j! B! S- A9 I; y4 R. H+ Z代码:0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口. ]- l$ k& Y$ j) k! i( C2 _
跟进 call CheckSerial_1to16- c+ v( V" r: y2 m
...... P* q7 V" F5 L. k6 d! _) ~4 u
......省略
4 x; c, H# _9 y( G/ G00508EEB lea edx, [ebp+var_18]
) S& o* B+ M4 y+ a' W: d' K00508EEE mov eax, ds:AppIDAndName_CryHex@Prt
" ~" t" E. g, w. {( l+ A* X00508EF3 mov eax, [eax]+ @& ]. g, p* I6 u7 p; E
00508EF5 call ConversionHex10To16" e' H% K& t+ N- [
00508EFA lea eax, [ebp+var_18]' h5 T- B. c X; k5 |& E- t" p1 Y# z
00508EFD lea edx, [ebp+var_8] K F) C* c/ ~: O2 ~' B1 ]
00508F00 call ConversionHexAndFNameToStr8 n' q6 A$ I& ^% c Q
00508F05 lea eax, [ebp+var_20]! P$ \: r( M0 ]4 k! O$ V2 u
00508F08 push eax
7 O* k, H, B$ I ~* v( Y00508F09 lea edx, [ebp+var_24]
~+ ]! |8 d2 q5 v5 H6 r, J00508F0C mov eax, ds:Serial_CryHex@Prt
: Q, @/ O* ?$ G! V, Y00508F11 mov eax, [eax]1 u5 t$ o+ I+ m$ F
00508F13 call CycleConversionStr& i& h& S- [; }' I8 S$ W
00508F18 mov eax, [ebp+var_24]
9 U& u1 Y% ~9 `& S# n# R00508F1B mov ecx, 10h8 ]% K5 ?4 E8 s' z
00508F20 mov edx, 1 ;取注册号 1~16 位- M! S/ u% ~. f) g+ f' m
00508F25 call LStrCopy
/ N# x. o) ]5 c0 E. b: f00508F2A mov eax, [ebp+var_20]/ M6 u, x5 {( p
00508F2D lea ecx, [ebp+var_1C]5 K1 t& L9 Y! O* @1 x) I& U' @+ [5 L
00508F30 mov edx, [ebp+var_8] ^+ t' I7 J- W0 W0 k+ Y9 ^; D1 z
00508F33 call DES_DecryStr ;这是 DES 的逆运算,我们再跟进
: o w/ B) u. y2 A' ?( j7 r00508F38 mov eax, [ebp+var_1C]
! D4 U- v- C* C, C* N: A00508F3B lea edx, [ebp+var_18]
2 H0 i$ m3 t9 N, ^& M+ Z/ H) j00508F3E call ConversionHex10To16
% o- r& k8 v. Q00508F43 lea eax, [ebp+var_18]
/ ^! L/ R- R. o) |$ h00508F46 push eax
1 ]5 P+ M2 f) q$ w. b* i00508F47 lea edx, [ebp+var_38]
+ z8 x1 P7 a+ T7 t00508F4A mov eax, ds:AppIDAndName_CryHex@Prt$ @+ y9 d% Z! Q, E L- I
00508F4F mov eax, [eax]
% |: \1 E0 B# E9 p4 _+ ^00508F51 call sub_4FBA70( C' Q6 h: y3 Z& A. ], l/ R
00508F56 mov eax, [ebp+var_38]7 D7 K6 L- Y# b; m- B& K+ R
00508F59 lea edx, [ebp+var_34] ;这里是我们要下断点的地方5 s# I; ~8 J7 w6 {1 [- }
......: o' Q! G- ?# r
...... 省略
, o) E& U, L( L+ I跟进 call DES_DecryStr
6 \& H$ M, O- t0 Q+ D......
" r8 F8 g, C( `; d' H......省略
+ b ~) |0 U, S0 W2 p! m9 R. R004F788E lea edx, [ebp+var_C]
0 R& z& n" H) R# `004F7891 mov eax, [ebp+var_4]. C( k q( w3 g
004F7894 call sub_4E97BC5 V- Y# U }# i9 i: b7 _7 [
004F7899 mov ecx, ebx
+ L0 ^/ O: x+ U+ e2 k1 {+ q( r004F789B mov edx, [ebp+var_8]; g" ]3 F6 u0 l1 @$ p, Y* t/ Z
004F789E mov eax, [ebp+var_C]1 n; S* }* L" w
004F78A1 call DecryStr ;DES 逆运算0 u! O$ Q% A1 h" Q& |6 n6 R6 Z
004F78A6 xor eax, eax ;这里是 moon 帮主提出下断点处,还有一些其他相应的做法
& m. J: i: { y# v: q ;请看 moon 原文。7 G, I* Z1 b; Z( q" V+ o
......
; S/ Z' X, M$ L. A......省略在OD中按 Ctrl-F2,重新启动,在00508F59下断点,同上,将 0055D0A6 的 jnz loc_55D157 Nop 掉,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 00508F59,下面是堆栈内容:
# p) @0 `+ z5 L( l8 P9 t! K6 q复制内容到剪贴板 3 c5 M( [) p" }0 k: U( q* _
代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"
% P) M6 D M' ~EBP-34 0012F914 00000000
# Y* P) X6 ]+ _EBP-30 0012F918 000000003 f. s* T ~" k& N( T
EBP-2C 0012F91C 00000000- F7 t) k4 K, P6 [; @# s& n, ^
EBP-28 0012F920 00000000
( q% q) P6 E B5 hEBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"
" f4 Q4 j& b1 M/ f! pEBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"% K, E) I3 _9 v' Z8 b0 {0 x. m+ N
EBP-1C 0012F92C 00F3009C' {8 _* @! l e
EBP-18 0012F930 C338FAD3
! x) \# {) |4 f, dEBP-14 0012F934 DD5CB3D0. L6 |2 m6 l" Z' {8 v6 X3 _* ^: J
EBP-10 0012F938 D5D42656' \! e8 q, o( ^3 E* O+ l- i
EBP-C 0012F93C A2BB6C94
; {6 J5 y1 m" R% Q ?' xEBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4": ^' E: o6 E$ K+ y7 `
EBP-4 0012F944 00000000注意: EBP-38 0 00F2A130 ASCII "5FF51115" 这是我们要的 DES 加密的明文。
% P6 [- c% t3 x$ d0 u EBP-8 0> 00F2FFE4 ASCII "M9BJBBRIDE88TNP4" 这是 Key。
4 M' M a- Q- B' `! n按 moon 帮主的方法,修改两句代码,进行逆运算,但我经过努力,总是没有成功,可能是对 moon 的方法不能深刻的理解,于是决定改用其他的方法。我们注意到如下代码:
$ p; c! u" F0 k复制内容到剪贴板
( z1 a9 } ^: O1 W! v& V( w代码:004F788E lea edx, [ebp+var_C]1 f. S" [1 p# ]5 W/ H! h
004F7891 mov eax, [ebp+var_4]" g2 F0 t) R3 w, J
004F7894 call sub_4E97BC
' E! P {: Y/ ~ {9 E; P004F7899 mov ecx, ebx
1 |. A2 G" h$ W! o& g- b004F789B mov edx, [ebp+var_8]5 @* s) e% d0 t
004F789E mov eax, [ebp+var_C]
3 V8 n7 D( x- _6 T* { r7 X! _% b004F78A1 call DecryStr ;DES 逆运算在最后一句 Call DecryStr 做的其实是DES的逆运算,前面还有一个辅助的运算,我认为,同益的代码中一定有一个DES的正向运算,即EncryStr,所以我找了一下,其实就在上面第三节--【获得的 17~22 位注册码】中出现过,下面我们跟进这个Call:
. M1 A% E( N, A7 e- g复制内容到剪贴板 1 h% _- _! R" F. S' x, w# Y5 }- \& ?
代码:0050C70B call DES_EncryStr- ?# T! D/ g* G1 k
跟进- g+ d2 `1 q% M% G) \+ K% u
......! M) b# W& n% G
......省略$ R( l8 c# _' O7 l
004F781A lea ecx, [ebp+var_C] ; 返回地址
% d4 J! v' @% o1 }* n7 P004F781D mov edx, [ebp+var_8] ; Key = M9BJBBRIDE88TNP4
?6 x5 q: h% e Q+ `5 n; }004F7820 mov eax, [ebp+var_4] ; Str = 5FF51115/ Q- t, x) U" X
004F7823 call EncryStr+ H# m: s) F+ t0 n+ C) {' S
004F7828 mov edx, ebx' k: g7 y% E; i
004F782A mov eax, [ebp+var_C]9 M$ i* r/ ~- D( K/ w3 ]8 O, a. `
004F782D call sub_4E63F4
' F: v6 C8 M2 B4 k; z: E4 a004F7832 xor eax, eax ;这里下断点$ X" o8 e" D0 I6 D, P: D8 e
......
" y) O+ U( Z9 f( T: t: h& g......省略可以看出,它和上面的代码正好相反,我们用下面的方法来获得 1~16 位的代码。
# l: Z8 D7 c9 L5 M! e8 f) s; U接前面,我们中断在 " {5 I# b# t7 X' Y# d. x+ O
复制内容到剪贴板
3 n- T- T8 N" `7 [代码:00508F59 lea edx, [ebp+var_34]在代码窗口中按 Ctrl-G,输入004F781A,转移到 004F781A。按 Ctrl-*,将Eip地址改到 004F781A。
* e! S% T) Y! X; {. Q我们要做的工作其实就是修改堆栈的地址,下面是具体操作。
- r/ s8 a4 N0 L% ?, T复制内容到剪贴板
+ H: q) x# [1 N$ q' T0 g) Y代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"
8 p; I4 x6 a' y6 AEBP-34 0012F914 00000000
+ b) C' u) h- J0 ]. rEBP-30 0012F918 00000000
: F& S1 l) \1 @4 ^0 |, E9 KEBP-2C 0012F91C 00000000
/ _0 ] N2 Z- F3 t. L+ _ `EBP-28 0012F920 000000006 G3 v* Z6 @5 x: }* W' P
EBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"* p3 k- U$ ]9 o# U E
EBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"/ r* p# R* ^- l1 _
EBP-1C 0012F92C 00F3009C( F2 n) p6 s! Z# X, W% l
EBP-18 0012F930 C338FAD3
, h. z; B% t" t3 UEBP-14 0012F934 DD5CB3D0
1 |: A) t+ f; N4 PEBP-10 0012F938 D5D42656
2 q- r0 R2 b; t8 k# P7 h/ mEBP-C 0012F93C A2BB6C94 结果返回地址,这里改为 0,程序运行时会自行分配新的内存; M) ^' o7 \+ n) e' S' Z7 y8 ?) J
EBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"/ X( V0 m8 ]4 S2 W5 l p
EBP-4 0012F944 00000000 这里是 Str 所以将这里改为 00F303D0,也就是[EBP-38] 指向的地址。另外,最终返回结果在 Ebx 中,而Ebx 是由上一级的过程传递过来的参数,已经由入口程序做过初始化,所以,必须分配一个有效的返回地址,这点和 [EBP-C] 不同,需要要注意,这里我们将 [EBP-24] 的堆栈地址分配给 Ebx, 也就是Ebx = 0012F924
1 b- o1 U. y! @- i& D改完后堆栈如下: * ^/ x8 c( {4 D
复制内容到剪贴板
i3 h# w* I6 Q/ [代码:EBP-C 0> 000000009 O( y- _: D3 S# {1 d* b' y# a5 U
EBP-8 0> 00F2FFF8 ASCII "M9BJBBRIDE88TNP4" Key
* e( t4 z4 u9 E mEBP-4 0> 00F303D0 ASCII "5FF51115" Str+ I6 i* P9 w: C) B u
在将 Ebx 的内容改为 EBP-24 的堆栈地址,即 Ebx = 0012F924 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"在 004F7832 下断点,F9 运行,d [Ebx], [Ebx] =0VBMHYAMA260CSD1 第 1~16 位的注册码8 e1 u4 m2 L& |) h0 v
现在我们来修改我们的注册码:* }/ u( g, q) M/ I8 d
1234567890123456 789012 34567 8 9011 H1 G6 ?& d/ N9 _, L6 P. }
0VBMHYAMA260CSD1 DEDAHI B8MBM B TUV
! A5 C4 f, y4 W用前面的小程序调位后得新注册码:) h2 `% Y: X1 y5 p: I
1234567890123456789012345678901
& l; G3 T" L$ y; y/ z. uMVB0MYAH026A1SDCAEDD8IBHBBMMTVU2 Z4 Z! K. ~5 e- `
五、 获取最后 29~31 位注册码; M3 B+ }$ B2 U" Q8 G( k" I
打开注册表编辑器:将Serial中的内容清除:; O* x: F) f+ D' x( B, R0 j; a
[HKEY_LOCAL_MACHINE\SOFTWARE\GoodSoft\GoodName]2 O7 Y* G/ n8 V7 n. t
"Appid"=dword:059c09352 K) X9 j( B+ b8 n& c g
"Serial"="MVB0MYAH026A1SDCAEDD8IBHBBMMTVU"8 X2 q" K3 q% R/ l$ a m1 |
"Serial"="0"
( k) R: [' ]7 J3 h, g- e在OD 中按 Ctrl-F2 重新启动,将下面两处 Nop 掉。
# m1 T, V; I% b复制内容到剪贴板 3 a. W: J2 e* [* j% R' T
代码:0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符
( x/ U/ h" \; B" L( B: L" B8 n$ ^0055CFD7 jnz loc_55D157 ;Nop 这里
7 m7 l- t' m7 d8 a0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同- ^2 X/ J8 }" j8 j( @# H
0055D02A jnz loc_55D0EA ;Nop这里5 Z: e1 h/ g& l6 H1 _# e
0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点在上面 0055D0A4 处下断点,F9运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(MVB0MYAH026A1SDCAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 0055D0A4,记录下Eax寄存器的内容,我这里是 2C3AH,换算成十进制数为 11322+ v( X: T0 h! s6 p7 @" N
根据 moon 帮主的文章:: V/ l- ]- r7 i- f
- P8 ?9 P: m3 t- O2 |, G! e9 L
求逆方法:
, {* f( r. M( O; A3 m7 M4 \' B1. 执行到00559E24,记下eax中的值x,或按照上面的方法计算出这个值;& A/ C T* @# w3 j8 T, w
2. x除以31,用余数查表"0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ",所得字符作为第31位;7 |+ ^5 h$ N7 o$ j% H
3. 第2步的商除以31,用余数查表,作为第30位;
2 z! _ ^6 `4 @9 j) V4. 第3步的商查表,作为第29位。
" Q. L, q2 o2 k( k--摘自 moon 帮主的文章
- \; n6 W! S* L
; o/ L( k1 @# L& m写如下Delphi 的小程序计算最后3位注册码。 4 O( R+ u: U8 u+ @6 p( ~& x6 A
复制内容到剪贴板
9 L, V* P. [ e- X1 S, g" k代码:procedure TForm1.Button3Click(Sender: TObject);
0 v1 N h+ B. f$ Econst" C% n" k% P3 D
Str = '0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ';
* K4 O( p: U- x# {! J3 L0 cvar& R2 b# ^( F# N4 _) a9 E% e1 r
x1, x2: Integer;
- w- `& M2 V" h5 m+ c& j S1, S2: String;
6 Q4 H' K5 B- V5 Y/ Y& c% ybegin
2 y; J3 w0 o+ q% {; y, N x2 := StrToInt(Edit1.Text);
/ u x. y+ h' j, A d' y x1 := x2 mod 31;
6 m; v; a- K5 a# J; v9 H S1 := Copy(Str, x1 + 1, 1);/ Q6 z2 x j3 t7 b9 ?+ s
x1 := (x2 div 31) mod 31;
% ?( K0 g' k) {' k! m S2 := Copy(Str, x1 + 1, 1);
# T6 @+ i1 {' g. E S1 := S2 + S1;
8 a! y& }9 t5 X7 ~" D4 A x1 := (x2 div 31) div 31;" j; }8 e9 g3 u V4 u9 [
S2 := Copy(Str, x1 + 1, 1);
7 e4 \7 L; O2 S% d, C Edit2.Text := S2 + S1;
- ^) v0 e8 a, ?/ N( @% G g( jend;在 Edit1 中输入 11322,按 Button3 键,在 Edit2 中给出结果 T8B/ O! _9 F7 {5 g, q/ U
现在我们将获得最终的注册号:) n& ?+ ~4 |6 {1 c& o) Z
1234567890123456 789012 34567 8 901% E# e( |* A8 x' z
0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B! r/ C7 m$ L, g. y& l# |/ e& j8 T8 J
用前面的小程序调位后得新注册码:; q0 [1 Z, F6 o. I
1234567890123456789012345678901
5 U8 u+ q1 M" R# T+ w) I7 Q+ s! WMVB0MYAH026A1SDCAEDD8IBHBBMMTB8
, ~& @( X* ~% O: e. l在我的机器上,注册号为 MVB0MYAH026A1SDCAEDD8IBHBBMMTB8 ,用未脱壳的原版注册后所有功能完全正常,公司后缀的分析类似,有兴趣的朋友可以自己试。 n f- t1 \/ ]/ G
另外,对于Delphi的小程序,什么版本都可以,但编译开关 Huge String 要勾上,我使用的是 Delphi 7。
9 {$ i. T& ]( R) x) R V) F说明:
( {9 |/ p6 `+ J7 _3 b
: ^- N- g# ?1 q. X1、对于调位操作,字符串长度必须是 31 位(不算空格),可以带空格输入,这样比较方便直接拷贝,如可以直接输入:
! J D7 R! m" h) ^"0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B"
. v8 W, ?0 o- d0 d' k% Y; _, j2、对于计算最后的第 29~31 位,可以直接输入十六进制数,不过要加 '$' 前缀,例如在我们这个例子中,可以直接输入 $2C3A (不分大小写)。
7 t5 u" c1 _4 W# D |