4

I am using method hooking/detour in my library.

What would be the solution for method hooking/detour on OS X since WriteProcessMemory/ReadProcessMemory are Windows API functions?

Edit:

Ok, let me put a bit more information here so it gets clearer why I am asking that question:

In an upcoming feature in my DSharp library I have this code:

procedure FreeInstance(Self: TObject);
begin
  ...

  Self.CleanupInstance;
  FreeMem(Pointer(Self));
end;

var
  FreeInstanceBackup: TXRedirCode;

initialization
  ...
  HookCode(@TObject.FreeInstance, @FreeInstance, FreeInstanceBackup);

finalization
  UnhookCode(@TObject.FreeInstance, FreeInstanceBackup);
  ...

end.

Fact is, I need to hook into the TObject.FreeInstance method to be notified of every object destruction (yes I know, it might not be called if someone decides to override it and does not call inherited).

Another unit that uses the WriteProcessMemory is ReturnTypePatch.pas which fixes QC #98687 which is nessecary for Mocking libraries like mine and Delphi Mocks from Vincent Parrett (he basically had a user reporting that problem before we both were aware of that problem).

Yet another use of WriteProcessMemory is in the AOP part of DSharp where I basically replace the VMT of a class with the proxy class VMT that is created from the TVirtualMethodInterceptor class from the RTTI. With TVirtualMethodInterceptor you can only proxify an existing object - my implementation does that for the whole class (so all existing and future objects, even if inherited).

In all cases the memory cannot be written by using Move because they are protected (getting AV when replacing WriteProcessMemory with a call to CopyMemory).

Hope that was enough information on what I am doing with these functions - and someone can point me to a solution that will work on OS X (unfortunately I don't have one so I cannot test anything).

Community
  • 1
  • 1
Stefan Glienke
  • 20,860
  • 2
  • 48
  • 102
  • Check this out, maybe it helps: http://stackoverflow.com/questions/10668/reading-other-process-memory-in-os-x-bsd – Lars Jun 01 '12 at 18:24
  • 1
    Are you asking for the equivalent API function? Or are you asking how to hook functions? If you say "both," you have an XY problem; don't assume the the solution to X lies in knowing how to do Y. Ask two separate questions if you really think you need to know both. Also, note that the linked hooking code could probably have used plain old `Move` (`memcpy`, for C folks) since it's hooking code in the current process. – Rob Kennedy Jun 01 '12 at 19:48
  • @Rob Well I basically need to know how I can rewrite memory of the running application. Like hooking, rewriting parts of the VMT and such. – Stefan Glienke Jun 01 '12 at 20:19
  • There are three basic ways to rewrite another process's memory: hooking your own code into the process (as Rob says, then you can just memcpy), attaching to the process as a debugger, or using the Mach APIs. Which one makes sense depends on what you're ultimately trying to accomplish—and, if you're porting something from Windows, what you're porting. – abarnert Jun 01 '12 at 20:53
  • I just noticed this is tagged delphi. Long ago, someone created an open source delphi project called something like GameCheatLib (loosely based on a similar Python library I'd written) that wrapped up the code for enumerating processes, attaching to a process, reading/writing its memory, etc. on Mac, Win32, and linux (or maybe any POSIX with complete ptrace?). You may want to google around for it; even if it's long dead, the source ought to be helpful. – abarnert Jun 01 '12 at 22:44
  • I have to check again, but I am pretty sure I could not simply use Move or CopyMemory when hooking or rewriting parts of the VMT. So I had to use the mentioned functions and/or functions like VirtualProtect to avoid AVs. – Stefan Glienke Jun 01 '12 at 22:44
  • Stefan are you tried using the [TVirtualMethodInterceptor](http://docwiki.embarcadero.com/Libraries/en/System.Rtti.TVirtualMethodInterceptor) class? – RRUZ Jun 02 '12 at 01:48
  • @RRUZ Yes I am very used to that class but I don't know how that relates to detouring reoutines or rewriting VMT (which is memory that is protected as far as I know) apart from finding the code of how to create a proxy class at runtime :) – Stefan Glienke Jun 02 '12 at 18:27
  • @StefanGlienke, sorry my recommendation was vague, I mean use`the TVirtualMethodInterceptor` class to catch an specified method and replace the implementation with your own, I know which this is technique is not flexible enough like a detour, but it can be useful in many cases. – RRUZ Jun 03 '12 at 02:47
  • @RRUZ see my edit - that class is not helping in these cases. – Stefan Glienke Jun 03 '12 at 04:22
  • OK, if you were starting from scratch, I would recommend injecting a library into the foreign process and then using normal memory operations. But given the existing code you're starting with, it probably is simpler to use the Mach VM calls. – abarnert Jun 04 '12 at 17:00

1 Answers1

10

The most direct equivalent to WriteProcessMemory/ReadProcessMemory are the Mach calls vm_write/vm_read. Instead of an HPROCESS you need a Mach task (which you can get via task_for_pid), and of course there are lots of little differences.

Since Apple has helpfully removed the manpages for these functions, and not documented them in any of the Xcode docsets, you have to deal with the slightly-out-of-date non-Apple Mach/MK/Gnu-Mach documentation, the header file comments (which are pretty good), and/or third-party articles like http://www.uninformed.org/?v=4&a=3 and http://www.phrack.org/issues.html?issue=66&id=16 (you can probably guess just from the URLs who their target audience is). But it's pretty easy. Porting a "memory cheat tool" from Windows to Mac, you'd spend a lot more time rewriting the GUI than implementing the low-level stuff.

But this may not be the best way to do method hooking. Especially if you're hooking ObjC methods, but even for C APIs. Describe what you want to do in more detail, and I can provide better alternatives.

abarnert
  • 354,177
  • 51
  • 601
  • 671