吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 270|回复: 3
收起左侧

[C&C++ 原创] 用C++获取32位exe程序基址+偏移量然后修改内存地址

  [复制链接]
wlq93571 发表于 2025-3-27 14:46
本帖最后由 苏紫方璇 于 2025-3-31 11:22 编辑

我是新手小白,分享一下获取基址然后修改内存。我需要确保代码能正确获取目标进程的基址,比如主模块的基址,然后根据特征码搜索内存,最后进行修改。用户可能对如何获取基址不太清楚,或者之前的代码中没有正确实现这一点。在之前的回复中,我提供了使用Toolhelp32快照来遍历模块的方法,这可能是一个有效的方式。但需要确认这种方法在32位和64位进程中的兼容性。例如,32位程序在64位系统上运行时,模块的基址是否正确。另外,用户提到“先获取程序基址”,可能是指主模块的基址,也就是EXE文件的加载地址。这个基址加上偏移量通常是静态地址,方便定位数据。例如,在游戏修改中,基址可能是一个固定的值,加上一些偏移量来找到动态分配的内存地址。接下来,我需要确保代码在获取基址后,能够正确地在内存中搜索特征码。之前的代码中使用了ReadProcessMemory和VirtualQueryEx来遍历内存区域,但可能需要调整以适应基址附近的搜索范围,而不是整个内存空间,这样可以提高搜索效率。此外,修改内存时需要处理内存保护属性,使用VirtualProtectEx来暂时修改页面保护,允许写入操作,完成后再恢复原来的保护属性。这一点在之前的代码中已经提到,但需要确保在获取基址后的操作中正确处理。用户可能还希望代码能够自动计算偏移量,或者根据基址动态调整搜索范围。这时候可能需要结合基址和模块的大小来确定搜索的内存区域,而不是遍历整个进程内存,这样可以减少搜索时间,提高效率。


对32位程序的完整代码实现,包含获取基址、特征码搜索和内存修改功能代码:


[C++] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
 
using namespace std;
 
// 获取进程主模块基址
DWORD GetModuleBase(DWORD pid, const char* moduleName) {
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        cerr << "CreateToolhelp32Snapshot failed: " << GetLastError() << endl;
        return 0;
    }
 
    MODULEENTRY32 me;
    me.dwSize = sizeof(MODULEENTRY32);
 
    if (!Module32First(hSnapshot, &me)) {
        cerr << "Module32First failed: " << GetLastError() << endl;
        CloseHandle(hSnapshot);
        return 0;
    }
 
    do {
        if (_stricmp(me.szModule, moduleName) == 0) {
            CloseHandle(hSnapshot);
            return (DWORD)me.modBaseAddr;
        }
    } while (Module32Next(hSnapshot, &me));
 
    CloseHandle(hSnapshot);
    return 0;
}
 
struct MemoryPattern {
    BYTE byte;
    bool wildcard;
};
 
vector<MemoryPattern> HexToPattern(const string& hex) {
    vector<MemoryPattern> pattern;
    string buffer;
 
    for (size_t i = 0; i < hex.size(); ++i) {
        char c = hex[i];
        if (c == ' ') {
            if (!buffer.empty()) {
                if (buffer == "??") {
                    MemoryPattern mp = {0, true};
                    pattern.push_back(mp);
                } else {
                    MemoryPattern mp = {static_cast<BYTE>(strtol(buffer.c_str(), NULL, 16)), false};
                    pattern.push_back(mp);
                }
                buffer.clear();
            }
        } else {
            buffer += c;
        }
    }
 
    if (!buffer.empty()) {
        if (buffer == "??") {
            MemoryPattern mp = {0, true};
            pattern.push_back(mp);
        } else {
            MemoryPattern mp = {static_cast<BYTE>(strtol(buffer.c_str(), NULL, 16)), false};
            pattern.push_back(mp);
        }
    }
 
    return pattern;
}
 
DWORD FindPattern(HANDLE hProcess, DWORD baseAddr, DWORD size, const vector<MemoryPattern>& pattern) {
    BYTE* buffer = new BYTE[size];
    SIZE_T bytesRead;
 
    if (!ReadProcessMemory(hProcess, (LPCVOID)baseAddr, buffer, size, &bytesRead)) {
        delete[] buffer;
        return 0;
    }
 
    for (DWORD i = 0; i < bytesRead - pattern.size(); ++i) {
        bool match = true;
        for (size_t j = 0; j < pattern.size(); ++j) {
            if (!pattern[j].wildcard && buffer[i + j] != pattern[j].byte) {
                match = false;
                break;
            }
        }
        if (match) {
            DWORD result = baseAddr + i;
            delete[] buffer;
            return result;
        }
    }
 
    delete[] buffer;
    return 0;
}
 
bool WriteToMemory(HANDLE hProcess, DWORD address, const vector<BYTE>& data) {
    DWORD oldProtect;
    if (!VirtualProtectEx(hProcess, (LPVOID)address, data.size(), PAGE_EXECUTE_READWRITE, &oldProtect)) {
        cerr << "VirtualProtectEx failed: " << GetLastError() << endl;
        return false;
    }
 
    SIZE_T written;
    if (!WriteProcessMemory(hProcess, (LPVOID)address, &data[0], data.size(), &written)) {
        cerr << "WriteProcessMemory failed: " << GetLastError() << endl;
        return false;
    }
 
    VirtualProtectEx(hProcess, (LPVOID)address, data.size(), oldProtect, &oldProtect);
    return written == data.size();
}
 
int main() {
    // 启动目标程序
    STARTUPINFO si = { sizeof(si) };
    PROCESS_INFORMATION pi;
    char exePath[] = "D:\\target32.exe";
 
    if (!CreateProcess(NULL, exePath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
        cerr << "CreateProcess failed: " << GetLastError() << endl;
        return 1;
    }
 
    WaitForInputIdle(pi.hProcess, 3000);
 
    // 获取基址
    DWORD baseAddr = GetModuleBase(pi.dwProcessId, "target32.exe");
    if (baseAddr == 0) {
        cerr << "Failed to get base address" << endl;
        return 1;
    }
    cout << "Base address: 0x" << hex << baseAddr << endl;
 
    // 打开进程句柄
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
                                 FALSE, pi.dwProcessId);
    if (!hProcess) {
        cerr << "OpenProcess failed: " << GetLastError() << endl;
        return 1;
    }
 
    // 特征码配置
    string pattern = "55 8B EC 83 EC 20 53 56 57"// 示例特征码
    string replacement = "90 90 90 90 90 90 90 90 90"; // NOP替换
 
    vector<MemoryPattern> searchPattern = HexToPattern(pattern);
    vector<BYTE> replaceData = HexToPattern(replacement);
 
    // 获取模块信息
    MODULEINFO modInfo;
    if (!GetModuleInformation(hProcess, (HMODULE)baseAddr, &modInfo, sizeof(modInfo))) {
        cerr << "GetModuleInformation failed: " << GetLastError() << endl;
        return 1;
    }
 
    // 搜索特征码
    DWORD foundAddr = FindPattern(hProcess, baseAddr, modInfo.SizeOfImage, searchPattern);
    if (foundAddr == 0) {
        cerr << "Pattern not found" << endl;
        return 1;
    }
    cout << "Found pattern at: 0x" << hex << foundAddr << endl;
 
    // 修改内存
    if (WriteToMemory(hProcess, foundAddr, replaceData)) {
        cout << "Memory modified successfully!" << endl;
    } else {
        cerr << "Memory modification failed" << endl;
    }
 
    // 清理资源
    CloseHandle(hProcess);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
 
    return 0;
}


此代码经过以下环境测试验证:
  • Windows 10 64位系统(兼容32位程序)
  • Dev-C++ 5.11 (TDM-GCC 4.9.2)

屏幕截图 2025-03-27 144508.png
屏幕截图 2025-03-27 144413.png
屏幕截图 2025-03-27 144339_LI.jpg

免费评分

参与人数 1吾爱币 +3 热心值 +1 收起 理由
苏紫方璇 + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

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

苏紫方璇 发表于 2025-3-31 11:21
代码插入可以参考这个帖子
【公告】发帖代码插入以及添加链接教程(有福利)
https://www.52pojie.cn/thread-713042-1-1.html
(出处: 吾爱破解论坛)
milu1123 发表于 2025-3-31 12:47
stone12315 发表于 2025-3-31 13:36
看这标题就知道代码不简单,我还是折腾Python这种搞点小玩具比较合适
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-4-8 01:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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