董督秀 发表于 2023-9-24 01:23

printf打印结果在部分情况下有误?

1.printf打印结果在部分情况下有误?具体情况和出现的问题,我已经在下面两张图里详细描述:





问题代码:
https://t.wss.ink/f/c98jlroq57n

2.该如何解决这个问题?{:1_937:}
@爱飞的猫 大佬麻烦帮忙看下吧,谢谢。

爱飞的猫 发表于 2023-9-24 01:23

3L 说得对,需要映射文件地址到虚拟地址。

首先加一些头文件,写起来方便:

```cpp
#include <vector>
#include <algorithm>
```

为了方便,启动时自动获取进程 PID:

```cpp
// 辅助方法: 进程名到 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;
```

将文件读入内存后需要解析 PE 文件的段(Section):

```cpp

// 简单定义些东西
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; // 找不到
        };
```

最后打印的时候从辅助函数里映射地址:

```cpp
                printf("搜索到的偏移: 0x%p\n", (uintptr_t)map_address((char*)地址数组) + (uintptr_t)me32.modBaseAddr);
```




修改后的 `代码调试.cpp`:




zpy2 发表于 2023-9-24 06:28

小顺_自用函数.h

函数体直接放到 .h?不是.cpp

另外,小顺_本进程_特征码_搜索_模糊,你这个明显是搜索跨进程的,用dll远程注入吧!

woflant 发表于 2023-9-24 07:53

HANDLE hFile = CreateFile(me32.szExePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

你这句代码是打开程序文件,xdbg是在进程内存中搜索,一个是FOA,一个是RVA

bester 发表于 2023-9-24 11:50

文件对齐了解一下

https://www.cnblogs.com/qintangtao/archive/2013/01/11/2857182.html

冥界3大法王 发表于 2023-9-26 16:07

好牛拜的插件捕获进程快照这函数delphi里也用过。
页: [1]
查看完整版本: printf打印结果在部分情况下有误?