c++ 自制一个极简的内存修改器

180it 2020-10-16 PM 2254℃ 0条
#undef UNICODE
//按老师说的改了项目属性还是没用,搜到的避免字符串转换问题的方法就是加这一句
#include<stdio.h>
#include<Windows.h>
#include<iostream>
BOOL FindFirst(DWORD dwValue); //开始查找所有符合值的地址
BOOL FindNext(DWORD dwValue); //在已查找到的地址中重新查找

DWORD g_arrList[1024]; //存储找到的地址,只存1024个
int g_nListCnt; //有效的地址个数
HANDLE g_hProcess; //目标进程的句柄

void ShowList(); //显示有效的地址列表
BOOL WriteMemory(DWORD dwAddr, DWORD dwValue); //修改地址处的值

int main(int argc, char* argv[]) {
    system("chcp 65001");
    //首先通过CreateProcess将目标进程加载,然后才能访问目标进程的内存空间
    char szFileName[100];
    //从命令行读取参数或者请求输入
    if(argc > 1)
        strcpy(szFileName, argv[1]);
    else{
        printf("请输入要修改的程序:\n");
        std::cin >> szFileName;
    }
    STARTUPINFO si;
    memset(&si, 0, sizeof(si));
    PROCESS_INFORMATION pi;
    BOOL bRet = ::CreateProcess(
            NULL,
            szFileName,
            NULL,
            NULL,
            FALSE,
            CREATE_NEW_CONSOLE,
            NULL,
            NULL,
            &si,
            &pi
    );
    g_hProcess = pi.hProcess; //将目标进程的句柄保存在全局变量中
    BOOL flag = TRUE;
    int iVal;
    while (flag) {
        // 接收输入一个目标值,并进行搜索比对
        printf("第一次搜索的数值:\n");
        std::cin >> iVal;
        //第一次查找
        FindFirst(iVal);
        //显示地址列表
        ShowList();
        int nListCnt{ 0 }, count{ 0 };
        while (g_nListCnt > 1) {
            nListCnt = g_nListCnt;
            printf("输入要修改的数值:\n");
            std::cin >> iVal;
            //下一次搜索
            FindNext(iVal);
            ShowList();
            if (nListCnt == g_nListCnt) {
                count++; //如果重复3次都是同样的地址,则不再查找,选择其中的第一个修改
                if (count > 1)
                    break;
            }
        }
        if (g_nListCnt == 1 || nListCnt == g_nListCnt) {
            printf("目标地址为:%p\n", g_arrList[0]);
            //获取输入的新值,修改替换
            printf("输入要修改为的值:\n");
            std::cin >> iVal;
            if (WriteMemory(g_arrList[0], iVal)) {
                printf("修改成功\n");
            }
        }
        else {
            printf("未找到地址\n");
        }
        printf("是否重新查找(y/n):\n");
        char c;
        std::cin >> c;
        if (c == 'y')
            flag = TRUE;
        else
            flag = FALSE;
    }
    system("pause");
    return 0;
}

BOOL ComparePage(DWORD dwBaseAddr, DWORD dwValue) {
    BYTE arBytes[4096];
    if (!::ReadProcessMemory(g_hProcess, (LPCVOID)dwBaseAddr, arBytes, 4096, NULL)) {
        return FALSE;
    }
    DWORD* pdw;
    //一个DWORD4个字节,所以从头开始一次取4个字节长度的值进行对比
    for (int i = 0; i < (int)4 * 1024 - 3; i++) {
        pdw = (DWORD*)&arBytes[i];
        if (pdw[0] == dwValue) {
            if (g_nListCnt >= 1024)
                return FALSE;
            g_arrList[g_nListCnt++] = dwBaseAddr + i;
        }
    }
    return TRUE;
}

BOOL FindFirst(DWORD dwValue)
{
    BOOL bRet = FALSE;
    const DWORD dwOneGb = 1024 * 1024 * 1024; //定义一个GB的大小
    const DWORD dwOnePage = 4 * 1024; //定义4KB一页
    g_nListCnt = 0;
    if (g_hProcess == NULL)
        return FALSE;
    DWORD dwBase = 64 * 1024; //刚开始的64kb是不能访问的,直接跳过
    for (; dwBase < 2 * dwOneGb; dwBase += dwOnePage) {
        //在2gb的空间里每次在4kb的页中寻找
        ComparePage(dwBase, dwValue);
    }
    return TRUE;
}

BOOL FindNext(DWORD dwValue)
{
    BOOL bRet = FALSE;
    int nOrgCnt = g_nListCnt;
    g_nListCnt = 0;
    DWORD dwReadValue; //存储读取值的地址
    for (int i = 0; i < nOrgCnt; i++) {
        if (::ReadProcessMemory(g_hProcess, (LPVOID)g_arrList[i], &dwReadValue, sizeof(DWORD), NULL)) {
            if (dwReadValue == dwValue) {
                g_arrList[g_nListCnt++] = g_arrList[i];
                bRet = TRUE;
            }
        }
    }
    return bRet;
}

void ShowList()
{
    for (int i = 0; i < g_nListCnt; i++) {
        std::cout << std::hex << g_arrList[i] << std::endl;
    }
}

BOOL WriteMemory(DWORD dwAddr, DWORD dwValue)
{
    return ::WriteProcessMemory(g_hProcess, (LPVOID)dwAddr, &dwValue, sizeof(DWORD), NULL);
}

来源:https://www.52pojie.cn/forum.php?mod=viewthread&tid=1255389&extra=page%3D1%26filter%3Dtypeid%26typeid%3D28

支付宝打赏支付宝打赏 微信打赏微信打赏

如果文章或资源对您有帮助,欢迎打赏作者。一路走来,感谢有您!

标签: none

c++ 自制一个极简的内存修改器