Hacker News new | ask | show | jobs
by usmannk 1633 days ago
Wow really? A common intro to security exercise (think CTFs and university courses) is to write increasingly complicated C programs that leverage W&X. Classic buffer overflow into the stack kind of stuff. On M1 it’s now impossible to exploit even a self-compiled toy in this way?
4 comments

Basically, yeah. In addition, the usual way to bypass W^X memory, using ROP chains, is also mitigated by the pointer authentication the M1 implements. It's not bullet proof, but it prevents most of the old exploit methods from working at all. You'd need to throw up a VM on an M1 Mac to learn much this way (although that'd be ideal anyway, to get an environment without other protections like ASLR)

I know at least OpenBSD also enforces W^X protection universally, anyone else? I know Linux can with the right SELinux policies, but not sure any distro ships with those by default.

Windows has had this enabled by default for a long time: https://docs.microsoft.com/en-us/windows/win32/memory/data-e...

There's a per program exception list to handle legacy programs though.

Windows DEP only applies W^X (more accurately, !X) to the default stack and heap; programs can still freely allocate new memory as PAGE_EXECUTE_READWRITE if they want RWX memory.

macOS W^X on Apple Silicon, however bans RWX memory outright, making it impossible to have a page in memory that is simultaneously writable and executable. Instead, if you want to be able to write instructions to a page and later execute them (e.g. for JIT compilation), you have to (1) have a special entitlement (or opt out of the Hardened Runtime), (2) map your memory with a special MAP_JIT flag, and (3) call special mprotect-like functions to toggle the protection between RW and RX every time you want to modify the code.

There does, however, seem to be a bit of a loophole: the JIT protection flags are applied per thread meaning that in principle one thread could have the page RW while another has it RX.

On M1 CPUs you cannot ever have simultaneously writable and executable memory. Windows just makes default allocations write only, you have to explicitly request RWX, which is what every other OS has been doing basically since x86 actually added support for non executable memory :)
Pointer authentication isn’t in 3rd party processes though, only system ones. (or maybe it’s available but optional, I forget)
> Pointer authentication isn’t in 3rd party processes though

Still isn’t, because the arm64e ABI isn’t stable. As such, any binaries not bundled with the OS, including Apple applications, use the arm64 ABI without pointer authentication.

You can use -arm64e_preview_abi as a boot argument to enable arm64e support for non-OS bundled processes.

Note that however the arm64e binaries that you compile might not work on future macOS releases.

System libraries are more than happy to use some parts of pointer authentication, such as return address signing.
System libraries use the full pointer authentication schema, because they’re updated as a whole with the entire system, so ABI changes don’t impact them (as much).
Offtopic, but can you recommend such a course?
Hey sorry, didn't check back on this comment for a while. I can't recommend any _courses_ in particular (unless you're a Georgia Tech student, in which case "CS 6265: Information Security Lab" is absolutely incredible).

One really fun way to hone your skills is https://microcorruption.com/, a ctf-style simulated hacking game originally made by Square and Matasano.

You can do it in a Linux VM container, it's just MacOS processes, not the HW.
Ohh that makes more sense, thanks.
It is possible using Rosetta 2