← All talks

Bypassing User-mode Hooks 101

BSides TLV · 201923:00153 viewsPublished 2024-11Watch on YouTube ↗
Speakers
Tags
CategoryTechnical
StyleTalk
About this talk
Bypassing User-mode Hooks 101 - Omri Misgav BSidesTLV 2019 - Tel Aviv University - 24 June 2019
Show transcript [en]

okay great hi everyone my name is Omri unlike Yossi I won't have a very nice and cool intro I can't top that I'm sorry I'm currently the security research team leader at and silo we are endpoint security startup and you can see what I do on our technical blog on breaking malware your modern invited to check it out today we're going to talk about user mode hooks and exactly how malware bypassing them in order to achieve their goals we're going to go over some technical background about user mode hooks and just to make sure all on the same page for those of you are not familiar with the subject and then I'm going to show you all the current known

techniques just a disclaimer none of them are my work it's also all stuff that other researchers did or stuff that are found in the wild by used by Mauer and to finish I will show up a couple of new techniques that we developed in attend silo so basically what is looking looking is used in order to intercept calls for functions so we can change how they work and affect their operation to our own liking the user mode walks are extensively used in many security products and tools especially at the endpoint sector a lot of products tend to rely on it mostly the newer ones but the question we need to ask ourself is actually why so first of all writing

user mode code is considered more stable more easy it won't cost cause bluescreens in case of an error most of the time and one of the other major reasons is that the fact that you just can unlike the kernel which on window newer versions of Windows comes with some sort of protection for those of you are familiar with patch guard so you can just do whatever you want in the kernel itself it's much more difficult for when and for the last reason is that at user mode you've got the full context meaning if we take an example web browsers if you use a secured connection with SSL so the data will be encrypted once it got

into the OS layer but before that you can use all the data which is decrypted in the user space like the URL like the headers and the response itself so this whole topic of how to bypass user mode hooks exists for a very long time I didn't invent it but the last couple of years there is significant number of new reports on this subject more and more malware that use that use those kind of techniques methods and a lot of pen testers that show off how they bypass certain products that they have to that they come across when they do their red teaming work so just to get basic familiarity with our function Co looks we will see the

following illustration you can see two types of calls of different system services we can see that there are a lot of points that we can decide to hook a specific function in order to change the result and if we'll take a look on the right we have we have a new layer that was added it's more of a specific case for 32-bit process that runs on a 64-bit machine the operating systems use another layer in user space in order to handle this transitioning from the 32-bit context to the OS itself so how can we actually hook the function like when we'll come to say how the memory looks like what we're going to make what are we going to find so I left

the whole topic of the IIT hooking aside for this talk you can go check it out if you're interested but it's less relevant because it's not very common among vendors what usually happens is that vendors tend to use use inline hooks meaning they go to the specific memory region and change the actual code in memory of the said function there are a couple of ways of doing that the most calm the more common one is by using control flow instructions such as jump or call and basically next our function will look something like that the hook function it's going to look something like that with a jump to a hook and then our code will be executed and we

can decide to do whatever we like change it go back to the original function or just return to the caller another way that we can hook functions is by generating exceptions either with interrupts or one on one byte patches that will create invalid instructions that's the out usually the outcome of using a debugger if you are not analyzing a malware dynamically so that what this is what happens behind the behind the scenes okay so now we're going to start with all the currently known techniques basically there's about eight techniques six of them are very common out there we divided them into four different categories the first one is secondary dll mapping which basically means that we are going

to create separate private instance of the DLL that we want to use and there and that way we it won't have any hooks installed on it the first method that we can do it is just by loading the DLL ourselves manually from the disk if we take a look at this illustration of the process memory we can just read the file and then use reflective loading in order to make it actually executable and usable for us and because we didn't use any actions any type of API is that the system you usually use no books will be installed reflective loading is very known technique that Muller used all the time to run code in memory and

basically you can find a lot of implementations for it online you know many open-source github the second technique is called clone DLL and basically what I'm going to create a new instance of the DLL on disk we're going to move it to a different path I'm going to give it a different name and then then just load it as every other DLL but because it will get a different name it won't be hooked by the specific product that is installed

it's it's very good because it looks like a very regular like every other DLL but it doesn't mean that it's lower levels can't be lower level - it cannot be hooked by it's by themselves so the last technique for this for this group for this category is called the section remapping basically we're gonna create another mapping in this in the same process of the DLL we want to use using the lower level native functions we're going to create a section that represents an image and then just map it once again in the process that way we still get two instances of the DL everyone use and it's pretty easy a lot of drawbacks to this function to this method is some of

them is because we only use the carrot part of the loader and not also the user-mode part of the slaughter the result will be that noise rejection happens so no dependencies are loaded no internationalisation happen because the dll entry point is not cold and the most problematic finger fall is because we map an additional section and relocations won't be handled so if you get the compressed complex code piece of code you wanna use be aware that it might be faulty and this is duet dirt restriction of the actual operating system and but we won't get into that too much so for our next group we got and for a next category and we'll do the system

cost directly usually what we are most interested in doing why we won and the machine is actually use the services that the machine provides and what those provides so we're gonna start up by looking at how the actual system call is done on Windows the the calling convention for for a system call is bypassing the parameters on the stack and placing the index that represents the service that we want to consume from the earth on the EAX register so usually what happens is that books are being placed on that on that instruction and so we can't you read read the instruction with the index ourselves for memory but what we can do is build the stubs our own in our own

code use the Cisco instruction in our own code compile it in our own code and then parse ntdll will note it to load it from the disk parse it and get the indexes themselves and then we can do the same cause ntdll provides the second method here is called evans gate now heaven's gate by itself is not a technique to bypass they work specifically it's more by product of it and it's a very known technique for a 32-bit process on a 64-bit machine to do the transition to the kernel from the 32-bit context without going through the system itself without going through the emulation layer that I mentioned earlier and we can say for the example of the memory

and the memory space and we have two cases here the first is that the 32-bit DLL is hooked so basically we can build a stub in our own code and jump jump directly to the native 64-bit ntdll instance and that's how we bypassed the hook and on the second case in case the 64-bit context is also hooked we can do the same parsing we did earlier for anti DLL and do the do the call ourselves using the Cisco instruction the last technique in this group is pretty self-explanatory it's called bring your own index so up until now if we had to parse all the stuff in order to make it work and now we can just

bring the index with us for example you can see here that I there is a copy of the same function from Windows 7 on the left and now the issue with that is that you have to support every new DLL every new operating system version that we is released so you have to mean - it's you have to maintain your own code you have to be able to deploy updates and if not on future update to the OS your code might break the next cutter will category what we're gonna discuss is by it's called binary restoration meaning that using some sort of memory manipulation we're gonna hand install the hook the first technique here the method that is used is called the

reflective DLL refresh and basically what you're gonna do is load a second instance of the same DLL we don't need it to be actually executable and using the furtive loading we're just gonna load it so we have the same the same code that should be originally on the target DLL we're gonna have separate copy of it and now we can see that there is we can basically do a bend if between the code sections and once we find the mismatch we can just copy over the original the original code and basically restore it and uninstall the hook so for our last group and the last technique in though in the known ones it's called code splicing which is

pretty presumptuous name to bite stealing basically we're gonna build disturbs ourselves of the functions and in different locations we can just read the file pass it we build the stubs in a different location and then in case it's get sucks it get tooked we can just call the stub will call we'll call the original function pass the original hook okay so now up until now we discussed everything that is known everything that has been done before and none of that was our work but we decided it will be a bit boring to show only work of other people and not something that we did so we came up we came up with a couple of new

techniques and there are actually more but had to cut it due to time constraints and so the first one is will be used for anti for direct system call invocation and if you think about it for a second the same interface that the user mode has the same native interface the kernel also sneed to support so it has to be familiar with the same same indexes same services everything else so it basically means that the indexes in ntdll also appear in the canner itself so we can just load it up ourselves and find the functions and indexes ourselves in order to actually you them when we do direct system called so the couple of variations for every

system call there is the empty version which is the actual implementation and there the CW version which is which holds the actual index and if we can if in case there is a ZW version is exported we can just get its address and then we can try and look into that function for the actual index next there is another case in which we don't have the CW version exported but we do have the anteversion exported like in the case of empty head atom and what we can do here is first of all actually find the address for it and now we need to find the SS DT itself in the memory of of the kernel of the kernel image

so basically we can leverage the first method that we used in finding the CW exports and the indexes to find enough candidates of both index and reference to the anti version and then we can just scan the memory and basically find the SS DT without the symbol itself once we found it we just need to traverse it again in order to find basically the reference to our target function so you probably don't understand why I say cannot so many so many times when I talk about user space and user mode code so you can load the kernel into user space also with the regular load library function some applications already do it for example if you're on Windows 10 then

just look at the modules that are loaded by Explorer I don't like I know why they do it I don't really but I don't really know why they do it they use a certain export for it to query the hypervisor though they can just copy/paste according to anti DLL as well if they really wanted the problem with this technique even though it solves us parsing ntdll itself is that not all service not all the system services are available us are available for us not everything is actually exported even though you can see in the list I in the list I compiled here it's pretty useful if you a bit of where with familiar with Marvel research

you can see that most of the functions here can be very useful for you so for our second and last take a new technique and overall new techniques we're going to basically do a binary situation but now we're going to do it in it a bit of a different way we first of all we're going to look at a process and if we just detected that there is an actual hook on this target or not on the DL we want to use we can just basically capture it state meaning that we'll go over on the private and writable sections where data was updated while it began running we're going to capture their values and the current protections

and next we need to refresh we do the Refresh action actually remove the hook will again use the anti the anti native functions we're going to create a section for an image and next up we're going to unwrap the original section and the original DLL and we'll finish by remapping the section at the same base address thus we will have a clean instance of it but if at this point we'll try and use it things won't go very well for us since again we didn't handle it in initializations so we just have to restore the state so we copy copy our buffers to the original to the regions that are writable again we have to

restore the import address table handle some of the exports operations disappear is this tasks to do basically it mainly requires memmove and mem copy operations so this technique is a pretty simple to implement and use and the result will be very much like the original operation of the OS not a lot of private pages for those of you that do some forensics work and stuff like that usually hooks won't be installed here and at this point using those functions but it does rely on anti or native system calls so you can't just use it as is for anti dealer for example and then you do have to take into consideration in a situation of situation of thread

safety and stuff like that so a couple of final words before we finish attackers learn how security products and tools work and they adjust themselves accordingly you can just try and Google protection against mimic cuts and see all the red teamers vitamins publications on this lately I didn't get into it too much but a lot of Malory families are using this kind of techniques those are not necessarily a sophisticated actors or a PT's or stuff like that but even the more common players are using it usually it's done only in the initial state of the attack meaning they implemented basic code injection process soloing and from that point on they are finished with it they don't care they

don't even care anymore if they are being monitored by hooks of some sorts those all of those techniques are very easy to use very simple very trivial most of them you can just find a code online you don't have to do too much except for copy paste the miter frame might have attached framework for those of you or familiar with for some reason and I'm not exactly sure why don't reference this kind of thing as a defense evasion if so if you bypass Asuma Duke they don't see you don't see it as a malicious for some reason and using using security using user mode hooks for security is just not enough this is just a beginning of a research

we did on the subject we're gonna we're gonna release it later on probably in the coming weeks along together with more techniques and new classes of techniques and the source code for some for the new techniques that I showed you today will be available on our github probably this week and any questions

[Applause]