【文章标题】: LibXL 算法分析(附注册机) 【文章作者】: GCCG 【软件名称】: LibXL 【下载地址】: http://www.libxl.com 【加壳方式】: 无加壳 【编写语言】: Visual C++ 【使用工具】: OllyDbg 【操作平台】: windows 【软件介绍】: LibXL is a library that can read and write Excel files. It doesn't require Microsoft Excel and .NET framework, combines an easy to use and powerful features. LibXL 可以原格式读写 Excel ,不需要电脑安装 Office, 具体使用请参照官网的文档:http://www.libxl.com/documentation.html 好久没练手了, 这次分析下算法. 看下 libxl.dll 中的导出函数 xlBookSetKeyA(BookHandle handle, const char* name, const char* key); 很容易找到关键地方。编写个测试 exe 进入 xlBookSetKey 开始调试。我只简单描述下关键地方.
[Asm]
纯文本查看
复制代码
1
2
3
4
5
6
|
10032640 /$ 55
push
ebp
10032641 |. 8BEC
mov
ebp
,
esp
10032643 |. 6A FF
push
-0x1
10032645 |. 68 CA4D3810
push
10384DCA
1003264A |. 64:A1 0000000>
mov
eax
,
dword
ptr
fs
:[0]
10032650 |. 50
push
eax
|
下面 是对用户名,注册码长度判断
[Asm]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
|
10032687 |. 85DB
test
ebx
,
ebx
10032689 |. 0F84 C2040000
je
10032B51
1003268F |. 85C0
test
eax
,
eax
10032691 |. 0F84 BA040000
je
10032B51
10032697 |. 50
push
eax
10032698 |. 8D4D 98
lea
ecx
,
dword
ptr
[
ebp
-0x68]
1003269B |. E8 B02DFDFF
call
10005450
100326A0 |. 837D AC 28
cmp
dword
ptr
[
ebp
-0x54], 0x28
100326A4 |. C645 FC 01
mov
byte
ptr
[
ebp
-0x4], 0x1
100326A8 |. C686 44030000>
mov
byte
ptr
[
esi
+0x344], 0x0
100326AF |. 8D4D 98
lea
ecx
,
dword
ptr
[
ebp
-0x68]
100326B2 |. 0F85 94040000
jnz
10032B4C
100326B8 |. 6A 08
push
0x8
|
[Asm]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
100327C4 |. E8 67D0FFFF
call
1002F830
100327C9 |. 56
push
esi
100327CA |. E8 01083300
call
10362FD0
100327CF |. 83C4 14
add
esp
, 0x14
100327D2 |. 6A FF
push
-0x1
100327D4 |. 6A 00
push
0x0
100327D6 |. 8D8D 7CFFFFFF
lea
ecx
,
dword
ptr
[
ebp
-0x84]
100327DC |. 51
push
ecx
100327DD |. 8B8D ECFEFFFF
mov
ecx
,
dword
ptr
[
ebp
-0x114]
100327E3 |. 81C1 A4090000
add
ecx
, 0x9A4
100327E9 |. E8 A2EBFCFF
call
10001390
100327EE |. 83EC 1C
sub
esp
, 0x1C
100327F1 |. 8D95 7CFFFFFF
lea
edx
,
dword
ptr
[
ebp
-0x84]
100327F7 |. 8BCC
mov
ecx
,
esp
100327F9 |. 89A5 E8FEFFFF
mov
dword
ptr
[
ebp
-0x118],
esp
100327FF |. 52
push
edx
10032800 |. E8 4BEDFCFF
call
10001550
10032805 |. 8D85 28FFFFFF
lea
eax
,
dword
ptr
[
ebp
-0xD8]
1003280B |. 50
push
eax
1003280C |. E8 2F750300
call
10069D40
10032811 |. 83C4 20
add
esp
, 0x20
|
下面一段代码 取出32位注册码的第1,3,5,7,9,11,13,15,17,19,21,23,25位,并将取出的字符连接成字符串
[Asm]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
100328E0 |> /83FE 20 /
cmp
esi
, 0x20
100328E3 |. |73 43 |
jnb
short
10032928
100328E5 |. |83FE 1A |
cmp
esi
, 0x1A
100328E8 |. |73 1B |
jnb
short
10032905
100328EA |. |56 |
push
esi
100328EB |. |8D8D F0FEFFFF |
lea
ecx
,
dword
ptr
[
ebp
-0x110]
100328F1 |. |E8 6A730300 |
call
10069C60
100328F6 |. |0FB600 |
movzx
eax
,
byte
ptr
[
eax
]
100328F9 |. |50 |
push
eax
100328FA |. |8D8D 0CFFFFFF |
lea
ecx
,
dword
ptr
[
ebp
-0xF4]
10032900 |. |E8 6BD5FFFF |
call
1002FE70
10032905 |> |8D4E 01 |
lea
ecx
,
dword
ptr
[
esi
+0x1]
10032908 |. |51 |
push
ecx
10032909 |. |8D8D F0FEFFFF |
lea
ecx
,
dword
ptr
[
ebp
-0x110]
1003290F |. |E8 4C730300 |
call
10069C60
10032914 |. |0FB610 |
movzx
edx
,
byte
ptr
[
eax
]
10032917 |. |52 |
push
edx
10032918 |. |8D8D 44FFFFFF |
lea
ecx
,
dword
ptr
[
ebp
-0xBC]
1003291E |. |E8 4DD5FFFF |
call
1002FE70
10032923 |. |83C6 02 |
add
esi
, 0x2
10032926 |.^\EB B8 \
jmp
short
100328E0
|
对上一步取出的字符串 求 MD5,并截取 前 16 位,比较 md5 值的 前 16 位 是否是 3f8bfcaff330c39f
[Asm]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
1003298E |. 8038 33
cmp
byte
ptr
[
eax
], 0x33
10032991 |. 0F85 41010000
jnz
10032AD8
10032997 |. 6A 01
push
0x1
10032999 |. 8D4D D0
lea
ecx
,
dword
ptr
[
ebp
-0x30]
1003299C |. E8 BF720300
call
10069C60
100329A1 |. 8038 66
cmp
byte
ptr
[
eax
], 0x66
100329A4 |. 0F85 2E010000
jnz
10032AD8
100329AA |. 6A 02
push
0x2
100329AC |. 8D4D D0
lea
ecx
,
dword
ptr
[
ebp
-0x30]
100329AF |. E8 AC720300
call
10069C60
100329B4 |. 8038 38
cmp
byte
ptr
[
eax
], 0x38
100329B7 |. 0F85 1B010000
jnz
10032AD8
100329BD |. 6A 03
push
0x3
100329BF |. 8D4D D0
lea
ecx
,
dword
ptr
[
ebp
-0x30]
100329C2 |. E8 99720300
call
10069C60
100329C7 |. 8038 62
cmp
byte
ptr
[
eax
], 0x62
100329CA |. 0F85 08010000
jnz
10032AD8
100329D0 |. 6A 04
push
0x4
100329D2 |. 8D4D D0
lea
ecx
,
dword
ptr
[
ebp
-0x30]
100329D5 |. E8 86720300
call
10069C60
100329DA |. 8038 66
cmp
byte
ptr
[
eax
], 0x66
...............................
...............................
|
以下代码, 可知注册码第 27, 29, 31 位满足关系
[Asm]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
1002EE13 |. 0FBE71 1C
movsx
esi
,
byte
ptr
[
ecx
+0x1C]
1002EE17 |. 81C6 79070000
add
esi
, 0x779
1002EE1D |. 83F8 1E
cmp
eax
, 0x1E
1002EE20 |. 73 09
jnb
short
1002EE2B
1002EE22 |. E8 6B3C3300
call
10362A92
1002EE27 |. 8B4424 24
mov
eax
,
dword
ptr
[
esp
+0x24]
1002EE2B |> 8B4C24 14
mov
ecx
,
dword
ptr
[
esp
+0x14]
1002EE2F |. 396C24 28
cmp
dword
ptr
[
esp
+0x28],
ebp
1002EE33 |. 73 04
jnb
short
1002EE39
1002EE35 |. 8D4C24 14
lea
ecx
,
dword
ptr
[
esp
+0x14]
1002EE39 |> 57
push
edi
1002EE3A |. 0FBE79 1E
movsx
edi
,
byte
ptr
[
ecx
+0x1E]
1002EE3E |. 83EF 69
sub
edi
, 0x69
1002EE41 |. 83F8 1A
cmp
eax
, 0x1A
1002EE44 |. 73 05
jnb
short
1002EE4B
1002EE46 |. E8 473C3300
call
10362A92
1002EE4B |> 8B4424 18
mov
eax
,
dword
ptr
[
esp
+0x18]
1002EE4F |. 396C24 2C
cmp
dword
ptr
[
esp
+0x2C],
ebp
1002EE53 |. 73 04
jnb
short
1002EE59
1002EE55 |. 8D4424 18
lea
eax
,
dword
ptr
[
esp
+0x18]
1002EE59 |> 0FBE50 1A
movsx
edx
,
byte
ptr
[
eax
+0x1A]
1002EE5D |. 8D8C37 87F8FF>
lea
ecx
,
dword
ptr
[
edi
+
esi
-0x779]
1002EE64 |. 3BD1
cmp
edx
,
ecx
1002EE66 |. 75 28
jnz
short
1002EE90
1002EE68 |. 81FE DD070000
cmp
esi
, 0x7DD
1002EE6E |. 7E 0F
jle
short
1002EE7F
1002EE70 |. 81FE DF070000
cmp
esi
, 0x7DF
1002EE76 |. 7C 18
jl
short
1002EE90
1002EE78 |. 75 0D
jnz
short
1002EE87
1002EE7A |. 83FF 03
cmp
edi
, 0x3
1002EE7D |. EB 06
jmp
short
1002EE85
1002EE7F |> 81FE DC070000
cmp
esi
, 0x7DC
|
由上面可得知 注册码第27, 29, 31 位 满足以下关系
[Asm]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
第29个字符串 d 0x64 + 0x779 = 0x7DD ->
ESI
第31个字符串 o 0x6F-0x69 = 0x6 ->
EDI
第27个字符串 j 0x6A
ESI
+
EDI
- 0x779 = 0x6A
if
ESI
<= 0x7DD then
if
ESI
< 0x7DC then
[
ebx
+0x9F8]= 0x1 失败
else
[
ebx
+0x99C]= 0 成功
end
if
else
if
ESI
< 0x7DF then
[
ebx
+0x9F8]= 0x1 失败
else
if
ESI
!= 0x7DF then
[
ebx
+0x99C]= 0 成功
else
if
EDI
< 0x3 then
[
ebx
+0x9F8]= 0x1 失败
else
[
ebx
+0x99C]= 0 成功
end
if
end
if
end
if
end
if
|
算法总结: 1. 注册码格式:windows-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(windows- 后面 32 位) 2. 32位注册码的第1,3,5,7,9,11,13,15,17,19,21,23,25位是固定值, 分别是 22200ce06b66a 3. 32位注册码的第2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,30, 32位是:用户名字符串,经过翻转, 求出 MD5 值, 然后 取 前 16 位 4. 32位注册码的第27, 29, 31 位满足以下关系: (1) ASC(29位)+ASC(31位)-0x69 = ASC(27位字母) (2) ASC(29位) >= 0x63 并且 ASC(29位) 不能等于 0x65, 而且 当 ASC(29位) = 0x66 时,ASC(31位) >=0x6C 以下是注册机源码的关键部分(使用 PowerBASIC 语言 )
[Visual Basic]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
function GetRegCode(byval hWnd as dword, byref edtstr as asciiz) as STRING
local i as LONG
local oMD5 as iMD5
Dim
bReg(32) as BYTE
local sName as asciiz * 260
local szMd5 as ASCIIZ * 40
local szChar as ASCIZ * 10
dim p as byte ptr
dim pRegCode as ASCIIZ ptr
if CheckIsDBCS(edtstr) = 1 THEN
MessageBox hWnd,
"用户名不能包含中文。"
,
"提示!"
, %MB_OK or %MB_ICONEXCLAMATION
END IF
for i = len(edtstr) to 1 step -1
sName = sName & Mid$(edtstr, i, 1)
NEXT
oMD5 = class
"MD5"
szMd5 = LCASE$(oMD5.calc(sName))
ARRAY ASSIGN bReg() = &H32,&H00,&H32,&H00,&H32,&H00,&H30,&H00,&H30,&H00,&H63,&H00,&H65,&H00,&H30,&H00,&H36,&H00,&H62,&H00,&H36,&H00,&H36,&H00,&H61,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
p = varptr(szMd5)
for i = 1 to 31
bReg(i) = @p
p=p+1
i=i+1
NEXT
szChar = GetThreeChar()
p = varptr(szChar)
bReg(26) = @p
p = p+1
bReg(28) = @p
p = p+1
bReg(30) = @p
pRegCode = varptr(bReg(0))
function =
"windows-"
& @pRegCode
END FUNCTION
function GetThreeChar() as STRING
local char27 as ASCIIZ * 2
local char29 as ASCIIZ * 2
local char31 as ASCIIZ * 2
char29 = Get29()
char31 = Get31(char29)
char27 = chr$(ASC(char29) + ASC(char31) - 105)
function = char27 & char29 & char31
END FUNCTION
function Get29() as string
local char29 as ASCIIZ * 2
randomize
char29 = chr$(int(rnd*24 + 99))
if asc(char29) = 101 THEN
Get29()
END IF
function = char29
END FUNCTION
function Get31(byref char as asciiz) as STRING
local char31 as ASCIIZ * 2
randomize
char31 = chr$(int(rnd*26 + 202- ASC(char)))
if ASC(char) <> 102 THEN
if ASC(char31) >= 97 and ASC(char31) < 123 THEN
function = char31
else
Get31(char)
END IF
else
if ASC(char31) >= 108 and ASC(char31) < 123 THEN
function = char31
else
Get31(char)
END IF
END IF
END FUNCTION
|
-------------------------------------------------------------------------------- 【版权声明】: 本文原创于吾爱破解论坛, 转载请注明作者并保持文章的完整, 谢谢! 附一张注册机截图:(帖子附件包含注册机,以及注册机的 PowerBASIC 源码 ) (提示:杀软可能会误报, 不信者可以自己编译。) 注册机+源码: Keygen for LibXL.rar (124 KB, 下载次数: 167) 用法: 见30楼:http://www.52pojie.cn/forum.php?mod=redirect&goto=findpost&ptid=566985&pid=14784663 |