3L 说得对,需要映射文件地址到虚拟地址。
首先加一些头文件,写起来方便:
#include <vector>
#include <algorithm>
为了方便,启动时自动获取进程 PID:
// 辅助方法: 进程名到 PID
std::vector<DWORD> find_all_pid_with_name(const wchar_t* process_name) {
auto hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE) {
return {};
}
PROCESSENTRY32W pe32{};
pe32.dwSize = sizeof(pe32);
if (!Process32FirstW(hSnap, &pe32)) {
CloseHandle(hSnap);
return {};
}
std::vector<DWORD> result{};
do {
if (_wcsicmp(pe32.szExeFile, process_name) == 0) {
result.push_back(pe32.th32ProcessID);
}
} while (Process32NextW(hSnap, &pe32));
CloseHandle(hSnap);
return result;
}
// main 函数下
auto pids = find_all_pid_with_name(L"MFC_33CD.exe");
if (pids.size() == 0) {
throw std::runtime_error("could not find process");
}
dwPid = pids[0];
将文件读入内存后需要解析 PE 文件的段(Section):
// 简单定义些东西
struct SectionInfo {
char* raw_addr;
size_t raw_size;
char* virt_addr;
size_t virt_size;
};
// 回到 main
auto nt_header = PIMAGE_NT_HEADERS(buffer + PIMAGE_DOS_HEADER(buffer)->e_lfanew);
std::vector<SectionInfo> sections;
if (nt_header->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
// 32 位
auto nt_header_32 = PIMAGE_NT_HEADERS32(nt_header);
auto n_headers = nt_header_32->FileHeader.NumberOfSections;
auto section_hdrs = PIMAGE_SECTION_HEADER(((char*)&nt_header_32->OptionalHeader) + nt_header_32->FileHeader.SizeOfOptionalHeader);
sections.reserve(n_headers);
for (int i = 0; i < n_headers; i++, section_hdrs++) {
SectionInfo section{};
section.raw_addr = (char*)section_hdrs->PointerToRawData;
section.raw_size = section_hdrs->SizeOfRawData;
section.virt_addr = (char*)section_hdrs->VirtualAddress;
section.virt_size = section_hdrs->Misc.VirtualSize;
sections.push_back(section);
}
}
else if (nt_header->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
// 64 位 - 作业自己做吧
}
// 将他们排序,按照虚拟地址从小到大排序
std::sort(sections.begin(), sections.end(), [&](SectionInfo &a, SectionInfo& b) {
return a.raw_addr < b.raw_addr;
});
auto map_address = [&](void* addr) -> void* {
auto p_addr = (char*)((char*)addr - buffer); // 文件偏移
// 找第一个符合条件的
for (auto& section : sections) {
if (p_addr >= section.raw_addr) {
return p_addr - section.raw_addr + section.virt_addr;
}
}
return p_addr; // 找不到
};
最后打印的时候从辅助函数里映射地址:
printf(" 搜索到的偏移: 0x%p\n", (uintptr_t)map_address((char*)地址数组[i]) + (uintptr_t)me32.modBaseAddr);
修改后的 代码调试.cpp :
代码调试.cpp@爱飞的猫.txt
(5.48 KB, 下载次数: 3)
|