Sandboxie on ARM64 design considerations

Discussion in 'Sandboxie (SBIE Open Source) Plus & Classic' started by DavidXanatos, Mar 21, 2022.

  1. DavidXanatos

    DavidXanatos Developer

    Joined:
    Sep 6, 2006
    Posts:
    2,524
    Location:
    Viena
    In the past month I have spent some time investigating how feasible a port on ARM64 would be, and well a few good news and a few not so good once.

    Running native ARM64 binaries sandboxed should not be problematic, also old 32bit arm binaries should be doable without much issues (although I wonder if there is any such software out there aside of may be a hand full out dated store apps, so may be Sandboxie don't even need to support this? MSFT does not even provide updated build tools for that).

    The more interesting part is however x86/x64 on ARM64, as it does not run natively and is just in time compiled to ARM64 code. As far as I found out MSFT intended for simple function hooking to work although that is not really working in all cases. In order to improve execution performance MSFT has introduced a new sort of binaries a Hybride format where the exported functions start as x64 or x86 and then quickly jump to an ARM implementation. This way system DLL's don't need to be jited, for x64 MSFT provides a toolchain to create such DLL's and also EXE's this is called ARM64EC, however not for x86.

    The x64 on ARM64 case is particularly well integrated as it does not need any filesystem or registry redirection, and all system dll's are provided as a joined ARM64 and ARM64EC binary (that's called ARM64X) the system loader picks the right portion of the DLL to link to when its loaded. With these as it seams all control flow always goes through the x64 stubs even when a system DLL does something internal it will go through the x64 stub which can be hooked with a x64 code as if we were running natively on x64. Now in a few cases Sandboxie hooks internal not exported functions, so here that would be ARM64 code to hook, how to deal with these while being in x64 mode I will have to look into, as the hook would need to transition from the ARM64 to x64 call the sbiedll detour function and than properly transition back to ARM64 before resuming the original control flow. But as MSFT offers a toolchain to create ARM64EC binary which do such things, so here such an EXE is internally ARM64 but it can load x64 dll's and call them, that should be reasonably easy to find out how to use the same methods for a ARM64 hook inside the native ARM64 portion of a system DLL and detour that to an x64 implementation.

    What however seams to be a huge problem is x86 on ARM64, first of all there is no publicly available toolchain to create such mixed binaries, these are called CHPE (in a way ARM64EC/ARM64X is CHAPEv2), but more problematic those older type of hybride binaries, when doing internal Operation, do not take the control flow through the x86 stubs as it seams. So we can not install the required x86 hooks which Sandboxie needs to operate. Luckily those CHPE dll's, all located in Windows\SyChpe32 are in a way all optional, that is, the system DLL loader when loading a dll from Windows\System32 (in reality of x86 operation Windows\SysWOW64) checks the SyChpe32 Folder and if a DLL is found there it is used instead of the x86 one from SysWOW64 and this Folder contains x86 duplicates for all the existing CHPE binaries, including the ntdll.dll. So by preventing the system loader from accessing SyChpe32 the SysWOW64 DLL's are loaded instead and with those we can install all the hooks Sandboxie needs to make x86 software run.
    The problem is that the SyChpe32\ntdll.dll is loaded by the system when a process is created, i.e. before Sandboxie gets involved so before we can do anything. The only way to prevent this was in fact just deleting/renaming the Windows\SyChpe32 and rebooting the system. So when this is done, not only the performance of x86 in Sandboxie would be bad, but out right the performance of any x86 binary on the system. Now to what extent I haven't measured, given that there is a cache for the jited code I would expect the impact to not be that big, but than properly compiled code will be much more optimized than the jited code so the impact may be not so small in the end, idk... In any case this is not a pretty workaround.

    So what can be done, well there are 2 ways out of this situation that I can Imagine.

    One would be once Sandboxie gets involved try to unload the SyChpe32\ntdll.dll and somehow manually load the SysWOW64\ntdll.dll instead, now how feasible this is I don't know yet. Given that all execution in any process always starts in the native ntdll.dll and only after some initialization from there the execution goes to the WOW version of the ntdll.dll we have a time window to inject some native ARM64 code and try to mess with the process startup. But than I don't see why the kernel always pre map's booth ntdll's into the Image, given that we start out natively the native ntdll could just load the wow ntdll on its own, couldn't it? That's a question to be clarified. One thing to notice here is that the native ntdll in fact loads other DLL's before transitioning to emulated code, like the aktual jit compiler (Xtajit.dll) for example.

    The other way out would be to try to hook the ARM64 code inside the CHPE system dll's this however poses a signifikant challenge, as described earlier in such a scenario we need to transition from ARM64 to x86 and then back, and this is completely undocumented, and to make things worse there is no toolchain for creating own CHPE binaries to experiment with, and to complicate Things even further CHPE being for 32 bit while using ARM64 code does this in a completely non standard way as it tries to behave like 32 bit, using 32 bit pointers, etc....

    So yea.... booth options are all but strait forward, and at this point I have no idea which of those two is less terrible, booth are quite unpleasant.
    So I wonder how horrible it would be to go the "delete the SyChpe32 directory" route?
    That said, other things one may think of relating to messing with the windows kernel to moderate the access to the SyChpe32 dll's are IMHO not usable for a production build as they would very likely trigger the kernel patch guard.



    So to summarize a couple of questions for the users:
    1. Does Sandboxie on ARM64 needs to support 32 bit ARM applications, are there any 32 bit ARM aside of some windows phone apps out there?
    2. Is the delete Windows\SyChpe32 folder a viable solution of everything else fails, what do you think?

    Thoughts ideas suggestions?
     
  2. soccerfan

    soccerfan Registered Member

    Joined:
    Oct 15, 2007
    Posts:
    585
    Interesting! What kind of end product do you have in mind?
    Will it be for mobile phones or(and) other platforms?
     
  3. DavidXanatos

    DavidXanatos Developer

    Joined:
    Sep 6, 2006
    Posts:
    2,524
    Location:
    Viena
    Nothing special just normal Sandboxie for normal Windows 11 on ARM64
    And yea you can install windows 11 on an old lumia phone if you want :D
     
  4. DavidXanatos

    DavidXanatos Developer

    Joined:
    Sep 6, 2006
    Posts:
    2,524
    Location:
    Viena
    BTW: I have found a good way to force selected processes to load the syswow64 ntdll instead of the sychpe32 ntdll :D
    So I think I can assess that a port is possible-
     
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.