# 破解

PUSHFD 指令把 32 位 EFLAGS 寄存器内容压入堆栈,而 POPFD 指令则把栈顶单元内容弹出到 EFLAGS 寄存器:

PUSHAD 指令按照 EAX、ECX、EDX、EBX、ESP(执行 PUSHAD 之前的值)、EBP、ESI 和 EDI 的顺序,将所有 32 位通用寄存器压入堆栈

脱壳之后记得 fix res

# 常用函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
了解Windows API:
//消息框
1.MessageBoxA/W

//弹网页
2.ShellExecuteA/W
3.WinExec
4.CreateProcessA/W

5.CreateThread

//注册表
6.RegCreateKeyExA/W
7.RegOpenKeyExA/W
8.RegDeleteKeyExA/W

//创建窗口
DialogBox
CreateWindowExA/W

# nop 填充

整条填充 00

image-20230817121220618

image-20230817121353324

nop 填充 MessageBox

image-20230817131409135

# 函数下段

1
2
3
4
//弹网页
2.ShellExecuteA/W
3.WinExec
4.CreateProcessA/W

image-20230817132219720

回车第一条转到调用的地方,同时注意有两个参数

image-20230817132458596

nop 填充

image-20230817132604822

一样的方法把调用的地方 nop

image-20230817132710378

# 修复改浏览器主页

image-20230817133248989

image-20230817133306465

整个函数都是修改注册表的

可以在首行 ret,或者一个个 nop

# 编辑资源

使用资源编辑器删除或者设置为不可见

建议使用工具 resourcehacker 或者 restorator

image-20230817134553253

# 查找窗口

procexp 查找窗口属于哪个程序

image-20230817135114574

# 调用函数过滤

处理窗口

一样给函数下段

// 创建窗口
DialogBox
CreateWindowExA/W

如果不知道调用的函数,使用 procmon

先使用过滤器找到程序名

image-20230817135804780

image-20230817135749844

# 编辑资源

1. 资源编辑工具

2.winapi

SetDlgItemTextW/A

DialogBox

3.16 进制编辑器

winhex

# 破解程序重启验证

1
2
3
4
5
6
7
8
9
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
吾爱破解培训第五课:反击作者的挑衅--实战解除程序重启验证

吾爱破解专用版Ollydbg:http://down.52pojie.cn/Tools/Debuggers/
ProcMon:http://down.52pojie.cn/Tools/Anti_Rootkit/

题外话:
编程是逆向的基础,破解只是逆向的一个很小的分支。如果真喜欢逆向,建议好好的去学一下编程,毕竟写软件不容易。

0xFFFFFFFF:预习
熟悉OD字符串插件的使用
Ctrl+F搜索字符串

熟悉OD如何下断点
Ctrl+G:直接断API
Ctrl+N:输入表断API
利用插件

熟悉procmon的使用
可以监控文件,注册表,网络,进线程信息
排除进程:ExClude
查看指定进程:Include

熟悉文件操作API的使用
CreateFileA(W):创建文件
ReadFile:读取文件
WriteFile:写入文件
CloseHandle:关闭句柄
读取文件:CreateFile->ReadFile->CloseHandle
写入文件:CreateFile->WriteFile->CloseHandle


熟悉注册表操作API的使用
创建注册表Key:RegCreateKey
打开注册表Key:RegOpenKey
查询注册表键值:RegQueryValue(Ex)
写入注册表键值:RegSetValueEx


0x0:什么是重启验证
重启验证顾名思义就是在程序启动时验证注册信息。

0x1:执行流程
基本的执行流程:注册信息输入-->程序重启-->执行验证机制-->正常执行

扩展的执行流程:注册信息输入-->执行部分验证机制/执行假验证机制-->程序重启-->执行真验证机制-->正常执行

对于有经验的作者来说,可以在注册信息输入和程序重启之间加入假的验证机制,假的验证机制一般比较简单,比如说只是当单纯的明码比较,当我们输入这个假的注册码的,程序一般会提示注册成功,此时程序就会知道我们是逆向者,在程序重启时就会假装注册成功,在执行程序功能时就会报错或是无反应,这就是所谓的暗桩。


0x2:重启验证的类型
重启验证根据写入信息位置的不同一般分两类,一类是将注册信息写入文件中,一类是将注册信息写入注册表中。

0x3:定位关键代码
1.字符串定位
通过OD字符串插件扫描敏感字符串,一般出现的文件路径或是注册表路径都可能是验证信息的保存位置

2.监控工具定位
通过procmon等监控工具监控注册信息的写入位置

3.API定位
通过定位CreateFile,RegCreateKey等API来获取注册信息的写入位置

0x4:Demo演示
重启验证1:写入信息进txt:JXU2MjExJXU2
CreateFile->WriteFile->ReadFile->比较算法
重启验证2:写入信息进ini
WritePrivateProfileStringA:写入配置信息
0012F530 00544638 |Section = "验证"
0012F534 00544634 |Key = "Key"
0012F538 001C9578 |String = "987654321"
0012F53C 001D7F70 \FileName = "C:\Users\Administrator\Desktop\52Pojie.ini"


GetPrivateProfileStringA:读取配置信息

NjJGJXU3NTI







重启验证3:写入信息进注册表


4JXU2MjM3

image-20230820115917972

image-20230820120137839

image-20230820133027331

# 写入到 txt

1. 在重启验证 1 处下段,关键代码如下

1
2
3
4
5
6
7
8
9
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
004026F0  |.  55                    push    ebp
004026F1 |. 8BEC mov ebp,esp
004026F3 |. 6A FF push -0x1
004026F5 |. 68 68385300 push 00533868
004026FA |. 64:A1 00000000 mov eax,dword ptr fs:[0]
00402700 |. 50 push eax
00402701 |. 83EC 0C sub esp,0xC
00402704 |. A1 B0275900 mov eax,dword ptr ds:[0x5927B0]
00402709 |. 33C5 xor eax,ebp
0040270B |. 8945 F0 mov [local.4],eax
0040270E |. 56 push esi
0040270F |. 57 push edi
00402710 |. 50 push eax
00402711 |. 8D45 F4 lea eax,[local.3]
00402714 |. 64:A3 00000000 mov dword ptr fs:[0],eax
0040271A |. 8BF1 mov esi,ecx
0040271C |. C745 EC 00000000 mov [local.5],0x0
00402723 |. E8 75270000 call 00404E9D
00402728 |. 33D2 xor edx,edx
0040272A |. 8BC8 mov ecx,eax
0040272C |. 85C9 test ecx,ecx
0040272E |. 0F95C2 setne dl
00402731 |. 85D2 test edx,edx
00402733 |. 75 0A jnz short 0040273F
00402735 |. 68 05400080 push 0x80004005
0040273A |. E8 B1ECFFFF call 004013F0
0040273F |> 8B01 mov eax,dword ptr ds:[ecx]
00402741 |. FF50 0C call dword ptr ds:[eax+0xC]
00402744 |. 83C0 10 add eax,0x10
00402747 |. 8945 EC mov [local.5],eax
0040274A |. 8D45 EC lea eax,[local.5]
0040274D |. 50 push eax
0040274E |. 8D8E C8000000 lea ecx,dword ptr ds:[esi+0xC8]
00402754 |. C745 FC 00000000 mov [local.1],0x0
0040275B |. E8 C8590100 call 00418128
00402760 |. 8B45 EC mov eax,[local.5] ; 获取文本框内容
00402763 |. 8378 F4 00 cmp dword ptr ds:[eax-0xC],0x0
00402767 |. 74 74 je short 004027DD
00402769 |. 6A 00 push 0x0 ; /hTemplateFile = NULL
0040276B |. 6A 00 push 0x0 ; |Attributes = 0
0040276D |. 6A 02 push 0x2 ; |Mode = CREATE_ALWAYS
0040276F |. 6A 00 push 0x0 ; |pSecurity = NULL
00402771 |. 6A 01 push 0x1 ; |ShareMode = FILE_SHARE_READ
00402773 |. 68 00000040 push 0x40000000 ; |Access = GENERIC_WRITE
00402778 |. FFB6 BC000000 push dword ptr ds:[esi+0xBC] ; |FileName
0040277E |. FF15 10345400 call dword ptr ds:[<&KERNEL32.CreateFil>; \CreateFileA
00402784 |. 8BF0 mov esi,eax
00402786 |. 83FE FF cmp esi,-0x1 ; 文件是否创建
00402789 |. 74 52 je short 004027DD
0040278B |. 8B4D EC mov ecx,[local.5] ; ecx就是我们输入的值
0040278E |. BA 01000000 mov edx,0x1
00402793 |. 2B51 FC sub edx,dword ptr ds:[ecx-0x4]
00402796 |. 8B41 F8 mov eax,dword ptr ds:[ecx-0x8]
00402799 |. 0BC2 or eax,edx
0040279B |. 8B79 F4 mov edi,dword ptr ds:[ecx-0xC]
0040279E |. 7D 0D jge short 004027AD
004027A0 |. 6A 00 push 0x0
004027A2 |. 8D4D EC lea ecx,[local.5]
004027A5 |. E8 B6EEFFFF call 00401660
004027AA |. 8B4D EC mov ecx,[local.5]
004027AD |> 6A 00 push 0x0 ; /pOverlapped = NULL
004027AF |. 8D45 E8 lea eax,[local.6] ; |
004027B2 |. 50 push eax ; |pBytesWritten
004027B3 |. 57 push edi ; |nBytesToWrite
004027B4 |. 51 push ecx ; |Buffer
004027B5 |. 56 push esi ; |hFile
004027B6 |. FF15 2C345400 call dword ptr ds:[<&KERNEL32.WriteFile>; \WriteFile
004027BC |. 85C0 test eax,eax
004027BE |. 74 16 je short 004027D6
004027C0 |. 6A 00 push 0x0
004027C2 |. 6A 00 push 0x0
004027C4 |. 68 60465400 push 00544660 ; 你选择的验证类型是重启验证1
004027C9 |. E8 B17F0000 call 0040A77F ; 弹窗
004027CE |. 6A 00 push 0x0 ; /ExitCode = 0x0
004027D0 |. FF15 40385400 call dword ptr ds:[<&USER32.PostQuitMes>; \PostQuitMessage
004027D6 |> 56 push esi ; /hObject
004027D7 |. FF15 24345400 call dword ptr ds:[<&KERNEL32.CloseHand>; \CloseHandle

执行完写文件程序会自动退出

image-20230821215838073

2. 重新载入程序,在 txt 处下段

image-20230821215937761

1
2
3
4
5
6
7
8
9
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
00402A60  /.  55                    push    ebp
00402A61 |. 8BEC mov ebp,esp
00402A63 |. 6A FF push -0x1
00402A65 |. 68 FB385300 push 005338FB
00402A6A |. 64:A1 00000000 mov eax,dword ptr fs:[0]
00402A70 |. 50 push eax
00402A71 |. 81EC 1C010000 sub esp,0x11C
00402A77 |. A1 B0275900 mov eax,dword ptr ds:[0x5927B0]
00402A7C |. 33C5 xor eax,ebp
00402A7E |. 8945 F0 mov [local.4],eax
00402A81 |. 53 push ebx
00402A82 |. 56 push esi
00402A83 |. 57 push edi
00402A84 |. 50 push eax
00402A85 |. 8D45 F4 lea eax,[local.3]
00402A88 |. 64:A3 00000000 mov dword ptr fs:[0],eax
00402A8E |. 8BF9 mov edi,ecx
00402A90 |. 89BD E4FEFFFF mov [local.71],edi
00402A96 |. E8 2E4B0000 call 004075C9
00402A9B |. FFB7 B8000000 push dword ptr ds:[edi+0xB8] ; /lParam
00402AA1 |. 8B35 44385400 mov esi,dword ptr ds:[<&USER32.SendMessageA>] ; |user32.SendMessageA
00402AA7 |. 6A 01 push 0x1 ; |wParam = 0x1
00402AA9 |. 68 80000000 push 0x80 ; |Message = WM_SETICON
00402AAE |. FF77 20 push dword ptr ds:[edi+0x20] ; |hWnd
00402AB1 |. FFD6 call esi ; \SendMessageA
00402AB3 |. FFB7 B8000000 push dword ptr ds:[edi+0xB8] ; /lParam
00402AB9 |. 6A 00 push 0x0 ; |wParam = 0x0
00402ABB |. 68 80000000 push 0x80 ; |Message = WM_SETICON
00402AC0 |. FF77 20 push dword ptr ds:[edi+0x20] ; |hWnd
00402AC3 |. FFD6 call esi ; \SendMessageA
00402AC5 |. 68 04010000 push 0x104
00402ACA |. 33DB xor ebx,ebx
00402ACC |. 8D85 ECFEFFFF lea eax,[local.69]
00402AD2 |. 53 push ebx
00402AD3 |. 50 push eax
00402AD4 |. E8 E7971100 call 0051C2C0
00402AD9 |. 83C4 0C add esp,0xC
00402ADC |. 8D85 ECFEFFFF lea eax,[local.69]
00402AE2 |. 50 push eax ; /Buffer
00402AE3 |. 68 04010000 push 0x104 ; |BufSize = 104 (260.)
00402AE8 |. FF15 14345400 call dword ptr ds:[<&KERNEL32.GetCurrentDirectoryA>] ; \GetCurrentDirectoryA
00402AEE |. 8D85 ECFEFFFF lea eax,[local.69]
00402AF4 |. 50 push eax
00402AF5 |. 8DB7 BC000000 lea esi,dword ptr ds:[edi+0xBC]
00402AFB |. 68 D8455400 push 005445D8 ; %s\52Pojie.txt
00402B00 |. 56 push esi
00402B01 |. E8 8AE9FFFF call 00401490 ; CString 拼接函数
00402B06 |. 8D8D ECFEFFFF lea ecx,[local.69]
00402B0C |. 51 push ecx
00402B0D |. 8D87 C0000000 lea eax,dword ptr ds:[edi+0xC0]
00402B13 |. 68 E8455400 push 005445E8 ; %s\52Pojie.ini
00402B18 |. 50 push eax
00402B19 |. 8985 E0FEFFFF mov [local.72],eax
00402B1F |. E8 6CE9FFFF call 00401490
00402B24 |. 8D87 C4000000 lea eax,dword ptr ds:[edi+0xC4]
00402B2A |. 68 F8455400 push 005445F8 ; Software\52Pojie
00402B2F |. 50 push eax
00402B30 |. E8 5BE9FFFF call 00401490
00402B35 |. 83C4 20 add esp,0x20
00402B38 |. 8D87 3C010000 lea eax,dword ptr ds:[edi+0x13C]
00402B3E |. 68 0C465400 push 0054460C ; 验证失败
00402B43 |. 8BC8 mov ecx,eax
00402B45 |. 8985 DCFEFFFF mov [local.73],eax
00402B4B |. E8 70990100 call 0041C4C0 ; 标签初始化
00402B50 |. 8D8F B0010000 lea ecx,dword ptr ds:[edi+0x1B0]
00402B56 |. 68 0C465400 push 0054460C ; 验证失败
00402B5B |. E8 60990100 call 0041C4C0
00402B60 |. 8D8F 24020000 lea ecx,dword ptr ds:[edi+0x224]
00402B66 |. 68 0C465400 push 0054460C ; 验证失败
00402B6B |. E8 50990100 call 0041C4C0
00402B70 |. 8B06 mov eax,dword ptr ds:[esi]
00402B72 |. 83E8 10 sub eax,0x10
00402B75 |. 50 push eax
00402B76 |. E8 F5F3FFFF call 00401F70
00402B7B |. 83C4 04 add esp,0x4
00402B7E |. 8D70 10 lea esi,dword ptr ds:[eax+0x10]
00402B81 |. 56 push esi ; /FileName
00402B82 |. FF15 0C345400 call dword ptr ds:[<&KERNEL32.GetFileAttributesA>] ; \GetFileAttributesA
00402B88 |. 33C9 xor ecx,ecx
00402B8A |. 83F8 FF cmp eax,-0x1 ; 判断文件是否存在
00402B8D |. 0F95C1 setne cl
00402B90 |. 83C6 F0 add esi,-0x10
00402B93 |. 83CF FF or edi,0xFFFFFFFF
00402B96 |. 8BC7 mov eax,edi
00402B98 |. 898D E8FEFFFF mov [local.70],ecx
00402B9E |. 8D4E 0C lea ecx,dword ptr ds:[esi+0xC]
00402BA1 |. F0:0FC101 lock xadd dword ptr ds:[ecx],eax
00402BA5 |. 48 dec eax
00402BA6 |. 85C0 test eax,eax
00402BA8 |. 7F 08 jg short 00402BB2
00402BAA |. 8B0E mov ecx,dword ptr ds:[esi]
00402BAC |. 56 push esi
00402BAD |. 8B01 mov eax,dword ptr ds:[ecx]
00402BAF |. FF50 04 call dword ptr ds:[eax+0x4]
00402BB2 |> 399D E8FEFFFF cmp [local.70],ebx
00402BB8 |. 74 24 je short 00402BDE ; nop 掉,或者跟入算法call
00402BBA |. 8B8D E4FEFFFF mov ecx,[local.71]
00402BC0 |. E8 1BF4FFFF call 00401FE0 ; 算法call
00402BC5 |. 85C0 test eax,eax
00402BC7 |. 74 15 je short 00402BDE
00402BC9 |. 8B8D DCFEFFFF mov ecx,[local.73]
00402BCF |. 68 18465400 push 00544618 ; 验证通过
00402BD4 |. E8 E7980100 call 0041C4C0
00402BD9 |. BB 01000000 mov ebx,0x1
00402BDE |> 8B85 E0FEFFFF mov eax,[local.72]
00402BE4 |. 8B00 mov eax,dword ptr ds:[eax]
00402BE6 |. 83E8 10 sub eax,0x10
00402BE9 |. 50 push eax
00402BEA |. E8 81F3FFFF call 00401F70
00402BEF |. 83C4 04 add esp,0x4
00402BF2 |. 8D70 10 lea esi,dword ptr ds:[eax+0x10]
00402BF5 |. 56 push esi ; /FileName
00402BF6 |. FF15 0C345400 call dword ptr ds:[<&KERNEL32.GetFileAttributesA>] ; \GetFileAttributesA


1
2
3
4
5
6
7
8
9
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
# 算法call
00401FE0 |$ 55 push ebp
00401FE1 |. 8BEC mov ebp,esp
00401FE3 |. 81EC 10010000 sub esp,0x110
00401FE9 |. A1 B0275900 mov eax,dword ptr ds:[0x5927B0]
00401FEE |. 33C5 xor eax,ebp
00401FF0 |. 8945 FC mov [local.1],eax
00401FF3 |. 56 push esi
00401FF4 |. 57 push edi
00401FF5 |. 33F6 xor esi,esi
00401FF7 |. 56 push esi ; /hTemplateFile => NULL
00401FF8 |. 56 push esi ; |Attributes => 0
00401FF9 |. 6A 03 push 0x3 ; |Mode = OPEN_EXISTING
00401FFB |. 56 push esi ; |pSecurity => NULL
00401FFC |. 6A 01 push 0x1 ; |ShareMode = FILE_SHARE_READ
00401FFE |. 6A 01 push 0x1 ; |Access = 1
00402000 |. FFB1 BC000000 push dword ptr ds:[ecx+0xBC] ; |FileName
00402006 |. FF15 10345400 call dword ptr ds:[<&KERNEL32.CreateFileA>] ; \CreateFileA
0040200C |. 8BF8 mov edi,eax
0040200E |. 83FF FF cmp edi,-0x1
00402011 |. 0F84 7F000000 je 00402096
00402017 |. 68 04010000 push 0x104
0040201C |. 8D85 F5FEFFFF lea eax,dword ptr ss:[ebp-0x10B]
00402022 |. 56 push esi
00402023 |. 50 push eax
00402024 |. C685 F4FEFFFF 00 mov byte ptr ss:[ebp-0x10C],0x0
0040202B |. E8 90A21100 call 0051C2C0
00402030 |. 83C4 0C add esp,0xC
00402033 |. 8D85 F0FEFFFF lea eax,[local.68]
00402039 |. 56 push esi ; /pOverlapped
0040203A |. 50 push eax ; |pBytesRead
0040203B |. 68 04010000 push 0x104 ; |BytesToRead = 104 (260.)
00402040 |. 8D85 F4FEFFFF lea eax,[local.67] ; |
00402046 |. 50 push eax ; |Buffer
00402047 |. 57 push edi ; |hFile
00402048 |. FF15 28345400 call dword ptr ds:[<&KERNEL32.ReadFile>] ; \ReadFile
0040204E |. 85C0 test eax,eax
00402050 |. 74 3D je short 0040208F
00402052 |. B9 24465400 mov ecx,00544624 ; JXU2MjExJXU2
00402057 |. 8D85 F4FEFFFF lea eax,[local.67]
0040205D |. 8D49 00 lea ecx,dword ptr ds:[ecx]
00402060 |> 8A10 /mov dl,byte ptr ds:[eax] ; strcmp
00402062 |. 3A11 |cmp dl,byte ptr ds:[ecx]
00402064 |. 75 1A |jnz short 00402080
00402066 |. 84D2 |test dl,dl
00402068 |. 74 12 |je short 0040207C
0040206A |. 8A50 01 |mov dl,byte ptr ds:[eax+0x1]
0040206D |. 3A51 01 |cmp dl,byte ptr ds:[ecx+0x1]
00402070 |. 75 0E |jnz short 00402080
00402072 |. 83C0 02 |add eax,0x2
00402075 |. 83C1 02 |add ecx,0x2
00402078 |. 84D2 |test dl,dl
0040207A |.^ 75 E4 \jnz short 00402060
0040207C |> 33C0 xor eax,eax
0040207E |. EB 05 jmp short 00402085


我们可以爆破跳过验证环节,也可以跟入算法 call 找到真正的验证码

# 写入到 ini

1
2
3
4
5
6
7
8
9
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
00402820  /.  55                    push    ebp
00402821 |. 8BEC mov ebp,esp
00402823 |. 6A FF push -0x1
00402825 |. 68 98385300 push 00533898
0040282A |. 64:A1 00000000 mov eax,dword ptr fs:[0]
00402830 |. 50 push eax
00402831 |. 83EC 08 sub esp,0x8
00402834 |. A1 B0275900 mov eax,dword ptr ds:[0x5927B0]
00402839 |. 33C5 xor eax,ebp
0040283B |. 8945 F0 mov [local.4],eax
0040283E |. 56 push esi
0040283F |. 50 push eax
00402840 |. 8D45 F4 lea eax,[local.3]
00402843 |. 64:A3 00000000 mov dword ptr fs:[0],eax
00402849 |. 8BF1 mov esi,ecx
0040284B |. C745 EC 00000000 mov [local.5],0x0
00402852 |. E8 46260000 call 00404E9D
00402857 |. 33D2 xor edx,edx
00402859 |. 8BC8 mov ecx,eax
0040285B |. 85C9 test ecx,ecx
0040285D |. 0F95C2 setne dl
00402860 |. 85D2 test edx,edx
00402862 |. 75 0A jnz short 0040286E
00402864 |. 68 05400080 push 0x80004005
00402869 |. E8 82EBFFFF call 004013F0
0040286E |> 8B01 mov eax,dword ptr ds:[ecx]
00402870 |. FF50 0C call dword ptr ds:[eax+0xC]
00402873 |. 83C0 10 add eax,0x10
00402876 |. 8945 EC mov [local.5],eax
00402879 |. 8D45 EC lea eax,[local.5]
0040287C |. 50 push eax
0040287D |. 8D8E C8000000 lea ecx,dword ptr ds:[esi+0xC8]
00402883 |. C745 FC 00000000 mov [local.1],0x0
0040288A |. E8 99580100 call 00418128 ; 获取输入
0040288F |. 8B45 EC mov eax,[local.5]
00402892 |. 8378 F4 00 cmp dword ptr ds:[eax-0xC],0x0
00402896 |. 74 51 je short 004028E9 ; 输入为空直接结束
00402898 |. 8B48 F8 mov ecx,dword ptr ds:[eax-0x8]
0040289B |. 8BB6 C0000000 mov esi,dword ptr ds:[esi+0xC0]
004028A1 |. BA 01000000 mov edx,0x1
004028A6 |. 2B50 FC sub edx,dword ptr ds:[eax-0x4]
004028A9 |. 0BCA or ecx,edx
004028AB |. 7D 0D jge short 004028BA
004028AD |. 6A 00 push 0x0
004028AF |. 8D4D EC lea ecx,[local.5]
004028B2 |. E8 A9EDFFFF call 00401660
004028B7 |. 8B45 EC mov eax,[local.5]
004028BA |> 56 push esi ; /FileName
004028BB |. 50 push eax ; |String
004028BC |. 68 34465400 push 00544634 ; |Key
004028C1 |. 68 38465400 push 00544638 ; |验证
004028C6 |. FF15 18345400 call dword ptr ds:[<&KERNEL32.WritePrivateProfileStringA>] ; \WritePrivateProfileStringA
004028CC |. 85C0 test eax,eax ; 写文件
004028CE |. 74 16 je short 004028E6
004028D0 |. 6A 00 push 0x0
004028D2 |. 6A 00 push 0x0
004028D4 |. 68 7C465400 push 0054467C ; 你选择的验证类型是重启验证2
004028D9 |. E8 A17E0000 call 0040A77F ; 弹窗
004028DE |. 6A 00 push 0x0 ; /ExitCode = 0x0
004028E0 |. FF15 40385400 call dword ptr ds:[<&USER32.PostQuitMessage>] ; \PostQuitMessage
004028E6 |> 8B45 EC mov eax,[local.5]


或者通过给函数下段也,也能断下来

image-20230821222933923

# 写入注册表

image-20230821223559082

通过下段找到写入和读取注册表的地方,读取注册表就是算法 call

image-20230821223930345

下段记得下的是 ExA

JXU2MjExJXU2

NjJGJXU3NTI

4JXU2MjM3

# 破解程序自校验 (md5)

1. 搜索字符串,找到关键字符串,比如注册,激活,通过 xx

image-20230820151928757

2、在关键字符串所在函数处下段

image-20230820151949493

3. 运行程序,点击注册,使程序断下来

image-20230820152059610

4. 搜索常量,找到有哪些位置访问了这个常量

image-20230820152736054

5. 对所有下段,找到常量的赋值点

image-20230820152806264

6. 重新运行程序,程序被断在,说明此处可能对上面说的常量做了改变

image-20230820153407165

7. 第一处关键点:会对前两个字符做验证,是否为 02

image-20230820193839511

8. 第二处关键点:sn 判断 call 跟进去

image-20230820193956146

9.sn 判断

image-20230820194328180

10. 跳过网络验证

image-20230820194548582

11. 找到验证函数最开始,直接 retn

image-20230820194627641

12. 去除自校验。对 delphi 程序下按键断点,去除无关断点,点击任意触发断点

image-20230821165626093

F7 进入函数,逐个函数跟踪

image-20230821165708555

跟入第一个 call 4b2dc0

image-20230821165755920

跟入 4B1F34

跟入 4B1F6A

image-20230821165849410

这个函数是读文件的地方

image-20230821165952866

返回到上层,4B1F74 就是读取 md5 的地方

image-20230821171219967

被修改后的 md5: 4b1f74

DE7449CB2D3E11159C405532F86B6657

重新安装找到原来的 md5:

11ea70a3c3735c29b48552776756406a

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
004B1F74  |.  8D5D EC       lea      ebx,dword ptr ss:[ebp-0x14]
004B1F77 |> 8D55 E8 /lea edx,dword ptr ss:[ebp-0x18]
004B1F7A |. 33C0 |xor eax,eax
004B1F7C |. 8A03 |mov al,byte ptr ds:[ebx]
004B1F7E |. E8 35F1FFFF |call 004B10B8
004B1F83 |. 8B55 E8 |mov edx,dword ptr ss:[ebp-0x18]
004B1F86 |. 8BC7 |mov eax,edi
004B1F88 |. E8 3F26F5FF |call 004045CC
004B1F8D |. 43 |inc ebx
004B1F8E |. 4E |dec esi
004B1F8F |.^ 75 E6 \jnz short 004B1F77

8D 5D EC 8D 55 E8 33 C0 8A 03 E8 35 F1 FF FF 8B 55 E8 8B C7 E8 3F 26 F5 FF 43 4E 75 E6


image-20230821181650298

找一块全 0 的地址 56b0a0

image-20230821180304129

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0056B0A0      C745 EC 11EA7>mov     dword ptr ss:[ebp-0x14],0xA370EA11
0056B0A7 C745 F0 C3735>mov dword ptr ss:[ebp-0x10],0x295C73C3
0056B0AE C745 F4 B4855>mov dword ptr ss:[ebp-0xC],0x775285B4
0056B0B5 C745 F8 67564>mov dword ptr ss:[ebp-0x8],0x6A405667
0056B0BC 8D5D EC lea ebx,dword ptr ss:[ebp-0x14]
0056B0BF 8D55 E8 lea edx,dword ptr ss:[ebp-0x18]
0056B0C2 33C0 xor eax,eax
0056B0C4 8A03 mov al,byte ptr ds:[ebx]
0056B0C6 E8 ED5FF4FF call 004B10B8
0056B0CB 8B55 E8 mov edx,dword ptr ss:[ebp-0x18]
0056B0CE 8BC7 mov eax,edi
0056B0D0 E8 F794E9FF call 004045CC
0056B0D5 43 inc ebx
0056B0D6 4E dec esi
0056B0D7 ^ 75 E6 jnz short 0056B0BF
0056B0D9 ^ E9 B36EF4FF jmp 004B1F91




附上 delphi 按键断点

1
2
3
4
5
6
7
8
9
10
11
12
13
var Addr
mov Addr,401000
loop:
find Addr,#740E8BD38B83????????FF93????????#
cmp $RESULT,0
je Exit
add $RESULT,0A
bp $RESULT
add $RESULT,1
mov Addr,$RESULT
jmp loop
Exit:
ret

# OD function script

# 导入表(IAT)

Import Address Table 由于导入函数就是被程序调用但其执行代码又不在程序中的函数,这些函数的代码位于一个或者多个 DLL 中。当 PE 文件被装入内存的时候,Windows 装载器才将 DLL 装入,并将调用导入函数的指令和函数实际所处的地址联系起来 (动态连接),这操作就需要导入表完成。其中导入地址表就指示函数实际地址。

1
2
3
4
5
sti   f7
sto f8
bp f2
run f9
bphws [],"r" 硬件断点 hr esp

# OEP script

1
2
3
4
5
bp oep
run
sti
MSG "OEP 到了"
ret

# IAT script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sti	;pushad
bphws esp,"r" ;hr esp
run
sti
sti
sti ;到了jnz
bp eip ;
@LOOP:
run
cmp esp,eax
jnz @LOOP
sti
sti
sti

MSG "到OEP了"
ret

通过 ff15 或 ff25 找 iat

1
2
3
4
5
6
7
8
9
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
# 查找ff 15
0041E0CC 56 push esi
0041E0CD 6A 00 push 0x0
0041E0CF FF35 2C3F4400 push dword ptr ds:[0x443F2C]
0041E0D5 FF15 6C214300 call dword ptr ds:[0x43216C]
0041E0DB 85C0 test eax,eax


# iat begin
00431FF8 00000000
00431FFC 00000000
00432000 00970306
00432004 0097030C
00432008 00970312
# iat end
00432548 0097045C
0043254C 00000000
00432550 009704AA
00432554 00000000
00432558 00000000

把原来的调用改成自己的地址,然后在自己的代码里,跳到真实的api地址

00970288 68 FF83837C push kernel32.ConvertDefaultLocale
0097028D C3 retn
0097028E 68 9906867C push kernel32.EnumResourceLanguagesW
00970293 C3 retn
00970294 68 75B4807C push kernel32.GetModuleFileNameW
00970299 C3 retn
0097029A 68 7C0D837C push kernel32.lstrcmpA
0097029F C3 retn
009702A0 68 0216817C push kernel32.GetLocaleInfoW
009702A5 C3 retn
009702A6 68 EBAE807C push kernel32.LoadLibraryW
009702AB C3 retn
009702AC 68 74A1807C push kernel32.WideCharToMultiByte
009702B1 C3 retn
009702B2 68 17D1807C push kernel32.CompareStringA
009702B7 C3 retn
009702B8 68 989C807C push kernel32.MultiByteToWideChar
009702BD C3 retn
009702BE 68 6EBC807C push kernel32.FindResourceW
009702C3 C3 retn
009702C4 68 55A0807C push kernel32.LoadResource
009702C9 C3 retn
009702CA 68 37CD807C push kernel32.SetHandleCount
009702CF C3 retn


# 修复 IAT

1
2
3
4
5
6
7
8
9
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
mov iat_b,00432000
mov iat_e,00432554
;iat_b=00432000

sti ;pushad
bphws esp,"r" ;hr esp
run
sti
sti
sti ;到了jnz
bp eip ;
@LOOP:
run
cmp esp,eax
jnz @LOOP
sti
sti
sti

MSG "到OEP了"

@IAT_LOOP:
mov iat,[iat_b]
cmp iat,0
je @NEXT_LOOP

mov api,[iat+1]
mov [iat_b],api ;重建iat

@NEXT_LOOP:
add iat_b,4
cmp iat_b,iat_e
jne @IAT_LOOP


MSG "OK IAT 修复已经完成 fuck kido"
ret

载入脚本,空格运行

image-20230824133330558

运行结束后,可以看到 iat 已经被修复

image-20230824133443438

修复完所有的 iat 都是有效的

image-20230824133958639

image-20230824134029024

或者直接使用 od 插件 ollydump 也能脱

image-20230824135813010

# 制作补丁

吾爱破解内存补丁生成器

keymake

1
2
3
4
4028AB 75 07 jnz short 004028B4

jnz 0x75
je 0x74

拖入程序

image-20230825105921769

导出补丁

如果注册码在程序中以明文存在,可以使用注册机

1
2
3
4
8B4D E8 mov ecx,[local.6]
8B45 E4 mov eax,[local.7]
402880 8A 10 mov dl, byte ptr ds:[eax] //eax 中即为真实注册码
3A 11 cmp dl, byte ptr ds:[ecx]

image-20230825111225188

image-20230825111048015

用户信息处可以自定义窗口和标题

生成

# x64

1
2
3
4
5
6
7
8
9
10
11
12
13
0000000000401000
R8b byte
R8w word
R8d dword
R8

AL
AH
AX
EAX
RAX

mov r8d,ecx

# IDA

导入文件

image-20230825113612693

Edited on

Give me a cup of [coffee]~( ̄▽ ̄)~*

John Doe WeChat Pay

WeChat Pay

John Doe Alipay

Alipay

John Doe PayPal

PayPal