You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过ReadProcessMemory跨进程读取std::string?(int类型读取正常但字符串读取失败)

Why Reading std::string with ReadProcessMemory Fails (And How to Fix It)

Ah, I see the issue here—reading a std::string across processes isn't as straightforward as reading a raw int, and your current code is hitting a classic pitfall with how C++ strings are stored under the hood. Let's break this down:

The Root Cause

Unlike an int (a simple value stored directly in memory), a std::string is a complex container object. It doesn't hold the actual string characters in its own memory space. Instead, it stores:

  • A pointer to a separate heap buffer where the real characters live
  • Metadata like the string's length and capacity

When you use ReadProcessMemory to read directly into your local std::string (&JoJo_string), you're only copying the pointer and metadata from the target process's std::string object. That pointer is only valid in the target process's address space—when your local process tries to use it, it's accessing invalid memory, which causes the crash or error you're seeing.

The Fix: Read the String in Two Steps

To correctly read a std::string from another process, you need to:

  1. Read the target std::string object's metadata (pointer to characters and string length)
  2. Use that metadata to read the actual character data from the target process's heap

Here's a revised Programm_B that implements this (note: this assumes both processes use the same compiler/architecture—e.g., 64-bit MSVC, since std::string layout varies between compilers):

#include <iostream>
#include <string>
#include <cstdlib>
#include <windows.h>

int main() { 
    int id; 
    std::cout << "Enter target process ID: ";
    std::cin >> id; 
    DWORD ProcessId = id; 

    // Open target process with read access
    HANDLE ProcessHandle = OpenProcess(PROCESS_VM_READ, FALSE, ProcessId); 
    if (!ProcessHandle) { 
        std::cout << "Process is not found...\n"; 
        return 0; 
    } 

    std::string addr_str; 
    std::cout << "Enter std::string address (hex): ";
    std::cin >> addr_str; 
    uintptr_t string_addr = std::strtoull(addr_str.c_str(), NULL, 16); 

    // Step 1: Read target std::string's metadata (matches MSVC layout)
    struct RemoteStringMetadata {
        char* data_ptr;
        size_t length;
        size_t capacity;
    };

    RemoteStringMetadata meta;
    if (!ReadProcessMemory(ProcessHandle, (LPVOID)string_addr, &meta, sizeof(meta), NULL)) {
        std::cout << "Failed to read string metadata\n";
        CloseHandle(ProcessHandle);
        return 0;
    }

    // Step 2: Read actual character data from target's heap
    std::string local_string;
    local_string.resize(meta.length); // Allocate space for characters

    if (!ReadProcessMemory(ProcessHandle, (LPVOID)meta.data_ptr, &local_string[0], meta.length, NULL)) {
        std::cout << "Failed to read string data\n";
        CloseHandle(ProcessHandle);
        return 0;
    }

    std::cout << "Read string: " << local_string << std::endl; 

    CloseHandle(ProcessHandle);
    return 0;
}

Critical Notes

  • Compiler Consistency: The RemoteStringMetadata struct depends on your compiler's std::string implementation. For GCC/Clang, you'll need to adjust the struct to match their internal layout (they use a union for short-string optimization).
  • Short-String Optimization (SSO): Even if the target string uses SSO (stored directly in the std::string object), this code still works—meta.data_ptr will point to the object's internal buffer, and ReadProcessMemory will correctly read that buffer from the target process's address space.
  • Error Handling: Always check the return values of ReadProcessMemory and OpenProcess to catch issues like insufficient permissions or invalid addresses.

内容的提问来源于stack exchange,提问作者St_rt_la

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 14:22:50