【问题标题】:How do i read a std::string from memory using RPM如何使用 RPM 从内存中读取 std::string
【发布时间】:2019-09-11 20:29:46
【问题描述】:

好的,最近我一直在使用 RPM(ReadProccesMemory)。但是在这样做的同时,我遇到了无法按照我想要的方式读取字符串的问题。

这是我听到/知道的: 我知道,在读取 std::string 时,我得到的是字符串 OBJECT 的内存地址,而不是包含实际文本的地址。我也知道“小字符串优化”,以及它在理论上的作用。

我希望能够在不更改虚拟程序代码的情况下读取 varString(DefaultString) 的内容(如果可能的话)。

我正在阅读的虚拟程序:

int main() {
    // Variables & Pointers
    int varInt = 123456;
    string varString = "DefaultString";
    cout << sizeof(varString);
    char arrChar[128] = { "Long char array right there ->" };
    int* ptr2int = &varInt;
    int** ptr2ptr = &ptr2int;
    int*** ptr2ptr2 = &ptr2ptr;

    // Printing them out
    while (true){
    cout << "Process ID: " << GetCurrentProcessId() << endl << endl;
    cout << "varInt (0x" << &varInt << ") = " << varInt << endl;
    cout << "varString (" << reinterpret_cast<const void*>(varString.data()) << ") = " << varString << endl;
    cout << "arrChar (0x" << &arrChar << ") = " << arrChar << endl << endl;

    cout << "ptr2int (0x" << &ptr2int << ") = " << &varInt << endl;
    cout << "ptr2ptr (0x" << &ptr2ptr << ") = " << &ptr2int << endl;
    cout << "ptr2ptr2 (0x" << &ptr2ptr2 << ") = " << &ptr2ptr << endl << endl;
    break;
    }

    cin.get();
    return 0;
}

我目前在做什么(不会按预期工作):

void reading_string(HANDLE handle_procces) {
    uintptr_t memoryAdress_2 = 0x0;
    cout << "Please write down the memory adress of \"varString\" > " << flush;
    cin >> hex >> memoryAdress_2;

    string read_string_object;
    ReadProcessMemory(handle_procces, (LPCVOID)memoryAdress_2, &read_string_object, sizeof(string), NULL);
    cout << "The value of this memory adress is: " << read_string_object << endl;
}

【问题讨论】:

  • std::string 中的某处应该有一个指向实际数据的指针。但是,std::string 的内存布局没有标准化,因此指针可以在任何地方。该位置可能会因进程而异,具体取决于使用的 std::string
  • "在 std::string 的某个地方应该有一个指向实际数据的指针。"我如何找到那个指针?通过手动搜索还是?
  • 你需要指针还是指针指向什么?有关返回指向数据的指针的函数,请参见 std::string::data()
  • @Jowen 通常你不使用它。您使用类接口并使用适当的成员函数(例如std::string::data())。但由于您正在访问另一个进程的数据,因此没有一种简单的内置方法可以做到这一点。

标签: c++ memory stdstring


【解决方案1】:

std::string 是一个容器,偏移量 0x14 是它管理的 char 数组的大小。如果字符串少于 15 个字符,则第二个变量(偏移量 0x4 或 0x8,取决于 x86/x64)是 char 数组本身。如果超过 15 个字符,则该变量变为指向动态分配的 char 数组的指针

我们可以使用这些信息从外部读取字符串,这是一个 hack,但它可以工作

这里有一些示例代码向您展示了它是如何完成的:

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

using namespace std;

void ReadExternalString(HANDLE hProc, uintptr_t addr, char* dstArray)
{

    unsigned int arraySize;
    //Get the size of the array, offset 0x14 is the size of the array
    ReadProcessMemory(hProc, (BYTE*)(addr + 0x14), &arraySize, sizeof(arraySize), 0);

    if (arraySize > 15)
    {
        uintptr_t addrOfCharArray;
        //dereference the pointer in the second member variable to get the dynamic address of the array
        ReadProcessMemory(hProc, (BYTE*)(addr + sizeof(void*)), &addrOfCharArray, sizeof(void*), 0);

        char buffer[500];
        //Read the array into buffer, +1 to get the null terminator
        ReadProcessMemory(hProc, (BYTE*)(addrOfCharArray), &buffer, arraySize + 1, 0);

        //copy the buffer into our ouput argument
        memcpy(dstArray, &buffer, strlen(buffer) + 1);
    }
    else
    {
        ReadProcessMemory(hProc, (BYTE*)(addr + sizeof(void*)), dstArray, arraySize, 0);
    }
}

int main()
{

    int processNumber;
    cout << "Enter the process number" << endl;
    cin >> processNumber;
    for (;;)
    {
        uintptr_t memoryAddress = 0x0;
        cout << "Enter memoryAddress" << endl;
        cin >> hex >> memoryAddress;
        cout << hex << memoryAddress << endl;

        HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processNumber);
        if (hProcess == NULL) { // Failed to get a handle
            cout << "OpenProcess failed. GetLastError = " << dec << GetLastError() << endl;
            system("pause");
            return EXIT_FAILURE;
        }

        char* cString = new char[500];

        ReadExternalString(hProcess, memoryAddress, cString);

        cout << "string char array = " << cString << endl;
        system("pause");
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-02
    • 2011-03-26
    • 2011-06-26
    • 2011-02-16
    • 2010-12-21
    • 1970-01-01
    • 2014-01-25
    • 2012-03-25
    相关资源
    最近更新 更多