Jump to content
dummzeuch

IOTAProcess.ReadProcessMemory / .WriteProcessMemory

Recommended Posts

The ToolsApi unit declares the IOTAProcess interface as follows:

  IOTAProcess = interface(IOTAProcess150)
    ['{FBECB2A2-80BF-400D-B4A6-0BCEABC2FF7D}']
    { Read the process memory at the given address }
    function ReadProcessMemory(Address: TOTAAddress; Count: Integer; var Buffer): Integer; overload;
    { Write to the process memory at the given address }
    function WriteProcessMemory(Address: TOTAAddress; Count: Integer; var Buffer): Integer; overload;

Unfortunately it does not say what the function results mean, and I haven't seen any code that checks that result.

My assumption from the values I have seen is that these functions return the number of bytes read / written, but is that true? Is it documented anywhere?

Share this post


Link to post
2 hours ago, dummzeuch said:

and I haven't seen any code that checks that result.

ReadProcessMemory does an internal check at the end of the operation. If it fails an exception is thrown then.

Quote

 My assumption from the values I have seen is that these functions return the number of bytes read / written, but is that true? 

On the right road 🙂 

Quote

Is it documented anywhere?

No idea but I doubt if it was ... I mean ToolsApi documentation is very poor :classic_sad: 

  • Like 1

Share this post


Link to post
5 hours ago, dummzeuch said:

My assumption from the values I have seen is that these functions return the number of bytes read / written, but is that true?

That would be my assumption as well, since the underlying Win32 API (Read|Write)ProcessMemory() functions return the number of bytes actually read/written.

Share this post


Link to post
27 minutes ago, Remy Lebeau said:

That would be my assumption as well, since the underlying Win32 API (Read|Write)ProcessMemory() functions return the number of bytes actually read/written.

The WinApi functions return a BOOL, not a number. They have an additional parameter for that:

BOOL ReadProcessMemory(
  HANDLE  hProcess,
  LPCVOID lpBaseAddress,
  LPVOID  lpBuffer,
  SIZE_T  nSize,
  SIZE_T  *lpNumberOfBytesRead
);

 

Share this post


Link to post

That's called returning a value through a parameter. If you look at this function, what else could these integer return values hold? 

Share this post


Link to post
7 minutes ago, David Heffernan said:

what else could these integer return values hold? 

HRESULT. In fact ReadProcessMemory calls an internal function that returns a HRESULT and then checks the value and returns the bytes count.

# ReadProcessMemory:
# ...
203BF56E            | 8B45 E8                 | mov eax,dword ptr ss:[ebp-18]                                                                                                                     
203BF571            | 50                      | push eax                                                                                                                                          
203BF572            | 8B00                    | mov eax,dword ptr ds:[eax]                                                                                                                        
203BF574            | FF50 40                 | call dword ptr ds:[eax+40]    # InternalReadProcessMemoryFunction that reads the bytes and returns a HRESULT                                                 
203BF577            | E8 7096FAFF             | call <dbkdebugide260.@Dbkhelper@CheckRetVal$qqrxl>   # check HRESULT    
# ...
203BF599            | 8B45 FC                 | mov eax,dword ptr ss:[ebp-4]  # result = bytes count                                                                                                         

 

Share this post


Link to post
3 hours ago, dummzeuch said:

The WinApi functions return a BOOL, not a number. They have an additional parameter for that

That parameter is what I was referring to.

Edited by Remy Lebeau

Share this post


Link to post
3 hours ago, Mahdi Safsafi said:

HRESULT. In fact ReadProcessMemory calls an internal function that returns a HRESULT and then checks the value and returns the bytes count.


# ReadProcessMemory:
# ...
203BF56E            | 8B45 E8                 | mov eax,dword ptr ss:[ebp-18]                                                                                                                     
203BF571            | 50                      | push eax                                                                                                                                          
203BF572            | 8B00                    | mov eax,dword ptr ds:[eax]                                                                                                                        
203BF574            | FF50 40                 | call dword ptr ds:[eax+40]    # InternalReadProcessMemoryFunction that reads the bytes and returns a HRESULT                                                 
203BF577            | E8 7096FAFF             | call <dbkdebugide260.@Dbkhelper@CheckRetVal$qqrxl>   # check HRESULT    
# ...
203BF599            | 8B45 FC                 | mov eax,dword ptr ss:[ebp-4]  # result = bytes count                                                                                                         

 

Seems unlikely. The winapi functions return a BOOL and call SetLastError. HRESULT seems very implausible. 

Share this post


Link to post
38 minutes ago, David Heffernan said:

Seems unlikely. The winapi functions return a BOOL and call SetLastError. HRESULT seems very implausible. 

No ! I'm 100% sure that the internal function returns HRESULT and IOTAProcess.ReadProcessMemory returns bytes count. 

Edited by Mahdi Safsafi

Share this post


Link to post
Guest

It is internal, means not the OS API, as shown here there is six calls up to the OS call

 

image.thumb.png.a0caf1acbbaca51df491a3040d46fe66.png

But one can only assume it does have the same parameters, because they have the same count and the same order, 

 

image.thumb.png.eab0b0abcdbadd4a3bc0c9ee4fde078f.png

 

I just tested it, but the strange thing is, i issued read for 100 bytes the monitor shows the actual API read 1024 byte instead and return 100 byte as result, after than my XE5 just keep crashing !

Share this post


Link to post

@Kas Ob. 

Quote

It is internal, means not the OS API, as shown here there is six calls up to the OS call

Yes that's what I meant.

Quote

I just tested it, but the strange thing is, i issued read for 100 bytes the monitor shows the actual API read 1024 byte instead and return 100 byte as result, after than my XE5 just keep crashing !

 

Good remark ! I made a test that asked for 100 byte and as you told exactly it reads 1024 bytes ! Asked for 4096 bytes and it reads 4096 bytes ... so I guess its doing that to cache the data because some IOTAProcess.ReadProcessMemory calls for small amount didn't pass all the time throw WinApi.ReadProcessMemory (fetched from the cache).
The weird thing for me is the crashing you got.

Share this post


Link to post
Guest

The crash is most likely from other experts and libraries i installed and played with, that XE5 is my lab mouse, i was and still building a CPU registers viewer, and went little further to get the LastError and LastStatusError form the debugged thread, this can be useful, even found where the constants names for them are included in the OS ( just like the x64dbg errordb.txt and ntstatusdb.txt), but still not finished as i work on it when got time and in the mood, these test project are still running on the IDE and they all using the debugger.

 

 

 

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×