正确获得同益起名大师v337 的注册号――解读 moon 帮主的妙文
7 u8 _ m, S) l( C" l【作者】gzgzlxg2 Z, R) Y0 g: [- F2 f' R% O
【声明】只是好奇,没有别的目的,如有,我就把注册机发表了(已经写好了),不要发信向我要注册机,我不会发表的,这也是看雪老大的要求,其实我觉得这篇文章已经很过分。按这篇文章,你100%可以得到正确的注册码。
; P& B9 G, j7 F9 F( L2 Y【工具】IDA,OllyDBG
) H+ F; V. a4 ^ s; t【软件】使用我在【ACProtect 1.41 -- 同益起名大师 v3.36、v3.37、vp3.33(专业版)完美脱壳】中所完美脱壳后的 GoodName.Exe v3.37版。使用脱壳版,跟踪比较容易,当然你也可以直接使用原版,但会困难一些。
3 _0 R5 S# F7 V9 xhttp://bbs.pediy.com/showthread. ... &threadid=16204. d8 G. W6 @$ z/ c# m
【注】读此文前,请先读 moon 帮主的【谜----同益起名大师3.36注册算法分析】,) U& v7 Z$ ?9 T& F1 u+ S
http://bbs.pediy.com/showthread. ... &threadid=14716 凡是和moon 相同的部分我就不再多废笔墨。* [: R6 B7 @: T5 E5 L$ [2 H9 s$ R
本文同时发表在看雪论坛和DFCG,转载时请保持完整,版主如果觉得不合适可以删除。
2 K" d, @9 o2 a. Y* D1 L. y前言:5 S, e1 D( K* t; R$ e8 B1 S: `" D
同益起名的注册码验证遍布全程序,在主窗体建立,子窗口建立,按键操作,对注册码和注册申请码的验证无所不在,而且计算方法来回重复,例如获取注册申请码就有三个完全相同的过程,DES 算法也有完整的两套。我们用来分析注册码取的是注册操作部分,其实在主窗口建立、子窗口建立的过程中都可以进行,因为他们是完全相同的。( Z2 v* M" u" F5 j* m, V
这是注册窗口(Tfxhm)VMT表中的方法表部分,(全表太长)。这些代码都是在 IDA 中分析得到的。
/ A) y7 I0 @! T复制内容到剪贴板
" U; x+ A, M- u' R/ Q4 ~* d( M" t代码:......+ w8 y a6 e0 g
0055647F TfxhmMethodTable dw 64 C, s& s, p& `: u1 t# H4 L3 D" x( Y
00556481 dw 16h
' ~$ Q6 o, Q1 s" s00556483 dd offset Tfxhm@suiButton2Click ;退出按键: v7 X7 w. l3 A; q
00556487 aSuibutton2click db 0Fh,'suiButton2Click'- @" E; i0 i* o6 i! G3 J5 [
00556497 dw 10h
9 q: D. ]) E& n! u00556499 dd offset Tfxhm@FormClose ;关闭窗口4 J9 P2 A1 l0 v6 A
0055649D aFormclose_0 db 9,'FormClose'
8 H1 ]) t7 ?5 K005564A7 dw 11h
) z/ c) n+ R/ D$ p; I; a; p. ?* e005564A9 dd offset Tfxhm@FormCreate ;建立窗口, d/ R1 H7 `7 E/ r" a% }0 O6 r) D, w
005564AD aFormcreate_0 db 0Ah
+ a. w/ I& e% o1 A005564AD db 'FormCreate'' s3 I9 o# ]# c3 l# P
005564B8 dw 16h X: E. z. F- P& w
005564BA dd offset Tfxhm@suiButton1Click ;注册按键$ U/ }9 j& k2 N1 h9 {' p. S
005564BE aSuibutton1cli ck db 0Fh,'suiButton1Click'/ Y' u* Y7 n' b9 W) z+ g; \
005564CE dw 0Fh: q9 J! |- }& ?! [( M6 G
005564D0 dd offset Tfxhm@get_text ;suiButton1Click 调用的校验注册申请码
3 G: Z% ]( E8 u# @0 U ;和注册码并注册的子过程
6 }0 t7 W3 M3 s0 C- X3 w* F) C005564D4 aGet_text db 8,'get_text'
6 r( l) Q+ j7 \. p/ v0 f005564DD dw 0Fh7 P8 f. H2 d# z8 z3 t# z
005564DF dd offset Tfxhm@FormShow ;显示窗口6 p+ K! c" k! n. L1 x- ?8 p3 ^
005564E3 aFormshow_0 db 8,'FormShow'
$ ?8 M& O( E; x005564EC Tfxhm db 5,'Tfxhm' ;类名
; E4 _* f/ v) {4 E005564F2 word_5564F2 dw 5, b* y' ~, P' j* U
005564F4 dd offset TsuiForm@VMT@Prt ;父辈 TsuiForm 的 VMT 表指针地址% [$ n# b: N) a t$ o5 j( u1 d
......我们分析的所有代码都是属于 Tfxhm@get_text 过程和它的子过程的。 Tfxhm@get_text 起始地址: 0055986C9 Z2 P, L, m7 g# V5 W0 X
一、 获取注册码第28位
* c# U' a- x0 j/ A6 |% [确定你想注册姓氏的正确笔划数(必须和同益数据库中 slzik 所查到的相同,以繁体字笔画数为准,同益库中有些字的笔画数并不正确,这时你可以在同益起名的姓名分析中获得姓氏的笔画数)。在下面的字符串中从左到右查寻,得到第 28 位注册码:例如,吕:繁体字为 7 划。(从0开始数)
! p3 @- F) D Y* G5 \- @3 L0123456 7 89012345678901234567890
0 Z1 ]2 P. j3 t' }% `0AH6CD3 B EF4TRS2PUV5K1MN78YZ9GIJ
4 y3 U8 ?, [: ]3 F6 |% [/ F* `% ^得到的字母为 B,这样我们的注册码有如下形式:(31 位)下面是我们的起始注册码$ D; l5 a* h# ^4 O" _
123456789012345678901234567 8 901: t6 n, a `' I' D+ S
123456789ABCDEFGHIJKLMNOPQR S TUV
p9 `. _; B+ D3 H加入第 28 个字母 B,得如下注册码:, @7 m/ [: R) Z: E
123456789ABCDEFGHIJKLMNOPQR B TUV( l" p6 [4 m6 y( _7 c9 h
根据 moon 提出的换位法(4*i+1位和4*(i+1)位互换,i=0,1,2,...,末尾不足4位时,最后两位互换),2528位对调,这个B应该在第25 位
+ G1 I) P- R U s7 M为了便于调位,写了几句Delphi的小程序来完成:(这种操作,还是汇编容易,所以实际还是汇编写的) 6 Y- y! ?. p7 N$ b
复制内容到剪贴板 $ o3 _6 M# D( [! M' I8 |
代码:procedure TForm1.Button2Click(Sender: TObject);" @6 j& p" O, ?2 B: ]& t7 }( V
var
' T7 ^* G+ d9 u Str: String;* C& @6 O6 V! N, c* f: e0 t
begin
. l, i8 H- e! z- H Str := Edit1.Text;5 [- f3 a* L( Q: U8 }# \
asm
o( H% A t6 R. {+ L PushA8 y: s5 ]3 b4 Y! E0 ?1 ]- F
Xor Edx, Edx1 X$ [) N8 q5 c" X8 `6 e* {
Mov Esi, Str
* p- H1 B$ U. F t# ?* M/ N8 Y Mov Ecx, 7% R: s O2 i+ R& C) I+ o
@1:
1 P& {( ]1 h% ? Mov Al, [Esi + Edx]
" q6 f' V6 {7 ^4 ? Xchg Al, [Esi + Edx + 3]
" ?$ m* O! T9 B- J6 Y) u: U Xchg Al, [Esi + Edx]- F$ U& k! p; e0 X8 {. h* ^
Dec Ecx
2 w; y. n, k6 d# p Add Edx, 4
. i+ A1 h7 c2 l, r Cmp Ecx, 03 i3 e' n1 m! @- V7 l( j. ?
Jnz @1
/ O8 O4 F6 _# {+ U# Z Mov Al, [Esi + Edx + 1]3 D1 y1 @7 [/ ?2 R
Xchg Al, [Esi + Edx + 2], V( @4 y" d" i, z6 J3 Q7 k: E7 n& Y
Xchg Al, [Esi + Edx + 1]* e! N% L! ^4 ]
PopA2 K, s' r. l* p, L0 w- M! N
end;6 Z* f+ w& v& q: C) t7 Q' q
Edit2.Text := Str;
4 \3 r# J4 l$ A3 F7 S2 ?& C* V" cend;在 Edit1 中输入 123456789ABCDEFGHIJKLMNOPQRBTUV,按 Button2 键得到下面的新注册码:- t6 s: \1 z1 I X4 K$ a
新注册码为:4 @% I4 C1 p p* X, M( V. i" G
123456789012345678901234 5 678901. r' Y q" g8 b* `6 r/ w% M- ]. `
42318675CAB9GEFDKIJHOMNL B QRPTVU
7 D' t4 j2 \9 u% C2 m" p' @, G E具体分析请看 moon 的解释。2 V% r6 r8 p3 w, Z9 u
二、 获取注册码 23~27 位注册码, C/ ^) ~+ t) t* E
用OD载如 UNGDN.exe (脱壳后的程序)
$ e6 I, E* s- k复制内容到剪贴板
( \' d" @3 s) z# o( ?代码:Tfxhm@get_text
3 B, e( s6 J/ Z9 t......# ~. ?, x! j( e9 w
......0 J0 l r( ^ F% [- K
0055CF7E mov eax, ds:AppIDAndName_CryHex@Prt ;注册申请号加姓氏和1FH 异或得到的结果
# O9 y& u/ O0 K+ H7 e' D: i0055CF83 mov eax, [eax]
! P) u6 I3 l' B* t) j$ S+ Q0055CF85 call sub_4FED88 ;EncodeFunction1 S4 i* e% |- q* S4 R( p$ F4 U
0055CF8A lea eax, [ebp+var_94] ;这里断下获取计算23-27位的三个字符
3 X4 w5 j3 i: r0055CF8A ;按照 moon帮主的给出的算法可以获得$ d$ t" E0 n7 `5 B
0055CF90 pus eax; G' _9 {- R4 |! e* v. a
0055CF91 lea edx, [ebp+var_98]$ G4 C$ e: v% a3 @) F& k, c8 N
0055CF97 mov eax, ds:Serial_CryHex@Prt ;注册号和 1FH 异或得到的结果
) n3 H1 i: n5 i% H' X$ n0055CF9C mov eax, [eax]5 j4 R, N! d* b$ I. J
0055CF9E call CycleConversionStr ;经过 1FH 异或,即还原
8 _" w9 r2 n8 R5 e$ M( O2 d2 S0055CFA3 mov eax, [ebp+var_98]
) U( @8 n- u0 u B+ u+ S0055CFA9 mov ecx, 5
' @ I: t3 U# ]+ _ `0055CFAE mov edx, 17h
# k1 \4 v2 L! ]2 i2 j& W* Y0055CFB3 call LStrCopy ;取第 23~27位! {0 P M* [6 m: c/ ]
0055CFB8 mov eax, [ebp+var_94]
3 B4 E0 ]1 {* q1 Z9 [0055CFBE lea edx, [ebp+var_90]7 ~/ Y9 H4 p8 t9 r
0055CFC4 call sub_4F0048 ;进行计算得到三个字符,如果和上面计算得到的三个字符相同,则过
( J8 p X9 X1 S& z: S& n: v0055CFC9 mov edx, [ebp+var_90], j) }; R% I* w" c7 n0 a
0055CFCF mov eax, [ebp+var_C]
# [* n/ _/ A& ~8 ]# W6 S0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符
! x& w" q y5 q4 k8 [0055CFD7 jnz loc_55D157: Q3 v) D% F) i4 o* R- R+ _. O
0055CFDD lea eax, [ebp+var_A0]
; X3 s) `( Y* I4 p% J# y0055CFE3 push eax
6 @6 P- r! N. m5 I% l0055CFE4 lea edx, [ebp+var_A4]. C2 _' }, F9 p! z/ B
0055CFEA mov eax, ds:Serial_CryHex@Prt D2 y/ R! Z( R% [7 c& D# l4 a
0055CFEF mov eax, [eax]
5 e3 v1 L$ Z6 `. r* K0055CFF1 call CycleConversionStr- _5 s' J6 h; z# z
0055CFF6 mov eax, [ebp+var_A4]% }. p9 y% x) Q5 G
0055CFFC mov ecx, 5
5 o5 q( Q1 N* v5 T$ b, \0055D001 mov edx, 17h ;取注册号23~278 K' p9 [+ E7 u4 j" p% E$ a$ Q
0055D006 call LStrCopy
/ z& i2 r, Q/ Y7 u/ y2 s+ h0055D00B mov eax, [ebp+var_A0]
/ r) ~+ \( o5 }- I1 _' |0055D011 lea edx, [ebp+var_9C]( k1 I1 P% x }5 r, e
0055D017 call sub_4F0048+ z1 @5 ]( E/ s' F+ W( e" C
0055D01C mov edx, [ebp+var_9C]: X3 Z' y) V3 l6 N$ t8 d. Q
0055D022 mov eax, [ebp+var_C]
( y. O! N& o5 V5 Q$ k6 Z0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同
% j$ }) w8 o5 z! ]0055D02A jnz loc_55D0EA
- ]# m8 x2 V0 A/ w& `0055D030 lea eax, [ebp+var_A8]
- [' z$ L3 M& L" ?0 s; k/ y0055D036 push eax$ f4 x) Q. F# v+ v) P
0055D037 lea edx, [ebp+var_AC]
( A) T( W' y+ L M; E; R0055D03D mov eax, ds:Serial_CryHex@Prt
. Q O% e5 w, ^9 `% i: n3 W% m* W0055D042 mov eax, [eax]
+ s+ P' `+ b( ~: g+ ~0055D044 call CycleConversionStr, d2 q$ Y; P ^4 g* M4 [- }& @4 \
0055D049 mov eax, [ebp+var_AC], n# u. a; l0 U/ w
0055D04F mov ecx, 32 K( p7 G a0 T
0055D054 mov edx, 1Dh ;取注册号 29~31 位
$ p8 W+ |; s+ i6 S; {; I0055D059 call LStrCopy6 T: s& Y5 d6 L$ {
0055D05E mov eax, [ebp+var_A8]+ m0 u0 \/ D" e! e. S
0055D064 call 31decimalToHex ;对29~31位注册码进行31进制到十六进制的转换; q4 U3 G2 m* Z0 b Y
0055D069 mov ebx, eax4 l* R' u1 s- M0 l# `2 K
0055D06B lea eax, [ebp+var_B0]; [2 N; P% E N& Y4 B
0055D071 push eax$ J6 h5 O9 y. `2 Y
0055D072 lea edx, [ebp+var_B4]
0 b+ G4 e7 O5 c6 f: W/ M# g- k% e0055D078 mov eax, ds:Serial_CryHex@Prt ;取注册号(经过1FH异或处理)
) i5 v/ W7 I9 n4 p4 g3 p1 r) [0055D07D mov eax, [eax]
7 r0 E' Q: P) F- c) M0055D07F call CycleConversionStr ;经过相同的过程还原/ b5 {0 U) g" l4 Y1 m
0055D084 mov eax, [ebp+var_B4]
& m9 k5 e. g1 M: _& _. v# u7 y A0055D08A mov ecx, 1Ch
, |/ G# }) [* r8 \# D* U0055D08F mov edx, 1 ;取注册号 1~28 位1 L0 ^ u2 l$ M2 w
0055D094 call LStrCopy; Q- Q* ^, w7 W8 J, @
0055D099 mov eax, [ebp+var_B0]. ]* G6 J& g: w2 T
0055D09F call SumSerial_1to28 ;做 1~28 位累加(中间还有判断是否大于27000,见moon帮主的解释)- c& V5 Y* E( }1 |- C
0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点
- b* H- C$ S: [- u, r8 O1 E V5 \0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉
( q; \# ]2 } D0055D0AC mov eax, offset a111_2 ; "111"" g2 S* z$ k3 g% `3 @1 p5 ?- u; d
0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口
9 F* U0 _- @- p0055D0B6 mov [ebp+var_1], al
1 @4 O+ u- i1 \) `% L0055D0B9 cmp [ebp+var_1], 0
T6 _9 k7 E+ e7 v3 D' B7 {0055D0BD jz short loc_55D0CC
/ I# n7 G0 Y" G- T0055D0BF lea eax, [ebp+var_C]
# ?, Z" [( v8 n5 I: g- |3 r0055D0C2 mov edx, offset a111_2 ;"111"# w8 I3 Y) a) K5 X) J8 K
0055D0C7 call LStrLAsg
$ {: y7 t6 j# F0 f0055D0CC- {/ w, M* m( j. q
0055D0CC loc_55D0CC:# |" S9 t$ F8 l, C+ c% B# y5 g
0055D0CC cmp [ebp+var_1], 0
$ |( T) d5 a3 E* }! [7 a0055D0D0 jz loc_55D157
8 U( P4 ^. w* i) U0055D0D6 mov eax, [ebp+var_C]! F# `% i6 ?3 O: j4 {8 u: L5 V# ^
0055D0D9 mov edx, offset a111_2 ;"111"
1 ?1 w9 W0 t( k: N, f0055D0DE call LStrCmp
9 }, \4 ^+ G( \7 k/ `0055D0E3 jnz short loc_55D0EA( V! ^3 a. d/ } U0 u6 S6 Z
0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口在0055CF8A 处下断点,F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',注册申请码是不能修改的,由你的机器的 CPU 和硬盘的参数变化而来。在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的 123456789ABCDEFGHIJKLMNOBWRSTUV 注册码拷贝到输入窗口。按【注册】键,中断在 0055CF8A ,清除断点(或关闭),由 [ebp - c] 中的内容,得到三个字符 VRB,记录下这三个字符,用moon帮主给出的方法:7 y* k) ^8 h$ m* j* O
5 w: s* | W( m; r) F求逆方法:
% t1 \( u' h9 Q3 Y2 h2 [8 y( U; Q% \7 x1. 执行到00559D0A,然后下:d [ebp-c],记下数据区显示的正确值x,y,z;
1 \/ b1 t% d0 I) b2. 对3个字节的正确值进行调位,得到5个字节a,b,c,d,e,调位方法为:# m4 @ c$ M* q; o
0,0,0,x7,x6,x5,x4,x3' G! w9 K' _) f4 l8 L' v* {* z2 V
0,0,0,x2,x1,x0,y5,y4, y2 ? u+ R) P7 m b
0,0,0,0 ,y3,y2,y1,y0
9 r* x# b Z& W7 j/ J: g( l8 X( O0,0,0,y7,y6,z7,z6,z5
6 q+ ~- k) a8 i1 }0,0,0,z4,z3,z2,z1,z0
1 E; ~3 X3 ?" X3. 根据5个字节查表"0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX",得到5位注册码即为23~27位。
0 u; W1 ^0 ~5 ]% {$ b$ |' d--摘自 moon 帮主文
4 f1 V8 D( P3 q. W. s. ^
) V) x' f* M1 C& Z9 s6 h我用Delphi写了几句小程序完成这个转换,程序如下: 9 N5 U: v- ~1 d4 H
复制内容到剪贴板 . v( @% c" ]6 h5 y" ?
代码:procedure TForm1.Button1Click(Sender: TObject);2 Z9 S& r2 f1 T9 J0 ~' X& J( T3 e/ ^
const
& b( k2 L; x. |2 j Str = '0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX';/ P. ~! ]/ E' U
var
2 B: D/ J0 I5 C7 h) u9 r X1, X2: Integer;
4 N3 m8 C0 L6 @: X! { x, y, z: Char;
6 M( f5 V+ z- r' I8 y a, b, c, d, e: string;- w8 I( c! O% @
Pin: string;/ k+ o" ]( ~% Z. f3 r
begin
M p: _- P0 v+ h" Q: j& j% V& O P Pin := Edit1.Text;) A4 Q, h2 B, S$ \0 ?# |
x := Pin[1];; T$ M! h4 l3 b: b
y := Pin[2];
) S7 K: r7 D, m0 x( X z := Pin[3];- D9 H, p3 [1 B
x1 := (Byte(x) shr 3) and $1F;; `# g! ?: @; ^7 v8 p
a := Copy(Str, x1 + 1, 1);/ R$ @! f1 P6 ?7 P* c
x1 := ((Byte(x) shl 2) and $1C) or ((Byte(y) shr 4) and $03);
6 o2 y* q+ V- V+ y' z b := Copy(Str, x1 + 1, 1);0 w* @5 n, i3 p5 d2 s. D4 x
x1 := Byte(y) and $0F;
& W! K: d/ Q: \& N3 K6 h$ O c := Copy(Str, x1 + 1, 1);
4 m" u7 T3 K9 g/ a+ ]# B x1 := ((Byte(y) shr 3) and $18) + ((Byte(z) shr 5) and $07);& O$ g# Y! ]6 I# D
d := Copy(Str, x1 + 1, 1);% `* A" m9 \# b) e
x1 := (Byte(z) and $1F);
! o9 e$ s7 e, Y5 U e := Copy(Str, x1 + 1, 1);
/ j! `% a( ^" d G& E, o5 \ Edit2.Text := a + b + c + d + e;& N/ O* U" C% x% f
end;在 Edit1 输入 VRB 按 Button1 键,在 Edit2 窗口中给出我们要的结果 B8MBM 。现在来继续完善我们的注册码。将得到的字符串替换原注册码中第 23~27 位:1 q6 {8 C% T# N7 S- T
1234567890123456789012 34567 8 901 p. ]% ~# C' n: u: x* p' K# w
123456789ABCDEFGHIJKLM B8MBM B TUV% z: D' n1 V, e- V
用前面的小程序进行调位,得新注册码如下:
. x" \ T+ C- o" j! f" ~4 v/ U$ U1234567890123456789012345678901
! O" v" [7 F* r) i42318675CAB9GEFDKIJH8MBLBBMMTVU
2 U6 K8 U: h) g! N+ o* b三、 获得的 17~22 位注册码:
* {0 e' z, W/ _% k, B- K在OD中按 Ctrl-F2组合键,重新运行程序,将 0055D0A6 的 jnz loc_55D157 Nop 掉 + l3 ?8 v1 f. ^3 W+ E' C
复制内容到剪贴板
3 w0 c9 M2 a% ?. ?# s! w% r) w8 N代码:0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉" X" s7 L O6 o0 |
0055D0AC mov eax, offset a111_2 ;"111"
% |7 ~5 \3 T" L3 k' G$ p/ H0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口
# [ o) x8 d6 ~! e6 \( o- c* S; m跟进 0055D0B1 call CheckSerial_17to22
5 Z( w/ d: d+ w9 _ u1 m; b......' A0 f+ x, G, j* q
...... 省略) f4 }. G x" i. q: @
0050C705 mov edx, [ebp+var_20]
R; K2 d( w& I- x/ M7 X0050C708 mov eax, [ebp+var_1C]% O; `2 _" h' ]9 d
0050C70B call DES_EncryStr ;在这里进行 DES 的 EncryStr 加密运算,运算结果再经过
* V$ K+ a5 Q; ? f. b+ `; h; s0050C70B ;另一过程处理,这个子过程我们后面还要用到
' u; D) c4 w1 O% J! W6 }$ T! h6 @0050C710 mov edx, [ebp+var_60] ;moon 文中提到在这个位置获取 17~22 位注册码,可能
. a w/ B4 [$ w0050C710 ;是帮主写文章时粗心了,正确的位置应该在下面删除第5位
5 _5 m) ~4 \- P0050C710 ;相同字母后才取结果。8 p" g& g% X' u, J6 W
0050C713 lea eax, [ebp+var_20]/ t. y' z& K8 u+ _9 {& c
0050C716 call LStrLAsg
6 j' Z7 `+ }& n* o' `0050C71B lea ecx, [ebp+var_64]
5 X9 S/ K2 z! Z0 g0 [/ g0050C71E mov eax, [ebp+var_20]
/ Z5 {$ k" Y; ?) o+ y0050C721 mov dl, [eax+5] ;取出 EncryStr 运算结果的字符串的第 5 位+ q' W9 |6 i; f+ { k
0050C724 mov eax, [ebp+var_20]
+ f8 [( l) {/ k7 a. |0050C727 call DelChr ;将 EncryStr 运算结果中凡是和第5位相同的字母删除# x( A( D9 Z- A8 _6 U0 W7 }2 \* r
0050C72C mov edx, [ebp+var_64]$ a2 P0 [+ F$ O1 x, \, S
0050C72F lea eax, [ebp+var_20] ;这里下断点,从Edx中取前6位,即我们要的第 17-22 位4 s' a6 p8 b$ G% q
......* G" H! x2 I0 K* t2 ~% }
......省略在 0050C72C 处下断点,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDKIJH8MBLBBMMTVU)拷贝过去。点击【注册】按键。中断在 0050C72F,在Edx 返回一个长度为30的字符串(这个字符串的长度是不一定为30的,要看删除相同字符的数目而定),取前 6 为,即为我们要的注册码的第 17~22位,在我们的例子中得到的字符串是:DEDAHI。现在我们来修改我们的注册码:
+ ]1 |9 P: I7 t* h! E1234567890123456 789012 34567 8 901
2 ~8 O4 n8 T# f$ v123456789ABCDEFG DEDAHI B8MBM B TUV |. ~+ [5 s% H( `7 R, n5 \
用前面的小程序调位后得新注册码:9 f5 B& Q; Z2 }9 X- X3 @
1234567890123456789012345678901* ~2 \/ b/ z5 V7 g. B; y
42318675CAB9GEFDAEDD8IBHBBMMTVU( }* w1 {/ z- ~4 ^
四、 获取 1~16 位注册码) M$ z1 O6 \# Z) b$ U1 X/ K5 V
我们首先来看看程序的代码,从前面列出的程序最后一句:
2 k; y$ n) x5 c$ e复制内容到剪贴板 : B5 ^7 d C0 H; I
代码:0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口0 z2 ~' k9 J5 ^5 m0 u; {
跟进 call CheckSerial_1to16
8 i# R" F/ f* O+ S2 v......8 \( @' j- g& U5 C$ u# _
......省略
4 I# w! d8 u7 i# E, ^00508EEB lea edx, [ebp+var_18]
( D+ t- _ P8 r/ n3 S8 {00508EEE mov eax, ds:AppIDAndName_CryHex@Prt8 O3 B/ q: ]- g2 ?+ j. T/ M
00508EF3 mov eax, [eax]( D! v; q0 m- w6 P
00508EF5 call ConversionHex10To16
5 j& [8 F5 T- `" Z4 H00508EFA lea eax, [ebp+var_18]
E/ K- F7 U+ I8 h: r& J" Q5 ]. ^00508EFD lea edx, [ebp+var_8]
4 W$ e) g+ A+ E5 {! s00508F00 call ConversionHexAndFNameToStr0 j$ a' u# q# R# X4 p" ]5 l
00508F05 lea eax, [ebp+var_20]
) }/ |0 M! G \! d& Q2 A0 y" d/ M00508F08 push eax: A9 ^0 {: c8 v0 `
00508F09 lea edx, [ebp+var_24]6 i- s* b, u/ c9 N& W# w
00508F0C mov eax, ds:Serial_CryHex@Prt5 U" D) e- o: F' j' [
00508F11 mov eax, [eax]
" U4 H( I+ y- S5 m% {00508F13 call CycleConversionStr/ w# _' f( y+ J s" \; U2 ]
00508F18 mov eax, [ebp+var_24]5 R; u K5 v% E3 O0 r3 n) X6 [
00508F1B mov ecx, 10h4 y# ^5 u; a# z2 I: M
00508F20 mov edx, 1 ;取注册号 1~16 位
5 m" C2 {! S0 f: w+ b! p. w, R2 S00508F25 call LStrCopy
- V$ m3 g( h* E' y- y+ v00508F2A mov eax, [ebp+var_20]1 ^$ n/ r, I' h6 b# @0 \
00508F2D lea ecx, [ebp+var_1C]
; m" J! C! c! S" D) d! Y6 l) w00508F30 mov edx, [ebp+var_8]
) H. `) B) L/ Y8 g- P% x' Q2 i: W00508F33 call DES_DecryStr ;这是 DES 的逆运算,我们再跟进' c% M; U) o8 P" i! ^* E
00508F38 mov eax, [ebp+var_1C]
" p, g" q0 K' q5 d00508F3B lea edx, [ebp+var_18]% d1 J. a. S( M( v
00508F3E call ConversionHex10To16
0 `" Z+ g( T# X! A00508F43 lea eax, [ebp+var_18]. n# h. P0 d& [8 m- r, c& `
00508F46 push eax- `! _. }3 H; l" ]
00508F47 lea edx, [ebp+var_38]1 l5 o, l, S6 s9 L
00508F4A mov eax, ds:AppIDAndName_CryHex@Prt2 M5 U$ T) }5 W2 Z: x4 [- W2 ?
00508F4F mov eax, [eax]2 u5 ^1 V. H3 I% N4 b8 J% H( z, t
00508F51 call sub_4FBA70
4 A, |" x( ?# w+ C/ f0 ?) S+ G) @; ~00508F56 mov eax, [ebp+var_38]& H8 {1 i: Q) G! L; @: [
00508F59 lea edx, [ebp+var_34] ;这里是我们要下断点的地方
1 \2 {1 J6 r/ |6 o& w......
k2 i1 [, F8 l% w; q4 f @...... 省略$ M0 m: l5 Y5 {! }9 g0 {5 H
跟进 call DES_DecryStr
/ o! K( @' G0 N+ c" V2 y* U0 ?......
2 i8 r/ i4 J2 s2 G. @% i4 g: Z......省略. d* |8 z/ L( k
004F788E lea edx, [ebp+var_C]. J! Z: c3 ] \8 u8 A. G
004F7891 mov eax, [ebp+var_4]
3 a k2 F4 p# ~- C( x004F7894 call sub_4E97BC% e) h* ?# D( F" i2 S* b/ L
004F7899 mov ecx, ebx
) y1 \# @* g& [$ {9 f004F789B mov edx, [ebp+var_8], C% T# `, ^! [; l+ Q
004F789E mov eax, [ebp+var_C]
: c! d* {7 J: T004F78A1 call DecryStr ;DES 逆运算
w1 F$ H* [# I) V9 _+ j) F" a004F78A6 xor eax, eax ;这里是 moon 帮主提出下断点处,还有一些其他相应的做法" s1 X5 u+ h) _9 b2 y# \0 [$ L/ q9 X
;请看 moon 原文。
4 N& O4 _4 j/ I8 {......1 v; [+ t. L5 m o- F4 f
......省略在OD中按 Ctrl-F2,重新启动,在00508F59下断点,同上,将 0055D0A6 的 jnz loc_55D157 Nop 掉,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 00508F59,下面是堆栈内容: . V( T- x6 Y- B
复制内容到剪贴板
- ^$ O% X* x* w; U5 j代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"! G4 q$ a. @' v" _# l
EBP-34 0012F914 00000000. A8 l8 ~% X$ _. `
EBP-30 0012F918 00000000
1 b# A- F% n; [6 I& t( H8 g5 B& JEBP-2C 0012F91C 000000002 Q/ A. B7 y4 Y3 h0 X
EBP-28 0012F920 00000000
0 j: M" k" o# C" mEBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"
8 F0 r) X8 C4 B. f8 `. eEBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"4 v t/ q' R4 \! ]* u
EBP-1C 0012F92C 00F3009C9 O2 p) i( H6 D4 W4 G" z. V
EBP-18 0012F930 C338FAD3. m0 u+ V! H& b" D: v/ h' M
EBP-14 0012F934 DD5CB3D0
1 b6 E0 D+ }0 }6 k" a& h7 dEBP-10 0012F938 D5D42656
: p+ o8 j5 S; O0 C! k, Q; xEBP-C 0012F93C A2BB6C94
! w" R. C2 O, b6 K; T9 [! N1 t- lEBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"
/ h/ A( K/ ?( ?( v4 Q) a5 vEBP-4 0012F944 00000000注意: EBP-38 0 00F2A130 ASCII "5FF51115" 这是我们要的 DES 加密的明文。
5 v g8 [* x2 a; g/ U1 |5 C0 y& t EBP-8 0> 00F2FFE4 ASCII "M9BJBBRIDE88TNP4" 这是 Key。
- e2 `* g+ }# B按 moon 帮主的方法,修改两句代码,进行逆运算,但我经过努力,总是没有成功,可能是对 moon 的方法不能深刻的理解,于是决定改用其他的方法。我们注意到如下代码:
4 K, [9 E( \9 b复制内容到剪贴板
+ x4 H- O+ H+ J N3 s6 `代码:004F788E lea edx, [ebp+var_C]" y% U* i9 B s! Q8 R1 b2 J" n$ i. P
004F7891 mov eax, [ebp+var_4]. N" B. I0 @2 u" h! H
004F7894 call sub_4E97BC% ]0 L8 A% R2 R1 |
004F7899 mov ecx, ebx
# H- N9 H# H! n1 e) j004F789B mov edx, [ebp+var_8]8 q9 x! P1 E6 k: d) _
004F789E mov eax, [ebp+var_C]
) l+ d+ v$ T1 B% u+ [: U+ g004F78A1 call DecryStr ;DES 逆运算在最后一句 Call DecryStr 做的其实是DES的逆运算,前面还有一个辅助的运算,我认为,同益的代码中一定有一个DES的正向运算,即EncryStr,所以我找了一下,其实就在上面第三节--【获得的 17~22 位注册码】中出现过,下面我们跟进这个Call: * v4 K- ]5 i7 g: t5 s0 @6 @
复制内容到剪贴板 . Q# s) z- n7 J V0 k
代码:0050C70B call DES_EncryStr
. Q! D: U' E3 K; d跟进& D+ i4 D6 ?3 L D# z. ^
......0 A( A) |! y7 @8 W! w+ q
......省略
4 E6 {! M; |. Q, a004F781A lea ecx, [ebp+var_C] ; 返回地址
# N' U8 ^; J0 W, p# J' m; h004F781D mov edx, [ebp+var_8] ; Key = M9BJBBRIDE88TNP49 C1 O1 H4 C& H! \# N0 S. U
004F7820 mov eax, [ebp+var_4] ; Str = 5FF511154 h" w4 |% j" P, E
004F7823 call EncryStr8 k m) c ]8 z# `' j
004F7828 mov edx, ebx; D3 `1 v R" D
004F782A mov eax, [ebp+var_C]
- B# I* G6 R+ R# M# \004F782D call sub_4E63F4
7 Y9 u4 K1 I, j' ^/ A! i004F7832 xor eax, eax ;这里下断点
) ?, o2 Y$ D T6 F......1 X, l1 {, J. e! X7 B
......省略可以看出,它和上面的代码正好相反,我们用下面的方法来获得 1~16 位的代码。
6 w1 w5 s- |0 v" b j接前面,我们中断在 3 s7 ~) q# D4 l- K5 C- \# f
复制内容到剪贴板 % ?0 b7 A8 R9 i$ _
代码:00508F59 lea edx, [ebp+var_34]在代码窗口中按 Ctrl-G,输入004F781A,转移到 004F781A。按 Ctrl-*,将Eip地址改到 004F781A。
' u+ t8 |: Y [+ s我们要做的工作其实就是修改堆栈的地址,下面是具体操作。
7 ?* ^ M+ u# ~5 ?) G7 i; \5 L. C1 |' y( _复制内容到剪贴板 : x7 a6 }; I) H5 v$ x: e: w
代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"
* @4 [, s* r4 g3 ^5 gEBP-34 0012F914 00000000
; O) C/ ` v: x3 J& zEBP-30 0012F918 00000000
7 A- a' Q: ~5 OEBP-2C 0012F91C 00000000
; X. I4 m: v8 z; U/ z4 BEBP-28 0012F920 00000000
; f* [; y h/ X* M; }EBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"
) P( ~* ~7 m9 U5 q# c6 \( m1 v. @EBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"
9 [: m3 G! b# l8 f- B ]. [( cEBP-1C 0012F92C 00F3009C) Z2 B& o8 w3 @1 y, A5 @2 n
EBP-18 0012F930 C338FAD3
- I7 v- R, [7 G' @% v) LEBP-14 0012F934 DD5CB3D01 i4 B( i& x6 P: ?' G# R
EBP-10 0012F938 D5D42656; a( i W2 ^# F" g/ U) }
EBP-C 0012F93C A2BB6C94 结果返回地址,这里改为 0,程序运行时会自行分配新的内存
1 [! F Q' m& t! K* s# qEBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"
8 K. `3 m, J5 r! gEBP-4 0012F944 00000000 这里是 Str 所以将这里改为 00F303D0,也就是[EBP-38] 指向的地址。另外,最终返回结果在 Ebx 中,而Ebx 是由上一级的过程传递过来的参数,已经由入口程序做过初始化,所以,必须分配一个有效的返回地址,这点和 [EBP-C] 不同,需要要注意,这里我们将 [EBP-24] 的堆栈地址分配给 Ebx, 也就是Ebx = 0012F924
5 K; i5 O7 }5 I; J$ P- q改完后堆栈如下:
( T% P( L8 u* @& i3 j复制内容到剪贴板
0 O. t0 W. D5 r6 A3 F6 a' q代码:EBP-C 0> 00000000
5 |5 I3 ^0 V! nEBP-8 0> 00F2FFF8 ASCII "M9BJBBRIDE88TNP4" Key( Q$ e3 g" t: {" x: H* H
EBP-4 0> 00F303D0 ASCII "5FF51115" Str8 }! ^. N3 U# [5 ~1 Q: a
在将 Ebx 的内容改为 EBP-24 的堆栈地址,即 Ebx = 0012F924 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"在 004F7832 下断点,F9 运行,d [Ebx], [Ebx] =0VBMHYAMA260CSD1 第 1~16 位的注册码" i9 M( _1 ^7 O$ f
现在我们来修改我们的注册码:/ }: F: }& w8 O( H% r
1234567890123456 789012 34567 8 901
. F# E6 L% b4 ~ l& M+ |5 A9 ^; s0VBMHYAMA260CSD1 DEDAHI B8MBM B TUV: {( g4 O) ^+ C3 _" L) m
用前面的小程序调位后得新注册码:
- A% L; ?; p o9 _( B9 D2 }1234567890123456789012345678901
) F& T: @* C/ x5 L! B+ MMVB0MYAH026A1SDCAEDD8IBHBBMMTVU
' ~& W8 P8 r1 k. W五、 获取最后 29~31 位注册码5 r2 j* h. o- c3 }' j5 I. `
打开注册表编辑器:将Serial中的内容清除: C" _9 |2 {' _- P3 i* `
[HKEY_LOCAL_MACHINE\SOFTWARE\GoodSoft\GoodName]
) e7 k7 [+ Y) m( c. D"Appid"=dword:059c09358 h" L( a6 i6 }4 b
"Serial"="MVB0MYAH026A1SDCAEDD8IBHBBMMTVU"& J1 K! X. g* ?3 L- s {4 n
"Serial"="0"
/ U) G& H! z7 m0 H6 v; u5 z6 q在OD 中按 Ctrl-F2 重新启动,将下面两处 Nop 掉。 7 M/ g, ?* X1 o, L5 D! F
复制内容到剪贴板
3 w) Z) Y1 o8 \7 ^代码:0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符
0 S) l) l5 k) ]+ Y1 F0055CFD7 jnz loc_55D157 ;Nop 这里
# L( q& l9 w3 j0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同
# _) C$ `# G/ F3 i1 w2 m0055D02A jnz loc_55D0EA ;Nop这里
m1 v j/ E' J ` s$ Q0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点在上面 0055D0A4 处下断点,F9运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(MVB0MYAH026A1SDCAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 0055D0A4,记录下Eax寄存器的内容,我这里是 2C3AH,换算成十进制数为 11322( L$ u; l: \4 W) t' q% ]5 f
根据 moon 帮主的文章:
- \: O" S0 i5 r3 g
! r6 C% u" e2 X+ a6 K求逆方法:
; B" V4 i% O# d7 P; o" ?9 k. c1. 执行到00559E24,记下eax中的值x,或按照上面的方法计算出这个值;
$ ?3 [3 i* C! U+ ?& I2 h5 ?* e2. x除以31,用余数查表"0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ",所得字符作为第31位;
1 h9 X9 s" n; f4 ]0 U3 v3. 第2步的商除以31,用余数查表,作为第30位;9 V$ I( M4 ]2 [
4. 第3步的商查表,作为第29位。
! w9 O. }* s0 k' d9 O9 @. n( F--摘自 moon 帮主的文章
" J- F# X2 i5 g& Z# j+ x/ ~8 S4 x0 e) a# U, F. P" R
写如下Delphi 的小程序计算最后3位注册码。
! ~: {5 U0 [# G" i t- h9 V复制内容到剪贴板
; D$ L0 Q. n5 S! |6 H! ^代码:procedure TForm1.Button3Click(Sender: TObject);8 F& ?6 X+ d. W
const+ V7 { T! O8 _/ q. ] Z5 G
Str = '0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ';* P7 D7 \0 A$ z8 b7 O, p8 b& n
var+ Q0 l9 B/ j* C J/ F; Y6 u0 X
x1, x2: Integer;/ l$ }9 N, W4 V! n X
S1, S2: String;
7 D2 u# f& _3 y* N. X* g: ~0 `begin
7 B$ C% l+ o8 `9 h9 |4 D x2 := StrToInt(Edit1.Text);
1 T R7 Y5 B5 a) c9 E$ M7 i" z x1 := x2 mod 31;+ h. ~3 i' p5 R7 k' \
S1 := Copy(Str, x1 + 1, 1);! O! |4 `& T5 C9 \6 Z! B' E' n3 A" M
x1 := (x2 div 31) mod 31;8 ], V- G) _* e5 [
S2 := Copy(Str, x1 + 1, 1);3 I% I2 K3 o0 ~$ N4 E- Z$ f6 C
S1 := S2 + S1;
8 r P$ `3 H" ~6 x ?! n% y' p x1 := (x2 div 31) div 31;% U t$ V( Q5 g( H
S2 := Copy(Str, x1 + 1, 1);
* w' N! ?+ \( C, o: k3 ? Edit2.Text := S2 + S1;" @7 w: v' L/ r* i6 K& v* p. T8 z
end;在 Edit1 中输入 11322,按 Button3 键,在 Edit2 中给出结果 T8B4 _0 s( C- k E( U: }2 }' K, _
现在我们将获得最终的注册号:
$ N& Z* b8 s1 g0 ^ y% ~7 u, Y4 V1234567890123456 789012 34567 8 901" d7 y8 a9 L: f: x7 X% ^" W
0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B l1 L4 B: f, E: f* s
用前面的小程序调位后得新注册码:6 Z2 b# S* I2 x' Y
1234567890123456789012345678901: d; l" E8 J% d1 x) P
MVB0MYAH026A1SDCAEDD8IBHBBMMTB8* L' }. K# r. V F8 t8 R% c! }* K4 j1 L
在我的机器上,注册号为 MVB0MYAH026A1SDCAEDD8IBHBBMMTB8 ,用未脱壳的原版注册后所有功能完全正常,公司后缀的分析类似,有兴趣的朋友可以自己试。
3 n. {7 n" b' q! S另外,对于Delphi的小程序,什么版本都可以,但编译开关 Huge String 要勾上,我使用的是 Delphi 7。
4 U J. a/ Y9 k& D b: [, y说明:
0 }. ]1 N1 p) P# s; }7 v7 R3 |1 x; y. S" }
1、对于调位操作,字符串长度必须是 31 位(不算空格),可以带空格输入,这样比较方便直接拷贝,如可以直接输入:* M2 A1 T, T7 z4 |, ~
"0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B"
* `9 f) b0 Y v; U3 j9 a0 c ]2、对于计算最后的第 29~31 位,可以直接输入十六进制数,不过要加 '$' 前缀,例如在我们这个例子中,可以直接输入 $2C3A (不分大小写)。" E, H2 V7 @' J1 K+ s" s
|