Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 01-25-2022, 04:13
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
Windows on Arm64, x86/x64 emulation

I'm wondering how the x86/x64 emulation on arm64 works, is the image loaded to memory the x86/x64 original and there is just a transpiled arm64 shadow copy, or is the code transpiled before and the loaded image is arm64 only.

I don't have any arm hardware yet, but am already thinking about how function hooks in x86/x64 emulated on arm64 would, or maybe wouldn't, work.

Anyone here who already has some experience and could shine some light on it?
Reply With Quote
The Following User Says Thank You to DavidXanatos For This Useful Post:
niculaita (01-25-2022)
  #2  
Old 01-25-2022, 17:52
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
I have found some information: https://blogs.blackberry.com/en/2019/09/teardown-windows-10-on-arm-x86-emulation

So it seams that what lives in memory is the x86/x64 image and its only transpiled piece by piece on demand. I hope a call to FlushInstructionCache will invalidate the cached transliled result ...

EDIT: now I just need some good device to experiment on, any suggestions?
Reply With Quote
The Following 2 Users Say Thank You to DavidXanatos For This Useful Post:
Acronys (01-29-2022), p4r4d0x (01-26-2022)
  #3  
Old 01-26-2022, 03:48
sh3dow sh3dow is offline
Family
 
Join Date: Oct 2014
Posts: 158
Rept. Given: 113
Rept. Rcvd 79 Times in 24 Posts
Thanks Given: 461
Thanks Rcvd at 202 Times in 75 Posts
sh3dow Reputation: 79
Was about to post that link but apparently I'm late and you found it, this one also has a good information https://wbenny.github.io/2018/11/04/wow64-internals.html

Also this fantastic CODE BLUE talk which has juicy details:
- https://www.slideshare.net/ffri/appearances-are-deceiving-novel-offensive-techniques-in-windows-1011-on-arm-250472833
- https://www.youtube.com/watch?v=amHAot3X8cE
Reply With Quote
The Following User Says Thank You to sh3dow For This Useful Post:
DavidXanatos (02-12-2022)
  #4  
Old 01-26-2022, 05:50
kino0924 kino0924 is offline
Guest
 
Join Date: May 2020
Posts: 2
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 2
Thanks Rcvd at 0 Times in 0 Posts
kino0924 Reputation: 0
You can try to run ARM64 windows on QEMU.
Im not sure about the part of capability of running x86/x64 app on ARM64 Windows tho
Reply With Quote
  #5  
Old 01-26-2022, 17:42
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
@sh3dow thanks

@kino0924 emulating arm64 on x64 which in turns emulates x86/x64 sounds painfully slow.
That I'm probably better of trying to run it naively on an old raspberry pi
Reply With Quote
  #6  
Old 02-12-2022, 03:17
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
Also interesting: https://oofhours.com/2021/02/19/running-x64-on-windows-10-arm64-how-the-heck-does-that-work/
Reply With Quote
  #7  
Old 02-15-2022, 01:11
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
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)
  #8  
Old 02-15-2022, 05:30
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
Interesting, I was under the impression it was booth the same, ARM64 code with provisions to
a) call x64 code
and
b) be callable from x64 code
so the ARM64X version contains full code for booth platforms, hence would be runable on a x64 windows as well?
Reply With Quote
  #9  
Old 02-15-2022, 05:55
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
So how is ARM64X different form a dll compiled as ARM64EC?
Reply With Quote
  #10  
Old 02-15-2022, 06:22
deepzero's Avatar
deepzero deepzero is offline
VIP
 
Join Date: Mar 2010
Location: Germany
Posts: 310
Rept. Given: 115
Rept. Rcvd 64 Times in 42 Posts
Thanks Given: 195
Thanks Rcvd at 224 Times in 95 Posts
deepzero Reputation: 64
So they have a new type of relocation that "relocates" imports, etc. rva depending on arm vs x64? That's actually pretty cool, I am now only half-mad they introduced yet another relocation type...
Reply With Quote
  #11  
Old 02-17-2022, 00:19
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
I have been experimenting with my HackLib with code injection into/from Arm64 processes and noticed something unexpected but in hindsight logic ARM64EC processes are more x64 than arm even if most of their compiled code is arm.
That I mean, when I hijack the main thread before it resumes, and point it to a peace of shell code of mine the shell code must be x64 in order to work.
The funny thing is my shell code loads a dll that hooks then in x64 various functions, for demo purposes for example MessageBoxW and alters its title and all that works as expected.
The ARM64EC app having its main and rest of user written functions being ARM64 code when calling MessageBoxW invoked the hooked x64 version just fine.
To be honest I would have expected a shorthand here where the arm code calls system API's directly, but no the control flow goes from Arm64 to the x64 stub which can be hooked and then back to Arm64 code in the system\user32.dll that is pretty nice. And in a way logical that a process that is supposed to be able to load native x64 dll's would for ideal compatibility have provisions to allow that dll to consistently hook functions even if that means a few more detours are taken.

Now about cross architecture code injection (assuming shell code and injected dll have the right architecture):
Code injection from an arm64 process into an x64 or arm64ec process works just fine using x64 code


What how ever currently fails is code injection from a x64 or arm64ec process into a arm64 process and it seams for a quite mundane reason, NtSetContextThread when called from a x64 process to act upon a arm64 process, returns STATUS_SET_CONTEXT_DENIED
I expect would the operation have been performed, the rest would succeed.

Since arm64 to arm64 injection using the same method works just fine I expert this being som sort of intentional limitation, perhaps not even a real security measure but rather a safeguard against screwing things up.


So the question, did anyone here already experienced this and would know if there is a easy way around, short of native arm64 spawning a helper process just to do that one function call.
Reply With Quote
The Following User Gave Reputation+1 to DavidXanatos For This Useful Post:
user1 (04-12-2022)
The Following 2 Users Say Thank You to DavidXanatos For This Useful Post:
niculaita (02-17-2022), user1 (04-12-2022)
  #12  
Old 02-23-2022, 03:56
sh3dow sh3dow is offline
Family
 
Join Date: Oct 2014
Posts: 158
Rept. Given: 113
Rept. Rcvd 79 Times in 24 Posts
Thanks Given: 461
Thanks Rcvd at 202 Times in 75 Posts
sh3dow Reputation: 79
Found this on my feed and wanted to share

├─Jack-in-the-Cache: A New Code injection Technique through Modifying X86-to-ARM Translation Cache (this one is from the same author I mentioned before in #3).
│ it's was presented for BlackHat con also the video this time is in English while the code blue one was in Japanese.

│─────https://i.blackhat.com/eu-20/Wednesday/eu-20-Nakagawa-Jack-In-The-Cache-A-New-Code-Injection-Technique-Through-Modifying-X86-To-Arm-Translation-Cache.pdf

└─────ttps://www.youtube.com/watch?v=8wg7X5IaEto

Quote:
Recently, the adoption of ARM processors for laptop computers is becoming popular due to its high energy efficiency. Windows 10 on ARM is a new OS for such ARM-based computers. Several laptop computers with this OS have already been shipped; notably, the recent launch of Microsoft Surface Pro X will be a driving force to facilitate the widespread use of Windows 10 on ARM.

You might think that there are new threats to such a new OS. Yes! We found such a threat.

In this talk, we present a new code injection technique to abuse a novel feature of Windows 10 on ARM: X86 emulation.
Remarkably, Windows 10 on ARM can run X86 apps via the X86 emulation feature that translates binary from X86-to-ARM just in time. To reduce the performance overhead of JIT binary translation, the OS has the mechanism to cache already-translated results as X86-to-ARM (XTA) cache files.

Our new code injection technique is performed by modifying this XTA cache file. Since this technique is difficult to detect and trace, appropriate countermeasures are necessary. Moreover, this technique can be used as an API hooking invisible to an X86 process. Therefore, this technique has already been a threat to Windows 10 on ARM.

We believe that future OSs have a JIT translation mechanism at the processor transition. For example, Apple has recently announced Rosetta 2, which is a similar mechanism for introducing their own ARM-based chip. For these OSs, the caching of already-translated results as files is a reasonable way to decrease performance overhead.

Our new code injection technique might also apply to such OSs.This presentation becomes a beneficial advisory for the developers of such future OSs, not limited to Windows 10 on ARM. PoC code of our new code injection technique and analysis results of the X86 emulation will be public on GitHub after this talk.
Excellent blog from the same author as well
├─Discovering a new relocation entry of ARM64X in recent Windows 10 on Arm

│─────https://ffri.github.io/ProjectChameleon/new_reloc_chpev2/

└─────https://github.com/FFRI/ProjectChameleon/

Last edited by sh3dow; 02-23-2022 at 09:04.
Reply With Quote
The Following 2 Users Say Thank You to sh3dow For This Useful Post:
niculaita (02-24-2022), tonyweb (02-25-2022)
  #13  
Old 02-24-2022, 05:04
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
hmpf... sooo I have a nice function hijacking code that from arm64 to arm64 works perfectly.

Now we also know that all processes in arm64 start execution as arm64 (or at least I think that) so at the very start of every program we should enter ntdll's LdrInitializeThunk and for arm64 on arm64 its of cause so.
For other architectures on arm64 we should at some point divert into emulated code.

When trying to inject a detour in LdrInitializeThunk of a created suspended x64 process on arm64 however that code does not seam to ever be executed. Meaning I can inject garbage and it will still startup just fine.

Now my assumption of how x64 on arm64 works is that as soon as execution goes into a system dll i.e. anything compiled as ARM64X we exit emulated x64 mode and execute the native arm code in the dll. So it stands to argue that wen bootstrapping a process, it behaves analogously everything is executed in native arm until it comes the time to call the x64 processes entry point.

Well it seams something isn't quite right here, one possibility is that the ARM64X dll's truly have all the code doubled including large portions of the arm code, so when I manipulate the LdrInitializeThunk I get i do it to a copy that will never be used.

Now I find that strange I would have assumed that the code wouldn't be doubled that MSFT would have some smart redirection in place allowing the ARM64X dll's to re use most of the arm code for the native and the emulated mode.

@RamMerLabs since you apparently have already a lot of experience with the layout of the new PE files, would you may be have a few tips is that really so that the code is fully separated?
Reply With Quote
  #14  
Old 02-24-2022, 16:10
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
After some more research I can confirm that this is what happens, when i get the address of #LdrInitializeThunk from the symbol file for ntdll and use these my injected code works.
Sooo... the next question is how to get the "export" addresses without the need of a pdb file.
It was already earlier written that this ARM64X files have a 2nd export directory, so I guess parsing that "by hand" would be the strait forward approach.
Unless there is a flag that can be passed to LdrLoadDll that would do this for me ?
Reply With Quote
  #15  
Old 02-25-2022, 05:21
DavidXanatos DavidXanatos is offline
Family
 
Join Date: Jun 2018
Posts: 183
Rept. Given: 3
Rept. Rcvd 47 Times in 33 Posts
Thanks Given: 59
Thanks Rcvd at 363 Times in 120 Posts
DavidXanatos Reputation: 47
Splendid! Where can i find some documentation/reverse engineering notes on the new PE features? As for my use case it's not enough to see them in a tool i need to programmatically get to the relevant addresses for code injection.
I already have found this: https://ffri.github.io/ProjectChameleon/new_reloc_chpev2/ but its from 2019 i imagine by now there should be more refined information available?
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Windows 11 ARM64 version 24H2 blue_devil General Discussion 9 11-20-2024 13:55
Question about PE format (ARM64) DavidXanatos General Discussion 0 04-28-2022 01:09


All times are GMT +8. The time now is 06:49.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( Since 1998 )