好,最近我一直在使用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是一个容器,偏移量0x14是它管理的char数组的大小。如果字符串少于15个字符,则第二个变量(偏移量0x4或0x8,取决于x86 / x64)是char数组本身。如果超过15个字符,则此变量将变为指向动态分配的char数组的指针
我们可以使用此信息从外部读取字符串,这是一种技巧,但可以使用
这里有一些示例代码向您展示了如何完成:
#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;
}