我正在尝试编写一个简单的代码,用另一个使用WPM替换程序中的字符串,我能够使它工作,但只是部分。这是我用来获得结果的代码的一部分。
string strWrite;
cin >> strWrite;
strWrite = strWrite + "\0";
if (WriteProcessMemory(hProcess, (LPVOID) reqdAddr, &strWrite[0], strWrite.size(), NULL) == false)
{
cout << "WriteProcessMemory failed. GetLastError = " << dec << GetLastError() << endl;
system("pause");
return EXIT_FAILURE;
}
当我尝试用DefaultString
替换原始字符串blabla
时,我得到的结果是blablatString
。我尝试过将strWrite.size()
替换为strWrite.size() + 1
,并意识到结果会更改为blabla String
。我需要帮助替换整个字符串而不仅仅是它的一部分。
答案 0 :(得分:1)
如果(如果是这样)目标字符串存储为std :: string,则此方法不起作用。它们有一个内部结构,程序员不应该知道(除非你在头文件中挖掘)并且你在那里的代码没有考虑到这一点。即使你这样做,下一版本的编译器可能会破坏你的代码。
因此,请考虑(如果可以)将目标字符串存储为简单的C字符串。只要你没有跑到最后并添加一个终止的nul,覆盖它就会很简单。我会明确地这样做 - 不要假设源字符串是nul-terminated,它可能不是。或者使用std::string.c_str()
并从中复制size() + 1
个字节。
答案 1 :(得分:0)
std :: string是在后端管理char数组的容器。
就目前而言,在x86上,如果要写入的字符串大小等于或小于当前字符串,则可以相对轻松地执行此操作,但不建议这样做。
容器的偏移量0x14是数组的大小 如果char数组少于15个字符,则该数组存储在偏移量0x4处 如果char数组大于15个字符,则此偏移量将变为指向其他位置的动态数组的指针
因此,您读取数组的大小,然后根据其大小写入正确的地址。此代码将执行此操作,并输出“再见m8”
void WriteExternalString(HANDLE hProc, BYTE* addr, char* newstr)
{
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);
//Write the buffer to the array, +1 to get the null terminator
WriteProcessMemory(hProc, (BYTE*)(addrOfCharArray), newstr, strlen(newstr) + 1, 0);
}
else
{
WriteProcessMemory(hProc, (BYTE*)(addr + sizeof(void*)), newstr, strlen(newstr) + 1, 0);
}
}
int main()
{
std::string str = "Hello Mate";
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
char newstr[] = "Goodbye m8";
WriteExternalString(hProcess, (BYTE*)&str, newstr);
cout << "string char array = " << str << endl;
system("pause");
return 0;
}