> that Win32 has already this kind of feature since ages: Process access routines such as OpenProcess() [1] coupled with ReadProcessMemory() [2]
And Unix has had ptrace(2) for a very long time too, which will accomplish the same thing. Also you can read another process's memory through /proc. So there are multiple paths.
Also keep in mind, the most "legit" use case for this stuff is for writing a debugger. If you have used a debugger you are already relying on this functionality being there.
Edit: I am not aware of a win32 equivalent of this thing that lets you easily handle another thread's page faults in user mode though. That seems a little wacky. You can use debugger APIs to handle "STATUS_IN_PAGE_ERROR" and "STATUS_ACCESS_VIOLATION", which might get you there.
A flaw in the Linux implementation, though, prevents one to run ptrace on a process that is using ptrace itself.
As more programs use ptrace, this flaw is becoming quite annoying.
What unfork does is more complicated than a mere read, though. I'm still not entirely clear on its use case, but it does all sorts of tampering that the code comments describe as "cursed." It also seems to be specifically targeting applications which have anti-debug measures.
The closest equivalent I can think of in Windows would be to mark pages as no-access and use vectored exception handling to trap access faults. During a fault, the exception handler would fill in the page (e.g. via ReadProcessMemory) and flip the page protection to read or read/write.
Since you wouldn't want to flip the page protection until after the memory had been updated, you would probably have to used a pagefile-backed section to update the memory at a separate virtual address with independent page protections. And unlike the userfaultfd approach, this mechanism would not help for cases where the mirrored memory was being passed to a syscall.
I think Linux could do this too, via a signal handler, but AFAIK the Linux memory manager does not efficiently support per-page access protection (unlike Windows). In the worst case, each page would get its own vma structure in the kernel, which would be quite expensive. So absent userfaultfd, the Windows memory manager probably has the edge.
Glibc used to have unexec(), which is fairly old, but it was removed because nobody used it (except Emacs, and there were better solutions to the problem it was solving).
It's as clean as any official Win32 API which uses their privilege system to restrict/allow accesses to each and any bit of information on the process state and/or memory.
> Can you simply exec the result?
This is possible using CreateThread() [1] which creates a remote thread inside another process execution context.
[1] https://docs.microsoft.com/en-us/windows/win32/api/processth...
> Glibc used to have unexec()
My understanding is that unexec() was more about making a snapshot of the whole process state to an executable on disk.
Taking a snapshot of other processes is also a basic use case of this family of functions [3].
[1] https://docs.microsoft.com/en-us/windows/win32/api/processth...
[2] https://docs.microsoft.com/en-us/windows/win32/api/memoryapi...
[3] https://docs.microsoft.com/en-us/windows/win32/toolhelp/taki...