
hey my name is lucas zamarin and i'm app sec engineer and i do some security researching and exploit development today i'm going to be talking about the current state of exploit mitigations in the linux kernel so the the whole idea of this talk is to give overall overview of uh you know mitigation in the kernel and how they can be bypassed so we're gonna be uh has an introduction we're gonna be talking about a few concepts uh in the linux kernel that's gonna be necessary to understand the mitigations so the first one is uh the kernel memory space so um the linux kernel and most of the modern uh operation systems kernels uh they separate the address space
in in two categories one is the kernel land the kernel addresses space the other one's user lens so in this slide we can see that uh we have some space allocated to the kernel in the higher addresses addresses and we also have the user space applications running in user land in the lower addresses right and the whole idea is the kernel should never directly access user space and user space should never access kernel space unless it's using a system call right uh for example when the kernel wants to access some data from user space uh he has to copy the data into kernel land and do whatever has to do with that data and then
when it wants to send some data to the application it has to copy that data to the userland memory address right so if you take a look in the linux kernel there is a couple functions uh it's copy from user space user user space and cut from copy to user space so those are the ways you manipulate memory uh between the you know the kernel land and the user lens and then we're gonna see later uh why we need that so first thing um the way the kernel allocates memory in the heap is using the function called uh k modlock which is similar to malloc in the gillebc which he allocates a chunk of memory uh
in the kernel addresses space right you can specify how much space you want and the kernel will find one of uh on a kernel cache that match that can fix the amount of memory you are requesting so sometimes you might request i don't know 32 k of memory and you get more than that because the kernel cache used to uh to allocate your the data you requested was bigger than that because the one before that one couldn't allocate 32 uh kilobytes of memory right and same has three in we have k3 that releases memory uh that was previously allocated in new zealand i'm sorry in kernel land right so one thing one thing is really
interesting about the kernel and i thought it was a good idea to to bring that up is the the ref counters so the reference counters in the kernel the reason why i brought i'm bringing that up is because there's a lot of that abilities related to reference counters and then we're going to be looking at one in this talk but what it basically does is it's an integer that can only be modified by atomic updates what that means what does that mean is only one kernel thread can increase or decrease that counter at a time right so it has a lock around that there is a function called atomic and the score increase icr and and
atomic underscore dcr if i'm not mistaking so those those two functions are used to uh you know increase and decrease the reference counter and the reference counter i mostly used to when you have a piece of memory that was allocated in the kernel and then you have different subsystems of different areas of the kernel using that so we got to keep reference so we make sure that we don't clean that memory up before uh all the other uh while we still have other areas in the kernel orders to the systems or functions or whatever uh using that right is a it is a is a way of avoiding things like double free or user use after free
but um it's uh it can also be a problem because sometimes it can get out of sync and it can be released uh while still there is um you know other uh areas of the car not using and we're gonna see that later in this talk right so uh the way that uh the on the kernel memory management works is the most used its lab is lab is the memory management and is also the chunk of memory that it is allocated to you so both things the the way that is allocated the the the code it's called its lab and also the chunks of memories also called slabs right and there are other two uh
different ways of allocating memory uh it depends how your kernel is being compiled but the default is labs so here we have an example so basically what is lab is it's a linked list of chunks of memory so in the in the memory in the kernel memory cache will have the size of that that uh those labs let's say we have a slab that is 32 k they're gonna be they all gonna be in the same link at least one point to another and um and they're gonna be linked to uh some sort of free list and then once they get out of located they it is removed from that link at least and is placed in the use list and once
it gets released it goes to the the front of the of the list so let's say if a chunk of memory was allocated and then released it goes right to the front and if it gets allocated another request relocated the same amount of memories is received most likely we use the one that was previously freed right so here uh we have a a better understanding so we have the full so the full list means it's a link at least without the how they uh slabs used so they how they all have been located and the partial has uh its labs they are used and the ones that are free in a free list all these labs that list they are all
free right uh let's move forward all right so today uh to explain how memory corruption the linux kernel works we're going to be looking at uh this is a old uh vulnerability but uh it was fixed in the kernel uh mains mainstream the main line of the kernel but a lot of the distributions used uh all the virtually they did not backboard they that fix uh back to to their kernels so there were a lot of systems uh vulnerable happen to you like two years ago or three years ago right so what happens for that ability it's is in the key ring subsystem so the key ring is used to store credentials in the kernel let's
say you have an application and you need to store some credentials and you want to make sure that other applications in user land cannot access that credentials in memory don't because it's going to be uh no store in the in your memory so what you do is you you do a system call and you ask the current and say hey can you store these in kernel space and only let my process myself to access and then you can also do other system calls and you can say okay how they how the child processes can also access this this um secret so and that's what the problem begins because every time you have uh let's say
uh the process the process is and you have another process trying to join that key ring so the usage uh field which is a reference counter was increased but then the bug happened when you are already in that you already have access to that key ring to that secret and you keep requesting access to it right so what happened is every time you request access the reference counter was increased and and then it would failed because uh you know the the you already have permission to that secret but it wasn't getting uh uh decreased right was being incremented incremented and it became a a buff sorry integer flow so you wrap around to negative numbers and until it got to
zero so if you keep requesting over and over again it will keep uh increasing until we have an integer overflow and then you ended up with the usage zero and at that point the the kernel uh uh garbage call actually just cleaned that up with basically k free that chunk of memory that you had but you still have a process running pointing to that specific slab so that key ring was stored was allocated in one of these labs in the kernel and then after the integer of the flow it would it was removed but you still had a user space uh process uh and and therefore like also like a kernel keyring process thinking assuming that the data is still there is
still valid right so if you can make the kernel allocate something else on top of that in replacing that same slab you might be able to get the kernel to execute a function that uh is controlled by you i hope that makes sense so the whole goal the exploitation goal to to privilege escalation is to get to these it's called no prepare kernel cred and commit credits with zero that would make your the current contacts invoking being invoked to become a root to become administration in the the system right so in every single local kernel exploitation um local can exploit not everything most of them the goal is to call those two functions with the kernel and
those functions are not you cannot call that from user space you need to need to find a way within the kernel to get that as executed right and uh so one way you could do this is basically let's say you have your key ring being allocated in the kernel space and then it gets you know there is the integer overflow and then it's freed and then you are able to actually allocate some memory in the in its place you can use something like uh send message the kernel that would try and send messages and then you can put your payload there and in the key ring for example it has function pointers which means it's a field is a pointer to
a function in memory so you could you could uh call system send message sending that payload with a function pointer point to a function that you wrote in user space and that function would try and and access uh uh commit kernel creds and prepare kernel credits right because it's still in the kernel context so so that's what uh they call the retro user so basically returning to user space there was a way that uh uh exploit developers used to write current exploits back in the day but then uh there was a mitigation for that which is map so his map does not allow you to do not allow the kernel to call functions in user space and same way
there is a variation in this map or is map that um with a that doesn't allow you to access memory in user space but the important one right now it's map with e uh where basically if the kernel tries to call a function in user space it would failed his map will prevent that and the way it does this is by checking the cr4 register so it checks if the uh one of the bits that is mapped between the training is positioned it's set if it is set it means that it's running in user is running in kernel space that way is map is enabled and and then you cannot invoke a function in user space
you could try and find a gadget that would change the value in that bit so the kind of would think that you are in in user space but that can't mess up the whole system make the whole system unstable and then you might have your kernel crashing so it's not really a uh at least as far as as fast as i know as far as my experience goes it's not really a stable way of writing a kernel exploit right um and now of course you know you can check whether this map is uh enabling your system if you're running a modern kernel for sure it is enabled so you can check in uh slash block flex uh cpu info
or if you have a kernel dump for a crash you can analyze that you can connect that with gdb and you can you can check the value of the cr4
all right uh so the kernel tape page table isolation it's somehow new it was came out of i would say about two to three years ago was a mitigation uh uh tube meltdown and and uh it turns out that it does something really similar to his map it prevents you from reading or or user space maps and and basically making all the user space uh memory not executable this way you wouldn't be able to execute a user space function it's not that it's preventing you to execute it's not like like smap like blocking you for executing it's more like making out the the user uh space page memory page uh are non-executable so this way you
cannot uh you know execute any function therefore you can't you cannot you know become root so it's similar to its map but it was more uh it was built for uh has a mitigation respect uh to melt down uh about two years ago but it turns out that is also protecting uh does something symmetry's map and also protect against uh some other kernel exploitation techniques okay so all right um now let's work with the bypasses right so um the way we do we can bypass this map and kind of uh page tab isolation it's by basically building a gadget okay so uh similar what we do with the user space uh gadgets we can go and we
can find the small or the the uh assembly instructions in the within the chrono and then we can build it up the whole execution the whole flow of execution using assembly only using kernel space address so if you look in this example they are all high addresses which means there are no instructions stored within the kernel user lens so you can you can go and you can build your whole no execution gadgets and you can get you commit credits prepare kernel credits by just use the get so that's uh that's the bypass in uh office map in in case uh kind of pages data isolation uh it works really well um you can definitely bypass but
on top of that uh mitigation there are more other mitigation so they all add up and try to build a a secure uh you know a stable uh um exploit mitigation uh chain all right um okay so again we here are examples so in the previous example we had all the addresses here uh that i'm building the gadget and then i'm just building my payload and i can put that let's say in my uh the data i'm using i'm going to use i'm going to send you the currently you send messages and that's going to get allocated and then i just want to make sure that um my gadget starts the same offset has the function point the pointer i'm
going to be the kernel thinks it's calling right so let's say for example the key ring it has a function pointer to a function called revoke which basically revokes the key ring so i need to make sure that uh when i send my payload it's well aligned that um my gadget starts right at the offset of that function so when the kernel calls that function it goes to my he actually goes to my payload and start executing my payload right all right so how can we prevent that how can we prevent uh you know uh rop return oriented uh uh programming uh uh in in in kernel exploits right so the way we do this it's
similar way we do that in the user space is by basically using address space layout randomization so uh kslr so it scares allies equivalent to aslr in user space so what it basically does is well every time you boot up your kernel it's going to create a number and you're going to use that number to randomize your address let's say uh just uh has an example if your number is two and then you would have and then you have a function at position i don't know position 10 right when when uh when the kernel when ksl is disabled if that function is let's say stored at position pane and then you enable kslr and then carousel generates a number
during blood time and adds that so that function now is no longer at position 10 in memory is going to be in position 12 right that's a really over simple uh example so what case law basically does is that like it's basically randomize your kernel kernel address space to prevent vulnerabilities to be exploited prevent rop payloads to be exploited right and that that in my experience it's been uh the most annoying part of writing kernel exploits because now you no longer one vulnerability in the kernel is probably no longer enough you're going to have to change a couple of variabilities together because what we need now to bypass kslr is to find a information leak so we're gonna find a
link in the kernel uh a function that uh uh i already currently that's leaking a function address right so once we have that linked we know in which position that functions is being stored and then as we disable castle when you're writing the exploit you disable slr and then you see which position that function has been called restore that position and then during both during the exploit expectation time your export is going to do the the the you're going to exploit the information leak leaks out that function address compare that to the one day static that that is one characterize disabled and then you would define the offset and then it's going to kind of
move all your you know rfp gadgets use that offsets you put your rop gadget in the right uh position so it is important that when you are writing an exploit you need to disable kslr to find the the real function address and then you enabled and then you see to which one is going to go to and of course every kernel it's different every machine is going to be different every time you reboot your system it's going to be the addresses will change and that will make the exploitation much much much harder for you right um yeah so as i mentioned like you gotta find an information lead that links the address function and then you're gonna use that as your
offsets uh to calculate your offset to find the the other functions address and if you want to disable kslr you just need to pass nokia slr a flag during boot and then find the editor for the previous functions right um so the way i usually i i try to when i'm when i have an ability to currently i'm trying to rather exploit i usually i disable all the mitigations and i write x to exploit get it to work and then one by one i started adding the mitigation try to bypass so usually i add the this map and kernel page page table isolation i i added those two and i tried to build my rop gadgets
and once i have that then i need to bypass kslr this is a really simple example uh right here so if you see up top the python script that has uh uh address which is as you can see is in the higher address so it's in the granola and right that's the address when castle is disabled so what it does is it's try it's trying to lick that address uh uh it's trying to leak uh his enabled slr licks that address and then you know should be tracked that the leak the leak the liquid address with a static one and then we know the offset so we know the kslr is light so by how many you know bytes we have to
slide the the our rp gadgets addresses so that's it i hope you all enjoyed my talk thank you very much and if you have any questions feel free to reach out um anytime by reach out on email or you know discord or you know just feel free thank
you