正确获得同益起名大师v337 的注册号――解读 moon 帮主的妙文
4 w _& }! G6 B' g【作者】gzgzlxg; g/ P& ?8 ~1 x* ]+ G% X
【声明】只是好奇,没有别的目的,如有,我就把注册机发表了(已经写好了),不要发信向我要注册机,我不会发表的,这也是看雪老大的要求,其实我觉得这篇文章已经很过分。按这篇文章,你100%可以得到正确的注册码。
* Z2 D5 E2 O4 D. Y【工具】IDA,OllyDBG
; M+ |6 U; i& [8 B) z【软件】使用我在【ACProtect 1.41 -- 同益起名大师 v3.36、v3.37、vp3.33(专业版)完美脱壳】中所完美脱壳后的 GoodName.Exe v3.37版。使用脱壳版,跟踪比较容易,当然你也可以直接使用原版,但会困难一些。5 O. i5 C5 v# {8 W: t4 W- Z& J
http://bbs.pediy.com/showthread. ... &threadid=16204
! T9 e" j) i6 l! p1 J$ w【注】读此文前,请先读 moon 帮主的【谜----同益起名大师3.36注册算法分析】,# w2 K5 P0 c6 A7 W$ ~% b, {" ]
http://bbs.pediy.com/showthread. ... &threadid=14716 凡是和moon 相同的部分我就不再多废笔墨。; C/ V9 @ d* g( m( m, ~
本文同时发表在看雪论坛和DFCG,转载时请保持完整,版主如果觉得不合适可以删除。
( t& d# [9 [# j前言:
V3 u, H3 l7 T' O8 p同益起名的注册码验证遍布全程序,在主窗体建立,子窗口建立,按键操作,对注册码和注册申请码的验证无所不在,而且计算方法来回重复,例如获取注册申请码就有三个完全相同的过程,DES 算法也有完整的两套。我们用来分析注册码取的是注册操作部分,其实在主窗口建立、子窗口建立的过程中都可以进行,因为他们是完全相同的。* L" o$ ]$ ?4 ~6 |; J8 B+ G
这是注册窗口(Tfxhm)VMT表中的方法表部分,(全表太长)。这些代码都是在 IDA 中分析得到的。
! Q( ?- \( z3 L O复制内容到剪贴板
6 R1 S2 l" c- @, R1 `8 [) ? ~代码:......# f4 @# p: r& ^# A. E
0055647F TfxhmMethodTable dw 60 g8 R& H; v' A# m+ K. M- e/ R
00556481 dw 16h
! f! Q, b# O3 F* X/ s00556483 dd offset Tfxhm@suiButton2Click ;退出按键" y+ F+ _8 u; v6 T3 ]
00556487 aSuibutton2click db 0Fh,'suiButton2Click'
8 O+ L, Z7 _' j00556497 dw 10h
' X; t- s, k) u9 C. m00556499 dd offset Tfxhm@FormClose ;关闭窗口& D' a0 _. C) C% ^, e( C
0055649D aFormclose_0 db 9,'FormClose'
$ N- m( c: i* W+ f005564A7 dw 11h
6 X: N \. G5 U- S$ X+ |( f005564A9 dd offset Tfxhm@FormCreate ;建立窗口& u' h) v4 M: h
005564AD aFormcreate_0 db 0Ah
5 E, F. t7 A h8 s. A005564AD db 'FormCreate'4 u3 u0 H1 n9 ?6 V# F X" |
005564B8 dw 16h
* h$ L5 ~; X/ d( T$ ^% v: {005564BA dd offset Tfxhm@suiButton1Click ;注册按键8 |. l; O7 l+ J {2 `, |. M
005564BE aSuibutton1cli ck db 0Fh,'suiButton1Click'
; X+ P& R6 x! ]& w, f' @* {) N0 Q005564CE dw 0Fh; c, X, K) T2 z2 @. D9 r' X
005564D0 dd offset Tfxhm@get_text ;suiButton1Click 调用的校验注册申请码7 Q7 M/ V9 o3 D$ Q9 n) E
;和注册码并注册的子过程0 ~. i5 G3 K4 h; U
005564D4 aGet_text db 8,'get_text'& K& ?( c7 A' y- O, c
005564DD dw 0Fh
, t* I4 a3 X0 u' H' [005564DF dd offset Tfxhm@FormShow ;显示窗口+ n, X4 I/ m+ V1 [# l! X) D
005564E3 aFormshow_0 db 8,'FormShow'
- a8 o1 {; G6 O/ A# t9 \005564EC Tfxhm db 5,'Tfxhm' ;类名
5 \! J# N$ s" M8 o005564F2 word_5564F2 dw 5
: W9 e% f% d' d- `( o$ Y( Y005564F4 dd offset TsuiForm@VMT@Prt ;父辈 TsuiForm 的 VMT 表指针地址0 Q* w+ m0 F4 V' }! A. s
......我们分析的所有代码都是属于 Tfxhm@get_text 过程和它的子过程的。 Tfxhm@get_text 起始地址: 0055986C
s/ a" [/ ?3 I/ d1 C, c) u+ m: e一、 获取注册码第28位8 N# d% h- {: y' I
确定你想注册姓氏的正确笔划数(必须和同益数据库中 slzik 所查到的相同,以繁体字笔画数为准,同益库中有些字的笔画数并不正确,这时你可以在同益起名的姓名分析中获得姓氏的笔画数)。在下面的字符串中从左到右查寻,得到第 28 位注册码:例如,吕:繁体字为 7 划。(从0开始数)
1 n8 l, H/ b% |6 G. }$ I0123456 7 89012345678901234567890
1 F( b, S/ Z, j d. R$ r, Q0AH6CD3 B EF4TRS2PUV5K1MN78YZ9GIJ
- l& U0 ^/ F6 {% `& S' l得到的字母为 B,这样我们的注册码有如下形式:(31 位)下面是我们的起始注册码+ |, K/ n( }- ?$ f( D
123456789012345678901234567 8 901
8 W) i# P$ }$ G I123456789ABCDEFGHIJKLMNOPQR S TUV5 Y) ]' q* T9 R) M
加入第 28 个字母 B,得如下注册码:
8 E) e6 N. }( N: | w) C3 {% N123456789ABCDEFGHIJKLMNOPQR B TUV
3 i- k7 E! ?- f( {& h4 V根据 moon 提出的换位法(4*i+1位和4*(i+1)位互换,i=0,1,2,...,末尾不足4位时,最后两位互换),2528位对调,这个B应该在第25 位
% n" K/ L& M6 D$ V为了便于调位,写了几句Delphi的小程序来完成:(这种操作,还是汇编容易,所以实际还是汇编写的)
5 t, A) F, C8 v+ k: I! b复制内容到剪贴板
' D! }( C8 M/ W; E代码:procedure TForm1.Button2Click(Sender: TObject);
; G1 J* K* q. Vvar
8 A3 B7 j ^7 A& H, J, L Str: String;4 M9 L5 R3 k: z" ^+ g. D
begin3 J# b( B2 D5 _0 M. J9 _
Str := Edit1.Text;
( S! ?. r; G7 E! B9 ~& P! i9 Z$ S asm9 x+ L0 `1 Q5 O( Y- o; Y2 [& f9 H1 `" r
PushA
# I6 o2 |- H, Q; U Xor Edx, Edx! i: S, g+ v: s) c5 C
Mov Esi, Str. M; H5 Z* }/ x+ W( W3 a- [. U
Mov Ecx, 7
1 P5 b# y7 _- ]9 o @1:
% g, m% l; w p/ c; | Mov Al, [Esi + Edx]0 g3 Y- X/ f0 h
Xchg Al, [Esi + Edx + 3]' g/ ~# p9 i& |* H: e' k1 v
Xchg Al, [Esi + Edx]! {4 C6 B# r0 u2 Y
Dec Ecx
3 F: V9 H$ \9 T1 A# J2 F/ A Add Edx, 4
/ V/ m c( @+ K K' G' a, w* ] Cmp Ecx, 0. C0 B" z- W: i ^* y, H
Jnz @1
\- q: s+ o+ H Mov Al, [Esi + Edx + 1]$ w9 |2 K" ^; i4 |+ j
Xchg Al, [Esi + Edx + 2]
5 t0 K/ L A9 j7 [# i Xchg Al, [Esi + Edx + 1]$ i6 Q( F# \* ^5 j/ \3 Z7 M
PopA
5 w H+ b' ?; m& I: W end;
: y& D' d4 t' L" U Edit2.Text := Str;
" D& P" f9 f1 j2 `( F1 Lend;在 Edit1 中输入 123456789ABCDEFGHIJKLMNOPQRBTUV,按 Button2 键得到下面的新注册码:
/ f% s/ U* r9 C; m: Z* I: \9 k新注册码为:
4 `' H3 o8 E2 ^123456789012345678901234 5 6789015 g- Q* `$ l8 ]( o" a
42318675CAB9GEFDKIJHOMNL B QRPTVU& e- W" S) H/ l- \4 x5 R0 V$ ]
具体分析请看 moon 的解释。6 K% l# D7 C. x1 C5 X, X3 }
二、 获取注册码 23~27 位注册码8 a7 X$ e% Q) i. l+ b
用OD载如 UNGDN.exe (脱壳后的程序) & V5 E0 Z d6 w2 \* a1 x& ?
复制内容到剪贴板 + z6 E6 D+ g2 d+ ]8 T* g; I: i% p; D
代码:Tfxhm@get_text
. M# x8 y5 \7 D5 e9 b: }) E) U......7 O. ?1 }, m% I; y
......
7 U# Q* B& O4 u' [7 k; s; L: d0055CF7E mov eax, ds:AppIDAndName_CryHex@Prt ;注册申请号加姓氏和1FH 异或得到的结果3 W* {2 T1 H# n0 M9 `
0055CF83 mov eax, [eax]& ^0 z8 M% a" i9 X! O3 c
0055CF85 call sub_4FED88 ;EncodeFunction1
. _* O) v2 m+ I* [0055CF8A lea eax, [ebp+var_94] ;这里断下获取计算23-27位的三个字符
# O% P5 p3 w: x0055CF8A ;按照 moon帮主的给出的算法可以获得& s" w7 s2 s$ Y; E% I
0055CF90 pus eax
" t. a! S/ C( G- T% d8 S; a6 R0055CF91 lea edx, [ebp+var_98]
5 v& R7 v6 M8 ]5 Q& U0055CF97 mov eax, ds:Serial_CryHex@Prt ;注册号和 1FH 异或得到的结果3 m& i, N9 n E3 f" X1 J7 ]
0055CF9C mov eax, [eax]
: b9 _; k4 C' J& m# \0055CF9E call CycleConversionStr ;经过 1FH 异或,即还原. R1 y% q7 o! w" B" b
0055CFA3 mov eax, [ebp+var_98]
; \+ { b0 c; z6 l- N! N0055CFA9 mov ecx, 5' j3 W& |; h9 J* C3 l$ O
0055CFAE mov edx, 17h! q5 C- }/ N4 S" E: t) A, E7 v
0055CFB3 call LStrCopy ;取第 23~27位* q! m: |+ I a) C8 w& P; ]
0055CFB8 mov eax, [ebp+var_94]
U+ j$ T& I. A9 P0055CFBE lea edx, [ebp+var_90]- K& h- j8 I6 T, x$ R! c4 M
0055CFC4 call sub_4F0048 ;进行计算得到三个字符,如果和上面计算得到的三个字符相同,则过3 e H& o3 u* B: d' A
0055CFC9 mov edx, [ebp+var_90]0 ~ ?: U( @8 I
0055CFCF mov eax, [ebp+var_C]
& N$ D) ?8 z! @6 D, U ~$ Q0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符0 Z+ m2 k! _+ K6 n0 C
0055CFD7 jnz loc_55D157
$ x* u7 X) @3 K0055CFDD lea eax, [ebp+var_A0]
' O) u5 @# m: K3 o- z0055CFE3 push eax
; ?3 y# t3 D J" q$ ~; Z0055CFE4 lea edx, [ebp+var_A4]9 u6 g$ U3 p# o6 _! k3 w- k
0055CFEA mov eax, ds:Serial_CryHex@Prt/ U& W4 R- s5 |0 B
0055CFEF mov eax, [eax]" p# p: f! x, s7 }1 h
0055CFF1 call CycleConversionStr) [2 f+ C/ k* f9 n
0055CFF6 mov eax, [ebp+var_A4] S( k6 F, o7 l" a: p; }. x
0055CFFC mov ecx, 5
) k, N% M) i2 r, P$ ~' [0055D001 mov edx, 17h ;取注册号23~27 M+ b4 o0 _, X+ a
0055D006 call LStrCopy
/ N# g4 n2 G, g% }, U; h0055D00B mov eax, [ebp+var_A0]: z+ P. h3 s S
0055D011 lea edx, [ebp+var_9C]
5 a$ R: V O) N0055D017 call sub_4F00482 L% K. X5 U* k8 b$ u s( S' q& o
0055D01C mov edx, [ebp+var_9C], `1 g& w8 { R. P8 r
0055D022 mov eax, [ebp+var_C]
/ f7 \5 [' V8 i3 O) h- e0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同8 Y7 T, D k6 K6 ~
0055D02A jnz loc_55D0EA. _8 p" ]/ x2 n, A Q0 o, u
0055D030 lea eax, [ebp+var_A8]
- s- q$ @1 C7 z0055D036 push eax
6 ~, r v* z) S0055D037 lea edx, [ebp+var_AC]
) I, K: x! z1 V, f$ T0055D03D mov eax, ds:Serial_CryHex@Prt# k+ G; F% U$ R( f' E5 `* [
0055D042 mov eax, [eax]. s( S# ^4 _9 w; @' R
0055D044 call CycleConversionStr
1 I) ]2 D% u$ J2 ?0055D049 mov eax, [ebp+var_AC]$ y* X% B: {/ S& A2 T; T
0055D04F mov ecx, 3" q9 R# k5 C0 D. q, H7 I) o
0055D054 mov edx, 1Dh ;取注册号 29~31 位
2 F0 Y" C$ }. u6 @ d- Y0055D059 call LStrCopy. }) l6 l$ O# ~2 D' H( H! M
0055D05E mov eax, [ebp+var_A8]
" {5 U9 D# k# [- Y2 M G0055D064 call 31decimalToHex ;对29~31位注册码进行31进制到十六进制的转换 H! z+ g# q% Y* Z# O: U9 p
0055D069 mov ebx, eax8 v- `# H! T: S2 r; g& g
0055D06B lea eax, [ebp+var_B0]$ l4 C$ M; B3 B( ?; `8 O
0055D071 push eax2 G. I( ?% X6 i- y6 r% |) L% t
0055D072 lea edx, [ebp+var_B4]
" X" r5 p8 V# W, |* o! J( I0055D078 mov eax, ds:Serial_CryHex@Prt ;取注册号(经过1FH异或处理)! y% E) ]. O/ [' Y t7 \' N
0055D07D mov eax, [eax]& T) W8 L6 J$ E2 B; o& y* Y
0055D07F call CycleConversionStr ;经过相同的过程还原
( T; V6 u2 v+ B! a6 I2 ^' K) l0055D084 mov eax, [ebp+var_B4]3 ]5 s% M( Y: _! v2 N/ m) K5 u
0055D08A mov ecx, 1Ch
0 o( U4 g0 n9 y0 ?, b7 A0055D08F mov edx, 1 ;取注册号 1~28 位, X* W' n2 n- t9 k- C6 M+ k
0055D094 call LStrCopy" v! q+ E; Z8 Y1 F0 r
0055D099 mov eax, [ebp+var_B0]% D' j+ H+ y' z- Z! J: O- `
0055D09F call SumSerial_1to28 ;做 1~28 位累加(中间还有判断是否大于27000,见moon帮主的解释)3 c( D% s$ D& R' \3 _1 s" \& L, s
0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点* H( K) K n/ y% E
0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉% A" k% J+ U7 H9 Q9 _5 }1 U
0055D0AC mov eax, offset a111_2 ; "111"
8 h4 z5 G& o( [+ H0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口
6 X% K/ C- b- F1 J, f0055D0B6 mov [ebp+var_1], al
' M" w. G% B- i1 J R: B. `; h0055D0B9 cmp [ebp+var_1], 0
( E: L; w8 {: H7 u& {+ e* w0055D0BD jz short loc_55D0CC N1 E% y8 g5 V
0055D0BF lea eax, [ebp+var_C]( s1 t7 u: M' ^( ?/ S; m9 F7 F
0055D0C2 mov edx, offset a111_2 ;"111"
) X4 Y- q) ?2 T$ V2 Q* s0055D0C7 call LStrLAsg" g- K$ s# R3 D1 \$ s0 K) Q
0055D0CC
1 k) l* n+ K; q9 q' ~0055D0CC loc_55D0CC:
& W! h* h. k+ |7 T/ F. S* X0055D0CC cmp [ebp+var_1], 0
4 f3 ?/ H2 ^ m- t0055D0D0 jz loc_55D157% _1 e% Q0 j1 e& j8 ]# ?! O, t
0055D0D6 mov eax, [ebp+var_C]# F8 c6 o9 O4 e5 Z1 s
0055D0D9 mov edx, offset a111_2 ;"111"
! [8 \9 \0 l3 G% \2 n( i0055D0DE call LStrCmp/ a7 F$ O9 k4 H+ L0 X, l
0055D0E3 jnz short loc_55D0EA; c8 {6 ?* q: z8 O( g1 f) @
0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口在0055CF8A 处下断点,F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',注册申请码是不能修改的,由你的机器的 CPU 和硬盘的参数变化而来。在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的 123456789ABCDEFGHIJKLMNOBWRSTUV 注册码拷贝到输入窗口。按【注册】键,中断在 0055CF8A ,清除断点(或关闭),由 [ebp - c] 中的内容,得到三个字符 VRB,记录下这三个字符,用moon帮主给出的方法:
, C( N1 S# E9 D2 A0 A# ~6 T/ e8 Z; p9 R& O% n
求逆方法:/ _. a( q3 _' p2 y4 E
1. 执行到00559D0A,然后下:d [ebp-c],记下数据区显示的正确值x,y,z;
3 B6 }+ k7 |$ [" M2. 对3个字节的正确值进行调位,得到5个字节a,b,c,d,e,调位方法为:
' E8 T( r; D: E0 _4 m0,0,0,x7,x6,x5,x4,x3
3 t; _' H# f1 ]. b$ K+ B0,0,0,x2,x1,x0,y5,y4! N; q" b G7 C: _: J5 e
0,0,0,0 ,y3,y2,y1,y0! ^5 J4 C# N3 E. W# h6 Y; G
0,0,0,y7,y6,z7,z6,z5, Q: \# F4 ]2 F8 \* f! Z$ I
0,0,0,z4,z3,z2,z1,z00 [: f& W* R) j1 _8 r" @" p" k. B
3. 根据5个字节查表"0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX",得到5位注册码即为23~27位。
* g2 ^, F3 R! k9 B' B! U) U: @9 S6 _--摘自 moon 帮主文
4 j: a/ I* Y, p$ X. I/ K4 H
4 p4 ?' u/ j" _5 q4 U% t我用Delphi写了几句小程序完成这个转换,程序如下:
3 L+ ]' Y& ^: q4 ^: ?5 v复制内容到剪贴板
4 w( I2 `" o' N2 g7 {1 R代码:procedure TForm1.Button1Click(Sender: TObject);. L" b: Q. `: n2 ^/ R4 j9 A
const5 V' h" e- F" _# r
Str = '0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX';0 x' X0 W7 ?4 j8 l! \% ^
var: y' `5 N$ {" a" `! b" |( J
X1, X2: Integer;
4 A/ j3 M) J6 [* u: z x, y, z: Char;% M! W% N) _" q
a, b, c, d, e: string;
' }& w7 J2 J& w+ t8 @& X! G- g0 I Pin: string;) }/ H) c( d5 s. f, X5 n' C) U
begin) q4 t! z4 m6 G" ~0 A. Y0 }
Pin := Edit1.Text;- V$ x6 j! Q8 A- ]' g( P; K
x := Pin[1];1 M; w9 s$ ]2 v* {, [+ {7 J' \
y := Pin[2];
* o3 J L2 s; R' u% o* Q, z z := Pin[3];6 z# X9 v5 E0 k& u; M9 M7 C4 o0 v
x1 := (Byte(x) shr 3) and $1F;9 c: [# D( V8 P
a := Copy(Str, x1 + 1, 1);2 A4 V* N7 Z8 D' l& `
x1 := ((Byte(x) shl 2) and $1C) or ((Byte(y) shr 4) and $03);
- Z/ P `4 N: u0 { b := Copy(Str, x1 + 1, 1);2 W/ l h& v4 B" c" W( ^: b/ |+ }4 C
x1 := Byte(y) and $0F;2 @" q# O2 d. h! k
c := Copy(Str, x1 + 1, 1);7 O* n M1 d( [' D5 ~8 Y' I
x1 := ((Byte(y) shr 3) and $18) + ((Byte(z) shr 5) and $07);
1 n% S0 E; q r) t3 L9 G d := Copy(Str, x1 + 1, 1);: N; g5 d2 _+ ]+ C T% ] n
x1 := (Byte(z) and $1F);# [2 D1 W7 I* ^+ S K. q* ?/ b
e := Copy(Str, x1 + 1, 1);$ w5 J2 Y7 D) P& h5 @9 N6 ~. p) I
Edit2.Text := a + b + c + d + e;- j0 E4 T8 M$ g! Q
end;在 Edit1 输入 VRB 按 Button1 键,在 Edit2 窗口中给出我们要的结果 B8MBM 。现在来继续完善我们的注册码。将得到的字符串替换原注册码中第 23~27 位:) }: u' z6 ?9 H( A# S7 M: \ C
1234567890123456789012 34567 8 9010 o9 f% Y7 U6 L5 F. k7 D4 u
123456789ABCDEFGHIJKLM B8MBM B TUV
! k3 N$ c6 S( a7 O, l6 R% i用前面的小程序进行调位,得新注册码如下:& g" M' |8 ~6 F- ?* A: `
1234567890123456789012345678901% b. j1 S J/ L
42318675CAB9GEFDKIJH8MBLBBMMTVU
H3 j/ N! b/ }! [7 L三、 获得的 17~22 位注册码:7 N+ }" M3 Y9 `3 T% [) |6 V$ _
在OD中按 Ctrl-F2组合键,重新运行程序,将 0055D0A6 的 jnz loc_55D157 Nop 掉 ! A- ~! F+ ], V( S# E8 D5 H
复制内容到剪贴板 : k: n9 \- ^$ r
代码:0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉/ v+ }6 {4 _9 R& B$ c+ k; U; V: [- _
0055D0AC mov eax, offset a111_2 ;"111"
; s% M$ B0 [8 C! U/ J0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口
' Q$ F9 a5 U5 `* j6 D" \. S! R跟进 0055D0B1 call CheckSerial_17to22/ W, m: p4 ~& c7 M5 L9 @
......3 F7 \! P* V9 P. t+ m
...... 省略" h- @# D* f2 ~' }) [
0050C705 mov edx, [ebp+var_20]0 |8 v0 @1 r* c& J! a4 _" D: n, f: x6 j
0050C708 mov eax, [ebp+var_1C]# G' W( p3 S9 \' ~
0050C70B call DES_EncryStr ;在这里进行 DES 的 EncryStr 加密运算,运算结果再经过
9 {; B% Q& Q7 i$ y" q0 L& d0050C70B ;另一过程处理,这个子过程我们后面还要用到1 i# w' I$ l% r8 r
0050C710 mov edx, [ebp+var_60] ;moon 文中提到在这个位置获取 17~22 位注册码,可能
; |2 v( } m2 ]1 W0050C710 ;是帮主写文章时粗心了,正确的位置应该在下面删除第5位, I' b6 E& {& J' [* M
0050C710 ;相同字母后才取结果。
/ n; v* n+ F4 O6 g2 x4 V- K8 F0050C713 lea eax, [ebp+var_20]
) s$ s( j+ y' @8 @4 Z% p) n6 \0050C716 call LStrLAsg
; j1 g4 T. @ K0050C71B lea ecx, [ebp+var_64]; Y; l7 E( z7 g/ Y- O9 w) {
0050C71E mov eax, [ebp+var_20]( Z) i* O h, E3 x. C2 H
0050C721 mov dl, [eax+5] ;取出 EncryStr 运算结果的字符串的第 5 位( D4 x' P2 z/ l2 u4 P3 q
0050C724 mov eax, [ebp+var_20]9 \) p. J+ K$ O6 ?2 J
0050C727 call DelChr ;将 EncryStr 运算结果中凡是和第5位相同的字母删除
7 _; N! J. k' H- c2 U; J _0050C72C mov edx, [ebp+var_64] ^, a$ e, `2 n, T5 t& a0 [
0050C72F lea eax, [ebp+var_20] ;这里下断点,从Edx中取前6位,即我们要的第 17-22 位) H( k6 J- g, w
......
: X; g5 ^( O9 |5 ?! P8 e......省略在 0050C72C 处下断点,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDKIJH8MBLBBMMTVU)拷贝过去。点击【注册】按键。中断在 0050C72F,在Edx 返回一个长度为30的字符串(这个字符串的长度是不一定为30的,要看删除相同字符的数目而定),取前 6 为,即为我们要的注册码的第 17~22位,在我们的例子中得到的字符串是:DEDAHI。现在我们来修改我们的注册码:
- {% t$ L/ @, |- M! [* ~) B1234567890123456 789012 34567 8 901" O% I& t! ? M4 x4 N* d5 f
123456789ABCDEFG DEDAHI B8MBM B TUV! B, S( v; c; [1 m/ ?4 C6 p
用前面的小程序调位后得新注册码:9 _& t+ R$ C9 b! X+ v u7 v
1234567890123456789012345678901& M% D5 x- b$ c* s: ^# G) @) ~
42318675CAB9GEFDAEDD8IBHBBMMTVU
' v( n8 C! y1 {1 _四、 获取 1~16 位注册码
X! H( p' P' m' H" d6 d, t我们首先来看看程序的代码,从前面列出的程序最后一句: 4 S0 Q2 c2 W% s, A7 C) k1 V
复制内容到剪贴板
; t' z2 q! y1 \1 D4 r" x; p代码:0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口
1 c- k8 F- l7 L% v跟进 call CheckSerial_1to16# P9 j3 J0 }* ]+ [* ]% r8 b! v) h8 F
......: }* R; z& U' j+ m! G) G
......省略% G) b4 n( Y0 N2 U5 X% I1 `4 G
00508EEB lea edx, [ebp+var_18]
( I' D5 y+ S4 P8 x6 T; S3 ^00508EEE mov eax, ds:AppIDAndName_CryHex@Prt5 z9 l+ E& R: q* L B: S5 z+ S
00508EF3 mov eax, [eax]- E9 M3 V- d7 ?) A \1 X# j+ T
00508EF5 call ConversionHex10To16% [0 V- y+ O3 q, `% w
00508EFA lea eax, [ebp+var_18]) O$ Q$ v9 R R+ P9 R' T9 C
00508EFD lea edx, [ebp+var_8]$ R' J3 p- z- W3 I1 D
00508F00 call ConversionHexAndFNameToStr
. N# o F$ ^; C5 F6 \1 s3 z! }, C00508F05 lea eax, [ebp+var_20]) b3 v; Y* F3 Z/ }2 Q
00508F08 push eax
' b8 A8 Y% z5 e# X, X: S00508F09 lea edx, [ebp+var_24]
- b" \( K+ B1 Y5 ?0 q00508F0C mov eax, ds:Serial_CryHex@Prt
3 d1 D& U! l4 R( |: Q I00508F11 mov eax, [eax]: x, r: J' i$ |" y
00508F13 call CycleConversionStr1 N2 }( x# f% \% _1 u
00508F18 mov eax, [ebp+var_24]1 r7 P/ {) H7 m6 [& U! P+ B
00508F1B mov ecx, 10h5 k% V# H; R1 k
00508F20 mov edx, 1 ;取注册号 1~16 位
2 s8 }$ y* @7 y$ }1 @2 R00508F25 call LStrCopy
! v8 G1 L" }! C6 P9 i00508F2A mov eax, [ebp+var_20]
I# N' m; h3 x00508F2D lea ecx, [ebp+var_1C]4 G0 h& {. j) x% ? |
00508F30 mov edx, [ebp+var_8]
6 J* n0 n3 ^5 j e: ^00508F33 call DES_DecryStr ;这是 DES 的逆运算,我们再跟进1 L1 g$ r! e, ^+ u
00508F38 mov eax, [ebp+var_1C]
2 i8 h7 q; T$ W7 g# t# P% J00508F3B lea edx, [ebp+var_18]3 g8 N. I. F& j# A' Q& B! X
00508F3E call ConversionHex10To164 {3 O a+ S3 r7 @3 h, a8 I
00508F43 lea eax, [ebp+var_18]0 Q+ n7 Z- d/ P7 P! x! \
00508F46 push eax
2 b6 N5 O5 K, O7 p$ M; m3 z00508F47 lea edx, [ebp+var_38]
+ @5 w$ J- }+ Z- [* E: n( V00508F4A mov eax, ds:AppIDAndName_CryHex@Prt
3 D- _* T+ N! r$ A" y* e* R00508F4F mov eax, [eax]
3 v& {+ ^6 R- Q+ m/ O" o) ?00508F51 call sub_4FBA70# y( e+ {/ j) _" g+ W( \
00508F56 mov eax, [ebp+var_38]
3 l/ F7 E& [0 C( z. @00508F59 lea edx, [ebp+var_34] ;这里是我们要下断点的地方- R/ v$ t% T6 i
......
% N7 h1 x2 p; d1 D...... 省略; r4 i- p1 W$ e/ a( c# ~! S1 q5 \
跟进 call DES_DecryStr
; r, t' T+ ?6 V8 }) L......9 F& E) ?5 M; O6 U- t
......省略7 z" V8 p) q5 Z) @+ {4 I* \0 C# V
004F788E lea edx, [ebp+var_C]7 }3 s* ~# {/ l# O
004F7891 mov eax, [ebp+var_4]5 G: v1 I' x3 q2 n/ \5 p6 c; u
004F7894 call sub_4E97BC
+ K0 s( H& V+ a- U$ K$ F; q; q004F7899 mov ecx, ebx' j6 K# j3 K* y% L. z
004F789B mov edx, [ebp+var_8]
! k V! o9 m$ P5 E004F789E mov eax, [ebp+var_C]3 q: P! N6 b$ ^2 N
004F78A1 call DecryStr ;DES 逆运算
' k6 C. q( X) y004F78A6 xor eax, eax ;这里是 moon 帮主提出下断点处,还有一些其他相应的做法
: }5 c0 _* K- t$ T$ k+ U" Q1 H ;请看 moon 原文。
& n) z+ m6 V; X/ J; e8 {6 r6 o......0 _% R0 b$ I! L0 H8 Q
......省略在OD中按 Ctrl-F2,重新启动,在00508F59下断点,同上,将 0055D0A6 的 jnz loc_55D157 Nop 掉,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 00508F59,下面是堆栈内容: % w) l; K- R4 C J" ^( ^
复制内容到剪贴板
( t y( l& V2 y' Q代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"
, W* A4 @9 u& D- [9 qEBP-34 0012F914 00000000
. [4 P) A6 h5 K$ f ~4 WEBP-30 0012F918 00000000
# Y8 ~ N$ @8 w. Z8 N9 C, o7 [0 w; N- CEBP-2C 0012F91C 00000000* z7 G9 {5 O( `
EBP-28 0012F920 000000007 v9 O: H# K, B2 d/ @6 G: |
EBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"
9 E8 K/ K1 {! o, QEBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"
$ {. a8 n/ n% KEBP-1C 0012F92C 00F3009C3 k! g1 K( m/ C5 z
EBP-18 0012F930 C338FAD37 a: ]. t C L
EBP-14 0012F934 DD5CB3D0* D Z& e# J& T9 }4 s' S1 l
EBP-10 0012F938 D5D42656
1 [& _ F# ~% P3 n! qEBP-C 0012F93C A2BB6C94
[6 s4 F# q- ~. o3 Q/ vEBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"4 Y. l8 t- @' w( Q
EBP-4 0012F944 00000000注意: EBP-38 0 00F2A130 ASCII "5FF51115" 这是我们要的 DES 加密的明文。
0 c1 v3 o7 D2 G$ r EBP-8 0> 00F2FFE4 ASCII "M9BJBBRIDE88TNP4" 这是 Key。
# W3 i5 M" F5 n6 c按 moon 帮主的方法,修改两句代码,进行逆运算,但我经过努力,总是没有成功,可能是对 moon 的方法不能深刻的理解,于是决定改用其他的方法。我们注意到如下代码: ) o8 T; B1 I& L: p5 Y
复制内容到剪贴板 " z% s" ~2 j1 Y
代码:004F788E lea edx, [ebp+var_C]
$ \' O0 X( q3 k5 `* S, H004F7891 mov eax, [ebp+var_4]
9 `+ Y' g4 d$ k' Y2 O& L004F7894 call sub_4E97BC
9 T5 Z" C4 {# f7 Q- {6 `004F7899 mov ecx, ebx
* W. g: k' c6 m* F9 t" o004F789B mov edx, [ebp+var_8]# p9 i9 @; [0 h* P# M( ?: D
004F789E mov eax, [ebp+var_C]
A* u2 }! t, W4 Q004F78A1 call DecryStr ;DES 逆运算在最后一句 Call DecryStr 做的其实是DES的逆运算,前面还有一个辅助的运算,我认为,同益的代码中一定有一个DES的正向运算,即EncryStr,所以我找了一下,其实就在上面第三节--【获得的 17~22 位注册码】中出现过,下面我们跟进这个Call:
G7 ~9 [- q6 \! q. t8 W& e复制内容到剪贴板
4 S$ J, k o2 H" d8 N- |) \: C3 e代码:0050C70B call DES_EncryStr
4 M; p0 O) I+ Q& @" i, |) [跟进
. u1 T8 `7 }+ R! q......
% _# ~1 N: \; h* {......省略$ \6 a4 ^& g) f6 ?) p! H
004F781A lea ecx, [ebp+var_C] ; 返回地址3 X) N# d, w3 O' T
004F781D mov edx, [ebp+var_8] ; Key = M9BJBBRIDE88TNP4
) a! _1 U' V; e004F7820 mov eax, [ebp+var_4] ; Str = 5FF51115
+ e5 K' u1 e! h+ e. I R* |3 z004F7823 call EncryStr
1 k+ M9 n+ v' P% Y. E: ~004F7828 mov edx, ebx
0 @8 w9 p' D9 ` V004F782A mov eax, [ebp+var_C]6 d( T6 u0 P5 _ q6 X. L* F, ?
004F782D call sub_4E63F4
6 P: N/ j* C9 j) d$ Q004F7832 xor eax, eax ;这里下断点
- A2 W6 G1 A6 y! |5 R$ I7 y......
! k6 _: k0 n. S: J......省略可以看出,它和上面的代码正好相反,我们用下面的方法来获得 1~16 位的代码。5 T3 V$ Y, n8 B/ V$ V3 d+ P) K
接前面,我们中断在 {1 s4 d& J1 z6 ^' q# c! b0 C9 \
复制内容到剪贴板 ! }" r; `+ H3 P$ T
代码:00508F59 lea edx, [ebp+var_34]在代码窗口中按 Ctrl-G,输入004F781A,转移到 004F781A。按 Ctrl-*,将Eip地址改到 004F781A。" `* a; x* r: h1 D% T) P
我们要做的工作其实就是修改堆栈的地址,下面是具体操作。 , I! e' K. `( h' R5 |
复制内容到剪贴板
9 ~, {" L. D2 z: @代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"8 f/ r% r% T: S! _7 a
EBP-34 0012F914 00000000
; @- d& B0 t6 P9 m) @EBP-30 0012F918 000000007 r# z: R* ^0 ?. U5 t
EBP-2C 0012F91C 00000000
) W5 |2 I L+ oEBP-28 0012F920 000000007 H! k3 u5 K7 m. {! A
EBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"
' i3 t# q6 b( B3 u2 U5 vEBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"
# V6 k, N. p: D' ^7 i8 n& S" LEBP-1C 0012F92C 00F3009C" J! V. Q% I! D7 Q
EBP-18 0012F930 C338FAD3
: m6 w- ~* a+ o, u6 q; AEBP-14 0012F934 DD5CB3D0
1 T: D+ N6 Q, MEBP-10 0012F938 D5D42656# v" K7 b" p$ r3 z* {8 l2 _$ x5 R
EBP-C 0012F93C A2BB6C94 结果返回地址,这里改为 0,程序运行时会自行分配新的内存 m0 P8 n% J* J% {) u- j* e
EBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"/ Y! |! U% J1 P, T: n1 v: j
EBP-4 0012F944 00000000 这里是 Str 所以将这里改为 00F303D0,也就是[EBP-38] 指向的地址。另外,最终返回结果在 Ebx 中,而Ebx 是由上一级的过程传递过来的参数,已经由入口程序做过初始化,所以,必须分配一个有效的返回地址,这点和 [EBP-C] 不同,需要要注意,这里我们将 [EBP-24] 的堆栈地址分配给 Ebx, 也就是Ebx = 0012F924" a) B! U8 Y* ^! y* C8 u) V" e9 V
改完后堆栈如下:
z0 E% S H0 F/ D5 M复制内容到剪贴板 9 e6 H: I0 P# O# t# b& ^! f
代码:EBP-C 0> 00000000; Z* K6 W1 i" v3 b* X/ X1 ~
EBP-8 0> 00F2FFF8 ASCII "M9BJBBRIDE88TNP4" Key: N$ m) `2 s" \; z1 n$ g
EBP-4 0> 00F303D0 ASCII "5FF51115" Str
$ f: ], y7 W. n+ k在将 Ebx 的内容改为 EBP-24 的堆栈地址,即 Ebx = 0012F924 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"在 004F7832 下断点,F9 运行,d [Ebx], [Ebx] =0VBMHYAMA260CSD1 第 1~16 位的注册码- K" }7 r- T+ j
现在我们来修改我们的注册码:
4 F( t) ?1 [5 ^5 r' c" K5 X1234567890123456 789012 34567 8 901
( d& @7 a( v" U# x. P+ i0VBMHYAMA260CSD1 DEDAHI B8MBM B TUV
) B4 \% ]" P5 b/ w, ~2 K' F用前面的小程序调位后得新注册码:
, U0 Q3 {5 b5 u; h1234567890123456789012345678901
9 T; |7 z3 A. Z1 BMVB0MYAH026A1SDCAEDD8IBHBBMMTVU8 t" w9 l; n8 }5 l
五、 获取最后 29~31 位注册码
' S1 ~7 g- [: l. Y* c" U打开注册表编辑器:将Serial中的内容清除:: Y+ U5 Q2 d5 a) n& H
[HKEY_LOCAL_MACHINE\SOFTWARE\GoodSoft\GoodName]
0 C( ?' ~" Z1 z! b4 W8 N7 z"Appid"=dword:059c0935
4 S+ |7 R1 t7 C# }" V r9 x"Serial"="MVB0MYAH026A1SDCAEDD8IBHBBMMTVU"& }( M0 N6 ~4 q$ a
"Serial"="0"$ _4 n& o* c: W
在OD 中按 Ctrl-F2 重新启动,将下面两处 Nop 掉。 , G, |0 ?. B' f2 n
复制内容到剪贴板
; [6 c* ^# Z' T9 s, P6 P代码:0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符! ~ x5 n1 e/ w' P: d' k
0055CFD7 jnz loc_55D157 ;Nop 这里: o& k9 N/ \8 d* n* C
0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同
4 g* ~8 x7 p) t* f" ^! I0055D02A jnz loc_55D0EA ;Nop这里
# g" c* g ~; C1 w, @$ E0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点在上面 0055D0A4 处下断点,F9运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(MVB0MYAH026A1SDCAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 0055D0A4,记录下Eax寄存器的内容,我这里是 2C3AH,换算成十进制数为 11322+ m' W# {4 c4 I0 B0 o5 P( m
根据 moon 帮主的文章:
* K1 p2 a7 ?! u, O; C0 E
' a3 [, f# F9 v* o7 F) \- _求逆方法:, l2 d3 L' \3 I! C% F: f" S, S- c
1. 执行到00559E24,记下eax中的值x,或按照上面的方法计算出这个值;4 _( c- I6 l7 O
2. x除以31,用余数查表"0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ",所得字符作为第31位;
" q9 D' \8 l. ^3. 第2步的商除以31,用余数查表,作为第30位;! {2 O l# E# b/ H
4. 第3步的商查表,作为第29位。+ r* F# W) f' H4 R
--摘自 moon 帮主的文章1 B' I2 O# h8 m F d3 r" @7 e
2 }* y& X8 I' o [. F# V写如下Delphi 的小程序计算最后3位注册码。
' W1 ^; p& {; B复制内容到剪贴板 ( C: G; R& {+ _5 U
代码:procedure TForm1.Button3Click(Sender: TObject);
. ]( |( X& a# J# ^ ?/ H! gconst
4 ~. [$ V1 G' U/ D" A Str = '0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ';
4 P3 p% F7 c$ O) zvar
1 A6 c, Q1 ^* R* r# e) u$ P x1, x2: Integer;% j6 Q- S$ c8 S, N; ^
S1, S2: String;) c! }; t$ q6 N
begin
9 q; Q g5 K. C4 S3 o x2 := StrToInt(Edit1.Text);
. b% W/ f0 w6 R4 c x1 := x2 mod 31;
8 `0 ?" y" b1 V4 J S1 := Copy(Str, x1 + 1, 1);! B& G" b9 [# p% [, X5 z4 ^" n
x1 := (x2 div 31) mod 31;
+ C3 @, Q" M2 e1 _ S2 := Copy(Str, x1 + 1, 1);
* \; o+ c/ [/ `& i, o) g& V S1 := S2 + S1;) l1 R3 R$ I, ~, l
x1 := (x2 div 31) div 31;
' b/ e8 R2 s- B' u S2 := Copy(Str, x1 + 1, 1);* O+ U2 Y+ V7 S% j2 }" @
Edit2.Text := S2 + S1;2 T+ o/ m/ U9 ` a6 j! m
end;在 Edit1 中输入 11322,按 Button3 键,在 Edit2 中给出结果 T8B
5 {& R8 p# O @9 S现在我们将获得最终的注册号:
) k. b7 `% ^' n$ _ D- h1234567890123456 789012 34567 8 901
9 K; ^4 {) K1 K1 n$ k0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B% _- h* X6 r3 ^" a# ~# E( ]# c+ U
用前面的小程序调位后得新注册码:/ S# j5 P8 ?4 z$ K/ i9 M
1234567890123456789012345678901
9 o4 p3 v, k- `6 Y$ c. NMVB0MYAH026A1SDCAEDD8IBHBBMMTB8
2 n" i5 Y1 B0 {9 y" m- r0 s* Q0 h在我的机器上,注册号为 MVB0MYAH026A1SDCAEDD8IBHBBMMTB8 ,用未脱壳的原版注册后所有功能完全正常,公司后缀的分析类似,有兴趣的朋友可以自己试。4 U" \: R, K- U5 { R+ U5 ]% `
另外,对于Delphi的小程序,什么版本都可以,但编译开关 Huge String 要勾上,我使用的是 Delphi 7。
0 k- k/ `( T! M2 F" c6 a说明:
: I1 y O R/ f, G
: p4 h- [+ e, k9 K- Q1、对于调位操作,字符串长度必须是 31 位(不算空格),可以带空格输入,这样比较方便直接拷贝,如可以直接输入: @% S5 N# @ G# Q
"0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B"5 v5 m9 a" `/ x0 X3 \& Q8 o% @, c
2、对于计算最后的第 29~31 位,可以直接输入十六进制数,不过要加 '$' 前缀,例如在我们这个例子中,可以直接输入 $2C3A (不分大小写)。
4 R+ P3 V' a$ D8 F {6 r2 X* s |