
so hello and welcome to my talk breaking windows with your arm I'll start with a few words about myself uh my name is Ram Salinas and I'm a security researcher in cyber arcs research Labs my work focuses on vulnerability research malware research and my expertise is Ral engineering and malware analysis I previously spoke at conferences such as RSA besides Las Vegas and digital crimes Consortium and in my free time I enjoy playing the drums you may follow me on Twitter as well um so our agenda today is a short introduction of the subject then we'll Dive Right into some windows on arm internals primer then we'll see some kernel mode wot key techniques and finally we'll
close with some takeaways and questions so what is uh sorry so what is arm exactly arm is all around us uh devices such as Smart TVs phones tablets raspberry pies and most recently even laptops and desktop computers are all running on arm but what is it so arm is a specification for processors based on the risk or reduced instruction set computer architecture as opposed to Intel's processors that are based on cisk compound instruction set computer architecture the main difference between risk and cisk architectures is that in a risk architecture every op code has a fixed by length while in cisk architecture each op code has a different or or variable bite length arm has become very popular uh
due to the low energy consumption and great performance and lately more popular than ever since the introduction of the MC chips or apple silicon as we know it windows on arm existed under many names in the past including Windows C Windows RT Windows phone and Windows 10 mobile and its latest Incarnation is Windows 11 on arm or actually Windows 11 on arm 64 Microsoft has launched several devices to use this platform uh including the windows 11 on arm 2023 devkit uh and the surface for laptops to encourage users and developers to adopt this technology and other vendors are also catching on to this including Lenovo Samsung and HP so in this presentation I will talk
about rootkits on the windows on arm platform which bring us to what is a rootkit exactly so a rot kit is a type of mware that hidees itself in order to evade detection specifically by subverting the OS and while insiding while hiding inside it typically living in the kernel space and the term root kit is taken from the Unix terminology where root is the most privileged user on the system now root kits are are usually divided into two basic types based on their privilege level kernel mode wood kits and user mode wood kits kernel mode wood kits are the typical wood kits uh they run as a highly privileged user such as an40 system in Windows in the
kernel itself and can modify kernel structures in memory which they do in order to manipulate OS while handing inside it uh in Windows this would typically mean running as a kernel driver user mode rootkits on the other hand do not have a mode component and would hide their presence on the system by using user mode techniques and apis um that manipulate the OS such as hooking and process injections these days many modern uh mware families contain some form of a user mode woodkin component as they usually do try to evade detection as well in this presentation I'm going to focus on kernel mode woodkids so in order to to begin This research I purchased a Windows on arm
2023 dev kit which comes pre-installed with a fully patched Windows 11 and my goal was to see if I was able to find any techniques that can be bypassed sorry that can be used for root kits uh on such a system and obviously ride a PC I also had a few assumptions made secure boot is off and both kpp Kel patch protection AKA patch guard and dsse digital sign in enforcement are off uh which basically means I had the kernel debugger attached to the system and I will explain about these mitigations later on the reason I made these assumptions is that by passing these mitigations um is a whole different idea than developing root KY techniques and hence
it was out of context uh the root kit techniques I will describe can be applied given the mitigations have been bypassed and finally I had the another goal which was once I discovered how to create hooks Etc on the system to write a tool to detect these techniques and the Tool uh I wrote was released on GitHub last
year okay so at this point let's jump right into some windows internals primer for Windows on arm so windows on arm like any any Windows OS is divided into user space and kernel space unlike X 8664 which has only two privilege level used uh ring zero and ring three arm64 has four exception levels called el0 el1 el2 and el3 which stand for usen mode kernel mode hypervisor and secure Monitor and in order to escalate to a higher exception level one would have to use one of the following instructions SVC hvc or SMC depending on the current exception level so in order to understand how user mode transition on Windows or now works let's take a look at some
example so here we have our application app.exe that needs to open a file from disk it uses kernel 32 API functions such as uh create file then when create file is invoked the implementation that resides in Kel F2 will pass the parameters pass to it and we'll call the undocumented anti create file in ntdll and basically up to this point everything we saw is just like X8 664 but how do we transition to Kernel mode so by taking a look at the disassembly uh or implementation of an create file which is located in ndl still in user mode we can see that it is implemented by using only two instructions SVC and red and basically the OS maintains a
table of handlers known as Ki arm 64 exception vectors where its base ASD veress is stored in a special register called the vbar ear one and each table entry is aligned to hex 200 and when an exception happens uh the CPU will immediately execute some code at some offset of the vector table for instance uh when SVC is executed a special trap is triggered which will transition to offset hex 400 in the table which is Ki user ex exception Handler the final part would be that Ki system service would eventually be called uh and will take the cisal number that was passed to the SVC instruction as an index to the ssdt table which will
translate the value found in that index to the Handler function for that specific CIS using a special formula which I will explain later once that is done the appropriate Kel version of ENT create file uh also can be referred as ZW create file located in OS kernel will be called which will do most of the work and um the appropriate dis driver will we will do the actual reading from dis so please remember this example when I will talk about some of the root KY techniques uh because this user mode to can canel mode switch provide us with several options to hook C calls in order to manipulate or temper past arguments and return values of this
mechanism and as I promised here are some of the mitigation I purposely disabled by using uh the debugging enabled boot option and attaching a kernel debugger so patch guard or kpp kernel patch protection is a mechanism that protects kernel structures from being changed in memory or patched by an attacker it periodically checks um each kernel structure for changes or inconsistencies and if it finds that a change was done it would cause the system to blue screen with a bug check such as critical stru corruption or Kel Security check failure you can see a list of inconsistencies in the right um and as you can see there aren't a few um and probably you can't read it but there's
really many many of them um this is also a good time to mention that patch guard uh kicks in in undisclosed intervals of between 15 to 30 minutes which leaves plenty of time for an attacker to revert his changes before risking of getting blue screen DSC or dig driver signature enforcement um is basically checking that a driver is signed by a trusted certificate before loading it and finally most recently Microsoft introduced a blacklist known as the vulnerable Drive sorry a blacklist of known to be vulnerable drivers that are not allowed to be loaded this mechanism when enforced is basically checking if the hash of the currently loaded driver is in The Blacklist and this is basically
to prevent uh bring your own vulnerable driver
attacks so now uh let's see some Kel mode root key techniques So In This research I uh implemented three techniques dcom ssdt hooking and uh a global hook in the Ki system service and this is a good time also to say a disclaimer that these techniques are not stable and uh patch guard would be S on most of them so the first technique I'm about to show is the was the easiest to find as it is pretty similar to X8 664 um the only difference is in the offsets used in the code since the relevant Kel structures are different the theory behind this technique and the example I will show here is that an eprocess object contains
a linked list of all the active processes in the system called the active process links where each link is also a new process and by looking for a specific process name in the image file name field we can find our Target process in the list and once we find it unlink it from the list now throughout the demos I will be using a tool uh which is basically a version of the detection tool I released with some extra features uh such as sending gals hooking Etc and I will be using it during the demos but don't worry I will explain everything you need to know about it um so let's continue so to our demo so basically in this demo I'll
start Task
manager and next I will start also
notepad and as you can see notepad has an entry in the task list and then I'll open my special tool I'll start a driver and I'll send a special I octal and now notepad is gone from the process list although the process is still active we can see it clearly the window and even if we look for the window in process Explorer it will say that it is unable to find the windows owning process in the current process list okay so that was pretty cool uh now before we go ahead with the next Technique we should talk about the concept of trampolin as an intro um in assembly a trampoline is a piece of code
uh whose sole purpose is to jump to some memory address in arm as opposed to inter architecture it is not possible to jump to an absolute address using a single instruction such as a far jump so in order to do that actually we need free op codes the first op code assigns a register with the page address of our Target address the second op code adds the offset within the page um to the same register which is basically the 12 least significant bits and the third op code jumps to the address stored in the same register and that brings us to our second technique which which is ssdt hooking uh but first what is the
ssdt the ssdt is a table uh whose purpose is to store function pointers that are used as handlers for different csols according to their index in 64-bit versions of Windows um the use of function pointers was changed to an encod dword called a compact offset a compact offset is basically a value that can be decoded into a function pointer by Shifting the value left by four bits and adding The Base address uh of the ssdt table so in order to hook this table we would need to overwrite a value in a specific index which is a compact offset with our own specially crafted compact offset that encodes a function pointer to our hop function our hook function will execute some
malicious code and then we'll jump back to the original cisal Handler function which we will get by decoding the original compact offset so to illustrate uh I made a nice diagram so this is basically how a proper ssdt table looks like where in index 55 uh hex 55 uh it contains a compact offset that can be decoded using the formula to OS scal version of anti create file so by hooking the table uh we will basically overwrite this value in index 55 the new compact offset will be decoded given the same formula to an address that points to an attacker control code and it will make some manipulation to the functions arguments and then we'll jump to the
original um cisal Handler function and this is done basically in order uh so the Cisco will actually be handled and the user will not notice anything wrong so in Fury everything works but in real life I stumbled upon some challenges um the first challenge is that when I tried to overwrite the index value in the ssdt table I found that the memory is flagged as wind only in the kernel so a trick I knew existed in 8664 Windows was basically that we could flip a single bit in cr0 to disable the Cur white protection but that couldn't work on arm well eventually I found that by using mdls I can create a mapping of the
same memory with different permissions and then write to that mdl which surprisingly worked uh and I call this function super copy memory and before the next slide I should introduce another concept called code caves so a code cave is an executable memory space uh in the process address space that contains either null bites un imported instructions or such as break points knobs or other uninitialized data and can be overwritten without disrupting the operation of the original binary so the second hurdle I stumbled upon was when I overwrote the compact offset I had to replace it with another compact offset that will decode using the formula to an address of some executable memory controlled by me or a
code cave where I could write my hook code and the tropine back to the original sisol Handler function address decoded from the original compact offset this means that I had uh double constraint I had to have executable memory and the memory address has to be relatively higher than the ssdt tables Base address but not too far off so the compact offset will not overflow the D size the trivial solution was to allocate some executable memory using ex allocate pu tag and hope that the address uh will fit in terms of being relative to the SS tables based address window so the formula would work but obviously it didn't work and actual solution was scanning all loaded drivers in the kernel for a
code cave pattern which consisted of two knobs which are eight bytes in arm 64 architecture followed by 16 n byes this uh guaranteed that the memory is surely um executable both executable and contain unused code hence it is executable and can be overwritten using the method from challenge one and the final step was to check that the specic the specially crafted compact offset encoded uh from the address can be decoded successfully and then writing the hook and overwriting the the entry so let's see a demo of that so here we have a Kel debugger and we just broke uh the kernel debugger and I'm looking at a specific um cisal Handler for anti add atom which is in entry hex
47 then I will use my tool to get all the csols and look at the code there and I will look for um the entry which is the uh 71 number 71 which is hex uh 47 and we can see that it's unchanged it's basically the original Handler nothing was done to it next I will put the index 47 and I will hook the ssdt and we'll take a second can look at the CIS
calls again entry 71 and here we can see a trampoline so let's investigate a bit in the colonel debugger so looking again at that same entry in HEX 47 we can see our trampoline and we can follow the trampoline um and see where it jumps
too so I I took the page offset and I added it to the original offset and we got anti- add atom so this is a quick PC that I did and basically the fact that we didn't crash means that it worked the third and last technique I found uh started as an attempt to find something similar to an MSR hook on Windows on arm um I began trying uh to overwrite the vbar el1 register that points to K arms exception Ender Vector table sorry but unfortunately I was not able to make this technique work except for making the machine unresponsive but after thinking I was able to get the same effect by hooking Ki system service effectively achieving
a global hook for all systs so basically on the left we have the original Ki system service and what we're going to do is basically overwrite the first three instructions with our trampoline which will jump to our hook then we have the first three instructions that we overwritten our malicious code and the second trampoline to jump back to the fourth instruction so let's see a demo of that so again we have the colel debugger and let's look at the Ki system service
Handler and as we we can see it's unchanged uh it's not hooked yet
okay let's go back to our machine and open our special tool we start our driver and let's investigate a bit so we have the vbar uh el1 address let's look at it and see that it actually points to our Ki arm 64 exception vectors and hex 200 um from that would be Ki kernel exception Handler and 400 from that would be Ki user exception Handler going back to our
tool we will hook the system service Handler now and again we didn't crash so it means it worked we are breaking again to investigate so let's look at the system K system service Handler so we can see that the first three instructions were replaced by our trampoline um and basically if we follow the trampoline uh with the offset and the page address we can see that we have the first three instructions that we overwritten and a second trampoline back um which we'll just validate and yeah it's the fourth instruction okay so thank you for bearing with me that far in the talk um so all the information I just talked about uh was released in a blog in cyber
AR threat research uh blog uh and also the Tool uh to uh check for uh or detect these techniques and let's have some takeaways so IR teams and meow analysts should prepare themselves for a new search of meow and root kits targeting arm and arm 64 security operations center teams and CIS admins should monitor and check mitigation such as secure boot patch guard and Driver signature verification enforcement that they're turned on for all users and machines and it is not recommended for users to install third party drivers from unverified sources even if signed they might contain bugs of vulnerabilities that might allow attackers to temper with the system and yeah that's it if you have
any questions thank you