好友
阅读权限 35
听众
最后登录 1970-1-1
solly
发表于 2019-7-15 02:25
本帖最后由 solly 于 2019-7-15 23:58 编辑
160 个 CrackMe 之 159 - Torn@do.2 是一个加了壳的 CrackMe ,文件信息如下:
显示未知的壳,用 "scan /t" 重新扫描一下:
这次显示为 "EncryptPE" 了。而且其文件末尾为字符串“eEnCrypter! :) 2nd&mi”,没见过,只有手动脱壳 了。
节信息如下:
看起来与我原来脱过的 043 Ding Boy 的壳很象,也是很多节,并依次对下一节解码,也就是节名为 ".Stone" 的节,都是解码用的。
在 Windows 10 下OD载入 CrackMe,如下图所示:
往下拖可以看到 0x0041F096 有一个 jmp eax,我们直接选择在这一条指令上按 F4 , 然后再 F8 就会跳转到下一节的解码代码,与这一节基本一样,也是到 jmp eax 处 F4, 再F8跳转到下一节的解码代码,这个操作有多次,一直来到下面代码处,如下图,才来到 OEP:
上图的 0x00403560 才是 OEP,到这里我们就可以脱壳了。
再往下拖一下,可以找到 WinMain() 函数的调用,如下图:
如上图,call 00401DE0 就是调用 WinMain() 函数。
我们先脱壳,脱壳后,我们运行一下,报一个错误,运行不了,错误提示如下所示:
是一个 API 函数的问题,这个 API 函数是 DefWindowProcA(),我们需要手动修复这个问题,我们重新来到 OEP。用“管理员身份运行” ImportREC,如下图所示:
可以看到,最后一行的 Thunk 的 Valid 为 NO,点击旁边的 ”Show Invalid" 按钮,如下图显示:
其中那条 NtdllDefWindowProc_A 就是要手动修复的,鼠标左键双击这一行,弹出手动导入表编辑对话框,如下图所示:
我们先在 "Module" 下拉列表中,将 “ntdll.dll” 改成 "User32.dll",如下图所示:
然后在 Function 列表中找到“DefWindowProcA”这一行并选择,如上图所示,选好后按 “OK” 即可,这时显示如下图:
所有的函数都有效了,这时就是可以 "Fix Dump" 了,如下图所示,选择要修复的 Dump 文件即可。
这样操作后,就可以正常在 Windows 10 运行了,如果还不行,还可以用 LordPE 来 dump,不用 OD 的 dump 功能,如下图所示:
再按前面的方法修复,就应该可以在 Windows 10 下运行了。
脱壳后,OD 重新载入 F9 直接运行,来到其界面:
随便输入几个信息,点“ValIDA te”,没有动静,按3次后,“Validate” 按钮不可用了,提示变成了:"TRY AGAIN!",如下图所示:
通过前面所述,我们知道 WinMain() 函数入口在 0x00401DE0,我们浏览一下这个 WinMain()函数,可以看到这是一个标准的 Windows 窗口API应用的代码,最后面是消息循环处理。
从最前的4行代码,我们找到了 WndProc 的入口为 0x00401FD0,如下所示:
[Asm] 纯文本查看 复制代码
1
2
3
4
00401DE0 83EC 4C
sub
esp
, 4C
00401DE3 C74424 00 30000000
mov
dword
ptr
[
esp
], 30
00401DEB C74424 04 03000000
mov
dword
ptr
[
esp
+4], 3
00401DF3 C74424 08 D01F4000
mov
dword
ptr
[
esp
+8], 00401FD0
我们跟随立即数,来到 0x00401FD0,如下所示,是 WndProc() 的主处理代码:
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
00401FD0 8B4C24 08
mov
ecx
,
dword
ptr
[
esp
+8]
00401FD4 56
push
esi
00401FD5 83F9 01
cmp
ecx
, 1
00401FD8 74 2F
je
short
00402009
00401FDA 83F9 02
cmp
ecx
, 2
00401FDD 0F84 84000000
je
00402067
00401FE3 81F9 11010000
cmp
ecx
, 111
00401FE9 0F84 86000000
je
00402075
00401FEF 8B4424 14
mov
eax
,
dword
ptr
[
esp
+14]
00401FF3 8B5424 10
mov
edx
,
dword
ptr
[
esp
+10]
00401FF7 8B7424 08
mov
esi
,
dword
ptr
[
esp
+8]
00401FFB 50
push
eax
00401FFC 52
push
edx
00401FFD 51
push
ecx
00401FFE 56
push
esi
00401FFF FF15 D4E24000
call
dword
ptr
[<&USER32.DefWindowProcA>]
00402005 5E
pop
esi
00402006 C2 1000
retn
10
最后那个 call User32.DefWindowProcA 就是我们前面修复的那个 API 调用。
我们再次跟随 WM_CREATE 消息处理的“je 00402009”,来到 0x00402009,如下所示:
[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
00402009 8B4424 14
mov
eax
,
dword
ptr
[
esp
+14]
0040200D 68 F4010000
push
1F4
00402012 68 88C14000
push
0040C188
00402017 6A 00
push
0
00402019 8B48 04
mov
ecx
,
dword
ptr
[
eax
+4]
0040201C 890D F8BE4000
mov
dword
ptr
[40BEF8],
ecx
00402022 FF15 64E24000
call
dword
ptr
[<&KERNEL32.GetModuleHandleA>]
00402028 50
push
eax
00402029 FF15 68E24000
call
dword
ptr
[<&KERNEL32.GetModuleFileNameA>]
0040202F 85C0
test
eax
,
eax
00402031 74 10
je
short
00402043
00402033 B9 5C000000
mov
ecx
, 5C
00402038 3888 88C14000
cmp
byte
ptr
[
eax
+40C188],
cl
0040203E 74 03
je
short
00402043
00402040 48
dec
eax
00402041 ^ 75 F5
jnz
short
00402038
00402043 8B7424 08
mov
esi
,
dword
ptr
[
esp
+8]
00402047 6A 00
push
0
00402049 C680 88C14000 00
mov
byte
ptr
[
eax
+40C188], 0
00402050 68 77777777
push
77777777
00402055 68 11010000
push
111
0040205A 56
push
esi
0040205B FF15 E4E24000
call
dword
ptr
[<&USER32.PostMessageA>]
00402061 33C0
xor
eax
,
eax
00402063 5E
pop
esi
00402064 C2 1000
retn
10
可以看到,在处理 WM_CREATE 消息时,在最后,给窗口 Post 了一条自定义的 WM_COMMAND 消息。我们再次回到前面的 WndProc()框架函数,来到 WM_COMMAND 消息处理跳转 "je 00402075",跟随这个跳转,来到 WM_COMMAND 消息处理代码处:
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
00402075 817C24 10 77777777
cmp
dword
ptr
[
esp
+10], 77777777
0040207D 75 21
jnz
short
004020A0
0040207F 8B7424 08
mov
esi
,
dword
ptr
[
esp
+8]
00402083 6A 00
push
0
00402085 68 B0204000
push
004020B0
0040208A A1 F8BE4000
mov
eax
,
dword
ptr
[40BEF8]
0040208F 56
push
esi
00402090 6A 65
push
65
00402092 50
push
eax
00402093 FF15 E0E24000
call
dword
ptr
[<&USER32.DialogBoxParamA>]
00402099 56
push
esi
0040209A FF15 F0E24000
call
dword
ptr
[<&USER32.DestroyWindow>]
004020A0 33C0
xor
eax
,
eax
004020A2 5E
pop
esi
004020A3 C2 1000
retn
10
这个消息处理非常简单,就是只要wParam为自定义的 0x77777777 就显示 CrackMe 的主对话框,因此这里就是显示主界面的地方,我们也找到了 DlgProc() 的入口为 0x004020B0。
再次“跟随立即数”,来到 0x004020B0,对话框消息处理框架代码如下:
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
004020B0 8B4424 08
mov
eax
,
dword
ptr
[
esp
+8]
004020B4 53
push
ebx
004020B5 56
push
esi
004020B6 83F8 02
cmp
eax
, 2
004020B9 57
push
edi
004020BA 0F84 C6000000
je
00402186
004020C0 3D 10010000
cmp
eax
, 110
004020C5 74 13
je
short
004020DA
004020C7 3D 11010000
cmp
eax
, 111
004020CC 0F84 9D000000
je
0040216F
004020D2 33C0
xor
eax
,
eax
004020D4 5F
pop
edi
004020D5 5E
pop
esi
004020D6 5B
pop
ebx
004020D7 C2 1000
retn
10
我们跟随 WM_INITDIALOG 消息处理跳转 "je 004020DA" 后,可以看到这样一段代码:
[Asm] 纯文本查看 复制代码
1
2
3
4
5
6
7
004020F6 6A 00
push
0
004020F8 8B35 A0E24000
mov
esi
,
dword
ptr
[<&USER32.GetDlgItem>]
004020FE 68 EC030000
push
3EC
00402103 53
push
ebx
00402104 FFD6
call
esi
00402106 50
push
eax
00402107 FF15 98E24000
call
dword
ptr
[<&USER32.EnableWindow>]
这段代码就是在 CrackMe 启动时将 "Request" 按钮的状态改为 "Disabled" 状态的。
我们再回到 DlgProc(),跟随处理 WM_COMMAND 跳转 "je 0040216F",来到其处理框架代码:
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
0040216F 8B4424 18
mov
eax
,
dword
ptr
[
esp
+18]
00402173 25 FFFF0000
and
eax
, 0FFFF
00402178 3D EB030000
cmp
eax
, 3EB
0040217D 7F 1B
jg
short
0040219A
0040217F 74 54
je
short
004021D5
00402181 83F8 02
cmp
eax
, 2
00402184 74 37
je
short
004021BD
00402186 A1 08BE4000
mov
eax
,
dword
ptr
[40BE08]
0040218B 50
push
eax
0040218C FF15 F4E14000
call
dword
ptr
[<&GDI32.DeleteObject>]
00402192 33C0
xor
eax
,
eax
00402194 5F
pop
edi
00402195 5E
pop
esi
00402196 5B
pop
ebx
00402197 C2 1000
retn
10
可以看到,跟随 “ je 004021D5” 后就可以到达注册验证的代码了:
[Asm] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
004021D5 > \8B5C24 10
mov
ebx
,
dword
ptr
[
esp
+10]
004021D9 . 53
push
ebx
004021DA . E8 31F1FFFF
call
00401310
004021DF . 83C4 04
add
esp
, 4
004021E2 . 8BF8
mov
edi
,
eax
004021E4 . B9 FFFFFFFF
mov
ecx
, -1
004021E9 . 2BC0
sub
eax
,
eax
004021EB . F2:AE
repne
scas
byte
ptr
es
:[
edi
]
004021ED . F7D1
not
ecx
004021EF . 2BF9
sub
edi
,
ecx
004021F1 . 8BC1
mov
eax
,
ecx
004021F3 . C1E9 02
shr
ecx
, 2
004021F6 . 8BF7
mov
esi
,
edi
004021F8 . BF 30BF4000
mov
edi
, 0040BF30
004021FD . F3:A5
rep
movs
dword
ptr
es
:[
edi
],
dword
ptr
[
esi
]
004021FF . 8BC8
mov
ecx
,
eax
00402201 . 53
push
ebx
00402202 . 83E1 03
and
ecx
, 3
00402205 . F3:A4
rep
movs
byte
ptr
es
:[
edi
],
byte
ptr
[
esi
]
00402207 . E8 74F1FFFF
call
00401380
0040220C . 83C4 04
add
esp
, 4
0040220F . 8BF8
mov
edi
,
eax
00402211 . B9 FFFFFFFF
mov
ecx
, -1
00402216 . 2BC0
sub
eax
,
eax
00402218 . F2:AE
repne
scas
byte
ptr
es
:[
edi
]
0040221A . F7D1
not
ecx
0040221C . 2BF9
sub
edi
,
ecx
0040221E . 8BD1
mov
edx
,
ecx
00402220 . C1E9 02
shr
ecx
, 2
00402223 . 8BF7
mov
esi
,
edi
00402225 . BF E0BD4000
mov
edi
, 0040BDE0
0040222A . F3:A5
rep
movs
dword
ptr
es
:[
edi
],
dword
ptr
[
esi
]
0040222C . 8BCA
mov
ecx
,
edx
0040222E . 53
push
ebx
0040222F . 83E1 03
and
ecx
, 3
00402232 . F3:A4
rep
movs
byte
ptr
es
:[
edi
],
byte
ptr
[
esi
]
00402234 . E8 B7F1FFFF
call
004013F0
00402239 . 83C4 04
add
esp
, 4
0040223C . 8BF8
mov
edi
,
eax
0040223E . B9 FFFFFFFF
mov
ecx
, -1
00402243 . 2BC0
sub
eax
,
eax
00402245 . F2:AE
repne
scas
byte
ptr
es
:[
edi
]
00402247 . F7D1
not
ecx
00402249 . 2BF9
sub
edi
,
ecx
0040224B . 8BD1
mov
edx
,
ecx
0040224D . C1E9 02
shr
ecx
, 2
00402250 . 8BF7
mov
esi
,
edi
00402252 . BF 28BE4000
mov
edi
, 0040BE28
00402257 . F3:A5
rep
movs
dword
ptr
es
:[
edi
],
dword
ptr
[
esi
]
00402259 . 8BCA
mov
ecx
,
edx
0040225B . 83E1 03
and
ecx
, 3
0040225E . F3:A4
rep
movs
byte
ptr
es
:[
edi
],
byte
ptr
[
esi
]
00402260 . 53
push
ebx
00402261 . 68 28BE4000
push
0040BE28
00402266 . 68 E0BD4000
push
0040BDE0
0040226B . 68 30BF4000
push
0040BF30
00402270 . E8 7BFAFFFF
call
00401CF0
00402275 . 83C4 10
add
esp
, 10
00402278 . 66:833D 20BE4000 28
cmp
word
ptr
[40BE20], 28
00402280 . 75 1E
jnz
short
004022A0
00402282 . 6A 00
push
0
00402284 . A1 F8BE4000
mov
eax
,
dword
ptr
[40BEF8]
00402289 . 68 A0254000
push
004025A0
0040228E . 53
push
ebx
0040228F . 6A 68
push
68
00402291 . 50
push
eax
00402292 . FF15 E0E24000
call
dword
ptr
[<&user32.DialogBoxParamA>
00402298 . 33C0
xor
eax
,
eax
0040229A . 5F
pop
edi
0040229B . 5E
pop
esi
0040229C . 5B
pop
ebx
0040229D . C2 1000
retn
10
004022A0 > 66:A1 74A04000
mov
ax
,
word
ptr
[40A074]
004022A6 . 66:40
inc
ax
004022A8 . 66:A3 74A04000
mov
word
ptr
[40A074],
ax
004022AE . 66:3D 0300
cmp
ax
, 3
004022B2 . 75 32
jnz
short
004022E6
004022B4 . 6A 00
push
0
004022B6 . 8B35 A0E24000
mov
esi
,
dword
ptr
[<&user32.GetDlgItem>
004022BC . 68 EB030000
push
3EB
004022C1 . 53
push
ebx
004022C2 . FFD6
call
esi
004022C4 . 50
push
eax
004022C5 . 8B3D 98E24000
mov
edi
,
dword
ptr
[<&user32.EnableWindow>
004022CB . FFD7
call
edi
004022CD . 68 68A04000
push
0040A068
004022D2 . 68 EE030000
push
3EE
004022D7 . 53
push
ebx
004022D8 . FF15 F8E24000
call
dword
ptr
[<&user32.SetDlgItemTextA>
004022DE . 66:A1 74A04000
mov
ax
,
word
ptr
[40A074]
004022E4 . EB 0C
jmp
short
004022F2
004022E6 > 8B3D 98E24000
mov
edi
,
dword
ptr
[<&user32.EnableWindow>
004022EC . 8B35 A0E24000
mov
esi
,
dword
ptr
[<&user32.GetDlgItem>
004022F2 > 66:A3 74A04000
mov
word
ptr
[40A074],
ax
004022F8 . 66:3D 0300
cmp
ax
, 3
004022FC . 7E 21
jle
short
0040231F
004022FE . 6A 00
push
0
00402300 . 68 EB030000
push
3EB
00402305 . 53
push
ebx
00402306 . FFD6
call
esi
00402308 . 50
push
eax
00402309 . FFD7
call
edi
0040230B . 6A 40
push
40
0040230D . 68 98A74000
push
0040A798
00402312 . 68 10A74000
push
0040A710
00402317 . 6A 00
push
0
00402319 . FF15 DCE24000
call
dword
ptr
[<&user32.MessageBoxA>]
0040231F > 33C0
xor
eax
,
eax
00402321 . 5F
pop
edi
00402322 . 5E
pop
esi
00402323 . 5B
pop
ebx
00402324 . C2 1000
retn
10
从上面的我的注释中,可以看到,前面三次都是没有用的验证,迷惑用的,实际用途只是取界面上输入的三个字符串。直正的验证是如下代码处:
[Asm] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
00402260 . 53
push
ebx
00402261 . 68 28BE4000
push
0040BE28
00402266 . 68 E0BD4000
push
0040BDE0
0040226B . 68 30BF4000
push
0040BF30
00402270 . E8 7BFAFFFF
call
00401CF0
00402275 . 83C4 10
add
esp
, 10
00402278 . 66:833D 20BE4000 28
cmp
word
ptr
[40BE20], 28
00402280 . 75 1E
jnz
short
004022A0
上面的 call 00401CF0 才是真正的验证代码,其代码下:
[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
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
00401CF0 /$ 53
push
ebx
00401CF1 |. 56
push
esi
00401CF2 |. 8B5C24 14
mov
ebx
,
dword
ptr
[
esp
+14]
00401CF6 |. 57
push
edi
00401CF7 |. 55
push
ebp
00401CF8 |. 53
push
ebx
00401CF9 |. E8 F2FCFFFF
call
004019F0
00401CFE |. 83C4 04
add
esp
, 4
00401D01 |. 53
push
ebx
00401D02 |. E8 19FAFFFF
call
00401720
00401D07 |. 83C4 04
add
esp
, 4
00401D0A |. 83F8 01
cmp
eax
, 1
00401D0D |. 74 0E
je
short
00401D1D
00401D0F |. 66:C705 20BE4000 FFFF
mov
word
ptr
[40BE20], 0FFFF
00401D18 |. 5D
pop
ebp
00401D19 |. 5F
pop
edi
00401D1A |. 5E
pop
esi
00401D1B |. 5B
pop
ebx
00401D1C |. C3
retn
00401D1D |> 8B6C24 20
mov
ebp
,
dword
ptr
[
esp
+20]
00401D21 |. 8B7C24 18
mov
edi
,
dword
ptr
[
esp
+18]
00401D25 |. 8B7424 14
mov
esi
,
dword
ptr
[
esp
+14]
00401D29 |. 55
push
ebp
00401D2A |. 53
push
ebx
00401D2B |. 57
push
edi
00401D2C |. 56
push
esi
00401D2D |. E8 EEFCFFFF
call
00401A20
00401D32 |. 83C4 10
add
esp
, 10
00401D35 |. 53
push
ebx
00401D36 |. E8 55FAFFFF
call
00401790
00401D3B |. 83C4 04
add
esp
, 4
00401D3E |. 83F8 01
cmp
eax
, 1
00401D41 |. 74 0E
je
short
00401D51
00401D43 |. 66:C705 20BE4000 FFFF
mov
word
ptr
[40BE20], 0FFFF
00401D4C |. 5D
pop
ebp
00401D4D |. 5F
pop
edi
00401D4E |. 5E
pop
esi
00401D4F |. 5B
pop
ebx
00401D50 |. C3
retn
00401D51 |> 53
push
ebx
00401D52 |. E8 89FAFFFF
call
004017E0
00401D57 |. 83C4 04
add
esp
, 4
00401D5A |. 83F8 01
cmp
eax
, 1
00401D5D |. 74 0E
je
short
00401D6D
00401D5F |. 66:C705 20BE4000 FFFF
mov
word
ptr
[40BE20], 0FFFF
00401D68 |. 5D
pop
ebp
00401D69 |. 5F
pop
edi
00401D6A |. 5E
pop
esi
00401D6B |. 5B
pop
ebx
00401D6C |. C3
retn
00401D6D |> 55
push
ebp
00401D6E |. 53
push
ebx
00401D6F |. 57
push
edi
00401D70 |. 56
push
esi
00401D71 |. E8 FAFDFFFF
call
00401B70
00401D76 |. 83C4 10
add
esp
, 10
00401D79 |. A1 80C34000
mov
eax
,
dword
ptr
[40C380]
00401D7E |. 50
push
eax
00401D7F |. 53
push
ebx
00401D80 |. E8 EBFAFFFF
call
00401870
00401D85 |. 83C4 08
add
esp
, 8
00401D88 |. 83F8 01
cmp
eax
, 1
00401D8B |. 74 0E
je
short
00401D9B
00401D8D |. 66:C705 20BE4000 FFFF
mov
word
ptr
[40BE20], 0FFFF
00401D96 |. 5D
pop
ebp
00401D97 |. 5F
pop
edi
00401D98 |. 5E
pop
esi
00401D99 |. 5B
pop
ebx
00401D9A |. C3
retn
00401D9B |> 55
push
ebp
00401D9C |. 53
push
ebx
00401D9D |. 57
push
edi
00401D9E |. 56
push
esi
00401D9F |. E8 8CFEFFFF
call
00401C30
00401DA4 |. 83C4 10
add
esp
, 10
00401DA7 |. 53
push
ebx
00401DA8 |. E8 63FBFFFF
call
00401910
00401DAD |. 83C4 04
add
esp
, 4
00401DB0 |. 83F8 01
cmp
eax
, 1
00401DB3 |. 74 0E
je
short
00401DC3
00401DB5 |. 66:C705 20BE4000 FFFF
mov
word
ptr
[40BE20], 0FFFF
00401DBE |. 5D
pop
ebp
00401DBF |. 5F
pop
edi
00401DC0 |. 5E
pop
esi
00401DC1 |. 5B
pop
ebx
00401DC2 |. C3
retn
00401DC3 |> 55
push
ebp
00401DC4 |. E8 97F6FFFF
call
00401460
00401DC9 |. 83C4 04
add
esp
, 4
00401DCC |. 5D
pop
ebp
00401DCD |. 5F
pop
edi
00401DCE |. 5E
pop
esi
00401DCF |. 5B
pop
ebx
00401DD0 \. C3
retn
这里説明一下,从上面代码中可以看到,有一个时间验证(call 004017E0),代码如下:
[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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
004017E0 /$ 83EC 04
sub
esp
, 4
004017E3 |. 33C9
xor
ecx
,
ecx
004017E5 |. 8D4424 01
lea
eax
,
dword
ptr
[
esp
+1]
004017E9 |. 56
push
esi
004017EA |. 8B5424 0C
mov
edx
,
dword
ptr
[
esp
+
C
]
004017EE |. 57
push
edi
004017EF |. 8BFA
mov
edi
,
edx
004017F1 |. 884C24 08
mov
byte
ptr
[
esp
+8],
cl
004017F5 |. 66:8908
mov
word
ptr
[
eax
],
cx
004017F8 |. 8848 02
mov
byte
ptr
[
eax
+2],
cl
004017FB |. B9 FFFFFFFF
mov
ecx
, -1
00401800 |. 2BC0
sub
eax
,
eax
00401802 |. F2:AE
repne
scas
byte
ptr
es
:[
edi
]
00401804 |. F7D1
not
ecx
00401806 |. 8BFA
mov
edi
,
edx
00401808 |. 2BC0
sub
eax
,
eax
0040180A |. 8A4C11 FB
mov
cl
,
byte
ptr
[
ecx
+
edx
-5]
0040180E |. 884C24 08
mov
byte
ptr
[
esp
+8],
cl
00401812 |. B9 FFFFFFFF
mov
ecx
, -1
00401817 |. F2:AE
repne
scas
byte
ptr
es
:[
edi
]
00401819 |. F7D1
not
ecx
0040181B |. 8BFA
mov
edi
,
edx
0040181D |. 8A4411 FC
mov
al
,
byte
ptr
[
ecx
+
edx
-4]
00401821 |. B9 FFFFFFFF
mov
ecx
, -1
00401826 |. 884424 09
mov
byte
ptr
[
esp
+9],
al
0040182A |. 2BC0
sub
eax
,
eax
0040182C |. F2:AE
repne
scas
byte
ptr
es
:[
edi
]
0040182E |. F7D1
not
ecx
00401830 |. 8BFA
mov
edi
,
edx
00401832 |. 2BC0
sub
eax
,
eax
00401834 |. 8A4C11 FD
mov
cl
,
byte
ptr
[
ecx
+
edx
-3]
00401838 |. 884C24 0A
mov
byte
ptr
[
esp
+A],
cl
0040183C |. B9 FFFFFFFF
mov
ecx
, -1
00401841 |. F2:AE
repne
scas
byte
ptr
es
:[
edi
]
00401843 |. F7D1
not
ecx
00401845 |. 8D4424 08
lea
eax
,
dword
ptr
[
esp
+8]
00401849 |. 8A5411 FE
mov
dl
,
byte
ptr
[
ecx
+
edx
-2]
0040184D |. 885424 0B
mov
byte
ptr
[
esp
+B],
dl
00401851 |. 50
push
eax
00401852 |. E8 291C0000
call
00403480
00401857 |. 83C4 04
add
esp
, 4
0040185A |. 8BF0
mov
esi
,
eax
0040185C |. E8 3FFEFFFF
call
004016A0
00401861 |. 2BC6
sub
eax
,
esi
00401863 |. 5F
pop
edi
00401864 |. 5E
pop
esi
00401865 |. 83F8 01
cmp
eax
, 1
00401868 |. 1BC0
sbb
eax
,
eax
0040186A |. 83C4 04
add
esp
, 4
0040186D |. F7D8
neg
eax
0040186F \. C3
retn
其中又有一个调用(call 004016A0),就是根据当前时间生成一段注册验证,对注册码最后4个数字进行验证:
[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
33
34
35
36
37
004016A0 /$ 83EC 10
sub
esp
, 10
004016A3 |. 8D4424 00
lea
eax
,
dword
ptr
[
esp
]
004016A7 |. 56
push
esi
004016A8 |. 50
push
eax
004016A9 |. FF15 6CE24000
call
dword
ptr
[<&kernel32.GetLocalTime>]
004016AF |. 33D2
xor
edx
,
edx
004016B1 |. 33C0
xor
eax
,
eax
004016B3 |. 66:8B5424 06
mov
dx
,
word
ptr
[
esp
+6]
004016B8 |. 33C9
xor
ecx
,
ecx
004016BA |. 66:8B4424 0A
mov
ax
,
word
ptr
[
esp
+A]
004016BF |. 0FAFD0
imul
edx
,
eax
004016C2 |. 66:8B4C24 0E
mov
cx
,
word
ptr
[
esp
+E]
004016C7 |. 8B4424 0C
mov
eax
,
dword
ptr
[
esp
+
C
]
004016CB |. 25 FFFF0000
and
eax
, 0FFFF
004016D0 |. 0FAFC1
imul
eax
,
ecx
004016D3 |. 0FBE0D 60BF4000
movsx
ecx
,
byte
ptr
[40BF60]
004016DA |. 03D0
add
edx
,
eax
004016DC |. 8B4424 04
mov
eax
,
dword
ptr
[
esp
+4]
004016E0 |. 2BD1
sub
edx
,
ecx
004016E2 |. 25 FFFF0000
and
eax
, 0FFFF
004016E7 |. 8D3402
lea
esi
,
dword
ptr
[
edx
+
eax
]
004016EA |. 56
push
esi
004016EB |. E8 A0FBFFFF
call
00401290
004016F0 |. 83C4 04
add
esp
, 4
004016F3 |. 85C0
test
eax
,
eax
004016F5 |. 74 06
je
short
004016FD
004016F7 |. 81C6 43010000
add
esi
, 143
004016FD |> 56
push
esi
004016FE |. E8 CDFBFFFF
call
004012D0
00401703 |. 83C4 04
add
esp
, 4
00401706 |. 85C0
test
eax
,
eax
00401708 |. 74 06
je
short
00401710
0040170A |. 81C6 71020000
add
esi
, 271
00401710 |> 8BC6
mov
eax
,
esi
00401712 |. 5E
pop
esi
00401713 |. 83C4 10
add
esp
, 10
00401716 \. C3
retn
也就是説,其验证时间精准到了分钟,生成的序列号有效时间最多60秒,如果注册机生成序列号与你输入序列号不是在同一分钟数字时(不是指1分钟内)序列号就是无效的,也就是説当输入序列号时,只要秒钟跨过了第59秒,就得重新生成序列号。
注册码前面两段是固定的,由 call 00401720 和 call 00401790 实现的,比较简单,这里不对其进行分析。
call 00401870 是对注册表中的一个值进行验证,这样,序列号与具体机器有关,不是通用的了,必须要有注册机才能搞定注册。这个调用是处理注册表中 FirstInstallDateTime 这个值的,不过这个值只有在 Windows 9x 系统下才有,Win NT 系列,如 Windows 10 下就没有这个注册表项。另外 CrackMe 还要用到一个注册表项: RegisteredOwner,这个也只有在 Windows 9x 下才有。这个调用的主要代码如下(其前面有一段代码中没有用的,迷惑用的,不贴上来了):
[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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
00401870 /$ 83EC 64
sub
esp
, 64
00401873 |. 53
push
ebx
00401874 |. 56
push
esi
00401875 |. 57
push
edi
00401876 |. 33DB
xor
ebx
,
ebx
00401878 |. 8D7C24 0D
lea
edi
,
dword
ptr
[
esp
+D]
0040187C |. 55
push
ebp
0040187D |. 33C0
xor
eax
,
eax
0040187F |. B9 18000000
mov
ecx
, 18
00401884 |. 885C24 10
mov
byte
ptr
[
esp
+10],
bl
00401888 |. F3:AB
rep
stos
dword
ptr
es
:[
edi
]
0040188A |. 66:AB
stos
word
ptr
es
:[
edi
]
0040188C |. AA
stos
byte
ptr
es
:[
edi
]
0040188D |. 33F6
xor
esi
,
esi
0040188F |. 8B6C24 7C
mov
ebp
,
dword
ptr
[
esp
+7C]
00401893 |. 3BE8
cmp
ebp
,
eax
00401895 |. 74 24
je
short
004018BB
00401897 |. 8B5424 78
mov
edx
,
dword
ptr
[
esp
+78]
0040189B |> 8BFA /
mov
edi
,
edx
0040189D |. B9 FFFFFFFF |
mov
ecx
, -1
004018A2 |. 2BC0 |
sub
eax
,
eax
004018A4 |. F2:AE |
repne
scas
byte
ptr
es
:[
edi
]
004018A6 |. F7D1 |
not
ecx
004018A8 |. 49 |
dec
ecx
004018A9 |. 46 |
inc
esi
004018AA |. 2BCD |
sub
ecx
,
ebp
004018AC |. 03CB |
add
ecx
,
ebx
004018AE |. 43 |
inc
ebx
004018AF |. 3BF5 |
cmp
esi
,
ebp
004018B1 |. 8A4411 FB |
mov
al
,
byte
ptr
[
ecx
+
edx
-5]
004018B5 |. 884434 0F |
mov
byte
ptr
[
esp
+
esi
+F],
al
004018B9 |.^ 72 E0 \
jb
short
0040189B
004018BB |> 8D4424 10
lea
eax
,
dword
ptr
[
esp
+10]
004018BF |. 50
push
eax
004018C0 |. E8 BB1B0000
call
00403480
004018C5 |. 83C4 04
add
esp
, 4
004018C8 |. 8BF0
mov
esi
,
eax
004018CA |. A1 FCBE4000
mov
eax
,
dword
ptr
[40BEFC]
004018CF |. 894424 10
mov
dword
ptr
[
esp
+10],
eax
004018D3 |. C74424 14 00000000
mov
dword
ptr
[
esp
+14], 0
004018DB |. DF6C24 10
fild
qword
ptr
[
esp
+10]
004018DF |. D9C0
fld
st
004018E1 |. E8 731C0000
call
00403559
004018E6 |. DC0D 20904000
fmul
qword
ptr
[409020]
004018EC |. DEE9
fsubp
st
(1),
st
004018EE |. E8 590D0000
call
0040264C
004018F3 |. 2BC6
sub
eax
,
esi
004018F5 |. 5D
pop
ebp
004018F6 |. 5F
pop
edi
004018F7 |. 83F8 01
cmp
eax
, 1
004018FA |. 1BC0
sbb
eax
,
eax
004018FC |. 5E
pop
esi
004018FD |. F7D8
neg
eax
004018FF |. 5B
pop
ebx
00401900 |. 83C4 64
add
esp
, 64
00401903 \. C3
retn
就是将 FirstInstallDateTime 进行简单计算后,与输入的序列号相关字段进行比较,相等即通过。
还有一个调用(call 00401910)就是对我们在界面上输入的用户名和公司名进行校验,当中还包括注册表项 RegisteredOwner 的验证,如下:
[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
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
00401910 /$ 83EC 64
sub
esp
, 64
00401913 |. 33C0
xor
eax
,
eax
00401915 |. B9 18000000
mov
ecx
, 18
0040191A |. 56
push
esi
0040191B |. C64424 04 00
mov
byte
ptr
[
esp
+4], 0
00401920 |. 57
push
edi
00401921 |. 8D7C24 09
lea
edi
,
dword
ptr
[
esp
+9]
00401925 |. F3:AB
rep
stos
dword
ptr
es
:[
edi
]
00401927 |. 66:AB
stos
word
ptr
es
:[
edi
]
00401929 |. BE 0C000000
mov
esi
, 0C
0040192E |. B9 FFFFFFFF
mov
ecx
, -1
00401933 |. AA
stos
byte
ptr
es
:[
edi
]
00401934 |. 8B5424 70
mov
edx
,
dword
ptr
[
esp
+70]
00401938 |. 2BC0
sub
eax
,
eax
0040193A |. 8BFA
mov
edi
,
edx
0040193C |. F2:AE
repne
scas
byte
ptr
es
:[
edi
]
0040193E |. F7D1
not
ecx
00401940 |. 49
dec
ecx
00401941 |. 2B0D 80C34000
sub
ecx
,
dword
ptr
[40C380]
00401947 |. 83E9 05
sub
ecx
, 5
0040194A |. 3BCE
cmp
ecx
,
esi
0040194C |. 76 24
jbe
short
00401972
0040194E |> 8A4432 FF /
mov
al
,
byte
ptr
[
edx
+
esi
-1]
00401952 |. 46 |
inc
esi
00401953 |. 8BFA |
mov
edi
,
edx
00401955 |. B9 FFFFFFFF |
mov
ecx
, -1
0040195A |. 884434 FB |
mov
byte
ptr
[
esp
+
esi
-5],
al
0040195E |. 2BC0 |
sub
eax
,
eax
00401960 |. F2:AE |
repne
scas
byte
ptr
es
:[
edi
]
00401962 |. F7D1 |
not
ecx
00401964 |. 49 |
dec
ecx
00401965 |. 2B0D 80C34000 |
sub
ecx
,
dword
ptr
[40C380]
0040196B |. 83E9 05 |
sub
ecx
, 5
0040196E |. 3BCE |
cmp
ecx
,
esi
00401970 |.^ 77 DC \
ja
short
0040194E
00401972 |> 8D4424 08
lea
eax
,
dword
ptr
[
esp
+8]
00401976 |. 50
push
eax
00401977 |. E8 041B0000
call
00403480
0040197C |. 83C4 04
add
esp
, 4
0040197F |. 8BF8
mov
edi
,
eax
00401981 |. E8 0AFCFFFF
call
00401590
00401986 |. 8BF0
mov
esi
,
eax
00401988 |. E8 B3FBFFFF
call
00401540
0040198D |. 33F0
xor
esi
,
eax
0040198F |. 68 E0BD4000
push
0040BDE0
00401994 |. 68 30BF4000
push
0040BF30
00401999 |. E8 42FCFFFF
call
004015E0
0040199E |. 83C4 08
add
esp
, 8
004019A1 |. 03C6
add
eax
,
esi
004019A3 |. 8D0CC0
lea
ecx
,
dword
ptr
[
eax
+
eax
*8]
004019A6 |. 8D14C8
lea
edx
,
dword
ptr
[
eax
+
ecx
*8]
004019A9 |. 8D0C52
lea
ecx
,
dword
ptr
[
edx
+
edx
*2]
004019AC |. C1E1 02
shl
ecx
, 2
004019AF |. 2BC8
sub
ecx
,
eax
004019B1 |. C1E1 06
shl
ecx
, 6
004019B4 |. 2BC8
sub
ecx
,
eax
004019B6 |. 03C9
add
ecx
,
ecx
004019B8 |. 894C24 08
mov
dword
ptr
[
esp
+8],
ecx
004019BC |. C74424 0C 00000000
mov
dword
ptr
[
esp
+
C
], 0
004019C4 |. DF6C24 08
fild
qword
ptr
[
esp
+8]
004019C8 |. D9C0
fld
st
004019CA |. D9FE
fsin
004019CC |. DC0D 28904000
fmul
qword
ptr
[409028]
004019D2 |. DEE9
fsubp
st
(1),
st
004019D4 |. E8 730C0000
call
0040264C
004019D9 |. 2BC7
sub
eax
,
edi
004019DB |. 5F
pop
edi
004019DC |. 5E
pop
esi
004019DD |. 83F8 01
cmp
eax
, 1
004019E0 |. 1BC0
sbb
eax
,
eax
004019E2 |. 83C4 64
add
esp
, 64
004019E5 |. F7D8
neg
eax
004019E7 \. C3
retn
其中,对用户名和公司名处理的调用(call 004015E0)如下所示:
[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
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
004015E0 /$ 83EC 08
sub
esp
, 8
004015E3 |. 33D2
xor
edx
,
edx
004015E5 |. B9 FFFFFFFF
mov
ecx
, -1
004015EA |. 53
push
ebx
004015EB |. 66:BB 0100
mov
bx
, 1
004015EF |. 56
push
esi
004015F0 |. 8B7424 14
mov
esi
,
dword
ptr
[
esp
+14]
004015F4 |. 57
push
edi
004015F5 |. 8BFE
mov
edi
,
esi
004015F7 |. 2BC0
sub
eax
,
eax
004015F9 |. F2:AE
repne
scas
byte
ptr
es
:[
edi
]
004015FB |. F7D1
not
ecx
004015FD |. 49
dec
ecx
004015FE |. 83F9 01
cmp
ecx
, 1
00401601 |. 76 2F
jbe
short
00401632
00401603 |> 0FBFC3 /
movsx
eax
,
bx
00401606 |. 0FBE4430 FF |
movsx
eax
,
byte
ptr
[
eax
+
esi
-1]
0040160B |. 8BC8 |
mov
ecx
,
eax
0040160D |. C1E0 02 |
shl
eax
, 2
00401610 |. 66:43 |
inc
bx
00401612 |. 8BFE |
mov
edi
,
esi
00401614 |. 8D04C0 |
lea
eax
,
dword
ptr
[
eax
+
eax
*8]
00401617 |. 8D0CC1 |
lea
ecx
,
dword
ptr
[
ecx
+
eax
*8]
0040161A |. 8D04C9 |
lea
eax
,
dword
ptr
[
ecx
+
ecx
*8]
0040161D |. B9 FFFFFFFF |
mov
ecx
, -1
00401622 |. 03D0 |
add
edx
,
eax
00401624 |. 2BC0 |
sub
eax
,
eax
00401626 |. F2:AE |
repne
scas
byte
ptr
es
:[
edi
]
00401628 |. 0FBFC3 |
movsx
eax
,
bx
0040162B |. F7D1 |
not
ecx
0040162D |. 49 |
dec
ecx
0040162E |. 3BC8 |
cmp
ecx
,
eax
00401630 |.^ 77 D1 \
ja
short
00401603
00401632 |> 66:BB 0100
mov
bx
, 1
00401636 |. 8B7424 1C
mov
esi
,
dword
ptr
[
esp
+1C]
0040163A |. 8BFE
mov
edi
,
esi
0040163C |. B9 FFFFFFFF
mov
ecx
, -1
00401641 |. 2BC0
sub
eax
,
eax
00401643 |. F2:AE
repne
scas
byte
ptr
es
:[
edi
]
00401645 |. F7D1
not
ecx
00401647 |. 49
dec
ecx
00401648 |. 83F9 01
cmp
ecx
, 1
0040164B |. 76 21
jbe
short
0040166E
0040164D |> 0FBFC3 /
movsx
eax
,
bx
00401650 |. 66:43 |
inc
bx
00401652 |. 8BFE |
mov
edi
,
esi
00401654 |. 0FBE4C30 FF |
movsx
ecx
,
byte
ptr
[
eax
+
esi
-1]
00401659 |. 03D1 |
add
edx
,
ecx
0040165B |. B9 FFFFFFFF |
mov
ecx
, -1
00401660 |. 2BC0 |
sub
eax
,
eax
00401662 |. F2:AE |
repne
scas
byte
ptr
es
:[
edi
]
00401664 |. 0FBFC3 |
movsx
eax
,
bx
00401667 |. F7D1 |
not
ecx
00401669 |. 49 |
dec
ecx
0040166A |. 3BC8 |
cmp
ecx
,
eax
0040166C |.^ 77
DF
\
ja
short
0040164D
0040166E |> 8D0492
lea
eax
,
dword
ptr
[
edx
+
edx
*4]
00401671 |. 8D0C42
lea
ecx
,
dword
ptr
[
edx
+
eax
*2]
00401674 |. 894C24 0C
mov
dword
ptr
[
esp
+
C
],
ecx
00401678 |. C74424 10 00000000
mov
dword
ptr
[
esp
+10], 0
00401680 |. DF6C24 0C
fild
qword
ptr
[
esp
+
C
]
00401684 |. D9FA
fsqrt
00401686 |. E8 C10F0000
call
0040264C
0040168B |. 5F
pop
edi
0040168C |. 5E
pop
esi
0040168D |. 5B
pop
ebx
0040168E |. 83C4 08
add
esp
, 8
00401691 \. C3
retn
另外对 RegisteredOwner 的验证有两次,比较简单,见注册机,不在此分析。另外,前面时间验证中,也用到了 RegisteredOwner 字符串的第1个字符(RegisteredOwner[0])的 ASCII 码值。
因为其有对注册表项进行验证,所以其需要读取注册表中的数据,不过,其在读取 FirstInstallDateTime 有问题,并没有取得这个值,而是取得保存这个值的地址,将这个地址参与了序列号的计算,这段取注册表信息的代码如下:
[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
00401E59 |. 68 F8A64000
push
0040A6F8
00401E5E |. 68 CCA64000
push
0040A6CC
00401E63 |. 68 02000080
push
80000002
00401E68 |. E8 43F6FFFF
call
004014B0
00401E6D |. 83C4 0C
add
esp
, 0C
00401E70 |. 8B2D B4E24000
mov
ebp
,
dword
ptr
[<&user32.wsprintfA>]
00401E76 |. 50
push
eax
00401E77 |. 68 C8A64000
push
0040A6C8
00401E7C |. 68 90BF4000
push
0040BF90
00401E81 |. FFD5
call
ebp
00401E83 |. 83C4 0C
add
esp
, 0C
00401E86 |. BF 90BF4000
mov
edi
, 0040BF90
00401E8B |. 68 90BF4000
push
0040BF90
00401E90 |. E8 EB150000
call
00403480
00401E95 |. 83C4 04
add
esp
, 4
00401E98 |. B9 FFFFFFFF
mov
ecx
, -1
00401E9D |. A3 FCBE4000
mov
dword
ptr
[40BEFC],
eax
00401EA2 |. 2BC0
sub
eax
,
eax
00401EA4 |. F2:AE
repne
scas
byte
ptr
es
:[
edi
]
00401EA6 |. F7D1
not
ecx
00401EA8 |. 49
dec
ecx
00401EA9 |. 68 B8A64000
push
0040A6B8
00401EAE |. 68 CCA64000
push
0040A6CC
00401EB3 |. 890D 80C34000
mov
dword
ptr
[40C380],
ecx
00401EB9 |. 68 02000080
push
80000002
00401EBE |. E8 EDF5FFFF
call
004014B0
问题出在调用 wsprintf() 这个函数的参数,因为 Call 004014B0 这个函数读取注册表信息后,返回的是一个地址,而 wsprintf()中,引用的是这个地址,所以转换成字符串也是一个地址值,不是真正的 FirstInstallDateTime的值,如果要修改这个 Bug,可以进行以下修改,如下图所示:
将 0x00401E6D处的 add esp, 0C 改成 mov eax, [eax],然后在下面 0x00401E83 处的 add esp, 0C 改成 add esp, 18,这样堆栈也平衡了,Bug也消除了。
基本的注册验证过程分析到这里,用注册机生成注册码,并抓紧时间输入(粘贴),校验正确时,显示如下:
一定要注意时间,最好在当前分钟的前 0~30秒内生成序列号,后30秒来输入注册码并验证,不然可能序列号就过期了。
另外,在 Windows 10 之类的新版 Windows 下,缺少注册表项,需要导入以下信息,不然也通不过 CrackMe 的注册验证,64位系统 如下:
[HTML] 纯文本查看 复制代码
1
2
3
4
5
6
7
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion]
"FirstInstallDateTime"=hex:c1,b1,98,4c
"RegisteredOrganization"="ite"
"RegisteredOwner"="solly"
"ProductId"="51163-030-0389753-07447"
32位系统 如下:
[HTML] 纯文本查看 复制代码
1
2
3
4
5
6
7
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion]
"FirstInstallDateTime"=hex:c1,b1,98,4c
"RegisteredOrganization"="ite"
"RegisteredOwner"="solly"
"ProductId"="51163-030-0389753-07447"
当然,键值可以改成自己的,键名不能改动。
分析完毕,下面是注册机源码,使用 Dev-C++调试通过:
[Asm] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
#
include
<iostream>
#
include
<stdlib.h>
#
include
<stdio.h>
#
include
<string.h>
#
include
<time.h>
#
include
<math.h>
#
include
<windows.h>
union
CBData{
DWORD
n;
byte
buffer[256];
};
CBData readKey(HKEY hKey, char * path, char * key);
void getRegInfo();
void getPart1();
void getPart2();
long getRegTimeStamp(
int
index);
long getCheckRegOwner();
long getCheck(char *
name
, char * company,
int
index);
void getCurrDateTime(
int
index);
bool testSoftICE95();
bool testSoftICENT();
char sn[48];
CBData data;
long nFirstInstallDateTime = 0;
long nLenOfFirstInstallDateTime = 0;
char sFirstInstallDateTime[128];
char RegisteredOwner[128];
char RegisteredOrganization[128];
char ProductId[128];
int
main(
int
argc, char** argv) {
memset(sn, 0, 48);
memset(sFirstInstallDateTime, 0, 128);
memset(RegisteredOwner, 0, 128);
memset(RegisteredOrganization, 0, 128);
memset(ProductId, 0, 128);
getRegInfo();
getPart1();
sn[5] =
'-'
;
getPart2();
sn[10] =
'-'
;
char
name
[] =
"solly88"
;
char company[] =
"ite company"
;
int
n = getCheck(
name
, company, 11);
sn[10+n+1] =
'-'
;
int
m = getRegTimeStamp(10+n+2);
sn[10+n+2+m] =
'-'
;
/// 最后4字节为当前时间检查
getCurrDateTime(10+n+3+m);
printf(
"\n SN = %s\n"
, sn);
return 0;
}
void getPart1() {
sn[1] = 0x0D ^ 0x49;
sn[2] = 0x07 ^ 0x44;
sn[3] = 0x0D ^ 0x39;
sn[0] = 0x1D ^ 0x54;
sn[4] = 0x09 ^ 0x39;
}
void getPart2() {
sn[7] = 0x06 ^ 0x52;
sn[8] = 0x07 ^ 0x45;
sn[9] = 0x1F ^ 0x53;
sn[6] = 0x11 ^ 0x54;
}
/**
***/
/// FirstInstallTime
long getRegTimeStamp(
int
index) {
/// 0040BF90: 1702516
//long a = 1702505;
////
//long FirstInstallDateTime = 1702516; /// 实际上是一个指向保存FirstInstallDateTime的内存地址 Win10
//long FirstInstallDateTime = 6617404; /// 实际上是一个指向保存FirstInstallDateTime的内存地址 Win98
//long FirstInstallDateTime = 6682940; /// 实际上是一个指向保存FirstInstallDateTime的内存地址 Win98_unpacked
long FirstInstallDateTime = nFirstInstallDateTime; /// 正常时是一个 Timestamp
long a = FirstInstallDateTime - tanh(FirstInstallDateTime) * 11.0; /// 当在win10下取的是地址时,这里是固定值 1702505
//char str_a[8];
sprintf(sFirstInstallDateTime,
"%d"
, a);
long n = strlen(sFirstInstallDateTime);
for
(
int
i=0; i<n; i++ ) {
sn[index + i] = sFirstInstallDateTime[i];
}
return n;
}
long getCheckRegOwner() { // Proc_00401590 和 Proc_00401540
long sum1 = 0;
long sum2 = 0;
long n = strlen(RegisteredOwner);
for
(
int
i=1; i<n; i++) {
sum1 += i*2;
sum2 += RegisteredOwner[i-1];
}
//printf(
"check reg owner: %d - %d\n"
, sum1, sum2);
return sum1 ^ sum2;
}
long getCheck(char *
name
, char * company,
int
index) { /// Proc_004015E0
long checkbase = getCheckRegOwner();
long sum = 0;
int
n = strlen(
name
);
for
(
int
i=0; i<n-1; i++) {
sum +=
name
[i] * 2601;
}
int
m = strlen(company);
for
(
int
i=0; i<m-1; i++) {
sum += company[i];
}
double x = sum * 11;
int
code1 = (long)sqrt(x);
////
//printf(
"check code1: %d, %d\n"
, sum, code1);
long a = code1 + checkbase;
long
c
= a * 111998;
double y =
c
- sin(
c
) * 1999.0;
long code2 = (long)y;
//printf(
"check code2: %d\n"
, code2);
char code_str[12];
sprintf(code_str,
"%d"
, code2);
int
len = strlen(code_str);
for
(
int
i=0; i<len; i++) {
sn[index+i] = code_str[i];
}
return len;
}
bool testSoftICE95() {
HANDLE h = CreateFile(
"\\\\.\\SICE"
,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if
(h != INVALID_HANDLE_VALUE) {
CloseHandle(h);
return true;
}
return false;
}
bool testSoftICENT() {
HANDLE h = CreateFile(
"\\\\.\\NTICE"
,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if
(h != INVALID_HANDLE_VALUE) {
CloseHandle(h);
return true;
}
return false;
}
/// Current date
and
time
void getCurrDateTime(
int
index) {
long a = RegisteredOwner[0];
time_t timer;
struct
tm *
st
;
time(&timer);
st
= localtime(&timer);
long t = (
st
->tm_year + 1900) + ((
st
->tm_mon + 1) *
st
->tm_mday - a) +
st
->tm_hour *
st
->tm_min;
///// SoftICE 检查,修正时间检查值(基本无用)
bool isExistsSICE95 = testSoftICE95();
bool isExistsSICENT = testSoftICENT();
if
(isExistsSICE95) {
t += 0x143;
}
if
(isExistsSICENT) {
t += 0x271;
}
char str_t[12];
itoa(t, str_t, 10);
sn[index] = str_t[0];
sn[index+1] = str_t[1];
sn[index+2] = str_t[2];
sn[index+3] = str_t[3];
///
//printf(
"time: %d-%d-%d %d:%d\n"
,
st
->tm_year+1900,
st
->tm_mon+1,
st
->tm_mday,
st
->tm_hour,
st
->tm_min)
}
CBData readKey(HKEY hKey, char * path, char * key) {
HKEY h = (HKEY)-1;
DWORD
cbData;
DWORD
regType = -1;
data.n = 1;
long s = RegOpenKeyEx(hKey, path, 0, KEY_READ, &h);
if
( s != ERROR_SUCCESS) {
data.n = -1;
return data;
}
s = RegQueryValueEx(h, key, NULL, NULL, NULL, &cbData);
if
(s == ERROR_SUCCESS) {
RegQueryValueEx(h, key, NULL, & regType, data.buffer, &cbData);
}
RegCloseKey(h);
return data;
}
void getRegInfo() {
char subKey[] =
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion"
;
char key1[] =
"FirstInstallDateTime"
;
char key2[] =
"RegisteredOwner"
;
char key3[] =
"RegisteredOrganization"
;
char key4[] =
"ProductId"
;
CBData cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key1);
nFirstInstallDateTime = cb.n;
struct
tm * tm_reg = localtime((time_t *)&nFirstInstallDateTime);
sprintf(sFirstInstallDateTime,
"%lu"
, nFirstInstallDateTime);
nLenOfFirstInstallDateTime = strlen(sFirstInstallDateTime);
printf(
" DateTime: %d-%d-%d %d:%d:%d\n"
, tm_reg->tm_year + 1900, tm_reg->tm_mon + 1,
tm_reg->tm_mday, tm_reg->tm_hour, tm_reg->tm_min, tm_reg->tm_sec);
printf(
"Timestamp: %d, len=%d\n"
, nFirstInstallDateTime, nLenOfFirstInstallDateTime);
////
cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key2);
strcpy(RegisteredOwner, (char *)cb.buffer);
////
cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key3);
strcpy(RegisteredOrganization, (char *)cb.buffer);
////
cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key4);
strcpy(ProductId, (char *)cb.buffer);
printf(
" ProductId: %s\n"
, ProductId);
printf(
" RegisteredOwner: %s\n"
, RegisteredOwner);
printf(
"RegisteredOrganization: %s\n"
, RegisteredOrganization);
}
免费评分
查看全部评分