加密与解密之补丁程序开发

发布时间 2023-04-04 15:49:14作者: z5onk0

开头

  • 看完《加密与解密第四版》,有些心得体会,收获主要集中在补丁程序开发、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);
}

效果展示

  • 打补丁前运行程序提示成功进入游戏,打补丁后,运行程序提示失败