View Single Post
Old 02-15-2022, 01:11
DavidXanatos DavidXanatos is offline
Join Date: Jun 2018
Posts: 168
Rept. Given: 2
Rept. Rcvd 40 Times in 27 Posts
Thanks Given: 53
Thanks Rcvd at 310 Times in 106 Posts
DavidXanatos Reputation: 40
So some things I learned about x64 on arm64, it seams MSFT went all in to provide a good interoperability between x64 and arm 64 code.

They have introduced a new type of PE so called CHPEv2 (Compiled Hybrid Portable Executable) which can contain booth x64 and arm64 code, as far as I understand in practice this is mostly arm64 code with x64 entry-points.
These are called ARM64EC in the VS 2019/2022 tool chain.

An executable compiled as x64 can load ARM64EC dll's and call them normally,
the x64 wrappers have some (as far as I can tell) dummy prollogs, large enough to install x64 hooks.
The intended use case for this is to load system libraries from system32 which on arm64 are all provided as such CHPE's so no C:\Windows\SysX8664 or alike.

So to say 64 bit is 64 bit no mater if its ARM or AMD, also no separate registry paths. Its all thoroughly mixed together, unlike SysWOW64 or SysArm32 that booth get an own system directory and an own registry redirection.

A executable compiled as ARM64EC can load x64 Dll's just fine, haven't looked into the hook ability in this scenario yet (TODO)
The intended use case is to allow developers to port a part of their application to Arm64 and keep the rest x64 for the time being, as well as to provide compatibility with x64 plugins and extensions (according to MSFT's docs).

So technically the x64 on arm thing is an own feature and should not be confused with being an other version or an extension of WOW its a separate interoperability feature, one which works quite different, unfortunately I don't know if MSFT named it somehow. Based on some dll and service names its probably called XTA that would probably stand for "x86_x64 to ARM", or something like that.

XTA is a just in time compiler that converts x64 or x86 code when needed to arm64 which is the being executed, the loaded binary image in memory stays untouched x64/x86, hooking any portion of it seams to work just fine, of cause FlushInstructionCache is probably particularly important to ensure the XTA cache gets updated.

When running a x86 application on a arm64 machine in fact booth WOW and XTA seam to work together, while the SysWOW64 directory contains only x86 dll's there is an other one called SyChpe32 that contains something like ARM64EC just in 32 bit so ARMEC (?) unfortunately MSFT did not provide a Toolchain to create such binaries for ourselves. There we have the most commonly used system dll's in such a hybrid format.

So WOW takes care of the syscall translation from 32 bit to 64 bit close to the kernel, be that on arm64 or on x64, and filesystem + registry redirection. While XTA takes care of the transition from emulated native code as close to the loaded user code.

In between lives native arm/arm64 code.

When running x64 on arm 64 only XTA is active and no WOW is in place, a call to IsWow64Process2 confirms that an x64 application running on arm64 does so without WOW.

Interestingly when querying NtQuerySystemInformationEx(SystemSupportedProcessorArchitectures, ...
ARM64EC binaries give the same result x64 binaries on arm64

Also when debugging ARM64EC binaries you need to use the x64 debugger, there is no dedicated ARM64EC one.
Reply With Quote
The Following User Says Thank You to DavidXanatos For This Useful Post:
niculaita (02-15-2022)