darfink / detour-rs

A cross-platform detour library written in Rust
Other
389 stars 71 forks source link

Multiple tests fail on macOS Catalina 10.15.2 #16

Closed darfink closed 3 years ago

darfink commented 4 years ago

The tests no longer work on macOS Catalina due changes of their linker (ld64). The default value of the maxprot attribute of the __TEXT segment in the Mach-O header has been changed.

Previously maxprot default value was 0x7 (PROT_READ | PROT_WRITE | PROT_EXEC). The default value has now been changed to 0x5 (PROT_READ | PROT_EXEC).

This means that mprotect cannot make any region that resides within __TEXT writable.

In theory, this should be resolved by providing the linker flag -Wl,-segprot,__TEXT,rwx,rx but it seems as if the max_prot field is ignored (ref: -segprot,<segment>,<max_prot>,<init_prot>).

In practice max_prot & init_prot are both set to the value of segprot's init_prot.

To top it all off, this becomes even worse due to the fact that init_prot cannot be set to rwx (macOS refuses to execute a file which has a writable __TEXT(init_prot) attribute).

A shoddy workaround is to manually modify and set __TEXT(max_prot) to 0x7 after linking.

printf '\x07' | dd of=<input_file> bs=1 seek=160 count=1 conv=notrunc

NOTE: This relies on the default __TEXT(max_prot) offset to be 0xA0 (the default with ld64).

To be continued...

See https://github.com/agiledragon/gomonkey/issues/10 See https://github.com/Zeex/subhook/issues/45

darfink commented 4 years ago

It seems as if there's no easy workaround nor fix for this. Until a better solution presents itself, I've written an ld drop-in replacement/wrapper that respects the max_prot field of the segprot parameter.

In my ~/.cargo/config I've added the following configuration (replace <home>):

[target.x86_64-apple-darwin]
rustflags = [
  "-C", "link-arg=-fuse-ld=<home>/.bin/ld",
  "-C", "link-arg=-Wl,-segprot,__TEXT,rwx,rx",
]

I believe Apple deliberately removed the ability to provide a value for max_prot, and therefore they are not likely to offer an alternative. In the meantime, let's hope LLVM's lld Mach-O implementation matures so it becomes a viable alternative.

darfink commented 3 years ago

This has been fixed to some extent with https://github.com/darfink/detour-rs/commit/6af8b287e7215d5226eede7cb623e9841afcc550, but the situation may worsen in the future depending on the direction of macOS's security model.