吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5674|回复: 9
收起左侧

[C&C++ 转载] 自制一个极简的内存修改器

[复制链接]
笙若 发表于 2020-8-27 19:03
本帖最后由 笙若 于 2020-8-27 19:13 编辑

这是前几天从论坛里发的教程里学到的,我觉得这个教程挺好的,对win32api编程有兴趣的可以学一学,链接是这个:
https://www.52pojie.cn/forum.php?mod=viewthread&tid=1247555&highlight=windows%B3%CC%D0%F2

[C++] 纯文本查看 复制代码
#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[]) {
        //首先通过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);
}


在老师的代码基础上做了一点点修改,老师是用纯C写的,但是vs2019里scanf老是会提示不安全,所以全部换成了c++的cin。
偶尔会用CE改游戏,通过这段代码也算稍微理解了一点原理,还是很有成就感的。
感兴趣的朋友希望可以一起坚持学下去。

免费评分

参与人数 4吾爱币 +10 热心值 +3 收起 理由
深水夜藏 + 1 + 1 我很赞同!
苏紫方璇 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
小小的石头13 + 1 + 1 可以呀楼主,看上去很厉害的样子!
Tonyha7 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

ps122 发表于 2020-8-27 19:33
谢谢分享,有编译好的可执行文件吗?
 楼主| 笙若 发表于 2020-8-27 20:36
ps122 发表于 2020-8-27 19:33
谢谢分享,有编译好的可执行文件吗?

链接: https://pan.baidu.com/s/1kPTvZZpB66O2JkFGT2KTVg 提取码: kau2
里面的MemChange是编译好的文件,然后tester是用来测试的,每按一次回车数字就会变

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
ps122 + 1 + 1 谢谢@Thanks!

查看全部评分

深水夜藏 发表于 2020-8-27 22:12
ps122 发表于 2020-8-28 07:59
笙若 发表于 2020-8-27 20:36
链接: https://pan.baidu.com/s/1kPTvZZpB66O2JkFGT2KTVg 提取码: kau2
里面的MemChange是编译好的文件 ...

非常感谢!
xiaohe_nh 发表于 2020-11-14 08:28
ComparePage中里面是从头按照4个字节比较的。有没有可能,程序因为存储类型等有两个字节或1个字节的空间占用。这样导致后续数据的错位,使得无法真正找到4个字节的数据?
天天54123 发表于 2021-1-19 16:26
没有提示这个 请输入要修改的程序
 楼主| 笙若 发表于 2021-1-19 17:28
天天54123 发表于 2021-1-19 16:26
没有提示这个 请输入要修改的程序

如果带有参数的话,第一个参数会被当做要修改的程序,就不会提示输入程序了
AA_BB_2AB 发表于 2021-4-2 15:26
谢谢,祝您身体健康!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 17:23

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表