
for coming to my talk I really appreciate it I really didn't think this many people would come but uh I'm really happy to see you all here anyways my name is jack or halt oh and I'm gonna talk to you guys about how to get goofy with Linux kernel functions so alario a little bit about me I've been doing rootkit stuff for about two years I mean my third year here at RIT and I do blue team red team and black team for RIT CCDC and rich SEC two of my co developers are Nicolas O'Brien in the back Thank You Nick and rain who can't be here today and recently they're graduating anyways what is a rootkit
real basic it hides things and allows you to maintain persistence with an avoid detection it's kind of the basic what a rootkit is originally some of them were just like kits of shims so you see IMLS at netstat etc to hide your connection hide your files whatever you're trying to hide you're writing a shim for that binary and then why write a rootkit obviously you know persistence but red teaming we want to not get kicked out of their box a lot of the red teaming we do is around like the competitions we host like IR sec and also for our CCDC team we Red Team them so that they can get practice so that when they go to Northeast and forest is
red teaming them they know somewhat what to expect so this project is born out of that and trying to help them get prepared it's a little over engineered for that but we'll talk about that so first off how many of you know how Linux system calls work like a rough understanding okay so what happens when you're writing a printf function is you have your printf you know library call you call that and printf is going to make a system call right to stand it out and so what it's doing is it starts an interrupt and it specifies some values and the registers the interrupts gets past an interrupt handler which is up in the kernel and it
says okay this is an interrupt for a system call I'm gonna pass this along to the system call table which then evaluates it and says this is this system call this is that system call so if I want to do right it's gonna pass it along and say oh here is the source the data I'm gonna print here's the output so we're doing standard out that's that file handle etc and after that it does the stuff and returns back to user space all from that one interrupt and so what we do when we are writing a rootkit is we're catching the interaction with the system call table so traditionally what happens is the rootkit overwrites the
system call table it's changing the actual address value so we go find right we overwrite it and we have a point to our code in the kernel that's usually some kind of a kernel module so after that you hijack code execution you can do whatever you want and then you can return data based on saving that original value and this allows us to do things like hide files so when they do a get dense call you hook get dense and you hide the file if they're doing that stat you hide list processes etc ideally what we'd like to move toward so that's a lot of the stinger capabilities and goof kit can do a lot of that we'd
ideally like to do look a port sharing which is where even if a service is already running on a port you also listen on the port as the kernel that way for like scored services during red teaming competitions we can have a back door on any scored service that they have which kind of sucks with your blue team oh oh well yeah so let's get into it what's actually happening so again get dance file hiding what we do is we have our magic string will say like RIT red team and any file that starts with RIT red team is going to be removed from the get dense entry so we're actually making a call to get dents first getting the
actual directory entries and then we look through it and say oh this one starts with RIT red team remove it so anything that has RIT red team in it is gonna get removed same thing with proc basically the only difference is we're checking for the process ID to hide processes and we just verify that we're in slash procs we're not hiding random files with the same number like if you hid process 1337 you don't want to hide all files that start with 1337 you really just want to hide that one and so let's talk about goo kit so like I said the standard group kits are overriding the system call table and they're changing where the pointers are
this is kind of easy to detect all you have to do is load the kernel module enumerate the system calls keep a list and keep checking and if the system called pointer ever changes someone's done something and you know that's bad so what we're doing instead of that is instead of overriding the actual pointers we follow the pointer to the function and we overwrite the actual function so there's actually inline assembly that we're injecting into each system call that we hook which hijacks control-flow and we save the original code so we can jump back to it the benefits so this is called inline hooking the benefit of this is that it's harder to detect and
then we couple it with trampolining so that instead of like sometimes you want to pause your rootkit and to do that traditionally what you've done is you've undone whatever rights you did to initiate the rootkit so if you are overriding the system call table you've wrote back your pointers or if you were doing in line hooking you would rewrite the actual functions instead of doing that we're doing trampolining so we copy out the old code we inject our hook our malicious function if it needs to call the ogee code will call the copied out part and then jump to after our hook and then just resumed execution if we want to pause it all we do is we remove
we skip over our malicious section and just let it keep going because we've already saved the og code the benefit of doing these two things is targeted attack and it is much less disk IO whenever you need to pause it which prevents an extremely nice race condition from happening but which if it does happen knocks their box offline which isn't really fun for anyone as a red team you're a part of the learning experience you're not there to be a bully you're there to help them learn and it's extremely extremely extremely disappointing when your box just stock starts stopping every time you try and do something and you're not going to learn a whole lot from that you're just
gonna get sad and probably leave so we're trying really hard to avoid that which is why we're doing that so are you guys tracking did I lose anyone about what's happening if I lost you it's okay we're about to have some pictures which I think will help describe this a little bit better so here's a standard implementation you have the system call table and it hijacks the pointer to our evil right once they're after they call right we get execution because the pointer is overwriting it now here's what goof kit does instead of hijacking the pointer we leave it alone and instead we inject our malicious jump right there in the red box and that'll jump to the kernel
module that we've loaded we do some execution bits if we need to call the original code we jump to the trampoline which is the original code we saved and then at the end of that we return into evil function and then jump back to the original code which is why it's a trampoline you bounced around a lot so there are a few things in place that you have to overcome in order to actually do a rootkit and the first one is you have to find the system call table every kernel after your two has stopped exporting the actual and external table the system call table they used to just have it exported so you could just call like system call
table entry to or entry 3 and get right but people are abusing it and writing rootkits for it so they stopped doing that they didn't do a very good job protecting it though kernel space is pretty limited so if you want to find it you just have to search all the kernel memory you take a known value like sis close and you search for it in the kernel table once you find it you know this one's sis close I'll back up 3 entries and also started my system call table and so that's what we're doing right here this is what a lot of root kits do there's other ways to do it but this is by and far the simplest and most
common way to do it so now that we've actually found our system call table we're going to do an actual hook for it so here's our malicious jump and here's our og code back here we copy out the og code copy over are malicious jump and then we build a trampoline from the og code and a template of our jump so that we can so we hook the function initially we jump to our malicious code which is out there when we want to call the original function we just have to call the function pointer for the trampoline which will execute jump back to the original system call and complete execution there yep so this is the in
line hooking and trampolining there are some protections like the CR zero bit which prevents writing to the kernel which is really great the bypass for it is to turn it off all you have to do is you write to the sixteenth fit in the CR zero register sided toin you say allow execution to disable it you undo it so that's all we're doing when we're writing to the actual colonel and after that this is what our code looks like after that runs so we have our initial hook again jump back so once you poach something there's kind of two things you'll do you're either going to do before you call the original function or after you can just never
call the original function - but that's super suspicious but that would be a way to break stuff so like one thing you might do if you're doing like a octal stuff you really need something to work you can just hard code I octal values and usually if you just return zero something will work it when you get into more complicated stuff it stops working as well but zero is a good return value but for this I did it you name so this was the first one I wrote just cuz it was super simple all we're doing here is we are running the original function we get the file struck the struck UTS name from running the original code right
here which is our this is our function pointer we run it here it creates this buff and then we modify the system variable so that we change it from Linux to a class so if you're running Linux and you see macca less when you're on you name probably something wrong and then the other side is we do who the malicious stuff before we call the original function so like with kill sorry with yeah so with our kill signal handler this is how we tell it which processes to hide and whether to reveal itself or not what we do here is we read the input so we check the process ID and which signal is being sent and then we
see okay this is one of our control signals we're gonna handle it in a special way if it's the process hide it'll find the process modify it and then it'll go back to normal kill execution if it's not one of our special signals then we just let it go and nobody notices so like I talked about there's some protections involved the system call table not being exported right here this is how we get around that by brute forcing there is do you all know what a SLR is so the kernel has its own version called kaa SLR she took me by surprise because I was trying to load it into like a bunch of 1804 and everything was
just being scattered everywhere and I didn't know what was happening I started googling I found out about KS law and I was like oh well yeah that checks out but again it's not too hard to set turn-off all you have to do is set the no ka SLR flag on boot and then reboot the system not great for like advanced persistent threat actors but for a college competition that's fine module sig in force so this is probably the best way to prevent rootkits is just to turn on signing enforcement SuperDuper hard to fake a signed kernel as a sign kernel module it's not really like something you see happen that's what this does is it's just enforcing signed enforcement
it is turning on signing enforcement so your kernel module needs to be signed before it can get loaded into the car there's a few ways to prevent blue team's from doing this one of the ways we do it is we just don't let them write to the file that would allow them to do this it's super obvious because they'll say like permission denied permission denied permission denied and you're like I'm running his route there's no I see Linux permission denied but they still can't do anything about it because what are they going to do and then yep here's our CIO zero bit right here here you can see us disabling the write protection and that's the little
Wikipedia article talking about it so recap this is a super duper over-engineered solution to getting persistence on college students boxes we didn't have to do this there's really no reason we should have done it this way I thought it was cool and so I did it and that's about it there's a really cool problem to solve we did some like inline assembly disassembly in the kernel to figure out where all the instructions need to line up and all the trampolining it's a super fun project again not super applicable or super reasonable solution for college students but it was fun to solve these problems yeah then gonna have questions or comments sure what's up DDS oh I don't know what that is oh are
you talking about like it'll do you preload okay I don't oh no probably not because I didn't know what that is that's really cool I haven't tried it'd be interesting to try out I don't know I don't know enough about fuse to tell you whether it should or should not have a problem but it'd be an interesting thing to try out are you saying statically compiled to not allow boot Flags or I
have not so actually the way to get around unsigned kernel modules that prevent you from writing is to boot into your BIOS or to boot to grub and then modify it there and you just have to do that every time you reboot because you can't actually modify it while the system's running so you have to boot in - you could live boot and modify this file there or do it in the grub config anyone else have questions so yep so this is for the Linux kernel specifically it targets oh sorry yep so Jake asked what kinds of kernels does this specifically target we're targeting the Lynx kernel it's been tested on some versions of four and some
versions of three it's on the github if you want to check out exactly which versions are supported but that's my project right now is one figuring out which versions are supported and then to adding more support because there's a few things that still break anyone okay so this one I've been working on and off for about a year I'm kind of excited to be somewhat done with it I have a lot of projects I want to move on to now yeah yeah so should competitors expect to see this an upcoming event yeah if I'm ready teaming you it might come up yep
where do I see root kits and stuff where
okay so the question was where are root kits going in the future how do I think they're going to change where I want to take this is I want to move it away from a lot of the detection mechanisms that currently work so usually the way you detect a rootkit is through process hiding so if they're hiding a process or the kernel module you can detect that because when you hide a process you're usually hiding it from get dense and so you just have to iterate through and check for known files in each process in the process ID space is relatively small so it's easy for a tool to brute force that and if get dense doesn't show
something but the tool detects something by doing like F stat on slash proc process ID slash like file descriptor slash one and it's checking if that exists because it should exist you'll run into a lot of problems where they'll just see oh yep Compton's hidden this is bad also volatility supports has a tool where you can load in a volatility kernel module and just see like who's hiding from the kernel module list because the way you hide yourself from the list of kernel modules is you unlink yourself from a linked list and so they just iterate through and they check for gaps all right cool thank you all [Applause]