开头
- 看完《加密与解密第四版》,有些心得体会,收获主要集中在补丁程序开发、Dll注入、函数hook、程序二次开发、加壳5个方面,可以统称为PEDIY
- 按照自己的理解和思考,上述5个方面各进行了一次实践,分4篇内容写出来,其中Dll注入一篇贯穿在二次开发和函数hook中,不单独写了
描述
- 本篇补丁程序分为文件补丁和内存补丁
- 写了个messagebox的例程,目标是通过补丁程序修改弹窗显示的内容
原程序
#include <windows.h>
int main(int argc, char* argv[])
{
MessageBox(NULL, "恭喜你成功进入游戏!", "成功", MB_OK);
return 0;
}
文件补丁
原理
步骤
- 首先在IDA打开程序,查找到title和text两个字符串的地址
- 由于IDA中看到的是默认加载的映像地址,还需要转化为文件地址才能使用,方法是减掉
.rdata
段的起始地址,得到段内偏移地址,再用PE Tools打开文件,查找到.rdata的文件地址,再加上段内偏移地址,即可定位到目标字符串在文件中的偏移地址0x89b0
- 接下来,编写程序打开目标文件,在指定偏移处填入字符串,需要注意一个中文字符占两个字节,多余的字节用
\x00
填充
代码
#include <windows.h>
#include <cstdio>
int main(int argc, char* argv[])
{
HANDLE hFile = CreateFile("Encoding.exe", 0xC0000000, 3, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("Error opening file. Error code: %d\n", GetLastError());
return 1;
}
DWORD dwBytesWritten;
char title[] = "失败";
DWORD title_offset = 0x89b0;
SetFilePointer(hFile, title_offset, NULL, FILE_BEGIN);
if (!WriteFile(hFile, title, sizeof(title)-1, &dwBytesWritten, NULL)) {
printf("Error writing to file. Error code: %d\n", GetLastError());
CloseHandle(hFile);
return 1;
}
char text[] = "进入游戏失败!\x00\x00\x00\x00\x00\x00";
DWORD text_offset = 0x89b8;
SetFilePointer(hFile, text_offset, NULL, FILE_BEGIN);
if (!WriteFile(hFile, text, sizeof(text)-1, &dwBytesWritten, NULL)) {
printf("Error writing to file. Error code: %d\n", GetLastError());
CloseHandle(hFile);
return 1;
}
CloseHandle(hFile);
}
效果展示
- 打补丁前运行程序提示成功进入游戏,打补丁后,运行程序提示失败