Okay, I guess we'll go ahead and get started. I am Julian Grizzard and I'm a graduate student at Georgia Tech and studying computer security. And today I'm gonna give you a talk on Surgical Recovery from Current-Level Rootkit Installations. And this is on Linux-based systems. So first off, the latest slides, tools, and our spine architecture work is available online. The links to this is on your CD. And so definitely download the latest, spent a lot of changes. All right, so first off, some background on Rootkits. What does a Rootkit do? So a Rootkit is a toolkit that an attacker will use to retain access to your system and hide activity that he's doing on your system. A Rootkit doesn't give you access to a system if you don't have prior access. You have to exploit the system by some known vulnerability or something you figured out, or social engineering or whatever. And then the attacker will usually install a Rootkit in order to come back into the system at a later point in case the password changes or his vulnerability's patched. So how many people have personally had experience with a Rootkit installed on a system they administered? We got some people, oh wow, we got lots of people out there. Interesting, and so what is the recommended thing to do when you get a Rootkit installed on your system? That's right, format and reinstall. So I'm actually going against that grain, you know what I'm saying? Okay, maybe there's more efficient ways to recover from a Rootkit. I mean, what if you got a server that every minute of downtime costs millions of dollars? I mean, how can you format and reinstall that system? So we're going to look at different ways to recover from a Rootkit. So first off, I want to give you guys some background on operating systems because what a Rootkit does is it replaces parts of your operating system. So it's important to understand how an operating system works in order to understand the design of Rootkits. So this is a monolithic operating system. That's just a fancy term for this particular architecture. Linux looks like this. Windows, all the windows look like this. Most systems look like this. So you've got two parts to an operating system. You've got the kernel space and this is the code that runs right on top of your hardware, controls all your devices, schedules your processes, does your file access, network stack, these kinds of things. And you have user space. User space is where the programs that you really care about run. So P1 could be your word processor, P2 could be a LS, bash command, and so on and so forth. Now I want to give you a contrasted operating system design that I'll come back to later. But I just want to give you a preview and compare and contrast to current OSs. This is the microkernel operating system design. The difference here is you have a very thin layer for the kernel space. You have minimal, I mean, only code you have in the kernel is the minimum amount of code needed to guarantee isolation among processes and that kind of thing. All the drivers, video, disk, hardware, network, all this stuff is pushed into user space sitting alongside your user space processes. And each bubble here is guaranteed isolated by the microkernel. So what guarantees this isolation? Well, on the Intel x86 architecture, a lot of you have probably heard of this ring architecture where you have level 0, 1, 2, 3. And it turns out modern operating systems only use two levels. They use level 0 for the kernel, which gives you unlimited access to the hardware. If you have a program running at level 0, you can do anything to any bit anywhere in the computer. And the user space processes run at level 3, which is shown in yellow here. And if you want access, they don't have direct access to the hardware. If you want access to the hardware, you have to make a system call, ask the kernel to do it for you. So I want to show you just real quick how this is implemented in the hardware. There's a 16-bit code segment register on Intel Pentiums and x86 processors. And the lower two bits of that register specify what privilege level you're running at, which is which ring you're in. And this is some test code to test and see which ring you're in. So I'm going to demo this code running real quick. Just a quick demo here. So I have a Linux box running over here to my right. I'm going to log into that. All right, so I have this getcpl program that gets your current privilege level. And it returns three, because I'm running a user space process forking off the command line. Now let's check out the kernel. All right, so I inserted a kernel module called... Well, it's way too big on there. I inserted a kernel module called getcpl, which all it does is... Right here, all it does is pops the CS register from into a variable, and ends it with a three to get the ring level. And if you look at the bar log sys log, you can see that, in fact, the kernel is running at ring zero. All right, I'm going to get my next demo set up, and we'll go back to the presentation. And so these slides here are just showing that. All right, so if you're looking at the operating system, and you want to make a user level rootkit, how do you do it? Well, you attack files on the hard disk, shown in red here. And so you replace ps, netstat, ls, top, password. These kinds of files, you replace those with malicious files that hide your activities. Hide files, hide network connections, these kinds of things. And so when you replace those files, they get loaded into your processes, the green bubbles up there. So that is pretty much the user level rootkit. It's pretty easy to detect. You just run tripwire, check your system against your known good state, and it's not too difficult. We know how to do that. Definitely tripwire has its issues, but there's a way to deal with those. Now kernel level rootkit attacks, they modify the running kernel code and the running data structures, which is this block shown here in red. So anything in there is suspect to being attacked by a kernel level rootkit. And all a kernel is, is a running program on your computer. So in essence, these kernel level rootkits are modifying code on the fly and redirecting that code to malicious code. In particular, the system calls is the gateway from user space to kernel, and that's a good target. And I'll go over those two examples. So first I want to go over a system call and why that is the most popular attack target for kernel level rootkits. So it's important to understand how a system call works in order to A, detect that the system call has been tampered with, and B, recover from it. So what happens, what do you use a system call for? Okay, say you're a user process and you want to read files from a hard disk. Then you can't do that directly because you don't have access to the hardware. So you issue a system call to the kernel to open, read the contents of those files, and so on and so forth. So for instance, let's say we have a sys read system call. What happens? Well, the first thing that happens is your user space process issues an int 0x80 instruction, which says a software interrupt, which indexes into 0x80th entry of the interrupt descriptor table. And that's shown right here. So as soon as you issue that interrupt, you go over to the kernel, the kernel looks up where the IDT is in memory, looks up that 0x80th entry, and executes the code pointed to by that entry. The code pointed to by that entry is the system call handler. And the system call handler is responsible for setting up parameters of your system call, generic parameters, it works, that's the first thing that's called for any system call. And then it calls the system call you specifically requested. So you see this pointer coming out of the code in the system call handler, which points to the system call table. So it references, let's say for sys read, you look up this entry number three in the system call table over here. And that redirects you down here to the sys read system call. And the sys read then takes the parameters given to it by a system call handler and executes your request. So what's the attack points here? Anything in this chain is an attack point. You could redirect the IDT entry, you could redirect the system call handler reference to the system call table, you could redirect individual system calls, you could overwrite the system call with a jump instruction to go somewhere else. All these are susceptible. So, how do you recover from this system call attack? Well here's the algorithm, it's basically installing a new system call table into the running kernel. This is exactly what a rootkit will do, in fact. But we're gonna use a good system call table that has known good state. So the best place to get that is to keep a copy of your kernel on another disk on safe storage and you can rip out these system calls using what I did was modify GDB to get that code out. And so you, it's pretty simple, you just, well, it's somewhat simple, it is kernel stuff, but basically you copy each system call into kernel memory and then you create a new system call table pointing to all those system calls and then you can set the handler to point to that system call table. And there's, you can go full blown, you can, if we go back to this picture, you can set this pointer right here which is on the left for you guys and you can point that to a new system call handler if you want and that way you'll know the whole chain is correct. Okay, so it's a little bit, just want to give you guys some details on, it's not quite that simple, you can't just copy stuff over. When you copy code around in memory, x86 code has these call instructions with relative offset parameters, so you have to adjust them, basically relink them into the kernel. So you could recompile the code if you know where it's gonna be loaded, but I chose just to recompute those relative offsets as I was inserting each system call into memory. And you adjust the relative offset based on where it's placed in memory because you allocate dynamic memory for it and you compare that to where it was originally in memory and you just subtract the difference. Of course, it's a little bit more confusing with the way the Intel architecture works, but that's the gist of it. So another thing is there's multiple ways into the kernel. I'll just give you some background. This is another tidbit of kernel-level rootkit stuff is you can insert a kernel module into the kernel and muck with the system call table. And that's one way to penetrate the kernel. Another way you can get into the kernel is through the dev.kmem.device file. This device file gives you access to the kernel memory as a file. So if you're a user space process, you can open that dev.kmem like it's a regular file. You can seek to it and you pass it a kernel memory address and it seeks that memory and then you can read that data or write to it. Is anybody familiar with the SuckIt rootkit from those people that have had installations on their computers? We got some people, all right. So there's a few more. Okay, so if you want to install your rootkit from dev.kmem without doing a kernel module, there's a couple of things that are tricky. First, how do you find the system call table? You don't have the symbols. And two, how do you allocate memory to insert new code into the kernel? All right, so first I'll just go over how you find the system call handler right quick. This is some code pulled out of SuckIt. First thing you do is you pop the IDT register into memory. And what that is, is that tells you the address. Let's go back a few slides real quick. That tells you where this table is in memory. All right, so now you know where that table is. So then you read the 0x80th entry of that table and you can compute where the system call handler is in memory. And then you can parse the system call handler to find out where the system call table is. All right, so how do you get dynamically allocated memory from the kernel from user space? If you write a kernel module, you just use kmalloc, but you don't have access to that code from user space. Well, the way SuckIt does it is sets up kmalloc as a system call. So there's a number of unused system calls in the system call tabler. SuckIt takes over one of those system calls and points it to kmalloc. So now you can issue system call 180 or something like that and pass it a size, memory allocation size and you'll get kernel memory returns. Okay, so now I wanna do my next demo. Okay, so the scenario here is I've already got root access to this machine, so I'm wanting to install my rootkit to retain access and to hide some files. In this folder right here, I have some bank accounts I wanna store on this computer and don't worry, these are not legit. At least I hope not. Okay, so we've got this data that I don't wanna store on my own computer, but I wanna store it on this machine that I've compromised so I can trade it with somebody else, something like that. So then I've already downloaded my SuckIt rootkit onto the system and I'm going to install it and it's done. So now that directory that I was just showing you up here, this hidden info.sk12 is now hidden. The way this works is anything that ends in .sk12 will be hidden. For instance, if I touch a file called hide.me, you can see that it's there. If I move hide.me to hide.me.sk12, it's gone. So now I'm the administrator of this computer and I believe I may have a rootkit on my system. So what I'm going to do is try and install a new system call table to see if there's any differences in the file system. Okay, so this takes a little bit of time because it's not optimized. It's good for demo though because I can explain a few things. So what you see here is each little block of code, it's copying a system call into kernel memory. It issues a kmalloc for each one of these, copies it in, and then you see these asterisks, asterisks, asterisks, found, dot, dot, dot. It's finding these call instructions and it's recomputing where they need to be relinked to and setting that. So right now we're at about 130 system calls that have been copied into memory. Turns out Linux has 255-ish system calls. And so we'll be through this here in a second. Does anybody have any questions so far? We've got a few more minutes. From what I've found, I mean, that's a possibility that they have absolute calls, but you could relink those in as well. From what I've found, they don't have absolute calls. Excellent, excellent question. I will get to that very shortly. All right, so the new system call table has been installed. Now notice these hidden files come back up. So as you can see, all Sucket was doing was redirecting some system calls. So we install a known good system call table into memory. All of a sudden, these files come back up. Does anybody have any other questions while we got a stopping point in the presentation? How does it catch it? Right, let's go back to that figure. All right, so you're saying this code right here is being overwritten or something like that. Okay, so first off, the tools I was just showing you do not do rootkit detection. Well, some of them do, but the recover rootkit itself does not. I do have the ability to read any system calls, or I could dump this code for sysread to a file and see if it's been overwritten. For instance, to answer your question, that would be the way to do it. It's changing memory. So the way the recovery tools work is, right now it actually just replaces this pointer to a new system call table. And so that's gonna shoot over here into memory somewhere. You got a new system call table over here, you got a new sysread over here. So even if this sysread right here was overwritten, that's not a problem because we aren't depending on that. Good question. Okay, so back to our gentleman's over here's question. Okay, so it turns out if you use devkmem to modify the kernel, as I do with my recovery tools, or even if you use a kernel module to do the recovery, either one of these approaches relies on system calls to do the recovery. So there's an obvious problem here. If you've installed a rootkit that's redirected system calls and you're depending on those system calls that's redirected, then you may be depending on code that's going to prevent your recovery tools from working. Does that make sense to everybody? It's a little bit confusing. Okay, so how do we deal with this? Well, I propose we need a new system architecture. And let me take a minute to explain the vision I have here, which goes much beyond rootkits and much beyond anything like that. I've got this vision of intrusion recovery system. So this is like, you know, you've got your intrusion detection system, you've got your intrusion prevention system, but bottom line is we still have compromises every day. It's still a problem for the foreseeable future. So we need to think about ways to more quickly recover from compromises given that they're going to be a problem. Systems are so complex. So that's why I've come up with this notion of an intrusion recovery system, which has a new system architecture that's not currently used in widely available OSs. And it's capable of verifying the integrity of the running system and repairing that state if it has some problems. And it has, you know, obviously there's got to be some kind of, this has got to be the top most secure piece of your system because you rely on it for, you know, your system running good. So you have to have some kind of way to store known good state for your system. Because if you store the known good state in your system that is accessible by root, then that can be changed. So this new architecture supports these kinds of things. It supports what I call a state hold, which is kind of like a strong hold, but it stores your state instead. And it does these other things. And I'll go over, this is my research right now. So it's certainly in development. And I'm looking for any kind of feedback you guys have. It's probably got some problems, but I'll show you what I've got. And we'll see what you say. So back to the beginning, I showed you, you've got the monolithic operating systems and then you've got these microkernel operating systems. Well, I'm gonna go back to this microkernel operating system. Turns out this looks really good for security applications. If you look at the microkernel, it has about 20,000 lines of code that run the kernel. Compare that to the Linux kernel, which has on the order of 4 million. So we can hopefully better guess or better rely on the microkernel for correctness. Matter of fact, there's some research microkernels out there that try and formally prove that the microkernel is correct. The system calls to the microkernel, there's only 14 or so, just depends on the implementation. Maybe on the order of 10. So you've got a small number of system calls that do basic stuff. You do IPCs, you do inter-process communication, you do thread management, that kind of thing. That's it, actually. All the hardware access, these kinds of things are pushed to user level. So based on this microkernel design, I've laid out this spine architecture for the intrusion recovery system. At the base of the architecture you have the microkernel, which I'm using L4 Fiasco implementation, which is developed by a university in Dresden, Germany. And on top of that runs the guest kernel, the L4 Linux implementation runs on top of that. So you can run a full-blown version of Linux on top of the microkernel. So you're probably more familiar with the term virtual machine than you are microkernel. Turns out these are very highly related topics. Essentially the microkernel does the same thing for us. And so we have this guest kernel, which is L4 Linux running on top of it. At the next level you've got your user processes, and those run just like they do on Linux. You don't even have to modify them. And then over here on the first, only Fiasco runs in kernel mode. So only Fiasco runs in that ring zero, and everything else runs in ring three. That means even if you have root access on the kernel machine, you're not guaranteed access to all bits in the computer system. So on the right here I have at each level a component of the intrusion recovery system. I call them L0, L1, L2, L3. And L0 is just the hardware. There's really no support for that right now, just except the ring stuff. Turns out Intel and IBM, these kinds of companies, are very interested in hardware support for virtual machines. So in the future this will definitely be huge. L1 is a component I have running at the microkernel. The importance of this component is it's able to verify that the guest kernel and the L2 component are operating correctly. And similarly for L2 to L3. And why do I have these various levels in the system? Well it turns out if you're looking at the entire Linux operating system from L1, you're gonna have a hard time interpreting all the data structures, interpreting what's good, what's bad. So it's much easier to run components in each level in order to understand the semantics of that level. And the vertical hierarchy is a way of guaranteeing that those components are not trojaned or stopped or bypassed, these kinds of things. So there's a lot more details here. I just wanna give you a few. I'll just show you the memory real quick. How does the memory work for instance? So down here at the bottom, you have the microkernel L1 which owns all the memory. And it can allocate some of the physical, by memory I mean the RAM. It can allocate some of the RAM to the guest kernel which is shown in red here. And you can see that portions of the memory are still owned by the microkernel and the Linux guest kernel cannot touch that memory. And then in turn, the guest kernel, the Linux kernel can map some of its memory to user space processes. All right, so this is the system. How do we attack it? So you can attack any of these things in user space. If you have root access, you have access to all these components highlighted in red here. So again, the L2 and L3 components of the intrusion recovery system are suspect to attack. And that's why we need L1 to verify that they're operating correctly. So right now, I'm still working on algorithms to determine when L2 and L3 are operating correctly. So far, I only have monitoring the PC instruction counter and verifying the hash of the code at L2 to verify and check that the program counter runs in that code periodically. If anybody's got some ideas on other ways to verify, I'd definitely like to talk to you. Okay, so now I wanna look at another kernel-level rootkit target. So it turns out these same kernel-level rootkits will work on this new spine architecture. They will attack the guest kernel instead of the host kernel. So I wanna go through another target to give you guys some more background on how kernel-level rootkits work. This target is the virtual file system. Now, the virtual file system in Linux is a wrapper that gives you access to all file systems in Linux. And so you can insert your own virtual file systems. If you have an ext3 formatted partition, then you insert that in the VFS and you don't have to readjust your system calls to point to that. Everything goes through the virtual file system. Let me show you how it works. So first off, a system call is issued. Let's say I'll go over the proc file system in this example. Let me back up a minute. So you have lots of different file systems in Linux. You have your file system for your hard disk. You have remote disk storage stored on another network drive. You have the proc file system, which is a file system built by the kernel and gives you information from the kernel, such as task IDs, and so on and so forth. So if you want to, remember, if you wanna get access to the file system, any file system, you have to issue a system call. So in this example, I want to read the contents of the proc directory to see what processes are running on my system. So first, my program will issue a sys read dir. That sys read dir indexes into the virtual file system, which then, and you've told it to open up this proc, some directory in proc. So the virtual file system knows, based on the path you gave it, where it needs to go to service your request. For proc, that's a special file system. It indexes into its root structure. And there's a lot of pointers in that root structure. The F underscore op stands for file operations, I believe. And so for the proc, you look up what are the file operations for that file system. And so there's a F op structure, which is standard. And for each file system, you have to implement a number of function pointers. In this case, read dir is the one I'm going to highlight. So you've indexed all the way in here to read dir. And finally, you get to the proc read dir code. And so that'll then return information back to your system call, and then return that information back to your user program. Okay, so what's the attack points here? Again, it's the same basic idea. Anytime you've got a function pointer, anytime you've got a reference, any code along the path can be redirected. All right, so what's the recovery algorithm for this? Well, now's when we sort of step back and make it more general. So generally, the recovery methods for kernel-level rootkits is consistency checking on the data structures in the kernel and the code running. And you can store a copy of this, what it should look like in your protected spine architecture. And you can use that to check and see if it's been modified in a manner that's against your policy. And if so, then you repair it back to its known good state. And the IRS can do this automatically. And that's sort of the vision, is you have this system that's constantly monitoring your computer for malicious rootkit installations. If that happens, it undoes the damage from it. And furthermore, have longer-term goals of, okay, so yeah, you've got a rootkit installed. You undo this damage. The attacker still got in your system somehow. You also have to figure out how he got out, kick him out, change passwords. It's more than just repairing the system. It's a lot more complicated. All right, so let's go for another demo. Now, for the purposes of this demo, I'm not using the automated repair of the system because you wouldn't be able to see that anything happened. But one thing I wanna show you real quick is I am, in fact, running the spine architecture now. And you can see that I'm running the Linux 2.6.11-L4 kernel, which is, the way it works for the Linux kernel is you port the Linux kernel to the L4 architecture as opposed to the I386, the alpha, so on and so forth. So, in fact, we can go in here and check out our getcpl again to see if our privilege levels have changed. And so, the user processes still run at ring three, which is expected. And let's see what the kernel is now running at. And so, can everybody see this in the back? Or should I call it out for you guys? Move it up? Sorry about that. Is that better? Thanks. Okay, so what I've just done, let me scroll back up for you guys then. Um, so right here I just did the getcpl and it returned ring three, running in ring three. And I've just inserted the getcpl into the running kernel. And you can tell the var log, sys log, and see that it was printed out as running in ring three now. So now the kernel is running in ring three. If anybody out there is familiar with user mode Linux, it's a very similar concept to that, but it's much, much faster. In terms of performance, I'll take a slight venture. Just in case you guys are wondering, you figure about a 10% performance penalty for running in this architecture. So it runs about 90% the speed of Linux running directly on your hardware. Okay, so for the second demo, I'm going to install the Adore Next Generation rootkit. And this rootkit works on the Linux 2.6 kernel. And what this rootkit does is exactly what I was just showing you with the virtual file system. It redirects the virtual file system to malicious structures so it can hide files and processes. Okay, so I've just loaded the rootkit. Notice first off that my Adore NG directory that I was just in is now hidden. That's part of the configuration. It hides whatever your rootkit directory is. And then I'm going to launch this rootme binary, which doesn't really do anything, but it runs. And you can see right here in the process list that rootme is running. Now I've got to scroll back up here and see what my directory was. So I'm going to go back into the Adore NG directory. I'm tabbing over right now, and that's another system call. It doesn't find that there's an Adore NG directory, so I have to type the full path. And there's a user-level utility to go with this Adore NG rootkit, which can hide processes for you. So I want to hide this process 644. So now rootme's gone. All right, so now I'm going to put on my system administrator hat again, and I suspect that a rootkit's been installed. This could be done automatically with the intrusion recovery system, but again, for the purposes of this demo, I will do it manually. And so what I'm going to do is a similar algorithm to the system call table repair. I am going to, but this time I made it a little bit simpler. I just fixed the pointers back to where they're supposed to be. Okay, so I've just repaired the proc file system, and now you can see the rootme file, our process is back. And you can see the adore-ng directory is back. So in fact, we've been able to recover from these kernel-level rootkits. Okay, let's go back to wrap up things here. All right, so I've shown you the ability to recover from some kernel-level rootkits, and presented you with an architecture that's perhaps more robust, and you can somewhat rely on for this recovery. So, I mean, definitely there's some limitations to this system, I'm still developing it now, so any feedback you guys have would be great. Some of the limitations, you know, first off, how can you trust this microkernel? What if the attacker installs a rootkit into the microkernel? Well, you know, that's a hard question, but it's relying on the smallness of the microkernel to be correct to prevent that capability. You know, one of the things that some of you guys are probably thinking about already is, what about direct memory access, where you program a controller to overwrite the microkernel? Well, that's definitely a problem right now, that's a limitation. In future, Intel architectures that support better isolation, that hopefully will not be a problem. So, and finally, you know, just like everything else with security, there's no be-all, end-all solution. However, I believe this IRS can make your systems more reliable and save us a lot more time and trouble. So thanks to a lot of people that have helped me out, you know, there's lots more people on here than I have listed. These people in particular have been helpful. I got some links for you guys, if you wanna find out some more information about what I've been talking about. Various architectures, system projects here, you know, check rootkit, our research. And at this time, we got a few starter questions, if anybody wants to comment on, and if not, if you got your own questions, that's fine. We got about five minutes or so. And also after the talk, I will be heading out that door over there. So if you guys wanna catch me, definitely link up with me outside. So first off, let me just ask these three questions, and I'll take either answer these comments to these questions or your own questions. So I've already asked this question, how many people have personally dealt with the recovery of rootkit? If anybody has a testimony, we might can share that in a minute. Let me read all three of these and then I'll start calling on people. Secondly is, I would definitely be interested to see if anybody's seen any rootkits that use DMA, direct memory access. I've seen a lot of talk about it. Maybe I just have not seen the public talk about it or public implementation. And finally, if anybody has not followed the conventional wisdom of wiping their system clean and reinstalling, I'd be interested to hear that. So this time I'll open it up for questions and comments. Over there. Okay, so the question was with the L4 architecture, can you run multiple instances of your kernel? And the answer is yes. The L4 architecture is in fact pretty much virtual machine architecture. So you can run multiple instances of Linux. System pipes and log files? I have not addressed that yet. Good question. Certainly, but I mean, so it's suspicious, but that's, it's kind of like running a virtual machine, you know. You can tell when you're running on VMware. But, you know, legitimate systems run on there. So that definitely would be able to tell something that's not a normal system. Absolutely. Right. Actually, a lot of the tools that I've written for the system call stuff, it gives you all kinds of information on the system call table. So for instance, you can check and, you can check out all the, each individual system call with these tools. And that is much more surgical. Definitely. Good, good comment. Question here. Hmm. So the question was, one, this system would be useful just for detection, correct? And absolutely. Why am I doing intrusion recovery system as well? Because I'm a research student and we gotta do new and exciting things. So absolutely. And lots of people have talked about using similar architectures for intrusion detection. That's an excellent idea. That'll be the way it works 10 years from now. Got guys in the back? People over here? Oh yeah, absolutely. Matter of fact, I was gonna do a demo on that for this presentation, but didn't have enough time. Recovery from user level rootkits, I've done some work on that. It's pretty much tying a tripwire or aid kind of thing to a recovery program, which just checks your file system periodically and replaces the binaries back to normal. That's absolutely a part of the system. Cause you need the full system. We got a question way back there in the back and then I'll come back up here. That's an excellent question. So Xen is another very similar architecture. In fact, I got a link to that in the slides. Xen is very hot right now. It's a virtual machine architecture, open source. I believe it's England people are doing that. And it's very fast. Matter of fact, so Xen and L4 compete. I am going to compare Xen to L4 in my thesis to see which one would be better. That's just an implementation difference. Either one is certainly suitable. I just chose L4. We had a question up here and then I'll quit after this guy. Okay, so the question is, what's more background on this microkernel? And the reason I chose L4 fiasco implementation is basically it's one of the more mature L4 implementations developed by a university at Dresden. And the team there has been really good at helping me out. You know, any kind of questions I've got, big team there, lots of questions, you know, they've got the mailing list and everything. Comparing it to other, there's also two or three other implementations I could have used. I happen to know the guys a little bit at Dresden, so that's really the only reason. It's a good question. And okay, so I'm going to wrap up and let the next speaker get in. I'll be out here in the hall if you guys got any more questions. Thank you.