正确获得同益起名大师v337 的注册号――解读 moon 帮主的妙文9 w- v/ y$ D0 {4 A$ d6 U) H
【作者】gzgzlxg
. i" r2 U) b, a Y# C【声明】只是好奇,没有别的目的,如有,我就把注册机发表了(已经写好了),不要发信向我要注册机,我不会发表的,这也是看雪老大的要求,其实我觉得这篇文章已经很过分。按这篇文章,你100%可以得到正确的注册码。2 E5 n5 q! w5 Z8 B5 ~( w/ ~& w, C
【工具】IDA,OllyDBG
% x- O5 d I0 ~2 Y【软件】使用我在【ACProtect 1.41 -- 同益起名大师 v3.36、v3.37、vp3.33(专业版)完美脱壳】中所完美脱壳后的 GoodName.Exe v3.37版。使用脱壳版,跟踪比较容易,当然你也可以直接使用原版,但会困难一些。4 Z: f8 H* v. Y) ?2 l$ p1 k ^: B
http://bbs.pediy.com/showthread. ... &threadid=16204) ?1 R7 m7 I+ W7 f% p4 I
【注】读此文前,请先读 moon 帮主的【谜----同益起名大师3.36注册算法分析】,
2 C1 G; c: L7 Z2 }$ y0 A2 y/ ehttp://bbs.pediy.com/showthread. ... &threadid=14716 凡是和moon 相同的部分我就不再多废笔墨。# W. s- O( ? H
本文同时发表在看雪论坛和DFCG,转载时请保持完整,版主如果觉得不合适可以删除。
- t: ]2 Y4 `' T: ~- L前言:4 G( y1 X8 }) S$ n8 k' K: F
同益起名的注册码验证遍布全程序,在主窗体建立,子窗口建立,按键操作,对注册码和注册申请码的验证无所不在,而且计算方法来回重复,例如获取注册申请码就有三个完全相同的过程,DES 算法也有完整的两套。我们用来分析注册码取的是注册操作部分,其实在主窗口建立、子窗口建立的过程中都可以进行,因为他们是完全相同的。& R8 T3 d4 q' {( {4 c8 T) L
这是注册窗口(Tfxhm)VMT表中的方法表部分,(全表太长)。这些代码都是在 IDA 中分析得到的。 ( q& k- j9 j! U
复制内容到剪贴板
9 J4 E0 q1 V: c代码:......' Z9 O/ F9 k9 Q3 q6 e4 z0 y
0055647F TfxhmMethodTable dw 6$ ^+ P" v3 k6 E) w; ~' k
00556481 dw 16h
4 P) \$ ]8 F5 m( D& u, ^0 q00556483 dd offset Tfxhm@suiButton2Click ;退出按键4 V% [) g8 V C
00556487 aSuibutton2click db 0Fh,'suiButton2Click'1 v( s" M5 K# ~5 f7 B) t; w
00556497 dw 10h i2 `" N; \1 R A+ }
00556499 dd offset Tfxhm@FormClose ;关闭窗口4 \5 p2 h+ U# y3 ` r
0055649D aFormclose_0 db 9,'FormClose', y2 D0 Y) g5 _ Q0 l& R
005564A7 dw 11h) f& y4 G# y, D$ b
005564A9 dd offset Tfxhm@FormCreate ;建立窗口8 Q9 M" `9 y2 t G5 O
005564AD aFormcreate_0 db 0Ah
8 x, y2 r& K; ^9 t005564AD db 'FormCreate'' z4 q; e4 T) h1 ]
005564B8 dw 16h# u9 C3 x! D0 H5 ^
005564BA dd offset Tfxhm@suiButton1Click ;注册按键
# R8 W* \: c d2 |% G; j005564BE aSuibutton1cli ck db 0Fh,'suiButton1Click'* c, h$ @5 T r5 R0 y5 I; m
005564CE dw 0Fh
1 C5 n# v( _. `5 H005564D0 dd offset Tfxhm@get_text ;suiButton1Click 调用的校验注册申请码4 J; q' ^0 C7 _! {# f
;和注册码并注册的子过程
8 s( Y$ |. ^, J4 \; S$ d. G) x! T005564D4 aGet_text db 8,'get_text'* V) R7 O' ^" B0 {
005564DD dw 0Fh
% n6 D3 P1 ? @2 R5 d005564DF dd offset Tfxhm@FormShow ;显示窗口5 c1 H4 C$ o+ G
005564E3 aFormshow_0 db 8,'FormShow'# o) f# n8 |7 R" D
005564EC Tfxhm db 5,'Tfxhm' ;类名
1 M( R2 G; z9 o f1 ~8 M005564F2 word_5564F2 dw 5
# x, W- p- ~# D5 j6 M. x4 r6 \% R4 Y! Z005564F4 dd offset TsuiForm@VMT@Prt ;父辈 TsuiForm 的 VMT 表指针地址: o, p* S" J; P6 T' A3 d
......我们分析的所有代码都是属于 Tfxhm@get_text 过程和它的子过程的。 Tfxhm@get_text 起始地址: 0055986C/ T$ \9 _/ m. z) X. _0 R( u& d
一、 获取注册码第28位/ o* [# \6 K a" x
确定你想注册姓氏的正确笔划数(必须和同益数据库中 slzik 所查到的相同,以繁体字笔画数为准,同益库中有些字的笔画数并不正确,这时你可以在同益起名的姓名分析中获得姓氏的笔画数)。在下面的字符串中从左到右查寻,得到第 28 位注册码:例如,吕:繁体字为 7 划。(从0开始数)6 t9 W+ }. v# J z' X& ]/ `( n
0123456 7 89012345678901234567890
, p+ a) `: k. c, v% L# P0AH6CD3 B EF4TRS2PUV5K1MN78YZ9GIJ
3 I" V9 @( A6 y3 `- n( r+ H j. ~得到的字母为 B,这样我们的注册码有如下形式:(31 位)下面是我们的起始注册码3 [% ?1 U) o% ~" `5 P1 U
123456789012345678901234567 8 901/ |/ c9 U2 n; `1 d: A, Y- _
123456789ABCDEFGHIJKLMNOPQR S TUV
( C$ @4 z; |" X3 D% ?; L3 A' y8 S加入第 28 个字母 B,得如下注册码:
' F- @. F& S' c2 n+ U8 m, j123456789ABCDEFGHIJKLMNOPQR B TUV
, s" z- `. t& u1 j$ b) C% P& z; ?根据 moon 提出的换位法(4*i+1位和4*(i+1)位互换,i=0,1,2,...,末尾不足4位时,最后两位互换),2528位对调,这个B应该在第25 位, d# S- Z0 F2 V
为了便于调位,写了几句Delphi的小程序来完成:(这种操作,还是汇编容易,所以实际还是汇编写的)
4 H; d7 c* ~) X3 n复制内容到剪贴板 . @- X3 O) \; _9 I* p2 B3 L+ `
代码:procedure TForm1.Button2Click(Sender: TObject);
3 U g( k1 m3 s+ F& G. ]" hvar+ i/ a# F/ k6 ? O; g4 ^% \: y
Str: String;8 i$ y. z% O `% K G8 w5 H0 Q) ^
begin
: {7 c9 U; \1 G: l( ^3 k Str := Edit1.Text;4 f+ U3 A6 `% j+ [, U
asm. F6 p A; ]% N
PushA' E. ]# F$ [( r/ _$ |2 i
Xor Edx, Edx
# z/ Z& N& q+ Y. w R, h3 N Mov Esi, Str: P5 @6 p+ R W5 O5 x
Mov Ecx, 7# t6 ~3 {3 Z; d) X4 x8 O
@1:/ m- X% v1 h) ]( O
Mov Al, [Esi + Edx]
& Z$ p V- V- | Xchg Al, [Esi + Edx + 3]( d Y: B( Q0 w( d
Xchg Al, [Esi + Edx]" z0 w3 d' q( W& H- _* v
Dec Ecx
+ z: X+ k8 P1 G/ J2 X7 l Add Edx, 4
; j4 O9 [4 x e" i Cmp Ecx, 03 T# P+ O+ \/ J6 n8 E
Jnz @14 r. C- Z7 J: j, X' a/ j
Mov Al, [Esi + Edx + 1]
' z- y) i. }! r; P Xchg Al, [Esi + Edx + 2]' d, e5 L: Y( K* R. P; l9 B
Xchg Al, [Esi + Edx + 1], A% `& a; H# t7 k
PopA( K3 `& \8 c7 x4 x
end;
) h# r$ h) `; f; x& Q, m7 ] Edit2.Text := Str;
7 B; E |. Y- N7 o+ U: m4 Nend;在 Edit1 中输入 123456789ABCDEFGHIJKLMNOPQRBTUV,按 Button2 键得到下面的新注册码:
( {! q) D# s& v" E4 g" n5 F) D# z* @/ e新注册码为:/ S, \1 h. J' f6 M8 x
123456789012345678901234 5 678901
' G. j/ ~3 l, b3 G8 R# N6 ]42318675CAB9GEFDKIJHOMNL B QRPTVU
& v* ?$ G' q& F; d; `# f/ N具体分析请看 moon 的解释。
2 T/ o! O3 ^% u, S7 d二、 获取注册码 23~27 位注册码
9 O H& p1 O1 _0 E' |2 j用OD载如 UNGDN.exe (脱壳后的程序)
/ C& k" }% f# Z: Q& o. f* U6 V( O) z- w复制内容到剪贴板
2 o* L% K* i0 R4 A, _# @代码:Tfxhm@get_text
1 \* z) x4 b/ }& b" I3 J0 C" u....... L3 n& n6 Y. t
......
: ^5 B v" i. w$ V6 p0055CF7E mov eax, ds:AppIDAndName_CryHex@Prt ;注册申请号加姓氏和1FH 异或得到的结果
9 ?% |. ] |! O$ f; p0055CF83 mov eax, [eax]6 a0 U& a: `1 L7 S* W- A
0055CF85 call sub_4FED88 ;EncodeFunction1# [" T9 M% j! T1 i
0055CF8A lea eax, [ebp+var_94] ;这里断下获取计算23-27位的三个字符
$ a: l( j3 B" S4 o6 g0055CF8A ;按照 moon帮主的给出的算法可以获得: u6 A1 }$ i# R" ?# P; f4 R
0055CF90 pus eax h6 H- e1 b% `2 L! v) O
0055CF91 lea edx, [ebp+var_98]
: |4 Y4 G) R5 N6 I! K+ L2 E: h. ?0055CF97 mov eax, ds:Serial_CryHex@Prt ;注册号和 1FH 异或得到的结果6 _9 z- G% X# K, x* I! T" D
0055CF9C mov eax, [eax]
+ I, {0 x y! g! r5 z5 l& I Z) c, V" ~- I0055CF9E call CycleConversionStr ;经过 1FH 异或,即还原2 D# F$ `2 B5 _+ A# d. I# I- A
0055CFA3 mov eax, [ebp+var_98]' }5 d8 e- ^2 f4 `+ `- Q3 h/ \. ?+ [
0055CFA9 mov ecx, 5
9 P: j& {. Q1 Q- l( I, T' m0055CFAE mov edx, 17h
* v% b; F# X. V# E% Z1 F0055CFB3 call LStrCopy ;取第 23~27位
; r9 J' B3 b5 Q: D8 O) O- ^) t2 a0055CFB8 mov eax, [ebp+var_94]
% I7 X( B/ p b( v, c- [% v0055CFBE lea edx, [ebp+var_90]5 G/ \0 q5 f' _" d: H9 s
0055CFC4 call sub_4F0048 ;进行计算得到三个字符,如果和上面计算得到的三个字符相同,则过$ B9 |7 ^+ p% N6 i5 s/ J) G
0055CFC9 mov edx, [ebp+var_90]
6 [8 N. D( d2 l0055CFCF mov eax, [ebp+var_C]6 `) A) Z' Q( A( c. V
0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符, e, Z# U" H9 r4 r+ h
0055CFD7 jnz loc_55D157$ q, @; q9 i$ H" A5 `5 f0 o
0055CFDD lea eax, [ebp+var_A0]
: L9 b1 J$ y( U/ o/ k8 e' f! O0055CFE3 push eax
- n3 {" x5 Q+ J" |+ m0055CFE4 lea edx, [ebp+var_A4]
2 A' x _3 a) S! {8 E0055CFEA mov eax, ds:Serial_CryHex@Prt
- o3 [5 z( s/ r$ i& O6 g; |& P0055CFEF mov eax, [eax]
3 c/ h w$ F0 p9 ?0055CFF1 call CycleConversionStr
) I8 ^2 g, Q# D9 {3 ^: C0055CFF6 mov eax, [ebp+var_A4]# f- b+ R' H3 U8 V9 H
0055CFFC mov ecx, 5
0 t" ^! r0 S9 M" X0055D001 mov edx, 17h ;取注册号23~27
: q& B* Z* O0 G+ C+ P0055D006 call LStrCopy
; ^) b+ v' ?- _- \& J# t | e% M* V0055D00B mov eax, [ebp+var_A0]' Z7 D% \( G+ u, O' Z+ b
0055D011 lea edx, [ebp+var_9C]
7 y! f6 `$ H7 }$ P0055D017 call sub_4F0048
- D. o5 `; A/ }0 e4 i' {0055D01C mov edx, [ebp+var_9C]
% S& F9 P: O% D# L- \4 I0055D022 mov eax, [ebp+var_C] f$ C8 G+ f3 v- m: k
0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同4 A4 b: ^$ C, o8 s: q1 @
0055D02A jnz loc_55D0EA) P' H k% t" ~. ^
0055D030 lea eax, [ebp+var_A8]# G: G6 H0 E' s* }' l: ?' b0 o6 [( c
0055D036 push eax5 B1 |9 K! K. ]# X x& b, X
0055D037 lea edx, [ebp+var_AC]
" z, ?% f; v! C0055D03D mov eax, ds:Serial_CryHex@Prt
1 }. R2 H% m9 k0 z% v- ~! S4 X0055D042 mov eax, [eax]2 r; k+ D4 U8 s% @# P J1 a1 S8 G
0055D044 call CycleConversionStr: ^1 b. l) r3 ~/ u6 ?/ r
0055D049 mov eax, [ebp+var_AC]: q- R, ]+ F* S' ]6 x; ^" `) i
0055D04F mov ecx, 34 I6 F* P6 }3 d& z' k& P
0055D054 mov edx, 1Dh ;取注册号 29~31 位
5 J( r* w) j* u. ~! V0055D059 call LStrCopy) i- N5 m( Y6 a0 B( r0 ?
0055D05E mov eax, [ebp+var_A8]9 W( k" }: |; P5 b0 d
0055D064 call 31decimalToHex ;对29~31位注册码进行31进制到十六进制的转换
' `) e2 B& Z4 _' z. O- q2 N# P. R0055D069 mov ebx, eax$ e/ }) Y v' d' p, k
0055D06B lea eax, [ebp+var_B0]
0 A. ?+ K+ K0 p/ I& }" S, K0055D071 push eax
$ m+ J" u7 Y: O* Y. l) c* f0055D072 lea edx, [ebp+var_B4]
% O- ^+ O) v: r0055D078 mov eax, ds:Serial_CryHex@Prt ;取注册号(经过1FH异或处理)
" N. m$ z) c8 N: m! ?0 ?" T+ _0055D07D mov eax, [eax]# ~" C2 v- i, D! p/ x! r; s2 Q9 s
0055D07F call CycleConversionStr ;经过相同的过程还原
- t9 Z; \) e$ Q) p$ t0055D084 mov eax, [ebp+var_B4]
, E# X7 s2 k# m# ^4 f% t0055D08A mov ecx, 1Ch
I( @- q* Q( Y- U& I0055D08F mov edx, 1 ;取注册号 1~28 位1 J+ x- G- \9 e- m- L4 y
0055D094 call LStrCopy8 c! }! e( a8 j# P
0055D099 mov eax, [ebp+var_B0]
' P( q, [1 j2 f4 J+ C2 d0055D09F call SumSerial_1to28 ;做 1~28 位累加(中间还有判断是否大于27000,见moon帮主的解释)
' U; m7 S* y7 q% O4 i0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点9 _) m5 i2 V. v; A. J
0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉; O5 b% L9 P/ d! V* n
0055D0AC mov eax, offset a111_2 ; "111"7 A4 ^; _' ?: B2 i! q" ~! E
0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口
% H' ]" a6 _/ [+ N3 K( l m: @0 v0055D0B6 mov [ebp+var_1], al* y+ P5 p0 |. d( S% f. n# X
0055D0B9 cmp [ebp+var_1], 0
; u$ w3 C9 H# p0 ]/ ^, k0055D0BD jz short loc_55D0CC. Z* j" t" j% ]$ W
0055D0BF lea eax, [ebp+var_C]7 C+ Z5 e8 a% l
0055D0C2 mov edx, offset a111_2 ;"111"+ S- k. ~) D1 P& G: E- U
0055D0C7 call LStrLAsg
w0 f7 X6 G( i; K- h0 t( V6 g0055D0CC
6 J3 k3 K2 S' I& P0055D0CC loc_55D0CC:( D% q- T5 n2 X; {2 i% P& o
0055D0CC cmp [ebp+var_1], 0
. B7 B t6 q$ d7 e4 u& A- z* s0055D0D0 jz loc_55D157/ F: Y+ v. x: n& @8 E* L' j' G4 v
0055D0D6 mov eax, [ebp+var_C]
0 Q8 ~ }3 c8 ?& B0055D0D9 mov edx, offset a111_2 ;"111". p5 w7 h% _% {0 o! r
0055D0DE call LStrCmp
- c: A4 f" W: } i0055D0E3 jnz short loc_55D0EA
, W9 W! r+ L+ U" H2 b2 L; h3 m' Q0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口在0055CF8A 处下断点,F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',注册申请码是不能修改的,由你的机器的 CPU 和硬盘的参数变化而来。在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的 123456789ABCDEFGHIJKLMNOBWRSTUV 注册码拷贝到输入窗口。按【注册】键,中断在 0055CF8A ,清除断点(或关闭),由 [ebp - c] 中的内容,得到三个字符 VRB,记录下这三个字符,用moon帮主给出的方法:0 E" |) T3 A- Z7 |, \% w$ x% ]8 J8 D
" V$ g5 `( ]* G& R求逆方法:
- c: {. o; M# X! w/ t1. 执行到00559D0A,然后下:d [ebp-c],记下数据区显示的正确值x,y,z;+ d4 g; d" V0 E) ^
2. 对3个字节的正确值进行调位,得到5个字节a,b,c,d,e,调位方法为:2 V- e5 K4 a2 y' s7 Q+ {
0,0,0,x7,x6,x5,x4,x34 C7 F5 b* T( a8 p) }6 j6 | w4 S3 }8 x& A
0,0,0,x2,x1,x0,y5,y40 ^' f) h# _+ b
0,0,0,0 ,y3,y2,y1,y0+ z0 v3 ^& z! v0 k/ s+ g8 r
0,0,0,y7,y6,z7,z6,z5: O5 B2 A! T& R
0,0,0,z4,z3,z2,z1,z0
- m0 T) Z. r, B- }3. 根据5个字节查表"0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX",得到5位注册码即为23~27位。" S# d8 e7 Q2 R: W; {! p
--摘自 moon 帮主文; }* b' V( P+ x5 f! ] ?6 d
3 P" [6 l( @$ C/ w/ L我用Delphi写了几句小程序完成这个转换,程序如下:
' }! O* O( a. I1 V* V复制内容到剪贴板
: S+ M# l- `! g" ?代码:procedure TForm1.Button1Click(Sender: TObject);
& i" f+ ~& b9 H, L5 l( c& y# U$ ?const- o, k8 I; {5 a2 R1 K5 u& q1 v
Str = '0KMT1EIJ2AB34FGH56PYZ7NRS89CDUVX';
' }+ M& k h/ A0 pvar w& C2 q( \# K: P& n' s
X1, X2: Integer;3 R$ j ^2 G8 H% k1 k
x, y, z: Char;' m) Z: _4 O& Z+ m) {
a, b, c, d, e: string;5 b) L! P* y* |" i
Pin: string;
+ ~ `& w8 A/ V7 @4 q0 }7 y7 Ebegin
+ K* a1 X- I2 W' R Pin := Edit1.Text;
% ^) L/ K: S& N* a/ G& R5 w x := Pin[1];
& K3 f3 }, ]3 _ y := Pin[2];$ U' g. @7 [ u+ k
z := Pin[3];" y: U+ Z/ r- z7 _% ?" A
x1 := (Byte(x) shr 3) and $1F;/ J( X) [/ [: I6 d" R. t# R0 P
a := Copy(Str, x1 + 1, 1);2 h5 g0 R% G: Y5 u
x1 := ((Byte(x) shl 2) and $1C) or ((Byte(y) shr 4) and $03);
; W, t- |& c5 s- L3 `- m b := Copy(Str, x1 + 1, 1);
0 e/ Y5 W+ k) p. H9 Z' i- t) O4 u5 l" ` x1 := Byte(y) and $0F;: ?# M6 M$ J: s( e% V d
c := Copy(Str, x1 + 1, 1);
' p* B' p7 j! Q0 x/ g3 h x1 := ((Byte(y) shr 3) and $18) + ((Byte(z) shr 5) and $07);
9 l9 W9 t2 X- b, l d := Copy(Str, x1 + 1, 1);
; T9 |! R. G6 t) p! h4 m x1 := (Byte(z) and $1F);
# V) V( j M% `+ Z e := Copy(Str, x1 + 1, 1);
( q0 U0 x. x' q; g: Z# K, } Edit2.Text := a + b + c + d + e;! E+ Q, V A) A% [; i
end;在 Edit1 输入 VRB 按 Button1 键,在 Edit2 窗口中给出我们要的结果 B8MBM 。现在来继续完善我们的注册码。将得到的字符串替换原注册码中第 23~27 位:
: _: m& ]7 Y' B1234567890123456789012 34567 8 901; Z2 p, e% H+ ]$ G! y, @6 p6 a; K
123456789ABCDEFGHIJKLM B8MBM B TUV
/ v# Z3 Y* y# r! j% ?4 k用前面的小程序进行调位,得新注册码如下:
' | H2 a0 U$ S) L _1234567890123456789012345678901& K- a, U& e, q" N1 z0 l( b* F8 A+ f
42318675CAB9GEFDKIJH8MBLBBMMTVU& @) o: {8 n+ E- H7 w C
三、 获得的 17~22 位注册码:3 I: J% S0 K% _. l4 @7 w
在OD中按 Ctrl-F2组合键,重新运行程序,将 0055D0A6 的 jnz loc_55D157 Nop 掉 8 ]( Y! j. f6 [- e/ U4 V' b
复制内容到剪贴板
9 D- u; r+ r7 A+ Z* W- n代码:0055D0A6 jnz loc_55D157 ;因为注册码没有完成,为了能够继续,暂时将这句 Nop 掉
2 z. {9 ?. t! I0055D0AC mov eax, offset a111_2 ;"111"" v( g/ f0 O7 |6 u; `5 L6 @
0055D0B1 call CheckSerial_17to22 ;这里是获取 17~22 位注册码的入口
. c) u$ i' g/ M; y5 D跟进 0055D0B1 call CheckSerial_17to225 l% y/ f' O4 J' |9 z% h z
......1 C1 s7 R! U% q7 p% z0 w( q
...... 省略
7 W3 [# S+ b. j% P5 S. l8 q* x0050C705 mov edx, [ebp+var_20]
3 }/ s, S* K. ~ o0 O0050C708 mov eax, [ebp+var_1C]7 E; X& I2 m$ c% s: ]( p4 w
0050C70B call DES_EncryStr ;在这里进行 DES 的 EncryStr 加密运算,运算结果再经过
1 n5 s+ c: ]# m5 G0050C70B ;另一过程处理,这个子过程我们后面还要用到
, Q ?+ `0 ]3 l7 m( F! b" l6 O9 f0050C710 mov edx, [ebp+var_60] ;moon 文中提到在这个位置获取 17~22 位注册码,可能; L0 l. Q) z/ b7 p
0050C710 ;是帮主写文章时粗心了,正确的位置应该在下面删除第5位, m0 j, l4 j6 b; x/ t
0050C710 ;相同字母后才取结果。; g: {# t- q& k0 O6 c
0050C713 lea eax, [ebp+var_20]: @/ w8 F+ _, I# b: g9 A' ^
0050C716 call LStrLAsg# K& {& _ V" {3 I% T
0050C71B lea ecx, [ebp+var_64]
4 r9 {5 E" l% S3 _( Q) B: Z0050C71E mov eax, [ebp+var_20]( l7 k( V4 C; X; w% ]
0050C721 mov dl, [eax+5] ;取出 EncryStr 运算结果的字符串的第 5 位9 S; n6 `& E2 H+ b
0050C724 mov eax, [ebp+var_20]9 T4 |) `0 n0 r% h6 R
0050C727 call DelChr ;将 EncryStr 运算结果中凡是和第5位相同的字母删除
4 O/ V! t7 a5 |- G0050C72C mov edx, [ebp+var_64]
$ K% a8 H# C- p" H$ z: Z7 X0 H0050C72F lea eax, [ebp+var_20] ;这里下断点,从Edx中取前6位,即我们要的第 17-22 位
# Q' b- N7 Q* T* u7 L* z) J) @......
9 {8 R1 c: f$ v1 S9 M: w......省略在 0050C72C 处下断点,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDKIJH8MBLBBMMTVU)拷贝过去。点击【注册】按键。中断在 0050C72F,在Edx 返回一个长度为30的字符串(这个字符串的长度是不一定为30的,要看删除相同字符的数目而定),取前 6 为,即为我们要的注册码的第 17~22位,在我们的例子中得到的字符串是:DEDAHI。现在我们来修改我们的注册码:0 V9 ^. T* c/ }! \# G3 G
1234567890123456 789012 34567 8 901# @5 t& U$ r& F7 k& s8 n' H+ _
123456789ABCDEFG DEDAHI B8MBM B TUV
- ]- o) R7 m0 h7 K' @% k用前面的小程序调位后得新注册码:
, O* x4 @5 W- O$ ?! T/ i2 `, N1234567890123456789012345678901& Q/ t0 I2 w8 M- O9 i
42318675CAB9GEFDAEDD8IBHBBMMTVU1 ^( T5 g) ?7 p
四、 获取 1~16 位注册码
" r. \3 j: Z/ L% F3 F- n: j2 _- e( a我们首先来看看程序的代码,从前面列出的程序最后一句:
+ L u" y" l& H+ J, ^6 v复制内容到剪贴板
1 e. `6 Y2 ]. c1 m代码:0055D0E5 call CheckSerial_1to16 ;这里是获取 1~16 位注册码的入口
) Y9 F( M4 \# L" s跟进 call CheckSerial_1to16
/ D Q" P: C6 D. e% a4 O....... p( u. G) b6 z' S) M; k
......省略 L* s' n& B- I u/ X2 E; L
00508EEB lea edx, [ebp+var_18]
' z2 _3 ]" ?3 {5 \7 p& X00508EEE mov eax, ds:AppIDAndName_CryHex@Prt. j P8 \: B& B
00508EF3 mov eax, [eax]
( ]! [+ u1 g5 }7 z3 R& Y4 S* \/ b00508EF5 call ConversionHex10To16( l" {% @; u) b2 L; c7 r
00508EFA lea eax, [ebp+var_18]
3 E5 |* O: x. q, h! E N6 d* {" _; K00508EFD lea edx, [ebp+var_8]5 H" F# `/ E- B' s; j+ B$ l5 @
00508F00 call ConversionHexAndFNameToStr( r) F6 p9 u: ]" w+ S
00508F05 lea eax, [ebp+var_20]' i5 N. X' G- ?. Y
00508F08 push eax- s" }: X4 i0 x7 C. ?7 ]
00508F09 lea edx, [ebp+var_24]& p4 \* g. x& Q5 w w# s& M
00508F0C mov eax, ds:Serial_CryHex@Prt! N% P Q. X$ y% a. Z4 p
00508F11 mov eax, [eax]
6 p W0 \1 S0 w0 z( n" s00508F13 call CycleConversionStr
, H2 b$ f7 M: d: H+ o00508F18 mov eax, [ebp+var_24]4 ?) U2 X0 z1 @- ?
00508F1B mov ecx, 10h# M; y: r+ V& t0 U% N% J7 E
00508F20 mov edx, 1 ;取注册号 1~16 位+ S) w0 L( ~/ f' Q2 l* A$ \) p
00508F25 call LStrCopy, o) f; ] l, X! ^
00508F2A mov eax, [ebp+var_20]
! c' I: ^) M* R- ~- `00508F2D lea ecx, [ebp+var_1C]4 T& Q! F1 `# p) `( D5 m
00508F30 mov edx, [ebp+var_8]( k7 A" J, K+ V0 _+ `4 p
00508F33 call DES_DecryStr ;这是 DES 的逆运算,我们再跟进
' {1 A' T5 w+ W00508F38 mov eax, [ebp+var_1C]! E2 `% j* p- O8 x
00508F3B lea edx, [ebp+var_18]
+ v0 T( V% ~9 J+ T2 w00508F3E call ConversionHex10To16
6 R. C, }9 W/ B' y8 F7 R2 [5 ]00508F43 lea eax, [ebp+var_18]; S3 a3 p! l+ r1 `, V4 h
00508F46 push eax
' S9 w$ r$ D! F00508F47 lea edx, [ebp+var_38]
9 d: Q& y+ W: l5 @00508F4A mov eax, ds:AppIDAndName_CryHex@Prt: m2 j* p1 d0 Q$ }
00508F4F mov eax, [eax]) q( P$ U) X% }
00508F51 call sub_4FBA70
" S4 l% o9 S9 [& ]5 Z0 a00508F56 mov eax, [ebp+var_38]
9 H" q- V; k6 w: }00508F59 lea edx, [ebp+var_34] ;这里是我们要下断点的地方
, U1 C; T4 I2 `* A2 F6 E7 D......2 q! }* v1 @5 G% I
...... 省略
: E& Q$ x" M6 Z% h3 N& l+ R0 ?跟进 call DES_DecryStr& j" s+ S3 k1 |% _( X. n4 D
....../ F y8 [) V6 {/ d
......省略
8 p* J: j+ L" p" j& f* M5 I004F788E lea edx, [ebp+var_C]" f" n* B0 s1 u* `! \3 P) V( a) O
004F7891 mov eax, [ebp+var_4], J8 a/ Y% R' O, o4 e
004F7894 call sub_4E97BC W+ d2 V& m- A1 Q9 i1 p
004F7899 mov ecx, ebx
3 U! x, @2 J% ~) l004F789B mov edx, [ebp+var_8]
% ~6 i9 `2 ?. |, W8 w004F789E mov eax, [ebp+var_C]
. s. x( F, y, w4 ]; O) j* ^; o- v. L/ D004F78A1 call DecryStr ;DES 逆运算- l; P/ ?5 j+ N$ j4 G% H0 o
004F78A6 xor eax, eax ;这里是 moon 帮主提出下断点处,还有一些其他相应的做法$ |2 ?! t5 L+ E" b
;请看 moon 原文。) I4 y6 \9 j4 k9 j1 {0 q
......4 B% d$ x! S9 }; w5 S1 k1 _
......省略在OD中按 Ctrl-F2,重新启动,在00508F59下断点,同上,将 0055D0A6 的 jnz loc_55D157 Nop 掉,按F9 运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(42318675CAB9GEFDAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 00508F59,下面是堆栈内容:
" s) M: g. Y* c2 j% V复制内容到剪贴板 3 n# T# B' ?' O4 ]% o
代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"% ~: G! y( `. J, D6 T0 G
EBP-34 0012F914 00000000
7 k/ g+ X# `$ _( ?/ t5 ~EBP-30 0012F918 000000002 a$ X2 x$ s, h( ^: Y
EBP-2C 0012F91C 00000000
+ O0 a( K- [7 x% |$ wEBP-28 0012F920 00000000
2 }) m9 u' y2 T7 d N5 o2 u) T: w, cEBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"' o3 O3 R4 V' }( R) Q: q/ Z$ @
EBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"
9 _7 _. A& A$ b; [+ NEBP-1C 0012F92C 00F3009C+ T' q' m8 s$ R0 S
EBP-18 0012F930 C338FAD3
) N' D* I f" u( O; f5 r7 M! lEBP-14 0012F934 DD5CB3D0 L7 _' W% U$ E; [5 b$ i3 U: F) q
EBP-10 0012F938 D5D42656
5 R0 Y1 x' D5 i# r( D y' R) I2 SEBP-C 0012F93C A2BB6C94
- s# S* K! h/ p" H: Z: ?1 EEBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4", S4 b. e& F g# W: S
EBP-4 0012F944 00000000注意: EBP-38 0 00F2A130 ASCII "5FF51115" 这是我们要的 DES 加密的明文。& W% J0 j3 l* J, E
EBP-8 0> 00F2FFE4 ASCII "M9BJBBRIDE88TNP4" 这是 Key。4 U0 v8 `( f" X- e1 g
按 moon 帮主的方法,修改两句代码,进行逆运算,但我经过努力,总是没有成功,可能是对 moon 的方法不能深刻的理解,于是决定改用其他的方法。我们注意到如下代码: $ T1 h+ m% O0 D: I
复制内容到剪贴板 4 }+ t+ l/ \: K" |/ c
代码:004F788E lea edx, [ebp+var_C]
7 \& D, Z* X% F# G9 K004F7891 mov eax, [ebp+var_4]
7 H- G2 Q& |: t+ n0 t8 U004F7894 call sub_4E97BC
* F- {, ^9 [% t004F7899 mov ecx, ebx
) @' \- a! h4 D: z: Q' O5 U) V004F789B mov edx, [ebp+var_8]. Y- n" i& k" y0 ]. F! v& l: C) F
004F789E mov eax, [ebp+var_C]
+ Y8 v. ]8 ~9 D8 @. N9 J9 M7 U004F78A1 call DecryStr ;DES 逆运算在最后一句 Call DecryStr 做的其实是DES的逆运算,前面还有一个辅助的运算,我认为,同益的代码中一定有一个DES的正向运算,即EncryStr,所以我找了一下,其实就在上面第三节--【获得的 17~22 位注册码】中出现过,下面我们跟进这个Call: & g7 B% H; G+ X m1 `4 c+ x* r
复制内容到剪贴板
. _4 W0 r$ V( z( ~, S. o0 m# o代码:0050C70B call DES_EncryStr3 D$ M: a1 T% P2 P- @
跟进
0 y6 F2 |8 X7 S......! |7 [4 S# `3 r- u3 J- [" Q
......省略
3 N4 h3 S2 g( ~! K; r. S004F781A lea ecx, [ebp+var_C] ; 返回地址5 H0 R: s- ^, Y8 Y9 o
004F781D mov edx, [ebp+var_8] ; Key = M9BJBBRIDE88TNP4
6 p9 O/ N. E# Y% G9 ^" N004F7820 mov eax, [ebp+var_4] ; Str = 5FF51115
. I7 k+ k: X) t2 ]2 \004F7823 call EncryStr
. v1 |" z. L' @" m1 Z- o- g2 c% J ]/ d004F7828 mov edx, ebx3 R6 |7 Y! g9 H* [1 r5 R% x
004F782A mov eax, [ebp+var_C], z1 L" v/ V8 E) Z. v
004F782D call sub_4E63F4
3 i+ F" I! u' O% N) k1 e9 }1 _004F7832 xor eax, eax ;这里下断点
2 U% ]/ P! l9 _5 [......+ x1 s+ K3 V' E7 T# V
......省略可以看出,它和上面的代码正好相反,我们用下面的方法来获得 1~16 位的代码。
2 O. D2 ^* i+ {& F0 q3 N; V: }* L# ~接前面,我们中断在
( R" g3 t* @' h( K9 i复制内容到剪贴板
4 C. b8 J2 ~. y* M5 j# f代码:00508F59 lea edx, [ebp+var_34]在代码窗口中按 Ctrl-G,输入004F781A,转移到 004F781A。按 Ctrl-*,将Eip地址改到 004F781A。( d; ~. R! t: k3 u! A. n
我们要做的工作其实就是修改堆栈的地址,下面是具体操作。 7 D/ l. B2 j& D8 i/ D
复制内容到剪贴板 ) }. ^, z+ I3 e1 |
代码:EBP-38 0012F910 00F303D0 ASCII "5FF51115"
: @0 R( S) E* mEBP-34 0012F914 00000000
' n' C9 v/ N. g* {9 T9 e' PEBP-30 0012F918 00000000
- l* l, t( r0 F6 G" _7 gEBP-2C 0012F91C 000000005 p/ ]3 B& U/ U) `8 \0 J. Q! `
EBP-28 0012F920 000000003 y/ Z1 c6 b+ b# \& d
EBP-24 0012F924 00F30038 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"
; }8 z$ p7 L: J+ PEBP-20 0012F928 00F29F5C ASCII "123456789ABCDEFG"
& |9 c5 ^3 V o& K) B4 ]EBP-1C 0012F92C 00F3009C
) h9 P+ c, W& ?: h/ C" g o9 oEBP-18 0012F930 C338FAD39 A8 [2 M; X" [% P- k5 ]8 Q* R' c
EBP-14 0012F934 DD5CB3D03 F& \1 }* t! X4 \8 q/ S
EBP-10 0012F938 D5D42656
* k2 Z- {2 J; Y1 U( M& kEBP-C 0012F93C A2BB6C94 结果返回地址,这里改为 0,程序运行时会自行分配新的内存
' M5 \* ^2 W* e2 j0 r' A3 ~1 j7 mEBP-8 0012F940 00F2FFF8 ASCII "M9BJBBRIDE88TNP4"
& x7 {. f$ Q# L# I& ZEBP-4 0012F944 00000000 这里是 Str 所以将这里改为 00F303D0,也就是[EBP-38] 指向的地址。另外,最终返回结果在 Ebx 中,而Ebx 是由上一级的过程传递过来的参数,已经由入口程序做过初始化,所以,必须分配一个有效的返回地址,这点和 [EBP-C] 不同,需要要注意,这里我们将 [EBP-24] 的堆栈地址分配给 Ebx, 也就是Ebx = 0012F924
. @4 h7 X3 o( C d. S4 P7 T" ]# G改完后堆栈如下:
' n' @. w+ {+ ]. U& @# i: I8 X7 P复制内容到剪贴板
* h1 p5 [( k9 m# o5 `2 K代码:EBP-C 0> 000000009 S% I( V/ @$ h% u
EBP-8 0> 00F2FFF8 ASCII "M9BJBBRIDE88TNP4" Key' i9 B' q3 j" n0 w* Z! B
EBP-4 0> 00F303D0 ASCII "5FF51115" Str7 F* x. [( d+ z }* T
在将 Ebx 的内容改为 EBP-24 的堆栈地址,即 Ebx = 0012F924 ASCII "123456789ABCDEFGDEDAHIB8MBMBTUV"在 004F7832 下断点,F9 运行,d [Ebx], [Ebx] =0VBMHYAMA260CSD1 第 1~16 位的注册码) J2 h, N* M' H2 H* W
现在我们来修改我们的注册码:$ B: I' O! p+ C/ X6 s
1234567890123456 789012 34567 8 901
) \: W- ?9 g+ Z- W$ C% u0VBMHYAMA260CSD1 DEDAHI B8MBM B TUV# @' [8 L; j, k' I
用前面的小程序调位后得新注册码:
& J1 b( \: b! A& Q1 `) ^& `1234567890123456789012345678901. m! X M# L9 {+ v7 i: N
MVB0MYAH026A1SDCAEDD8IBHBBMMTVU
6 V1 s% H# W* y' k- H五、 获取最后 29~31 位注册码
' n$ x! J* i' A打开注册表编辑器:将Serial中的内容清除:
6 ^7 C' j( p. j8 _+ G% R {, ]' S[HKEY_LOCAL_MACHINE\SOFTWARE\GoodSoft\GoodName]0 ~8 Q+ b* s5 I7 _# i
"Appid"=dword:059c0935
0 _; F) M# Y; G+ l/ k"Serial"="MVB0MYAH026A1SDCAEDD8IBHBBMMTVU"
! Z. z* c5 l* @ r"Serial"="0": ~1 d7 k4 S$ e" w
在OD 中按 Ctrl-F2 重新启动,将下面两处 Nop 掉。 : @/ o3 s5 ]; ]
复制内容到剪贴板
$ o4 k+ o o0 l. I* Z$ }( W代码:0055CFD2 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符0 B" e% f/ s8 F6 }
0055CFD7 jnz loc_55D157 ;Nop 这里" F y3 W1 G/ Q2 {, I
0055D025 call LStrCmp ;关键比较,比较两种方式和数据计算得到的三个字符,和前面相同
8 j; ]7 ]+ g( x9 D9 y0055D02A jnz loc_55D0EA ;Nop这里4 c& L+ D4 b1 n1 U
0055D0A4 cmp ebx, eax ;关键比较,将前面进制转换得到的数和累加和比较,在这里下断点在上面 0055D0A4 处下断点,F9运行,出现同益启动画面后选‘注册’->‘输入注册码',在【起名的姓氏】中输入你的姓氏,我这里是输入‘吕’,在【输入注册码】中将上面的最后得到的注册码(MVB0MYAH026A1SDCAEDD8IBHBBMMTVU)拷贝过去。点击【注册】按键。中断在 0055D0A4,记录下Eax寄存器的内容,我这里是 2C3AH,换算成十进制数为 113223 `# ]; K" k6 m. _2 ~) B" U+ I
根据 moon 帮主的文章:
! {1 f% B7 q. H# M! V3 [! K4 ?5 P1 U h# K/ K8 z, C
求逆方法:6 P( h, j) e5 D/ n, n
1. 执行到00559E24,记下eax中的值x,或按照上面的方法计算出这个值; i/ y; M- l3 S7 B/ J/ T' a
2. x除以31,用余数查表"0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ",所得字符作为第31位;
( f1 P: j0 c% Q. ` _9 H% Y8 j3. 第2步的商除以31,用余数查表,作为第30位;
* a$ t! d9 h5 Y; X Q' @3 H6 D9 e4. 第3步的商查表,作为第29位。' a% A1 {2 W& V2 B# ~# n% j6 A. m
--摘自 moon 帮主的文章
h( ~4 g$ Q0 ?! ` U6 [4 C4 \3 o; }0 z/ R) [4 @& b9 M7 Z2 i
写如下Delphi 的小程序计算最后3位注册码。 * z7 D" ^: W( B$ z' B# V
复制内容到剪贴板 % m, D' K9 Y+ ~/ r: s' ^% h
代码:procedure TForm1.Button3Click(Sender: TObject);
6 s) k+ A" Q- y4 B# O8 u. } pconst d8 j$ Y+ B) T% O% X0 g! r/ q/ u
Str = '0AH6CD3BEF4TRS2PUV5K1MN78YZ9GIJ';! l6 }# r1 j5 T# b
var3 M( p/ V8 b1 J- X& n/ m% N# N
x1, x2: Integer;
- c3 M/ @" p/ K4 F6 G( j- Y S1, S2: String;/ F% ~3 [. d# V0 Z4 z' V: B8 |* G1 W
begin
- S) G2 }" z4 j0 V% p( M8 S x2 := StrToInt(Edit1.Text);+ A5 i" L) o+ V# S7 R8 v
x1 := x2 mod 31;, O6 G3 d6 d; E. I0 I
S1 := Copy(Str, x1 + 1, 1);+ D' n& `* B' k$ c5 g
x1 := (x2 div 31) mod 31;# D! W8 \5 Q, c& K) S4 X/ c
S2 := Copy(Str, x1 + 1, 1);' `; Q. V1 m3 y2 ]* k
S1 := S2 + S1;
6 Y7 s0 s! f& J1 @5 n5 n x1 := (x2 div 31) div 31;2 e" W$ H+ n8 I$ o& _$ I$ r. F4 I
S2 := Copy(Str, x1 + 1, 1);) [1 P1 X% s4 g, ~2 t6 f
Edit2.Text := S2 + S1;
* d2 l& r( u7 H' Iend;在 Edit1 中输入 11322,按 Button3 键,在 Edit2 中给出结果 T8B
* |1 Z' N6 l, O/ L现在我们将获得最终的注册号:: ^& ^2 k! o3 T; Q# M3 d9 g8 X
1234567890123456 789012 34567 8 9014 D0 \* {, F& `' H% b! _
0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B. }- e, f1 x# p. R% X' y
用前面的小程序调位后得新注册码:5 }% W4 f% C: }5 p9 ?
1234567890123456789012345678901
4 g4 \, k4 V' v: t% b% U) AMVB0MYAH026A1SDCAEDD8IBHBBMMTB8, I3 w4 [" F4 ]: l" R6 O
在我的机器上,注册号为 MVB0MYAH026A1SDCAEDD8IBHBBMMTB8 ,用未脱壳的原版注册后所有功能完全正常,公司后缀的分析类似,有兴趣的朋友可以自己试。 j; c! n+ Q2 a
另外,对于Delphi的小程序,什么版本都可以,但编译开关 Huge String 要勾上,我使用的是 Delphi 7。% B* U- Y$ o# ]* w: ^
说明:* K% H+ Y4 o& O- K/ g- H
: l& J3 R" l2 O: s5 r
1、对于调位操作,字符串长度必须是 31 位(不算空格),可以带空格输入,这样比较方便直接拷贝,如可以直接输入:
: r. j3 D# C/ o$ f) \% |"0VBMHYAMA260CSD1 DEDAHI B8MBM B T8B"2 x! C# [, J1 _
2、对于计算最后的第 29~31 位,可以直接输入十六进制数,不过要加 '$' 前缀,例如在我们这个例子中,可以直接输入 $2C3A (不分大小写)。+ P& \4 r; c) c
|