破解补丁

1、程序实例

Cosh.1.exe
破解前:
YViAL6.png
破解后:
YVi6TU.png

2、查找打补丁地址

通过字符串搜索,可以定位到关键点。

1
2
地址            硬编码           汇编代码
0040138C 0F84 F3000000 je Cosh.1.00401485

YVFHuq.png
如果比较结果为相等,则跳转,输出字符串“Well done,Cracker”。将跳转指令je改成jmp,实现无条件跳转,输出“Well done,Cracker”。

1
2
3
地址            硬编码           汇编代码
0040138C E9 F4000000 jmp Cosh.1.00401485
00401391 90 nop

YVAfpQ.png
通过上面过程可以看出只要将内存地址0x0040138C处的6个字节0F 84 F3 00 00 00改成E9 F4 00 00 00 90就能达到破解目的。

3、代码实现

1、实现这个功能首先我们需要了解几个API。

1、CreateToolhelp32Snapshot()能获得系统进程快照的句柄。

1
2
3
4
5
6
HANDLE
WINAPI
CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);

2、Heap32ListFirst()查找系统进程快照中的第一个进程。

1
2
3
4
5
6
BOOL
WINAPI
Heap32ListFirst(
HANDLE hSnapshot,
LPHEAPLIST32 lphl
);

3、Process32Next()获得下一个进程。

1
2
3
4
5
6
BOOL
WINAPI
Process32Next(
HANDLE hSnapshot,
LPROCESSENTRY32 lppe
);

4、tagPROCESSENTRY32结构体能够保存进程的信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct tagPROCESSENTRY32
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID; // this process
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID; // associated exe
DWORD cntThreads;
DWORD th32ParentProcessID; // this process's parent process
LONG pcPriClassBase; // Base priority of process's threads
DWORD dwFlags;
CHAR szExeFile[MAX_PATH]; // Path
} PROCESSENTRY32;
typedef PROCESSENTRY32 * PPROCESSENTRY32;
typedef PROCESSENTRY32 * LPPROCESSENTRY32;

4、OpenProcess()用来打开一个已存在的进程对象,并返回进程的句柄。

1
2
3
4
5
6
7
8
WINBASEAPI
HANDLE
WINAPI
OpenProcess(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwProcessId
);

5、WriteProcessMemory()对内存区域进行读写。

1
2
3
4
5
6
7
8
9
10
11
WINBASEAPI
_Success_(return != FALSE)
BOOL
WINAPI
WriteProcessMemory(
_In_ HANDLE hProcess,
_In_ LPVOID lpBaseAddress,
_In_reads_bytes_(nSize) LPCVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_opt_ SIZE_T* lpNumberOfBytesWritten
);

2、代码

先在系统中查找需要打补丁程序的进程名与进程ID,然后通过WriteProcessMemory()函数对内存进行读写,将内存地址0x0040138C处的6个字节0F 84 F3 00 00 00改成E9 F4 00 00 00 90。

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
#include <Windows.h>
#include <stdio.h>
#include <TlHelp32.h>

int main()
{
HANDLE hProceessnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//创建进程快照
if (hProceessnap == INVALID_HANDLE_VALUE)
{
printf("创建进行快照失败\n");
return -1;
}
else
{
PROCESSENTRY32 pe32;
byte Patch[] = { 0xE9, 0xF4, 0x00, 0x00, 0x00, 0x90 };//补丁数据
pe32.dwSize = sizeof(pe32);
BOOL hProcess = Process32First(hProceessnap, &pe32);
char buff[1024];
char name[26] = "Cosh.1.exe";//要打补丁程序的进程名
while (hProcess)
{
if (_stricmp(pe32.szExeFile, name) == 0)//进行比较
{
HANDLE hHandle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pe32.th32ProcessID);//获得进程句柄
WriteProcessMemory(hHandle, (LPVOID)0x0040138C, Patch, 6, NULL);//写入内存
MessageBoxA(0, "成功!", "补丁", 0);
break;
}
memset(buff, 0x00, 1024);
hProcess = Process32Next(hProceessnap, &pe32);
}
}
CloseHandle(hProceessnap);
system("pause");
return 0;
}

将程序Cosh.1.exe运行,再运行编译成功的补丁程序。
YVeh5V.png
通过Windbg的附加功能,我们可以看到,地址0x0040138C处的六个字节代码已经呗更改,破解成功。
YViFQ1.png