Win API ReadProcessMemory at base address of DLL returning unexpected data - c++

I'm trying to read the contents of a DLL from memory for some academic research. Specifically, the NTDSA.DLL library for the purpose of mutating specific instructions to simulate programming errors to force the system to fail. The failure will then be recorded to train machine learning algorithms to predict future failures (this is an attempt to generalize previously published research seen here).
I'm getting what I believe to be the base address in virtual memory of the lsass.exe process (which loads the target DLL) through the process outlined here. I'm then calling ReadProcessMemory with an allocated buffer and the handle to lsass obtained by calling OpenProcess with 'PROCESS_ALL_ACCESS' set. The ReadProcessMemory returns with error code 299 80% of the time (partial read) with zero bytes read. My assumption is that the area I'm trying to access is in use when the call is made. Fortunately, it will occasionally return the number of bytes I'm requesting. Unfortunately, the data returned does not match what is on disk when compared to the static DLL in the System32 directory.
So the question is, is ReadProcessMemory doing something funny with the address that I give it, or is my virtual address wrong? Is there another way to figure out where that DLL gets loaded into memory? Any thoughts? Any help or suggestions would be greatly appreciated.
Adding Code:
// FaultInjection.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <psapi.h>
#include <string>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <io.h>
#include <tchar.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]) {
// Declarations
int pid = 0;
__int64* start_addr;
DWORD size_of_ntdsa;
DWORD aProcesses[1024], cbNeeded, cProcesses;
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
HMODULE hmods[1024];
unsigned int i;
// Get All pids
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)){
cout << "Failed to get all PIDs: " << GetLastError() << endl;
return -1;
}
// Find pid for lsass.exe
cProcesses = cbNeeded / sizeof(DWORD);
for (i = 0; i < cProcesses; i++) {
if (aProcesses[i] != 0) {
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);
if (hProc != NULL) {
HMODULE hMod;
DWORD cbNeededMod;
if (EnumProcessModules(hProc, &hMod, sizeof(hMod), &cbNeededMod)) {
GetModuleBaseName(hProc, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR));
}
if (wstring(szProcessName).find(L"lsass.exe") != string::npos) {
pid = aProcesses[i];
}
CloseHandle(hProc);
}
}
}
cout << "lsass pid: " << pid << endl;
HANDLE h_lsass = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!h_lsass) {
cout << "Failed to open process (are you root?): " << GetLastError() << endl;
return -1;
}
// Get Process Image File Name
char filename[MAX_PATH];
if (GetProcessImageFileName(h_lsass, (LPTSTR)&filename, MAX_PATH) == 0) {
cout << "Failed to get image file name: " << GetLastError() << endl;
CloseHandle(h_lsass);
return -1;
}
// Enumerate modules within process
if (EnumProcessModules(h_lsass, hmods, sizeof(hmods), &cbNeeded)) {
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(h_lsass, hmods[i], szModName, sizeof(szModName) / sizeof(TCHAR))) {
if (wstring(szModName).find(L"NTDSA.dll") != string::npos) {
_tprintf(TEXT("%s\n"), szModName);
MODULEINFO lModInfo = { 0 };
if (GetModuleInformation(h_lsass, hmods[i], &lModInfo, sizeof(lModInfo))){
cout << "\t Base Addr: " << lModInfo.lpBaseOfDll << endl;
cout << "\t Entry Point: " << lModInfo.EntryPoint << endl;
cout << "\t Size of image: " << lModInfo.SizeOfImage << endl;
start_addr = (__int64*)lModInfo.lpBaseOfDll;
size_of_ntdsa = lModInfo.SizeOfImage;
}
else {
cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
}
}
} else {
cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
}
}
}
else {
cout << "Failed to enum the modules: " << GetLastError() << endl;
}
// Ready to continue?
string cont = "";
cout << "Continue? [Y|n]: ";
getline(cin, cont);
if (cont.find("n") != string::npos || cont.find("N") != string::npos) {
CloseHandle(h_lsass);
return 0;
}
void* buf = malloc(size_of_ntdsa);
if (!buf) {
cout << "Failed to allocate space for memory contents: " << GetLastError() << endl;
CloseHandle(h_lsass);
return -1;
}
SIZE_T num_bytes_read = 0;
int count = 0;
if (ReadProcessMemory(h_lsass, &start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
cout << "Read success. Got " << num_bytes_read << " bytes: " << endl;
} else {
int error_code = GetLastError();
if (error_code == 299) {
cout << "Partial read. Got " << num_bytes_read << " bytes: " << endl;
} else {
cout << "Failed to read memory: " << GetLastError() << endl;
CloseHandle(h_lsass);
free(buf);
return -1;
}
}
if (num_bytes_read > 0) {
FILE *fp;
fopen_s(&fp, "C:\\ntdsa_new.dll", "w");
SIZE_T bytes_written = 0;
while (bytes_written < num_bytes_read) {
bytes_written += fwrite(buf, 1, num_bytes_read, fp);
}
fclose(fp);
cout << "Wrote " << bytes_written << " bytes." << endl;
}
CloseHandle(h_lsass);
free(buf);
return 0;
}

Code works as described minus my amateur mistake of sending the address of the variable I was using to store the address of the location in virtual memory of the target application. In above code, changed:
if (ReadProcessMemory(h_lsass, &start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
to
if (ReadProcessMemory(h_lsass, start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
Works like a charm. Thank you ssbssa for pointing out mistake, sorry for wasting anyone's time.

Related

Trying to null a string on explorer.exe but it cant read the memory [duplicate]

I know that there are other people that have asked this question but it seems as though none of them reached a satisfying or understandable conclusion. I can't use what isn't answered. I am not quite sure what the problem is and I have tried various different solutions with no success so here is my code:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);
if(hProc == NULL)
{
cout << "Error: " << GetLastError() << endl;
}
HANDLE token;
OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token);
void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(baseAddr == NULL)
{
cout << "VirtualAllocEx has failed" << endl;
}
else
{
cout << "Base Address: " << baseAddr << "\n" << endl;
}
DWORD prevProt;
if(VirtualProtectEx(hProc, &baseAddr, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &prevProt) == 0)
{
if(GetLastError() == 87)
{
cout << "ERROR_INVALID_PARAMETER\n" << endl;
}
else if(GetLastError() == 487)
{
cout << "ERROR_INVALID_ADDRESS\n" << endl;
}
}
void *buffer;
if(ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(SIZE_T), NULL) == 0)
{
if(GetLastError() == 299)
{
cout << "ERROR_PARTIAL_COPY" << endl;
}
}
}
Any contribution and knowledge you can offer is deeply appreciated! :)
I see some issues with your code.
Bad error handling. If an error happens, you log it, but keep going forward with bad data. If an error happens, STOP. And you are misusing GetLastError().
You are passing the wrong base addess to VirtualProtectEx(). &baseAddr neds to be baseAddr instead. Also, you are allocating and protecting the memory with EXECUTE permissions, which you should not be using unless you intend to store executable code in the memory (which this code is not doing).
You are using sizeof(DWORD) to set protection flags on the remote memory, but you are using sizeof(SIZE_T) to read the memory. DWORD is a fixed 32 bits in size, but SIZE_T is 32 or 64 bits, depending on the platform you are compiling for. Change SIZE_T to DWORD to match the rest of your code.
You are not allocating any memory in the calling process for ReadProcessMemory() to write to. Change void *buffer; to DWORD buffer;.
Try this:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD dwError;
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);
if (hProc == NULL)
{
dwError = GetLastError();
cout << "OpenProcess has failed. Error: " << dwError << endl;
return 0;
}
HANDLE token;
if (!OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token))
{
dwError = GetLastError();
cout << "OpenProcessToken has failed. Error: " << dwError << endl;
return 0;
}
void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_READWRITE);
if (baseAddr == NULL)
{
dwError = GetLastError();
cout << "VirtualAllocEx has failed. Error: " << dwError << endl;
return 0;
}
cout << "Base Address: " << baseAddr << endl;
DWORD prevProt;
if (!VirtualProtectEx(hProc, baseAddr, sizeof(DWORD), PAGE_READWRITE, &prevProt))
{
dwError = GetLastError();
cout << "VirtualAllocEx has failed. Error: ";
if (dwError == ERROR_INVALID_PARAMETER)
{
cout << "ERROR_INVALID_PARAMETER";
}
else if (dwError == ERROR_INVALID_ADDRESS)
{
cout << "ERROR_INVALID_ADDRESS";
}
else
{
cout << dwError;
}
cout << endl;
return 0;
}
DWORD buffer;
if (ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(DWORD), NULL))
{
dwError = GetLastError();
cout << "ReadProcessMemory has failed. Error: ";
if (dwError == ERROR_PARTIAL_COPY)
{
cout << "ERROR_PARTIAL_COPY";
}
else
{
cout << dwError;
}
cout << endl;
return 0;
}
cout << "Value: " << buffer << endl;
return 0;
}
Some more issues:
You are reserving memory in the remote process, but you are not committing physical storage for that memory, and you are not writing anything into the memory before reading from it. Reading reserved uncommitted memory is not very useful, and is the likely culprit of your error:
https://stackoverflow.com/a/4457745/65863
ReadProcessMemory would return FALSE and GetLastError would return ERROR_PARTIAL_COPY when the copy hits a page fault.
Working Set
When a process references pageable memory that is not currently in its working set, a page fault occurs.
You are not using the token returned by OpenProcessToken(), so that call is useless.
You are protecting the remote memory with VirtualProtectEx() using the same protection flags you specified when allocating the memory. So this call is useless, too.
The expression &buffer is wrong - ReadProcessMemory won't allocate buffer for you, it will write on the buffer you provide. You need to allocate memory, and pass that buffer to ReadProcessMemory. Possible approach:
void *buffer = new BYTE[512];
ReadProcessMemory(hProc, baseAddr, buffer, sizeof(SIZE_T), NULL);

WriteProcessMemory not working for some reason

This is all the source code for a program i'm trying to make, and I can't get WriteProcessMemory to work at all. It returns the correct messages, saying that everything went successfully, but nothing actually changes in the game. Does anyone know of a fix?
#include <iostream>
#include <Windows.h>
using namespace std;
// variables
int plcHold = 1;
string hlthLoop = "OFF";
string ammoLoop = "OFF";
DWORD pid;
DWORD playerAddr;
DWORD hlthOffs = 0xF8;
// main function
int main()
{
// finding pid, opening proc, finding player address
HWND hwnd = FindWindowA(NULL, "AssaultCube");
if(hwnd == NULL)
{
cout << "Error; Couldn't find window" << endl;
} else{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(pHandle == NULL)
{
cout << "Error; Couldn't open process" << endl;
} else{
ReadProcessMemory(pHandle, (LPCVOID)0x50F4F4, &playerAddr, sizeof(playerAddr), 0);
if(ReadProcessMemory != FALSE)
{
cout << "Health successfully read!" << endl;
} else{
cout << "Error code " << GetLastError << endl;
}
}
while(plcHold == 1){
cout << "========== *****'s Assault Cube Trainer ==========\n" << endl;
cout << "=============== Health Loop - " << hlthLoop << " ================" << endl;
Sleep(1500);
system("cls");
if(GetAsyncKeyState(0x5A))
{
cout << "Health successfully edited!" << endl;
WriteProcessMemory(pHandle, LPVOID(playerAddr + hlthOffs), 0, sizeof(999), 0);
CloseHandle(pHandle);
}
}
}
return 0;
}
You're passing a null pointer to WriteProcessMemory for the third (lpBuffer) parameter. You have to pass the address of the actual value, not the value itself. If you want to write an integer value, try this:
DWORD val = 0; // or 999?
WriteProcessMemory(
pHandle, static_cast<LPVOID>(playerAddr + hlthOffs),
&val, sizeof(val), 0);

Decode Registry Value stored in HKCU\...\Lock Screen\SlideshowDirectoryPath1

I am having trouble to decode the SlideshowDirectoryPath1 in my local Windows 10 computer by C++ program. I read this link:
"https://social.msdn.microsoft.com/Forums/en-US/edc2e1de-c7c6-4bef-becb-cf4924165551/decode-encrypted-path-from-slideshowdirectorypath1?forum=windowsgeneraldevelopmentissues"
It seems that the value is Base64 encoded. So I decoded it and then I passed the decoded result to SHGetPathFromIDList. After I successfully decoded the value (see my attached test program), the code failed in the call "SHGetPathFromIDList". The program always prints "Error when converting the path". And I have no clue on what was going wrong. I have tried my program in more than one computer.
Anyone could shed me some lights?
// ConsoleApplication1.cpp : Defines the entry point for the console
// application.
//
#include "stdafx.h"
#include <Shlobj.h>
#include <WinCrypt.h>
#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
#include <sstream>
#include <vector>
#include <windows.h>
using namespace std;
int main() {
cout << "Testing" << endl;
CRegKey regKey;
LSTATUS status;
TCHAR path[2000] = _T("");
ULONG size = 2000;
if (ERROR_SUCCESS !=
(status = regKey.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Wi")
_T("ndows\\CurrentVersion\\")
_T("Lock Screen"))) ||
ERROR_SUCCESS != (status = regKey.QueryStringValue(
_T("SlideshowDirectoryPath1"),
reinterpret_cast<LPTSTR>(path), &size))) {
regKey.Close();
cerr << "Error in getting registry SlideshowDirectoryPath1, " << status
<< endl;
return 1;
}
cout << size << endl;
wcout << path << endl;
DWORD outSize;
status = CryptStringToBinary(path, _tcslen(path), CRYPT_STRING_BASE64, NULL,
&outSize, NULL, NULL);
if (status == 0) {
DWORD dw = GetLastError();
cerr << "Error in converting base 64 step 1, " << dw << endl;
return 1;
}
ITEMIDLIST item;
status = CryptStringToBinary(path, _tcslen(path), CRYPT_STRING_BASE64,
(BYTE *)&item, &outSize, NULL, NULL);
if (status == 0) {
DWORD dw = GetLastError();
cerr << "Error in converting base 64 step 2, " << dw << endl;
return 1;
}
cout << "Getting Path value, input size:" << outSize << endl;
TCHAR *result = new TCHAR[MAX_PATH];
if (!SHGetPathFromIDList(&item, result)) {
cerr << "Error when converting the path" << endl;
return 1;
}
wcout << result << endl;
regKey.Close();
delete result;
return 0;
}

ReadProcessMemory error 299 after checking page rights + page backing [duplicate]

I know that there are other people that have asked this question but it seems as though none of them reached a satisfying or understandable conclusion. I can't use what isn't answered. I am not quite sure what the problem is and I have tried various different solutions with no success so here is my code:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);
if(hProc == NULL)
{
cout << "Error: " << GetLastError() << endl;
}
HANDLE token;
OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token);
void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(baseAddr == NULL)
{
cout << "VirtualAllocEx has failed" << endl;
}
else
{
cout << "Base Address: " << baseAddr << "\n" << endl;
}
DWORD prevProt;
if(VirtualProtectEx(hProc, &baseAddr, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &prevProt) == 0)
{
if(GetLastError() == 87)
{
cout << "ERROR_INVALID_PARAMETER\n" << endl;
}
else if(GetLastError() == 487)
{
cout << "ERROR_INVALID_ADDRESS\n" << endl;
}
}
void *buffer;
if(ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(SIZE_T), NULL) == 0)
{
if(GetLastError() == 299)
{
cout << "ERROR_PARTIAL_COPY" << endl;
}
}
}
Any contribution and knowledge you can offer is deeply appreciated! :)
I see some issues with your code.
Bad error handling. If an error happens, you log it, but keep going forward with bad data. If an error happens, STOP. And you are misusing GetLastError().
You are passing the wrong base addess to VirtualProtectEx(). &baseAddr neds to be baseAddr instead. Also, you are allocating and protecting the memory with EXECUTE permissions, which you should not be using unless you intend to store executable code in the memory (which this code is not doing).
You are using sizeof(DWORD) to set protection flags on the remote memory, but you are using sizeof(SIZE_T) to read the memory. DWORD is a fixed 32 bits in size, but SIZE_T is 32 or 64 bits, depending on the platform you are compiling for. Change SIZE_T to DWORD to match the rest of your code.
You are not allocating any memory in the calling process for ReadProcessMemory() to write to. Change void *buffer; to DWORD buffer;.
Try this:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD dwError;
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);
if (hProc == NULL)
{
dwError = GetLastError();
cout << "OpenProcess has failed. Error: " << dwError << endl;
return 0;
}
HANDLE token;
if (!OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token))
{
dwError = GetLastError();
cout << "OpenProcessToken has failed. Error: " << dwError << endl;
return 0;
}
void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_READWRITE);
if (baseAddr == NULL)
{
dwError = GetLastError();
cout << "VirtualAllocEx has failed. Error: " << dwError << endl;
return 0;
}
cout << "Base Address: " << baseAddr << endl;
DWORD prevProt;
if (!VirtualProtectEx(hProc, baseAddr, sizeof(DWORD), PAGE_READWRITE, &prevProt))
{
dwError = GetLastError();
cout << "VirtualAllocEx has failed. Error: ";
if (dwError == ERROR_INVALID_PARAMETER)
{
cout << "ERROR_INVALID_PARAMETER";
}
else if (dwError == ERROR_INVALID_ADDRESS)
{
cout << "ERROR_INVALID_ADDRESS";
}
else
{
cout << dwError;
}
cout << endl;
return 0;
}
DWORD buffer;
if (ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(DWORD), NULL))
{
dwError = GetLastError();
cout << "ReadProcessMemory has failed. Error: ";
if (dwError == ERROR_PARTIAL_COPY)
{
cout << "ERROR_PARTIAL_COPY";
}
else
{
cout << dwError;
}
cout << endl;
return 0;
}
cout << "Value: " << buffer << endl;
return 0;
}
Some more issues:
You are reserving memory in the remote process, but you are not committing physical storage for that memory, and you are not writing anything into the memory before reading from it. Reading reserved uncommitted memory is not very useful, and is the likely culprit of your error:
https://stackoverflow.com/a/4457745/65863
ReadProcessMemory would return FALSE and GetLastError would return ERROR_PARTIAL_COPY when the copy hits a page fault.
Working Set
When a process references pageable memory that is not currently in its working set, a page fault occurs.
You are not using the token returned by OpenProcessToken(), so that call is useless.
You are protecting the remote memory with VirtualProtectEx() using the same protection flags you specified when allocating the memory. So this call is useless, too.
The expression &buffer is wrong - ReadProcessMemory won't allocate buffer for you, it will write on the buffer you provide. You need to allocate memory, and pass that buffer to ReadProcessMemory. Possible approach:
void *buffer = new BYTE[512];
ReadProcessMemory(hProc, baseAddr, buffer, sizeof(SIZE_T), NULL);

WriteProcessMemory returns 0 in C++

I am developing a small cash hack for GTA V and I found that when I use
WriteProcessMemory(hp, (LPVOID)0x1417C4C18, &cashVal, (DWORD)sizeof(cashVal), 0)
that the WriteProcessMemory returns 0. Here is the full source code of my small hack.
#include <Windows.h>
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int cashVal = 0;
cout << "Enter the amount of cash you want: " << endl;
cin >> cashVal;
HWND hwnd = FindWindow(0, "Grand Theft Auto V");
if (hwnd == 0) {
cout << "Cannot find the GTAV window. Make sure its running in Windowed mode!" << endl;
}
else {
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!hp) {
cout << "Could not get a handle to GTAV. Try again :(" << endl;
}
else {
int success = WriteProcessMemory(hp, (LPVOID)0x1417C4C18, &cashVal, (DWORD)sizeof
(cashVal), 0);
if (success > 0) {
cout << "You now have " << cashVal << " money!" << endl;
}
else {
cout << "Writing the memory failed!" << endl;
cout << "Error code: " << success << endl;
}
CloseHandle(hp);
}
}
cin.get();
return 0;
}
I basically ask the user to input the cash they want, and it's meant to set it in the game, but it returns a code of 0 and fails. It doesn't fail trying to find the game window because it doesn't print that message to the standard output. Please help me!
NOTE: The hack will be used on single player
First, don't use PROCESS_ALL_ACCESS. Only request what you actually need. WriteProcessMemory() only needs PROCESS_VM_WRITE and PROCESS_VM_OPERATION access, so request only that.
Like many other API functions, when WriteProcessMemory() fails, GetLastError() will tell you why. Your code is assuming that WriteProcessMemory() itself returns an error code directly, but it does not. It returns a BOOL (not an int) to indicate success or failure, and then GetLastError() returns the error code if failure. This is documented behavior:
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is 0 (zero). To get extended error information, call GetLastError. The function fails if the requested write operation crosses into an area of the process that is inaccessible.
Try this:
#include <windows.h>
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int cashVal = 0;
cout << "Enter the amount of cash you want: " << endl;
cin >> cashVal;
HWND hwnd = FindWindow(0, "Grand Theft Auto V");
if (hwnd == 0) {
cout << "Cannot find the GTAV window. Make sure its running in Windowed mode!" << endl;
}
else {
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
HANDLE hp = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);
if (!hp) {
cout << "Could not get a handle to GTAV. Try again :(" << endl;
}
else {
BOOL success = WriteProcessMemory(hp, (LPVOID)0x1417C4C18, &cashVal, sizeof(cashVal), 0);
if (success) {
cout << "You now have " << cashVal << " money!" << endl;
}
else {
DWORD errCode = GetLastError();
cout << "Writing the memory failed!" << endl;
cout << "Error code: " << errCode << endl;
}
CloseHandle(hp);
}
}
cin.get();
return 0;
}
You are most likely trying to write to a memory path where you don't have access to... probably you are using a 32-bit program to write to a 64-bit memory address(that's if u use a 64-bit computer), I think I had this problem a few years back porting solved my problem then forgive me if I am wrong atleast that was what I thought.
Try the code on a 32-bit address and if it works... that solves your problem.
And for the Getting_Last_Error you can add this lil' bit of functionality I use.
void PrintLastErrorMsg(){
LPTSTR pTmp = NULL;
DWORD errnum = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
errnum,
LANG_NEUTRAL,
(LPTSTR)&pTmp,
0,
NULL
);
cout << "Error(" << errnum << "): " << pTmp << endl;
}
Be free to make changes.