Packing Malware in Rosetta 2

gok1 pts0 comments

/etc/kernelkennel • Packing malware in Rosetta 2Skip to contentPacking malware in Rosetta 2<br>noblenote 19th Aug 2026•13 min read•Tags: talks, security, macOS, dyldUpdated on 19th Aug 2026Table of Contents<br>TL;DRIntroductionUnderstanding how Rosetta 2 ends up giving us AARCH64 Ahead-of-timeJust-in-timeWhat else is in Rosetta 2?Gamehacking over Rosetta 2 Setting up the game cheatApple Silicon security paradigms in Rosetta 2 Attack Surfaces in Rosetta 2 AOT ChecksumsCode like you're on x86_64 (for malware)Examples of this in North Korean malwaresSetting up a sneakier attack on Rosetta 2 Finding a target on a dependent libraryUnderstanding time of resolution and useSwizzling with your own function pointers Ensuring it's cosy in our applications directory with all the other librariesOK FINE here's the calcConclusion and afterthoughtsSlides from SummerCon<br>How to use DYLD and Rosetta 2's characteristics to pack whatever ya want! TL;DR<br>If you want the slides, I've appended them to the end of this page. You can use them to follow along with the talk that was listed at SummerCon's recording of the talk.I'm also keen on internships or knowing more folks in security - feel free to reach out! Introduction<br>Rosetta 2 is a translation layer that allows macOS to run Mach-O x86_64 binaries on Apple Silicon. To make it short and sweet, it is a transpiler tool that uses static compilation when it can to convert code and cache it away via oahd_helper and for branching out to indirect calls, it will hand it over to JIT compilation.It will be phased out in the next major MacOS update - with the new tools being the GPTK (Game Porting ToolKit) which packages Windows for game review/porting and then other items of Linux, like VZVirtualMachine. Who knows how it will be architected, but this is a nice little tool that has been used to smooth out the transition to M-series chips! Understanding how Rosetta 2 ends up giving us AARCH64<br>Ahead-of-time<br>Like I mentioned above, we want to first understand how Rosetta 2 leverages both ahead-of-time and just-in-time compilation to keep MachO zippy.Using the oahd-helper daemon, we first check any exec call that is made against a given x86_64 target, calculate a hash and then check it against a known cache at /var/db/oah/. If we find it, no problem.If it isn't found, we instead try to perform as much one-for-one x86_64 to AARCH64 translation as possible, and then cache it in a given exec.aot file. We also do this for any required frameworks that are needed by the executable.This is done for all binaries required, and we put it under a directory. If we can't translate a given block, we'll stub a branch that we can figure out later and resolve at runtime - without going into the major differences, this is similar-ish to how dyld works in how we use dyld to resolve dynamic library calls but 'make space' in the LAZY_SYMBOL_POINTERS section of a given MachO file.This is going to be verbose as we have many differences from ARM64 to x86, and we want to keep state. Why? We need to also append the original x86 instrucitons to a processes' memory so we can refer to them later when needing to find instructions for JIT translation.We'll also want to be quick for first launch- there's details on this on dougallj's blog I have referred to before.To show the AOT section: Just-in-time<br>Cool, so we've got the aot file cached and kept away in a location where SIP is gonna protect it from the nasties. Since we have stubbed any indirect calls, when we end up running the program, we'll need to resolve any stubs at runtime.This is for extern calls, indirect branching available in x86_64 and anything else we can't really deterministically resolve. runtime from Rosetta 2 will lookup the original instructions we mentioned before and walks down a red-black binary tree of these to resolve new instructions and hand it back to the TEXT segment responsible for executing code on your Macbook!And the JIT section: What else is in Rosetta 2?<br>We have other cool goodies to help with mimicking all sorts of characteristics that isn't on AARCH64:A Rosetta Return Stack is allocated for RIP-relative addressing, includingRosetta Thread Info is allocated for thread-local storageother gubbin' that isn't something I looked at, you can always mmap!We aren't going to see this since LLDB and debugging shims the same x86 so we can't see the resulting instructions that get run. It helps the developer that worked on their Intel Mac apps to still debug on Apple Silicon, neato!The AOT shared_cache and runtime will work together to review and resolve all function starts and code blocks to combat the lack of heavy optimisation - this isn't investigated with regards to of exec primitives. There's a variety of protections available in malloc to prevent cross-pollution of x86 and AARCH64 memory. Gamehacking over Rosetta 2<br>Okay, so I already did the bulk of this in a prior talk at Ruxmon Melbourne in 2025. This was initially inspired by Jai Vermas blog on...

rosetta resolve aarch64 x86_64 time want

Related Articles