正确获得同益起名大师v337 的注册号――解读 moon 帮主的妙文 J) A/ j7 H3 T6 \
【作者】gzgzlxg4 }& `- o* [. A1 b
【声明】只是好奇,没有别的目的,如有,我就把注册机发表了(已经写好了),不要发信向我要注册机,我不会发表的,这也是看雪老大的要求,其实我觉得这篇文章已经很过分。按这篇文章,你100%可以得到正确的注册码。
/ |+ \. c# P- f- k【工具】IDA,OllyDBG1 `9 C+ o2 H% Y2 Y- y% p. C: a' |
【软件】使用我在【ACProtect 1.41 -- 同益起名大师 v3.36、v3.37、vp3.33(专业版)完美脱壳】中所完美脱壳后的 GoodName.Exe v3.37版。使用脱壳版,跟踪比较容易,当然你也可以直接使用原版,但会困难一些。
& l" U0 }8 }% r" F, Mhttp://bbs.pediy.com/showthread. ... &threadid=16204/ \/ m0 A4 L$ \# I
【注】读此文前,请先读 moon 帮主的【谜----同益起名大师3.36注册算法分析】,$ i- ?: ^ Q: R6 v5 j
http://bbs.pediy.com/showthread. ... &threadid=14716 凡是和moon 相同的部分我就不再多废笔墨。
6 c" P3 F2 L" X4 f3 E2 w本文同时发表在看雪论坛和DFCG,转载时请保持完整,版主如果觉得不合适可以删除。
0 c$ h3 C5 T6 a" s6 X1 o) C7 A前言:5 k5 @ a% C8 L1 ~
同益起名的注册码验证遍布全程序,在主窗体建立,子窗口建立,按键操作,对注册码和注册申请码的验证无所不在,而且计算方法来回重复,例如获取注册申请码就有三个完全相同的过程,DES 算法也有完整的两套。我们用来分析注册码取的是注册操作部分,其实在主窗口建立、子窗口建立的过程中都可以进行,因为他们是完全相同的。4 ?! s9 E: p7 v3 r- u) {5 t; E
这是注册窗口(Tfxhm)VMT表中的方法表部分,(全表太长)。这些代码都是在 IDA 中分析得到的。 & D0 A* `1 A" r. K% t) F
复制内容到剪贴板 : I3 A! t. E- v) T0 ^0 F
代码:......7 P4 L" ~. x n4 L# \, X% t
0055647F TfxhmMethodTable dw 6( m S9 Q+ I8 M0 e. v
00556481 dw 16h9 c( }9 }: ~9 K2 s7 W/ B1 Y! t
00556483 dd offset Tfxhm@suiButton2Click ;退出按键
. V0 T( K' B1 B. B& H00556487 aSuibutton2click db 0Fh,'suiButton2Click'
$ W8 z! ~2 U B3 T! Q00556497 dw 10h" N) ]0 T7 ]' Y
00556499 dd offset Tfxhm@FormClose ;关闭窗口6 f* R$ c2 `8 d: x& ` @- o3 e
0055649D aFormclose_0 db 9,'FormClose'
4 ]; C: d: q H2 G" I# {# E005564A7 dw 11h
0 q! R5 ]- Y3 C1 U( ^; a005564A9 dd offset Tfxhm@FormCreate ;建立窗口
# o6 J( p h, ^" q" S; n3 T005564AD aFormcreate_0 db 0Ah
( h. m, Z$ f3 b! ]; U2 [) k* n005564AD db 'FormCreate'1 @7 {4 ~4 T& c. y5 F
005564B8 dw 16h( q. J' l }! h ~. F3 z Q
005564BA dd offset Tfxhm@suiButton1Click ;注册按键
. l, G* a6 j! M" A7 s005564BE aSuibutton1cli ck db 0Fh,'suiButton1Click'
7 e/ @7 | P) D0 R' `: d005564CE dw 0Fh
4 F' f! ?3 b% b- L& j$ y005564D0 dd offset Tfxhm@get_text ;suiButton1Click 调用的校验注册申请码; _, w) T% g+ b* F- D; y% c1 P
;和注册码并注册的子过程3 h7 e* q' l3 i, Y
005564D4 aGet_text db 8,'get_text'
0 o8 M. Q5 F- }6 k. S005564DD dw 0Fh
; c- U. ^2 n% }0 e4 G& f; B005564DF dd offset Tfxhm@FormShow ;显示窗口
/ E+ b! o+ S$ t9 M6 ?" a005564E3 aFormshow_0 db 8,'FormShow'
: e+ Q; J& D- ^4 A2 z" G% a/ @% I2 S005564EC Tfxhm db 5,'Tfxhm' ;类名
7 z& a8 f5 e/ f2 C9 _ R' F: ?9 E4 Y005564F2 word_5564F2 dw 51 u* T+ M. d- i8 b, a& }2 \( a4 n
005564F4 dd offset TsuiForm@VMT@Prt ;父辈 TsuiForm 的 VMT 表指针地址 D7 S* V7 L5 Z/ f& P; K
......我们分析的所有代码都是属于 Tfxhm@get_text 过程和它的子过程的。 Tfxhm@get_text 起始地址: 0055986C' {( I- d% j7 J& W
一、 获取注册码第28位+ B, P1 }% \ s2 p
确定你想注册姓氏的正确笔划数(必须和同益数据库中 slzik 所查到的相同,以繁体字笔画数为准,同益库中有些字的笔画数并不正确,这时你可以在同益起名的姓名分析中获得姓氏的笔画数)。在下面的字符串中从左到右查寻,得到第 28 位注册码:例如,吕:繁体字为 7 划。(从0开始数)
; l2 }* E" i7 G$ n9 g, @, l. \4 L. K0123456 7 89012345678901234567890
% W( M/ |- v7 ^4 \1 h: p6 J0AH6CD3 B EF4TRS2PUV5K1MN78YZ9GIJ
6 y' ~5 m2 h% O得到的字母为 B,这样我们的注册码有如下形式:(31 位)下面是我们的起始注册码
5 F! U9 N# s+ o123456789012345678901234567 8 901
5 M9 l9 r2 @, Q$ d1 I123456789ABCDEFGHIJKLMNOPQR S TUV
O' B: w. o( q. n- N# R加入第 28 个字母 B,得如下注册码:) z0 _1 }$ z6 g
123456789ABCDEFGHIJKLMNOPQR B TUV( [. s* B0 `" U
根据 moon 提出的换位法(4*i+1位和4*(i+1)位互换,i=0,1,2,...,末尾不足4位时,最后两位互换),2528位对调,这个B应该在第25 位% W; }( k) `. [7 \2 L2 s
为了便于调位,写了几句Delphi的小程序来完成:(这种操作,还是汇编容易,所以实际还是汇编写的) $ z0 ?5 l, @; G. _
复制内容到剪贴板
) @0 f: ]" |6 S5 C; |代码:procedure TForm1.Button2Click(Sender: TObject);
8 k4 B; [& z. avar
6 J. i0 _7 o* d* ^1 R- ?' I Str: String;
& u4 o2 g( }2 p2 dbegin
2 C$ |) P/ z4 [1 c+ Z0 J2 l Str := Edit1.Text;
; O3 y! u, ]4 e( v, h" E# S asm
3 w; C! ?+ Q7 y) Z PushA
4 F5 W0 L& x; q3 D6 l Xor Edx, Edx# X) C4 ~8 U! [9 p
Mov Esi, Str' N/ x! ?! u i+ }3 h) E
Mov Ecx, 7' d# r, o4 [, r. v
@1:8 F/ e/ R; v: p) q( L) ~7 z+ n; V
Mov Al, [Esi + Edx]- n/ i- ^$ E) R, k" ^9 Y
Xchg Al, [Esi + Edx + 3]0 Q; q- E/ Z6 w# S
Xchg Al, [Esi + Edx]
" E" K& n% A3 }) f8 R+ y/ G* ], E Dec Ecx8 E! L' K6 r! O2 C1 `* t+ [
Add Edx, 4
4 ` l3 n( v) ]" `1 i Cmp Ecx, 07 V8 J9 J% H$ G3 ~, ]' ^
Jnz @1
: D, L6 X8 r* u2 s6 W2 @2 J Mov Al, [Esi + Edx + 1]
' _3 n, c B$ b' R: a5 \( i+ T Xchg Al, [Esi + Edx + 2]: Y. O" z- N8 x/ j
Xchg Al, [Esi + Edx + 1]& e* H& o8 R6 a( L% F. T X) L
PopA
$ S& s3 S+ E; n' c$ | end;. } @! O8 U% _! Z5 F
Edit2.Text := Str; B# h0 ]5 C- O b/ N0 W+ F* {
end;在 Edit1 中输入 123456789ABCDEFGHIJKLMNOPQRBTUV,按 Button2 键得到下面的新注册码:/ f8 h- Y- J& b6 D D
新注册码为:
1 X5 y3 N {% V$ @* }1 O123456789012345678901234 5 678901$ u& R9 V: d5 Y! p3 Z
42318675CAB9GEFDKIJHOMNL B QRPTVU
+ J/ k3 }1 C4 S5 E5 L2 N4 {: d. P* p( h具体分析请看 moon 的解释。
: o6 t2 e- I: b2 }& K$ D, |1 ?二、 获取注册码 23~27 位注册码
* G' y& o% ?/ l% z d用OD载如 UNGDN.exe (脱壳后的程序)
, ?$ D7 Z/ v' d0 \ f) W复制内容到剪贴板 5 U' v e- G2 O; M( p
代码:Tfxhm@get_text
. ]9 Q( X+ ?: x; N4 P+ ~......! |8 I7 p/ Y6 k! B' {; {7 d
......7 \& k1 q; o4 S, Z7 D. S
0055CF7E mov eax, ds:AppIDAndName_CryHex@Prt ;注册申请号加姓氏和1FH 异或得到的结果
! |+ Z/ H( r. {1 G% V0 x2 c, \0055CF83 mov eax, [eax]4 Z! b/ i g" S( Z
0055CF85 call sub_4FED88 ;EncodeFunction10 f% B8 s- m+ C x& O
0055CF8A lea eax, [ebp+var_94] ;这里断下获取计算23-27位的三个字符
- \/ k4 p% ~/ {$ f: o0055CF8A ;按照 moon帮主的给出的算法可以获得
/ E/ F1 E2 X2 l! ? ^' o0055CF90 pus eax
. V( P" N5 g0 e {+ }( T# E0055CF91 lea edx, [ebp+var_98]
+ C8 ^ G* q' y" Z6 N( ^ j0 H6 t6 p0055CF97 mov eax, ds:Serial_CryHex@Prt ;注册号和 1FH 异或得到的结果0 h$ g/ D' r+ w( O
0055CF9C mov eax, [eax]: A4 ?- I# _3 S8 @3 C3 q9 p
0055CF9E call CycleConversionStr ;经过 1FH 异或,即还原* G6 L& h+ p/ N0 C/ \- h' j1 d
0055CFA3 mov eax, [ebp+var_98]1 o1 k; g# v, v2 B* H; H; U/ ^
0055CFA9 mov ecx, 5/ Q4 ^0 y0 n% e
0055CFAE mov edx, 17h% f8 }8 j) a" F1 F2 g
0055CFB3 call LStrCopy ;取第 23~27位0 r7 L/ h7 W' C. U
0055CFB8 mov eax, [ebp+var_94]+ Y! Y' l( g% B2 _6 U( p d
0055CFBE lea edx, [ebp+var_90]
3 T1 R5 H$ Y3 Y- x( o6 n+ E1 O0055CFC4 call sub_4F0048 ;进行计算得到三个字符,如果和上面计算得到的三个字符相同,则过! [4 A( j/ f4 x& ^
0055CFC9 mov edx, [ebp+var_90]# X& u4 X+ h7 @# a/ L( A
0055CFCF mov eax, [ebp+var_C]$ f T; l+ d% C* Q1 I' V( I0 l1 `) N9 O
0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符
. |. O6 z5 N- L U, F" `0055CFD7 jnz loc_55D157
+ G" j& G Y- X$ j; m1 [7 X0055CFDD lea eax, [ebp+var_A0]5 n3 y6 ]; F0 {5 f& r# G1 u
0055CFE3 push eax# [1 N; M; G4 X/ j0 V; z9 O' B& u
0055CFE4 lea edx, [ebp+var_A4]- ~& b( W( {% I4 w$ N$ \
0055CFEA mov eax, ds:Serial_CryHex@Prt) _7 |" ?! b& r$ j; T+ |4 Y# r
0055CFEF mov eax, [eax]
4 V9 B* F6 M8 S/ z6 f0055CFF1 call CycleConversionStr+ `4 k8 U$ G7 Q; ^0 U2 t/ I
0055CFF6 mov eax, [ebp+var_A4]) W- x: k, h0 ^+ H' W, q
0055CFFC mov ecx, 5
& X2 I+ {$ H- S0055D001 mov edx, 17h ;取注册号23~27
! p+ `& h, ~. n+ v% }: s0055D006 call LStrCopy2 Y3 Z' \9 U5 C3 z( P" |" A, V
0055D00B mov eax, [ebp+var_A0]
% X7 D* Q# v- i$ E/ J" B7 [0055D011 lea edx, [ebp+var_9C]' c+ O3 ?8 c- k# |2 F! G
0055D017 call sub_4F0048
2 m6 o! p4 B5 L/ _4 Z: C0055D01C mov edx, [ebp+var_9C]
6 e* q# L: d" _, F$ i7 X7 v0055D022 mov eax, [ebp+var_C]/ v* S7 \3 R. c4 j
0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同5 c7 ^4 o, Y2 C/ p
0055D02A jnz loc_55D0EA
$ w9 N+ d3 Y. T( o% z/ R0055D030 lea eax, [ebp+var_A8]7 ^$ C; N8 z! |& w# ~
0055D036 push eax) ^7 @( f: h; N- d) a3 o7 `6 d% R
0055D037 lea edx, [ebp+var_AC]1 Y( T; q. T+ `& u9 F! ?
0055D03D mov eax, ds:Serial_CryHex@Prt
: Z Q7 M! |# H' _5 T3 I8 z0055D042 mov eax, [eax]
4 _( i, T" {* |0055D044 call CycleConversionStr
4 p/ R1 N& r9 z! z- X. A; W0055D049 mov eax, [ebp+var_AC]
& ]: p6 D" A% J+ S O0055D04F mov ecx, 3
* `- R- r0 q4 Q6 q$ m% m0055D054 mov edx, 1Dh ;取注册号 29~31 位2 P+ _) |7 g, T1 K* _
0055D059 call LStrCopy
$ i& m/ H1 j3 T/ S0055D05E mov eax, [ebp+var_A8]
: V. l8 A- J# ]2 m8 B0055D064 call 31decimalToHex ;对29~31位注册码进行31进制到十六进制的转换- e1 |. M, U2 B$ b
0055D069 mov ebx, eax0 a, ~/ E7 ]9 D5 W! s
0055D06B lea eax, [ebp+var_B0] ]; v0 `! `' ~1 I
0055D071 push eax
n& x7 t& s/ c6 Q. Q& P0055D072 lea edx, [ebp+var_B4]7 q* w' o1 W' n
0055D078 mov eax, ds:Serial_CryHex@Prt ;取注册号(经过1FH异或处理)3 O$ ^6 w3 d2 t* H' i
0055D07D mov eax, [eax]+ H: N1 b5 j" r. b
0055D07F call CycleConversionStr ;经过相同的过程还原3 ]$ c& ?3 D. y0 a- A6 U1 @- m8 }- l1 ?
0055D084 mov eax, [ebp+var_B4]6 x+ Y @, N" U' U8 r
0055D08A mov ecx, 1Ch
2 p6 F% F5 V" u* x" k1 u0055D08F mov edx, 1 ;取注册号 1~28 位8 P" w( `0 j6 y/ M; u$ U
0055D094 call LStrCopy
3 d- c ?* X' D* b0055D099 mov eax, [ebp+var_B0]8 m2 r1 \ Y f
0055D09F call SumSerial_1to28 ;做 1~28 位累加(中间还有判断是否大于27000,见moon帮主的解释)$ ^& E( ^. H4 C4 u9 B
0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点
/ [+ _8 D3 M! ^' f w8 c$ L5 V0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉
, B: R4 Y# h1 I! t# P, i$ o0055D0AC mov eax, offset a111_2 ; "111"* W9 c$ J k7 t9 i7 w7 v( y3 H" G
0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口
% D3 C: C, D$ J x( z! r5 E6 e0055D0B6 mov [ebp+var_1], al
" Q0 }* a: v& e% ^( g0 H: Z; s' }0055D0B9 cmp [ebp+var_1], 0" I6 {% p; P! P8 @- x2 s
0055D0BD jz short loc_55D0CC
- h* @! D% n. Q, h0055D0BF lea eax, [ebp+var_C]* n( C) L- S* J2 q' u
0055D0C2 mov edx, offset a111_2 ;"111"
: Z: M" n7 F* N/ n1 ~3 e0055D0C7 call LStrLAsg
4 d. }( ~( I9 c* v0 b$ c& A% L! O/ e! r0055D0CC
i& X( J5 V" } x& Y0055D0CC loc_55D0CC:( B3 D1 q. g2 X
0055D0CC cmp [ebp+var_1], 0
; _' Z; `8 u% ^: o" X* G0055D0D0 jz loc_55D1570 I( G Z4 h# |9 D5 n( l
0055D0D6 mov eax, [ebp+var_C]
' O, G) b: H" G$ i+ `0055D0D9 mov edx, offset a111_2 ;"111", M$ K7 Z% }5 v) O h
0055D0DE call LStrCmp& T0 f: a3 {7 f8 c" M; z! @
0055D0E3 jnz short loc_55D0EA1 F/ v, `4 i+ D# K* R/ q& v
0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口在0055CF8A 处下断点,F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',注册申请码是不能修改的,由你的机器的 CPU 和硬盘的参数变化而来。在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的 123456789ABCDEFGHIJKLMNOBWRSTUV 注册码拷贝到输入窗口。按【注册】键,中断在 0055CF8A ,清除断点(或关闭),由 [ebp - c] 中的内容,得到三个字符 VRB,记录下这三个字符,用moon帮主给出的方法:1 ?" X8 U7 N; S$ ?4 r/ L* L
0 u7 ^0 a: V8 d, t' ]求逆方法:
( Q; c7 ^* Y B9 V( A8 {+ D1. 执行到00559D0A,然后下:d [ebp-c],记下数据区显示的正确值x,y,z;
) U8 w' @" u8 }- E; o2. 对3个字节的正确值进行调位,得到5个字节a,b,c,d,e,调位方法为:" v0 h" J+ O2 z, a0 o
0,0,0,x7,x6,x5,x4,x3
/ S8 n" M/ r1 H8 [; x% X0,0,0,x2,x1,x0,y5,y46 ^4 i9 ]; B$ B
0,0,0,0 ,y3,y2,y1,y04 a+ C$ q2 r* A o# Z5 E. p1 U/ o+ i
0,0,0,y7,y6,z7,z6,z5
. I5 D3 ?5 M( k* _0,0,0,z4,z3,z2,z1,z0
3 t+ U, k/ U& h, P1 a4 ~0 P3. 根据5个字节查表"0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX",得到5位注册码即为23~27位。! r/ T# w$ K3 G z8 V1 B: N3 [$ Q
--摘自 moon 帮主文
, @. O1 {) |2 V- k; K. ^+ M" p5 o6 I
我用Delphi写了几句小程序完成这个转换,程序如下:
1 D; {! A/ l+ u, i1 K' b" V复制内容到剪贴板 ( y# ~$ ]# B6 r9 t
代码:procedure TForm1.Button1Click(Sender: TObject);4 u3 T2 }/ ~, e3 G/ e
const
9 M8 u4 a( \5 j) q* O6 D, K- z Str = '0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX';
, p. N/ D- z) i( D& H2 P6 Vvar
9 w9 B7 W& u/ Q; T- D# r; O+ y. _ X1, X2: Integer;
1 K9 P2 u& F3 J$ M x, y, z: Char;/ i' Y/ g( {" u9 w8 j% D& T: L8 }2 P
a, b, c, d, e: string;- R3 _4 h, s3 {4 N" ^# C* P
Pin: string;
" B' \4 b/ o! M8 cbegin' q' {' C# o( v! z2 b# ^
Pin := Edit1.Text;# t* ]+ N V5 ~, N* z; I8 }
x := Pin[1];
, O7 o9 D# J; m8 |7 E2 F; `( i, z y := Pin[2];- k/ w7 r1 [+ n
z := Pin[3];
0 f$ Z- C2 B: I8 H x1 := (Byte(x) shr 3) and $1F;
, _3 Q* v4 A5 t* p- X" S a := Copy(Str, x1 + 1, 1);8 w5 k, L8 N0 m4 G" T( i
x1 := ((Byte(x) shl 2) and $1C) or ((Byte(y) shr 4) and $03);7 T0 d ~! D6 s6 B5 E v; x/ L
b := Copy(Str, x1 + 1, 1);
7 k! W9 C1 v2 G5 i x1 := Byte(y) and $0F;: i+ ~1 {3 w8 O9 V
c := Copy(Str, x1 + 1, 1);; Y; D6 G, I/ ^1 [* z: R% a
x1 := ((Byte(y) shr 3) and $18) + ((Byte(z) shr 5) and $07);- W9 E; @; Y) s, O% i- \! |
d := Copy(Str, x1 + 1, 1);
8 _3 m2 A4 b4 Z& T8 @ x1 := (Byte(z) and $1F);
3 I3 J% e( u' O7 r6 | e := Copy(Str, x1 + 1, 1);
$ ^3 I( G; A' [& }0 l# [0 S8 I Edit2.Text := a + b + c + d + e;
; c: |3 s5 U$ O" P6 mend;在 Edit1 输入 VRB 按 Button1 键,在 Edit2 窗口中给出我们要的结果 B8MBM 。现在来继续完善我们的注册码。将得到的字符串替换原注册码中第 23~27 位:8 w a6 V# O( g% b
1234567890123456789012 34567 8 901" ~* L9 C9 |* [' Q) Q, K6 r
123456789ABCDEFGHIJKLM B8MBM B TUV/ m% T: ]2 a; H/ F2 Z8 u
用前面的小程序进行调位,得新注册码如下:0 {* x6 o: y; f9 U! D# ^2 s
1234567890123456789012345678901
. Y" ^' f) {: \+ l! v42318675CAB9GEFDKIJH8MBLBBMMTVU
; H4 j' G3 x" F7 K R& l三、 获得的 17~22 位注册码:
2 ~4 N) d8 [( G; W: O( M- f在OD中按 Ctrl-F2组合键,重新运行程序,将 0055D0A6 的 jnz loc_55D157 Nop 掉
0 X- e9 h9 \- g/ t7 {' z7 X: {复制内容到剪贴板
* f7 k9 S: L' a代码:0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉. c' D6 _8 u T, u0 b* P& t. ? e' Y
0055D0AC mov eax, offset a111_2 ;"111"6 C# L; g. r+ J" Q4 s+ l( M' {
0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口, i2 y/ V8 p: D. A4 j3 l
跟进 0055D0B1 call CheckSerial_17to22: t7 Q1 e$ M# F6 e! o
......
' @' N$ J1 Z0 p...... 省略7 f8 }& ^; Q; G- H
0050C705 mov edx, [ebp+var_20]8 k# o' W% k2 F. u2 I+ z
0050C708 mov eax, [ebp+var_1C]/ M M9 Q7 m4 l
0050C70B call DES_EncryStr ;在这里进行 DES 的 EncryStr 加密运算,运算结果再经过% z( ?9 ~3 R, ]$ I. u
0050C70B ;另一过程处理,这个子过程我们后面还要用到
3 r' d1 i0 u/ W0050C710 mov edx, [ebp+var_60] ;moon 文中提到在这个位置获取 17~22 位注册码,可能' ~' l) A4 Q! {, m
0050C710 ;是帮主写文章时粗心了,正确的位置应该在下面删除第5位
# c* e K6 m3 f8 X0050C710 ;相同字母后才取结果。; _6 q& h6 S; u5 H% K+ x
0050C713 lea eax, [ebp+var_20]
5 S& C/ P7 c5 v& w" ~0050C716 call LStrLAsg1 R0 X6 Y# G$ {5 e+ ~2 I t
0050C71B lea ecx, [ebp+var_64] U; d/ R. E& f' `/ o
0050C71E mov eax, [ebp+var_20]* w: P; l& i% P* {3 p) r0 T
0050C721 mov dl, [eax+5] ;取出 EncryStr 运算结果的字符串的第 5 位
; o# Z+ ?0 u& e. A. w# g7 e0050C724 mov eax, [ebp+var_20]% r2 Q# K. t5 z) i# t
0050C727 call DelChr ;将 EncryStr 运算结果中凡是和第5位相同的字母删除
* E8 T8 A# G W" I+ j ~0050C72C mov edx, [ebp+var_64]
7 m, {5 w: M6 [3 k0050C72F lea eax, [ebp+var_20] ;这里下断点,从Edx中取前6位,即我们要的第 17-22 位
1 b, X# w: }. Y/ D......' U# Y0 n* G3 }8 ]/ y6 Y7 ^8 O- Y
......省略在 0050C72C 处下断点,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDKIJH8MBLBBMMTVU)拷贝过去。点击【注册】按键。中断在 0050C72F,在Edx 返回一个长度为30的字符串(这个字符串的长度是不一定为30的,要看删除相同字符的数目而定),取前 6 为,即为我们要的注册码的第 17~22位,在我们的例子中得到的字符串是:DEDAHI。现在我们来修改我们的注册码:9 k- o# O$ p4 h+ f9 x+ R
1234567890123456 789012 34567 8 9019 z4 h( u- _* M g: |9 _) m
123456789ABCDEFG DEDAHI B8MBM B TUV9 }1 K- |- s0 J7 k$ k0 h9 M
用前面的小程序调位后得新注册码:1 _2 \, ]4 t4 b, M
1234567890123456789012345678901$ K: R6 K& {* R( Q; c6 Z! j3 C
42318675CAB9GEFDAEDD8IBHBBMMTVU3 {" v, D) V o
四、 获取 1~16 位注册码
) X- P( V* }* g# r5 J& g我们首先来看看程序的代码,从前面列出的程序最后一句: 2 K7 E9 t9 w: j% O$ y
复制内容到剪贴板 ; s9 D8 [' } H9 p) n" \
代码:0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口
6 `6 H8 {. Q2 J) W! Y跟进 call CheckSerial_1to16
$ w0 o/ k& P9 n; b......
[ C2 \+ N- ]! a0 _......省略4 P1 T' x& J3 O+ S$ G
00508EEB lea edx, [ebp+var_18]
* ]# I/ I ?: M00508EEE mov eax, ds:AppIDAndName_CryHex@Prt
# g1 A6 _7 C5 o3 x& S6 z4 m8 F00508EF3 mov eax, [eax]
# M' |) p3 K) h$ K4 ?: z00508EF5 call ConversionHex10To16
1 ~9 R, n, m$ t( n+ y) a' F0 Z2 @00508EFA lea eax, [ebp+var_18]
, d- T# P' |8 z3 E00508EFD lea edx, [ebp+var_8]! g, ?4 E# u' n" p
00508F00 call ConversionHexAndFNameToStr
& a% ~* Z- D$ p, I00508F05 lea eax, [ebp+var_20]4 @/ Q3 p/ H. w \
00508F08 push eax
9 Q& \+ t$ L9 X3 U: }3 y/ K1 ~00508F09 lea edx, [ebp+var_24]
, j' K& H; X4 S% M, X3 ^00508F0C mov eax, ds:Serial_CryHex@Prt
# L5 r: {% z$ Q7 \+ n6 H. V. j8 V00508F11 mov eax, [eax]. }$ p7 C ~$ U2 v3 R. n* R2 K. R
00508F13 call CycleConversionStr$ [! j( Q. f" G, t- k! ~( S, Q
00508F18 mov eax, [ebp+var_24]- L. t) U4 H0 z7 g6 h) Q1 w# F+ J
00508F1B mov ecx, 10h
2 M& c0 i" ~# [3 h# ]5 m3 I9 y m00508F20 mov edx, 1 ;取注册号 1~16 位
( q1 z9 {$ `' \7 q4 D, T00508F25 call LStrCopy
( I5 N6 z1 c% w9 p00508F2A mov eax, [ebp+var_20]( p {* p6 P% l( M: x
00508F2D lea ecx, [ebp+var_1C]
8 }/ e% N4 l+ C% F3 J0 J7 d0 }00508F30 mov edx, [ebp+var_8]" w& ?7 G" R; l
00508F33 call DES_DecryStr ;这是 DES 的逆运算,我们再跟进+ L4 b/ x, R2 R' h& Z$ D* o! f4 i
00508F38 mov eax, [ebp+var_1C]
3 |$ A' B% z Y p; @# m00508F3B lea edx, [ebp+var_18]# n9 u) M+ k, i# b; C- B
00508F3E call ConversionHex10To16
7 l' S) W( C9 K% A00508F43 lea eax, [ebp+var_18]
H$ A# a0 Y2 ~, M00508F46 push eax! p3 f, P- |5 {1 V, {0 {+ w+ A
00508F47 lea edx, [ebp+var_38]
# m6 G k/ |: g" R! V. H% @) |6 M00508F4A mov eax, ds:AppIDAndName_CryHex@Prt9 @! B/ _: A. H. u1 P
00508F4F mov eax, [eax]; P& g8 w, y ^( A7 Q
00508F51 call sub_4FBA70
6 e0 D/ S8 Y( u# J% i00508F56 mov eax, [ebp+var_38]
- M; b3 X' j3 k( n( Y. t2 |9 Z00508F59 lea edx, [ebp+var_34] ;这里是我们要下断点的地方
6 `3 {3 z% `; ?; y8 a6 g0 X H0 w....../ K; e+ I- ^( p) G! L
...... 省略% N4 I8 h7 N+ q
跟进 call DES_DecryStr8 r7 v5 |+ l# [
......0 k2 ?. Y3 f/ e W7 z5 z3 Q
......省略
9 }* r# d$ P1 P' H3 A0 `6 t004F788E lea edx, [ebp+var_C]
4 w* k; Y" i1 g' z- @004F7891 mov eax, [ebp+var_4]2 L/ _( v9 b j% o* Z5 L+ M
004F7894 call sub_4E97BC
; p, Q' U! S$ S: U0 w, l8 I6 p004F7899 mov ecx, ebx! P: r0 {5 c! @# D) r- i
004F789B mov edx, [ebp+var_8]1 e! `3 e+ B7 ^' r0 A: h
004F789E mov eax, [ebp+var_C]
# W" p5 T0 i* q6 l; ~0 i1 Z0 d004F78A1 call DecryStr ;DES 逆运算2 Y" Z" B' t% X5 x5 ^9 r4 J2 a
004F78A6 xor eax, eax ;这里是 moon 帮主提出下断点处,还有一些其他相应的做法
& o3 u% B( C/ B7 r8 ?% T' B. X/ Y ;请看 moon 原文。" e2 l" @/ ~0 k0 U5 c) }2 `' _
......( h# W* s8 ?, z# s8 o0 Z
......省略在OD中按 Ctrl-F2,重新启动,在00508F59下断点,同上,将 0055D0A6 的 jnz loc_55D157 Nop 掉,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 00508F59,下面是堆栈内容: & h. T9 x6 I0 _, _0 s
复制内容到剪贴板 / f# r8 ~8 h" M7 o* r
代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"
8 W, r. `) E9 a( k% oEBP-34 0012F914 00000000+ p- v* j# x7 w: J% a
EBP-30 0012F918 00000000
4 n8 P( n" |; m! B! {4 tEBP-2C 0012F91C 00000000
' `+ \# E. h- V# k" J* q1 PEBP-28 0012F920 000000004 b [3 B: a3 T8 [1 H% U
EBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV". S/ m) ^1 W# E! O
EBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"0 |# M% [) V) ^0 z& d; B: m3 _
EBP-1C 0012F92C 00F3009C$ S2 R7 h( a& O: d( I
EBP-18 0012F930 C338FAD3
2 E+ H# R" y( w& \ _; |/ V. g! R, q3 OEBP-14 0012F934 DD5CB3D0
8 ~ _! P+ u5 t- vEBP-10 0012F938 D5D42656" [* P/ j3 P* l
EBP-C 0012F93C A2BB6C94" G Y9 F# t+ t3 Z+ ? s* M2 K
EBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"
4 }1 E R0 k9 [2 w6 w1 m6 _6 s+ hEBP-4 0012F944 00000000注意: EBP-38 0 00F2A130 ASCII "5FF51115" 这是我们要的 DES 加密的明文。4 o* O) k6 l' L' O$ L6 \. I
EBP-8 0> 00F2FFE4 ASCII "M9BJBBRIDE88TNP4" 这是 Key。. Y; W$ l: |% W9 v
按 moon 帮主的方法,修改两句代码,进行逆运算,但我经过努力,总是没有成功,可能是对 moon 的方法不能深刻的理解,于是决定改用其他的方法。我们注意到如下代码:
+ w1 B+ p5 u0 E复制内容到剪贴板
$ n l; ] v5 n; F" a ]代码:004F788E lea edx, [ebp+var_C]
8 k' x: k: r, ?8 u6 K004F7891 mov eax, [ebp+var_4]
+ G5 v- P+ \! I% f' [" U% x004F7894 call sub_4E97BC
1 p. v n1 R8 m' T7 c% H( I. I004F7899 mov ecx, ebx2 I% S$ ~2 ?7 b7 k
004F789B mov edx, [ebp+var_8]
0 R! [- p0 H* Q) r004F789E mov eax, [ebp+var_C]
( h$ q0 D5 Z6 |7 ~/ M1 f& q( d+ d004F78A1 call DecryStr ;DES 逆运算在最后一句 Call DecryStr 做的其实是DES的逆运算,前面还有一个辅助的运算,我认为,同益的代码中一定有一个DES的正向运算,即EncryStr,所以我找了一下,其实就在上面第三节--【获得的 17~22 位注册码】中出现过,下面我们跟进这个Call:
! }/ L m' N0 d+ i: h4 h) P复制内容到剪贴板
4 k- g! [' n* W$ y$ x/ z M代码:0050C70B call DES_EncryStr
) y' O+ C7 g( r [; v" m跟进/ v1 M3 x; W' j. G$ ~8 m' W- B
......2 `$ x% k. s G4 U6 d
......省略
1 C% q9 t9 n9 I6 ~& N" V3 ?/ |/ a/ l2 z004F781A lea ecx, [ebp+var_C] ; 返回地址
5 [8 [$ R3 ~" x+ \. E/ b* H; x0 {004F781D mov edx, [ebp+var_8] ; Key = M9BJBBRIDE88TNP4 n2 ?9 t& m5 b6 K5 `7 V+ v
004F7820 mov eax, [ebp+var_4] ; Str = 5FF51115* k+ g7 h, ^8 C% k: [6 H2 A
004F7823 call EncryStr
4 e1 u- X! ^2 C/ n: q' U004F7828 mov edx, ebx
1 l+ ?; J) B$ T6 v* g004F782A mov eax, [ebp+var_C]& [2 l# `* O; l" J$ h9 F& H3 E/ |
004F782D call sub_4E63F4' L" v' E# M! s9 _" B
004F7832 xor eax, eax ;这里下断点* M! g* S/ j* a+ m
......" J& U3 R& c Q' G
......省略可以看出,它和上面的代码正好相反,我们用下面的方法来获得 1~16 位的代码。
7 l$ @& q: V. G& x接前面,我们中断在 * Y5 E- B: f* m" O4 }
复制内容到剪贴板
) R# C2 [$ h% v1 y9 @; J) A代码:00508F59 lea edx, [ebp+var_34]在代码窗口中按 Ctrl-G,输入004F781A,转移到 004F781A。按 Ctrl-*,将Eip地址改到 004F781A。
# ~# O: o6 K! |- Q0 J1 m" j( ^我们要做的工作其实就是修改堆栈的地址,下面是具体操作。 1 }* x' v# I& v% g& Z
复制内容到剪贴板
9 V9 R* w# e/ d$ p* u# ?( R代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"' c$ r# f' f, j {
EBP-34 0012F914 000000006 |. |6 } x! f: O# U$ O& a
EBP-30 0012F918 00000000
+ i2 e# \1 S- k. R0 w6 Z4 KEBP-2C 0012F91C 00000000
# q+ h6 N* \& e+ _0 V$ eEBP-28 0012F920 00000000
- _* S9 C& _# P. V2 k! w- J3 ZEBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"# H( A# p. T0 [; w8 v7 j2 L7 J/ r
EBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"' t @* _4 A- r' \: c4 @
EBP-1C 0012F92C 00F3009C
! c# p( `1 d$ N8 @$ dEBP-18 0012F930 C338FAD3
- t+ F0 z* y0 X6 x/ B; W0 g* YEBP-14 0012F934 DD5CB3D0: T7 F: x8 _' R5 r! I
EBP-10 0012F938 D5D42656
; y) @! d$ g% v2 g: j% nEBP-C 0012F93C A2BB6C94 结果返回地址,这里改为 0,程序运行时会自行分配新的内存
5 `/ |4 r& P7 g" P) YEBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"3 ~8 `2 G0 C/ V* Q" N7 c% Y) U' T
EBP-4 0012F944 00000000 这里是 Str 所以将这里改为 00F303D0,也就是[EBP-38] 指向的地址。另外,最终返回结果在 Ebx 中,而Ebx 是由上一级的过程传递过来的参数,已经由入口程序做过初始化,所以,必须分配一个有效的返回地址,这点和 [EBP-C] 不同,需要要注意,这里我们将 [EBP-24] 的堆栈地址分配给 Ebx, 也就是Ebx = 0012F924
& U/ `' ^, o r# d改完后堆栈如下: ) {# b" t4 F1 d- W! p
复制内容到剪贴板 * g8 u9 @5 i) R- j8 l" {( y
代码:EBP-C 0> 000000007 o0 N( \1 `/ t6 ]0 B( J7 W5 `
EBP-8 0> 00F2FFF8 ASCII "M9BJBBRIDE88TNP4" Key
2 c0 Q# x& a# _# E9 fEBP-4 0> 00F303D0 ASCII "5FF51115" Str
* I! q: \' B7 K4 ~8 g% W在将 Ebx 的内容改为 EBP-24 的堆栈地址,即 Ebx = 0012F924 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"在 004F7832 下断点,F9 运行,d [Ebx], [Ebx] =0VBMHYAMA260CSD1 第 1~16 位的注册码
( T0 r/ _7 t* c2 F8 q! s5 g9 A现在我们来修改我们的注册码:1 K* C: w1 [5 B4 ~6 V9 d
1234567890123456 789012 34567 8 901
0 M! y# J( I5 Y/ _0VBMHYAMA260CSD1 DEDAHI B8MBM B TUV. ^( [+ N9 i6 I( A8 }7 Y0 I& A
用前面的小程序调位后得新注册码:3 R0 p8 W6 ^5 ]1 E# C
1234567890123456789012345678901; W5 |5 f1 W0 W- E9 W
MVB0MYAH026A1SDCAEDD8IBHBBMMTVU
1 G9 B! v5 @4 t H* [* ~五、 获取最后 29~31 位注册码
5 U r$ G8 b1 Q) \打开注册表编辑器:将Serial中的内容清除:' E! X& t$ e: X* n5 {5 O
[HKEY_LOCAL_MACHINE\SOFTWARE\GoodSoft\GoodName]: D4 L3 h1 W; G) F: {- p& R- k
"Appid"=dword:059c0935$ Z* D) y& _- ?6 r: J; m. V9 F8 G
"Serial"="MVB0MYAH026A1SDCAEDD8IBHBBMMTVU". \2 W0 H6 X% {2 [5 |
"Serial"="0"8 r3 i1 i3 J5 i( G
在OD 中按 Ctrl-F2 重新启动,将下面两处 Nop 掉。
$ r5 S, |5 V" \. c# {- ?复制内容到剪贴板 : `0 q9 h2 b+ f: b u8 s: r
代码:0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符1 _" u8 R3 E: c- E) g8 m; P
0055CFD7 jnz loc_55D157 ;Nop 这里
- W. |. |. f+ p# m/ s' O) f; C3 ]0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同
) x5 n4 J3 u# N" n! }9 X0055D02A jnz loc_55D0EA ;Nop这里) U7 C8 [( d$ v2 L+ C
0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点在上面 0055D0A4 处下断点,F9运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(MVB0MYAH026A1SDCAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 0055D0A4,记录下Eax寄存器的内容,我这里是 2C3AH,换算成十进制数为 11322
4 X2 H1 x2 n7 Y; @* e9 c根据 moon 帮主的文章:
* o6 p! x& A5 i; v2 q
7 N4 @7 e- t1 r1 ]. k5 J" e求逆方法:# u* P3 s5 Y& f4 U1 f5 C5 e! T
1. 执行到00559E24,记下eax中的值x,或按照上面的方法计算出这个值;
8 L, e2 x7 @. [, `( m- V" ~, a2. x除以31,用余数查表"0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ",所得字符作为第31位;" ]7 J8 B) x( ~9 b4 J* z: w7 D, B4 K
3. 第2步的商除以31,用余数查表,作为第30位;+ G8 S# d+ P1 j6 d' ^! V2 q- x
4. 第3步的商查表,作为第29位。
' m" Q% X1 v P' X$ ]3 w; O. K--摘自 moon 帮主的文章1 u7 b I& q: r
! p( ?( O, J) F, f3 c
写如下Delphi 的小程序计算最后3位注册码。
5 k4 _% N: a% r1 H% J复制内容到剪贴板 & c. h: \6 O: G
代码:procedure TForm1.Button3Click(Sender: TObject);; m7 \: ]* P, y+ {( }/ u
const; r s$ [' Q+ H3 ~+ \
Str = '0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ';
8 ^; N! O) l+ G+ B0 M; D4 x7 wvar3 [1 ?; O/ [$ f) k, C
x1, x2: Integer;
. l( t' W! Q! x9 u9 h S1, S2: String; I5 `' k, d3 S) Z0 p7 O
begin
+ ` e- y# R2 A x2 := StrToInt(Edit1.Text);
$ ^. l. I5 F. W! W x1 := x2 mod 31;
' }3 x5 K+ K6 w4 L4 C) V S1 := Copy(Str, x1 + 1, 1);
4 A+ V2 z0 V& j% F$ F% i x1 := (x2 div 31) mod 31;7 B1 H. E' l0 ?0 g! F% r' A* l
S2 := Copy(Str, x1 + 1, 1);
. F- q9 a% |' z S1 := S2 + S1;
- N' m% F7 O" y' `& ^0 h" C x1 := (x2 div 31) div 31;6 E) W$ G! V( [9 }
S2 := Copy(Str, x1 + 1, 1);
0 F- p, x) e8 l2 _1 T Edit2.Text := S2 + S1;( ]5 C/ C" A# H. Q4 F H! v
end;在 Edit1 中输入 11322,按 Button3 键,在 Edit2 中给出结果 T8B* S' A3 F$ B) K0 U+ L" }8 ^) u- D
现在我们将获得最终的注册号:
' p% q" a# D Q" R1234567890123456 789012 34567 8 901
) D, B9 b: l) U4 Q7 M ^0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B
. L) |+ I0 u- o5 G4 L3 M用前面的小程序调位后得新注册码:( U! E0 W- |& c% k
12345678901234567890123456789010 ?8 N" v# g8 {: F
MVB0MYAH026A1SDCAEDD8IBHBBMMTB87 \' @0 z4 r+ j3 m3 [, p+ G; R; t( G
在我的机器上,注册号为 MVB0MYAH026A1SDCAEDD8IBHBBMMTB8 ,用未脱壳的原版注册后所有功能完全正常,公司后缀的分析类似,有兴趣的朋友可以自己试。
6 w/ [- q( h# S4 J: K另外,对于Delphi的小程序,什么版本都可以,但编译开关 Huge String 要勾上,我使用的是 Delphi 7。
8 n, U4 ~( Z6 `8 g1 R; e7 @0 L说明:3 [9 B0 Q) v' Z( p2 O7 d" r- e$ P A
8 H6 W/ T9 P" z1、对于调位操作,字符串长度必须是 31 位(不算空格),可以带空格输入,这样比较方便直接拷贝,如可以直接输入:; V6 N W: d$ o9 f' F5 ]
"0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B"" @0 c. M: T+ Z' D. Q5 R/ ~
2、对于计算最后的第 29~31 位,可以直接输入十六进制数,不过要加 '$' 前缀,例如在我们这个例子中,可以直接输入 $2C3A (不分大小写)。+ q# y9 u2 K, d+ \. K
|