here's a code snippet form a tool I'm writing. it's in C++ but might help.
The concept is to wrap the real ReadProcessMemory and use the new one. The code I wrote in C++ is useful because for classes derived from the one here attached there's nothing to change, and you might write the code as before.
I hope it helps: despite you are programming in ASM the concepts are the same and also the code structure doesn't change that much.
AccessMemory.h
Code:
#include <windows.h>
typedef BOOL (__stdcall *ACCESS_PROCESS_MEMORY_FCN)(HANDLE, LPVOID, LPVOID, DWORD, LPDWORD );
class CAccessMemory
{
public:
CAccessMemory();
virtual ~CAccessMemory();
BOOL ReadProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer,
DWORD nSize, LPDWORD lpNumberOfBytesRead);
BOOL WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer,
DWORD nSize, LPDWORD lpNumberOfBytesWritten);
private:
BOOL _accessProcessMemory(
ACCESS_PROCESS_MEMORY_FCN fcn,
HANDLE hProcess,
LPVOID lpBaseAddress, LPVOID lpBuffer,
DWORD nSize, LPDWORD lpNumberOfBytesWritten);
};
AccessMemory.cpp
Code:
CAccessMemory::CAccessMemory()
{
}
CAccessMemory::~CAccessMemory()
{
}
//A wrapper for the ::ReadProcessMemory which set also the memory
//access right properly
BOOL CAccessMemory::ReadProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer,
DWORD nSize, LPDWORD lpNumberOfBytesRead) {
ACCESS_PROCESS_MEMORY_FCN fcn;
//There's a little difference between the two function pointers or
//::ReadProcessMemory and ::WriteProcessMemory, because the two prototypes are different
//This trick cast the pointer of the function pointer of ::ReadProcessMemory to a
//void* then cast it back to an ACCESS_PROCESS_MEMORY_FCN function pointer.
//The differences between these two prototypes are not important and
//everything works excellently.
fcn=(ACCESS_PROCESS_MEMORY_FCN)((void*)&(::ReadProcessMemory));
return _accessProcessMemory(fcn, hProcess, lpBaseAddress, lpBuffer,
nSize, lpNumberOfBytesRead);
}
//A wrapper for the ::WriteProcessMemory which set also the memory
//access right properly
BOOL CAccessMemory::WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer,
DWORD nSize, LPDWORD lpNumberOfBytesWritten)
{
ACCESS_PROCESS_MEMORY_FCN fcn;
//Assign the function pointer, this time there are no problems,
//because ACCESS_PROCESS_MEMORY_FCN is the prototype of ::WriteProcessMemory
fcn=::WriteProcessMemory;
return _accessProcessMemory(fcn, hProcess, lpBaseAddress, lpBuffer,
nSize, lpNumberOfBytesWritten);
}
//It is used by the WriteProcessMemory and ReadProcessMemory methods.
//It worry to grant access to memory.
BOOL CAccessMemory::_accessProcessMemory(
ACCESS_PROCESS_MEMORY_FCN fcn,
HANDLE hProcess,
LPVOID lpBaseAddress, LPVOID lpBuffer,
DWORD nSize, LPDWORD lpNumberOfBytes)
{
DWORD OldProtection=0;
//It is not really used because the VirtualProtectEx function always requires a valid
//variable to hold the old page protection values, otherwise fails. When restoring the
//protection values of the page, on the existing of this program, the old values are not
//important of course.
DWORD dummyProtection=0;
BOOL bVal=FALSE;
int tries=0;
//Do 3 tries loop, so as not the block forever..
while(tries<3) {
__try {
tries++;
bVal=fcn(hProcess, lpBaseAddress, lpBuffer,nSize, lpNumberOfBytes);
if(!bVal)
//The RaiseException function raises an exception in the calling thread.
RaiseException(1, // exception code
0, // continuable exception (non death exception)
0, NULL); // no arguments
}
__except(TRUE) {
if(IsBadReadPtr(lpBaseAddress, nSize) || IsBadWritePtr(lpBaseAddress, nSize))
VirtualProtectEx(hProcess, lpBaseAddress, nSize,
PAGE_EXECUTE_READWRITE, &OldProtection);
continue;
}
break;
}
//Restore the previous protections of the patched address.
//OlProtection is !=0 if the previous VirtualProtectEx has been done.
if(OldProtection!=0)
VirtualProtectEx(hProcess, lpBaseAddress, nSize,
OldProtection, &dummyProtection);
return bVal;
}