SolvedWriteProcessMemory on an Android VM

Posts 1–15 of 25 · Page 1 of 2
WriteProcessMemory on an Android VM
Hello,
I recently posted a thread on my string scanner, but figured out the problem (sorry).
It seemed like my program wasn't finding values on an Android VM (Andy), but after some testing: it is working fine.

My problem is that WriteProcessMemory isn't working on the virtual Android program, which is strange.
Cheat Engine can change the exact same values I'm trying to change - no problem.

I tried an infinite loop of changing all found values constantly, but it just isn't working. Also tried running as administrator.

WriteProcessMemory works on other applications, but not this one apparently.
Code:
void changeDoubles(double fromDouble, double toDouble, vector<int> addresses) {
    double changeVal = toDouble;
    for (int x = 0; x < addresses.size(); x++) {
        double getVal;
        int g2g = ReadProcessMemory(phandle,(void*)addresses[x],&getVal,8,0);
        if (g2g != 0) {
            if (getVal == fromDouble) {
                cout << "Changed: " << hex << addresses[x] << endl;
                WriteProcessMemory(phandle,(void*)addresses[x],&changeVal,sizeof(changeVal),0);
            }
        }
    }
}
Outputs "Changed: __" for all found addresses correctly. No changes in the actual values, though.
Did you maybe OpenProcess(READ_ONLY) ?
Check the return value of Wpm(), and maybe even check GetLastError.

I went to check your code in the other post, but you erased it.

edit: msdn for writeprocessmemory: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
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.

...

Remarks

WriteProcessMemory copies the data from the specified buffer in the current process to the address range of the specified process. Any process that has a handle with PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process to be written to can call the function.
Code:
if (WriteProcessMemory(phandle,(void*)addresses[x],&changeVal,sizeof(changeVal),0))
{
 cout << "Write: " << hex << addresses[x] << " OK" << endl;
}
else
{
 cout << "Write: " << hex << addresses[x] << " ERROR" << endl;
}
Quote Originally Posted by abuckau907 View Post
Did you maybe OpenProcess(READ_ONLY) ?
Check the return value of Wpm(), and maybe even check GetLastError.

I went to check your code in the other post, but you erased it.

edit: msdn for writeprocessmemory: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx


Code:
if (WriteProcessMemory(phandle,(void*)addresses[x],&changeVal,sizeof(changeVal),0))
{
 cout << "Write: " << hex << addresses[x] << " OK" << endl;
}
else
{
 cout << "Write: " << hex << addresses[x] << " ERROR" << endl;
}
You were right.
I was doing
Code:
phandle = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, false, pid);
Adding PROCESS_VM_WRITE makes it so OpenProcess fails.
Calling GetLastError returns 5.
If I remove the write access, the program works again but cannot change values.

Suggestions to do at this point?

- - - Updated - - -

Ah gotcha..
Needed to give administrative rights.

Should be working fine now, as it is beginning to scan in admin mode.
Will update this if I have any other troubles.

Thank you!!

- - - Updated - - -

I was apparently too quick to judge.
No values changed, and I added PROCESS_VM_WRITE and PROCESS_ALL_ACCESS.
It still finds all the values it should, though.
msdn for WriteProcessMemory: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
WriteProcessMemory copies the data from the specified buffer in the current process to the address range of the specified process. Any process that has a handle with PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process to be written to can call the function.
"Any process that has a handle with process_vm_write AND process_vm_operation ...can call this function"

Code:
	HANDLE pH = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE,false,targetPID);
 
full test code

Code:
#include <Windows.h>
#include <iostream>


using namespace std;

int main()
{
	cout << "test" << endl;

	HANDLE pH = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE,false,4728);

	if (pH)
	{
		cout <<"OpenProcess() OK!" << endl;
		int newHealth = 420;
		if (WriteProcessMemory(pH,(void*)0x0014A000,&newHealth,4,0))
		{
			cout <<"WPM() OK" << endl;
		}
		else
		{
			cout <<"WPM() FAIL" << endl;
		}
	}
	else
	{
		cout <<"OpenProcess() Failed :(" << endl;
	}

	system("pause");
}
excuse the hardcoded numbers, but you get the gist.



edit: since you want to read also,
Code:
HANDLE pH = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,false,targetPID);
Quote Originally Posted by abuckau907 View Post
msdn for WriteProcessMemory: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx

"Any process that has a handle with process_vm_write AND process_vm_operation ...can call this function"

Code:
	HANDLE pH = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE,false,targetPID);
 
full test code

Code:
#include <Windows.h>
#include <iostream>


using namespace std;

int main()
{
	cout << "test" << endl;

	HANDLE pH = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE,false,4728);

	if (pH)
	{
		cout <<"OpenProcess() OK!" << endl;
		int newHealth = 420;
		if (WriteProcessMemory(pH,(void*)0x0014A000,&newHealth,4,0))
		{
			cout <<"WPM() OK" << endl;
		}
		else
		{
			cout <<"WPM() FAIL" << endl;
		}
	}
	else
	{
		cout <<"OpenProcess() Failed :(" << endl;
	}

	system("pause");
}
excuse the hardcoded numbers, but you get the gist.



edit: since you want to read also,
Code:
HANDLE pH = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,false,targetPID);
Thanks for your help!
But that still didn't work.
Same results: found addresses, didn't change values.
Calling GetLastError after WriteProcessMemory fails, I am still returned with 5 - Access Denied.
Run Visual Studio as Admin.
(you mentioned 'giving it admin rights', I figured u were doing this already.?)

If you have an icon on the task bar -- right click on the icon and then right click on "Microsoft Visual Studio [your version]", then left click on "Run as administrator."
Else, right click on the shortcut/actual program and "Run as administrator"

edit: please post relevant code -- I basically know what you have, but post it anyway..
I'm using Code::Blocks, but still no change.
Here's my code for changing all found addresses, since it's the only relevant piece.
Code:
double sResult;
   for (int xy = 0; xy < searchResults[curResult].size(); xy++) {
      if (ReadProcessMemory(phandle,(void*)search_results[cur_result][xy],&sResult,8,0) != 0) {
         if (sResult==double_val) {
            if (WriteProcessMemory(phandle,(void*)searchResults[curResult][xy],&double_ans,8,0)) {
                //Don't do anything here
             } else {
                cout << GetLastError() << endl;
             }
          }
      }
}
Scanning for addresses is working for fine, changing the values of those addresses is not working on the VM.
Changing the values of the addresses on other programs that aren't a VM is working fine, so I don't understand.
"since it's the only relevant piece."
..also the call to OpenProcess() is important.

Last thing I can think of (should have been the first..): maybe the memory isn't writable.

https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx

PAGE_EXECUTE
0x10

Enables execute access to the committed region of pages. An attempt to write to the committed region results in an access violation.

This flag is not supported by the CreateFileMapping function.

PAGE_EXECUTE_READ
0x20

Enables execute or read-only access to the committed region of pages. An attempt to write to the committed region results in an access violation.

Windows Server 2003 and Windows XP: This attribute is not supported by the CreateFileMapping function until Windows XP with SP2 and Windows Server 2003 with SP1.

PAGE_EXECUTE_READWRITE
0x40

Enables execute, read-only, or read/write access to the committed region of pages.

Windows Server 2003 and Windows XP: This attribute is not supported by the CreateFileMapping function until Windows XP with SP2 and Windows Server 2003 with SP1.

PAGE_EXECUTE_WRITECOPY
0x80

Enables execute, read-only, or copy-on-write access to a mapped view of a file mapping object. An attempt to write to a committed copy-on-write page results in a private copy of the page being made for the process. The private page is marked as PAGE_EXECUTE_READWRITE, and the change is written to the new page.

This flag is not supported by the VirtualAlloc or VirtualAllocEx functions.

Windows Vista, Windows Server 2003, and Windows XP: This attribute is not supported by the CreateFileMapping function until Windows Vista with SP1 and Windows Server 2008.

PAGE_NOACCESS
0x01

Disables all access to the committed region of pages. An attempt to read from, write to, or execute the committed region results in an access violation.

This flag is not supported by the CreateFileMapping function.

PAGE_READONLY
0x02

Enables read-only access to the committed region of pages. An attempt to write to the committed region results in an access violation. If Data Execution Prevention is enabled, an attempt to execute code in the committed region results in an access violation.

PAGE_READWRITE
0x04

Enables read-only or read/write access to the committed region of pages. If Data Execution Prevention is enabled, attempting to execute code in the committed region results in an access violation.

PAGE_WRITECOPY
0x08

Enables read-only or copy-on-write access to a mapped view of a file mapping object. An attempt to write to a committed copy-on-write page results in a private copy of the page being made for the process. The private page is marked as PAGE_READWRITE, and the change is written to the new page. If Data Execution Prevention is enabled, attempting to execute code in the committed region results in an access violation.

Use VirtualQueryEx() to check if it's writable or not --> if not, use VirtualProtectEx() to modify it (and optionally (?), when finished, to restore original protection).
msdn for VirtualQueryEx: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
msdn for VirtualProtectEx: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx

tip: if the memory was originally executable, and you change the protection, make sure the new protection is also executable or you run the risk of getting an access error as described above (and likely a crash). ie. use EXEC_READ_WRITE and you should be ok. But then again, if you're changing .code, you'll likely cause a crash anyway
If it wasn't executable, PAGE_READWRITE should work.
Quote Originally Posted by abuckau907 View Post
"since it's the only relevant piece."
..also the call to OpenProcess() is important.

Last thing I can think of (should have been the first..): maybe the memory isn't writable.

https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx



Use VirtualQueryEx() to check if it's writable or not --> if not, use VirtualProtectEx() to modify it (and optionally (?), when finished, to restore original protection).
msdn for VirtualQueryEx: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
msdn for VirtualProtectEx: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx

tip: if the memory was originally executable, and you change the protection, make sure the new protection is also executable or you run the risk of getting an access error as described above (and likely a crash). ie. use EXEC_READ_WRITE and you should be ok. But then again, if you're changing .code, you'll likely cause a crash anyway
If it wasn't executable, PAGE_READWRITE should work.
I tried looking how to check if a single hex value is writable (I.E if 0x10023000's value can be changed) and found nothing online.
I then tried
Code:
phandle = OpenProcess(PAGE_EXECUTE_READWRITE | PAGE_READWRITE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, pid);
(with a mixture of without PAGE_EXEC_RW or without PAGE_RW, etc.) which had no change in results.

As for write access, Cheat Engine can change the values no problem, so I don't see why I'm not able to.

- - - Updated - - -

Also, my scanning isn't done with VirtualQueryEx, and I don't want it to use that (simply because I searched for days, hours at a time, trying to figure out how to do double scans and string scans, to no avail).
I'm doing a modified version of the code from this link:
http://www.cplusplus.com/forumdows/19725/
PAGE_**** constants are not used in the call to OpenProcess() ...no idea why you tried that. Did you read the msdn for OpenProcess? It clearly says which constants to use. If you're just trying random things, that's never going to work..

You don't have to use VirtualQueryEx() in your scanning code (why are we even talking about this? You said it works; leave it at that), but if you're getting "access denied" when calling writeprocessmemory() then it would seem the memory region ISN'T writable, and you should use virtualqueryex() to check. CE is almost certainly using VirtualQueryEx (and if needed, VirtualProtectEx) before performing a write.

Look for an example of how to use VirtualQueryEx() I guess. Sorry, my spoon isn't that big; you have everything you need.

edit: basically looks like
Code:
MEMORY_BASIC_INFORMATION mBI;

VirtualQueryEx(pHandle, (void*)0x11223344, &mBI, sizeof(MEMORY_BASIC_INFORMATION));
		
if ((mBI.State == MEM_COMMIT) && (mBI.Type == MEM_PRIVATE) && (mBI.Protect == PAGE_READWRITE)) // we care about .protect

// if (not_writable)
// VirtualProtectEx(make_it_writable)
//
// perform write
//
// if changed .protect, change it back to original value
Quote Originally Posted by abuckau907 View Post
PAGE_**** constants are not used in the call to OpenProcess() ...no idea why you tried that. Did you read the msdn for OpenProcess? It clearly says which constants to use. If you're just trying random things, that's never going to work..

You don't have to use VirtualQueryEx() in your scanning code (why are we even talking about this? You said it works; leave it at that), but if you're getting "access denied" when calling writeprocessmemory() then it would seem the memory region ISN'T writable, and you should use virtualqueryex() to check. CE is almost certainly using VirtualQueryEx (and if needed, VirtualProtectEx) before performing a write.

Look for an example of how to use VirtualQueryEx() I guess. Sorry, my spoon isn't that big; you have everything you need.

edit: basically looks like
Code:
MEMORY_BASIC_INFORMATION mBI;

VirtualQueryEx(pHandle, (void*)0x11223344, &mBI, sizeof(MEMORY_BASIC_INFORMATION));
		
if ((mBI.State == MEM_COMMIT) && (mBI.Type == MEM_PRIVATE) && (mBI.Protect == PAGE_READWRITE)) // we care about .protect

// if (not_writable)
// VirtualProtectEx(make_it_writable)
//
// perform write
//
// if changed .protect, change it back to original value
Thanks!
Here's what I tried:
Code:
MEMORY_BASIC_INFORMATION mBI;
DWORD OLDPROTECT;
double sResult;
for (int xy = 0; xy < search_results[cur_result].size(); xy++) {
   if (ReadProcessMemory(phandle,(void*)search_results[cur_result][xy],&sResult,8,0) != 0) {
      if (sResult==double_val) {
         VirtualQueryEx(phandle, (void*)search_results[cur_result][xy], &mBI, sizeof(MEMORY_BASIC_INFORMATION));
         //if ((mBI.State == MEM_COMMIT) && (mBI.Type == MEM_PRIVATE) && (mBI.Protect == PAGE_READWRITE)) {
            bool isWritable=(mBI.Protect == PAGE_READWRITE || mBI.Protect == PAGE_WRITECOPY || mBI.Protect == PAGE_EXECUTE_READWRITE || mBI.Protect == PAGE_EXECUTE_WRITECOPY);
            if (!isWritable) {
               VirtualProtectEx(phandle,(void*)search_results[cur_result][xy],8,PAGE_READWRITE,&OLDPROTECT);
               cout << "Wasn't writable, is now!" << endl;
            } else {
               cout << "Was writable!" << endl;
            }
            WriteProcessMemory(phandle,(void*)search_results[cur_result][xy],&double_ans,8,0);
            if (!isWritable) {
               VirtualProtectEx(phandle,(void*)search_results[cur_result][xy],8,OLDPROTECT,&OLDPROTECT);
            }
         //}
      }
   }
}
My output is a bunch of "Wasn't writable, is now!" but the values of the addresses still aren't changing.
That commented out if-statement was not working; wouldn't run the code inside of it.

Thank you so much for your help so far.

Edit:
It seems VirtualProtectEx is returning 0 (failed).
I'm not sure why this may be.
Did you run the IDE as admin? I'm not sure this is necessary, but if you're getting "access denied", it could be.

..also the call to OpenProcess() is important.
^^ see first red text below. I won't ask again for you to post relevant code.

msdn for VirtualProtectEx: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
hProcess [in]
A handle to the process whose memory protection is to be changed. The handle must have the PROCESS_VM_OPERATION access right. For more information, see Process Security and Access Rights.

...

Return value

If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Quote Originally Posted by abuckau907 View Post
Did you run the IDE as admin? I'm not sure this is necessary, but if you're getting "access denied", it could be.


^^ see first red text below. I won't ask again for you to post relevant code.

msdn for VirtualProtectEx: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
Running the IDE as admin made no changes in how the program is running.

Current OpenProcess:
Code:
phandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, pid);
GetLastError() when "Wasn't writable, is now!" returned 5 - Access Denied yet again
Last thing i can think of (i dont use code blocks)-- maybe even though the IDE is being run as admin, maybe the executable isnt (?); try compiling and then manually run the executable as admin.

Edit: silly question, but are both the vm and your program 32/64 bit?
I honestly couldn't tell you what bit they are.

It seems when I add PROCESS_ALL_ACCESS to OpenProcess, my program is now saying "Was writable!" (from the code I posted shortly ago).
Which is strange, because the values still are not changing.

Ran the program itself in Admin Mode - no change
Posts 1–15 of 25 · Page 1 of 2
This thread is closed for replies.

Similar Threads

Tags for this Thread

None

Talk with us