We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

(emulate|fuzz|break) kernels

00:00

Formal Metadata

Title
(emulate|fuzz|break) kernels
Title of Series
Number of Parts
102
Author
License
CC Attribution 4.0 International:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
This talk will give an introduction to kernel fuzzing using *unicorefuzz*. Yes, yes. We all know fuzzing is a powerful tool to find bugs. For user space software, this is so 2014. Fuzzing kernels, however, can still be a daunting task. The state of the art kernel fuzzer, syzkaller, is somewhat complex to set up. So many unhappy parsers in the kernel remain unfuzzed to this day! Why can we not simply start fuzzing from some random breakpoint in the kernel, you ask? Well of course we can. Let's drop the whole thing into Unicorn Engine, a CPU emulator, and give it input. Simple as that. To stay on the punny side of things, we shall call this method *unicorefuzz*.
29
30
Thumbnail
32:05
53
59
65
81
86
Thumbnail
1:42:59
95
96
Thumbnail
35:58
ConvolutionTelecommunicationChaos (cosmogony)VideoconferencingGame theoryConvolutionRoundness (object)Multiplication signStreaming mediaCASE <Informatik>JSONXMLLecture/Conference
QuiltParsingConvolutionOpen setAvatar (2009 film)Web pageFuzzy logicConvolutionGoodness of fitBitOnline helpOpen sourceRight angleDegree (graph theory)Ocean currentShooting methodComputer animation
outputWeb pageSummierbarkeitData bufferBuffer overflowStack (abstract data type)Fuzzy logicConvolutionStructural loadSoftware bugProper mapCone penetration testCodeMultiplication signInitial value problemComputer animationUMLDiagram
Fuzzy logicCodeoutputNP-hardCodeoutputPosition operatorTransport Layer SecurityConvolutionRepresentation (politics)Right angleComputer animation
Fuzzy logicConvolutionComputer hardwareoutputNP-hardWeb pageState of matterConvolutionSemiconductor memoryInteractive televisionBootingCrash (computing)2 (number)Computer animation
System callConvolutionDifferent (Kate Ryan album)Key (cryptography)QuicksortComputer animation
Server (computing)EmulationDeterminismAsynchronous Transfer ModeConvolutionEmulatorHypercubeWeb pageProduct (business)Convolution1 (number)Software bugEmulatorLevel (video gaming)Different (Kate Ryan album)Computer animation
EmulationSystem callWritingDisk read-and-write headComputer animation
Fuzzy logicParsingBuffer solutionParsingComputer hardwareWeb pageRippingParsingConvolutionControl flowParsingMultiplication signFunction (mathematics)Abstract Syntax Notation OneBuffer solutionComputer hardwareComputer animation
Source codeCodeIdeal (ethics)State of matterConvolutionFunction (mathematics)ParsingMaizeOpen sourceParsingSpacetimeConvolutionFuzzy logicSlide ruleMortality rateSource codeMereologyState of matterBlogComputer animation
Fuzzy logicEmulatorParsingBlock (periodic table)EmulationBefehlsprozessorMultiplicationoutputSoftware testingEmulatorFuzzy logicComputer animation
EmulatorBefehlsprozessorEmulationBlock (periodic table)MultiplicationScripting languageMultiplication signMultiplicationFuzzy logicBlock (periodic table)Translation (relic)MereologyComputer architectureHydraulic jumpComputer animation
Read-only memoryState of matterVirtual machineInstallable File SystemCache (computing)ArchitectureAvatar (2009 film)Wrapper (data mining)Web pageDrop (liquid)Semiconductor memorySoftware bugMultiplication signLibrary (computing)Web pageComputer programmingLevel (video gaming)Computer animation
Wrapper (data mining)Set (mathematics)Core dumpAvatar (2009 film)Read-only memoryPhysical systemWeb pageTablet computerVirtual machineBlock (periodic table)CodeCache (computing)Shared memoryInheritance (object-oriented programming)Control flowWeb pageCore dumpSource codeRight angleProcess (computing)Computer programmingState of matterSemiconductor memoryPoint (geometry)AreaSet (mathematics)1 (number)RepetitionScripting languageComputer configurationDemo (music)Multiplication signConvolutionComputer animation
CloningEmulationFuzzy logicInstallation artWeb pageConvolutionScripting languageProcess (computing)Group actionComputer animation
Function (mathematics)ParsingoutputTask (computing)ParsingoutputMathematical analysisConvolutionRevision controlRight angleComputer animation
outputFunction (mathematics)Read-only memoryControl flowModule (mathematics)LengthImplementationStrutData bufferEmpennageOpen setConfiguration spaceKernel (computing)Open setFunctional (mathematics)Fuzzy logicBuffer solutionPosition operatoroutputParsingOcean currentSemiconductor memoryPoint (geometry)Data structureRow (database)View (database)Set (mathematics)Computer animation
StrutPointer (computer programming)Drop (liquid)outputEmpennageWeb pageFuzzy logicRead-only memoryParsingPointer (computer programming)Real numberoutputStructural loadNetwork socketBuffer solutionWrapper (data mining)ConvolutionData structurePosition operatorControl flowComputer programmingWeightPoint (geometry)Computer animation
Fuzzy logicoutputVirtual machineTime travelComputer animationSource code
Thresholding (image processing)Physical systemDressing (medical)Core dumpAsynchronous Transfer ModePasswordComplete metric spaceFuzzy logicAddress spaceFunction (mathematics)LengthArchitectureFingerprintRead-only memoryModule (mathematics)Control flowSpacetimeConvolutionBlogRippingoutputElectric currentImplementationParsingWeb pageServer (computing)SurfaceVirtual machineFunctional (mathematics)Address spaceConfiguration spaceWrapper (data mining)Arithmetic progressionForcing (mathematics)Revision controlSource codeComputer animation
FlagConvolutionNetwork socketRippingException handlingComplete metric spaceBlogoutputElectric currentFunction (mathematics)Read-only memoryImplementationParsingServer (computing)Interrupt <Informatik>Letterpress printingDirected graphSynchronizationVideo game consoleEmulatorComputer animation
Read-only memoryoutputElectric currentFunction (mathematics)ImplementationParsingVisual systemRight angleWeb pageQuicksortFunctional (mathematics)outputLengthBuffer solutionParsingParameter (computer programming)Computer animation
Hardware-in-the-loop simulationMathematical analysisControl flowModule (mathematics)Function (mathematics)Fuzzy logicLengthAddress spaceComplete metric spaceBlogRippingCore dumpPhysical systemStreaming mediaSineDirectory serviceProcess (computing)DialectInformation securityEmailError messageNetwork socketCloud computingTDMAPrincipal ideal domainOrder (biology)Read-only memoryLine (geometry)Range (statistics)AveragePower (physics)Patch (Unix)Server (computing)Broadcast programmingBefehlsprozessorTask (computing)Keyboard shortcutPort scannerToken ringoutputComputer fileLink (knot theory)Binary fileSource codePersonal digital assistantStatisticsSoftware testingTotal S.A.Uniqueness quantificationCrash (computing)Execution unitLevel (video gaming)Data dictionaryPopulation densityStability theoryGeometryStrategy gameBootingHydraulic jumpVirtual machineEaster egg <Programm>Block (periodic table)LaptopEmulatorDirection (geometry)Point (geometry)Control flowTraffic reportingDrum memoryBitMultiplication signComputer programmingComputer animation
GeometryLevel (video gaming)Strategy gameProcess (computing)Execution unitCrash (computing)Population densityData dictionaryUniqueness quantificationStability theoryGoodness of fitCausalityLecture/ConferenceComputer animation
Complete metric spaceCore dumpStability theoryGeometryLevel (video gaming)Execution unitCrash (computing)Data dictionaryProcess (computing)Strategy gameUniqueness quantificationTotal S.A.Population densityComputer fontReading (process)Block (periodic table)CAN busData typeWritingFlagExclusive orRead-only memoryWordAddressing modeDecimalSoftware testingSystem callError messageException handlingLine (geometry)Computer fileLocal ringAddress spaceFunctional (mathematics)Address spaceBitGastropod shellReading (process)Point (geometry)ConvolutionPointer (computer programming)Crash (computing)Semiconductor memorySoftware bugBookmark (World Wide Web)Level (video gaming)Function (mathematics)PlotterOvalRow (database)Computer clusterVideo gameComputer animation
Uniqueness quantificationStability theoryExecution unitCrash (computing)GeometryLevel (video gaming)Data dictionaryProcess (computing)Strategy gamePopulation densityComplete metric spaceRead-only memoryReading (process)Communications protocolWebsiteLocal ringComputer fileGame controllerThread (computing)Order (biology)Web pageCodeError messageServer (computing)FlagData bufferNetwork socketCache (computing)RippingRaw image formatException handlingConvolutionGoodness of fitEmulatorConvolutionoutputArithmetic progressionSoftwareComputer animation
Network socketRippingRaw image formatConvolutionException handlingMaxima and minimaDynamic random-access memorySoftware testingFlagoutputSoftwareConvolutionCrash (computing)Software bugComputer animationSource code
ParsingDevice driverInstallable File SystemoutputLocal ringAsynchronous Transfer ModeWeb pageNetwork socketRippingConvolutionStability theoryGeometryLevel (video gaming)Complete metric spaceExecution unitCrash (computing)Data dictionaryProcess (computing)Strategy gameUniqueness quantificationTotal S.A.Population densitySoftware testingRange (statistics)BefehlsprozessorTask (computing)Parallel portBinary fileServer (computing)Personal digital assistantBroadcast programmingCore dumpKeyboard shortcutDirectory serviceFunction (mathematics)Port scannerToken ringLink (knot theory)Computer fileStatisticsParsingAbstract Syntax Notation OneSoftware bugWeb pageParsingMultiplication sign1 (number)Virtual machineSpeech synthesisCausalityComputer animation
LaptopPairwise comparisonCore dumpSingle-precision floating-point formatComputer hardwareAsynchronous Transfer ModeEmulationStability theoryGeometryLevel (video gaming)Complete metric spaceExecution unitCrash (computing)Process (computing)Strategy gameUniqueness quantificationTotal S.A.Population densityWeb pageCodeMathematical analysisCondition numberInterrupt <Informatik>Multiplication signVirtual machineState of matterLipschitz-StetigkeitProcess (computing)System callMathematical analysisCondition numberComputer animation
CASE <Informatik>Address spaceXML
ArmAddress spaceWeb pageDampingArmPoint (geometry)Computer animation
Fuzzy logicConvolutionObject (grammar)Function (mathematics)DebuggerPersonal digital assistantInterrupt <Informatik>Uniqueness quantificationStability theoryExecution unitCrash (computing)GeometryLevel (video gaming)Complete metric spaceData dictionaryProcess (computing)Strategy gamePopulation densityFlagRead-only memoryExclusive orError messageWordSystem callModule (mathematics)Line (geometry)Computer fileAutomationBlock (periodic table)EmulatorPerformance appraisalProper mapArmWeb pageArmSystem callSoftware bugNP-hardComputer animation
Open setFuzzy logicParsingDensity of statesDenial-of-service attackConvolutionMultiplication signSoftware bugOpen sourceComputer animation
JSONComputer animation
Transcript: English(auto-generated)
the right talk which I already announced before. So I'm really happy to have here a talk which goes more in technical detail
than the one which you had in the morning. It's about Emulate Fuzz and Break Kernels. So fuzzing is something you perhaps know since quite a time, but now it's about fuzzing kernels which is something I'm really curious about. I'm really happy to have Dominic here. I hope I pronounced that right. You can explain later how it's correctly.
If you have any questions during the talk, please wait until the end, then go to the mic and ask it in there. Because if you just showed them in, that's okay for here, but everybody on the stream and in the video will have to play a game of Jeopardy. So guessing which question it was when they just hear the answer.
So please go to the mic at the end. For now, please give a big round of applause. Yeah. Good morning, everybody. I'm Dominic from TU Berlin, and I'm going to talk a bit about kernel fuzzing.
So we created a little tool. We called it Unicore Fuzz. We, that's me and Bastiaan and Benedict. It's based on a lot of other tools. Right. What does it do? So fuzzing, I think everybody kind of knows. And it'll help you fuzz the kernel using AFL Unicorn,
which is a cool tool by Nathan Foss, and Avatar 2, which is a nice tool from Uricom, and it finds bugs, and it works on anything that you can attach a GDB target, like get a GDB stub in. And it's open source.
So yeah, kernels. You all know what kernels are. Kernels are these things. Fuzzing, I think you also all know what fuzzing is. Fuzzing is basically shooting at things until they break. It's not that interesting. But still, I mean, AFL, which is the main known coverage guided fuzzer,
has been around for quite some years, but we still find loads of bugs. Like, that doesn't make any sense. We shouldn't have any bugs anymore. Why do we still have bugs, even though we have fuzzing now? Well, lots of code is legacy code. Legacy code is not written to be tested. It's pretty hard to test. It depends on all kinds of things,
like globals, proper, non-initialized values that are hard to fuzz and all that things. And also, it's sometimes really hard to get the right input in the right position. So yeah, it's pretty hard to set up a fuzzing harness. And then, you know, the kernel is this weird beast
that interacts with everything around it. It's like this monolithic thing, at least Linux, that if it crashes, it's just gone. You have to restart it or find a way to respawn it quickly. And maybe you overwrite some memory and it doesn't crash. That's even worse because you found a bug, but you will never know about it because it just runs on.
So yeah, it's even worse. And obviously, getting the right state in a kernel, it takes 30 seconds to boot or depends on your kernel. But people are using. I mean, people are already fuzzing kernels, so there must be a way, right? So most of these fuzzers here, prior fuzzers, Trinity, Defuse, Triforce, Syscaller,
and also Sorts, they all use Syscall. So they have this API from Userland, talk to the kernel. KFL's a bit different. That's actually pretty good. Can also do similar things to us. But, you know, for example, Triforce AFL, which is a fuzzer for kernels,
and it's using QEMU to emulate, it's really shaky. Like, if you tried it out and something forks first, like QEMU is an emulator, it emulates the kernel and so on and so forth, if something already had forked at this stage, then it would be weird, and you would be really hard-pressed
to find the same bug again, and so on and so forth. And it's not really, nobody really cares about the product anymore, sadly. The other ones have different problems. You don't get coverage in the earlier fuzzers. And Syscaller is pretty good, for example, but you have to write harnesses for that, pretty,
like, they can only use Qiskalls and so on and so forth. And there's this one guy, Brandon Fogg, who's doing crazy things, but that's just above my head. No, so. Okay, I had this idea, like, let's rip out parsers from the kernel and fuzz them anywhere else. So that sounds like a fun idea, right? Why parsers?
Well, parsers are the main things. They take something, they interpret it, and they output something, and that is really hard to do right, apparently. So that stuff breaks all the time. I have not yet seen a bug-free ASN1 parser, for example. It's just all really hard to do. And they also almost never interact with anything
apart from their little buffer that they operate on. So it's really easy for us to fuzz. We don't have any hardware that needs to interact and everything. So yeah, just copy-paste the whole parser to user and fuzz it there, right? That would be pretty perfect. Yeah, yeah, it would be. But then we come back to the initial slide where I said it's really hard to set up
the correct state for everything. So you would have the parser sometimes rely on weird globals in the kernel or some space that, you know, the kernel is just this land that nobody, you may not even be on Linux or something where you have the source, or you may be on Linux but you have a weird blob
from some vendor that is not open source. So what do you do? Yeah, as I said before, we emulate it. So we use the fuzzer, the kernel, and fuzz it inside an emulator. Along comes AFL Unicorn by Nathan Fuss. It takes input, it drops it in a test harness, and then it fuzzes it.
It uses Unicorn underneath. Unicorn is a fork of QEMU that is just there to be used in like a Python script or some random script. And it can emulate a multitude of architectures. Basically almost everything that QEMU can do more or less. So and then, you know, AFL Unicorn just adds instrumentation on top of Unicorn.
So every time, you know, QEMU does block for block translation, every time a new block gets translated, it just, the jump will be part of the coverage. So it says, oh, I found a new block here. New block is interesting for the fuzzer. Let's fuzz from there next time. Or let's take this into our seats or harness, whatever.
Yeah, so what we do, we have a GDB stub that we can connect to using Avatar 2, which is a Python library that can orchestrate your runs. Like it can also interact with other things than GDB stub, but so far we've only used GDB stub to implement.
And then we have on the other side, we have AFL Unicorn. And every time Unicorn finds some memory that it has not seen before, it'll go ahead, drop like a request to the probe wrapper, as we called it, that will then go on to fetch the memory from the stub.
And if it cannot fetch the memory, that means we found a page that cannot be mapped. So yay, we found a bug. Yup, so the probe wrapper, the one, the thing that wraps Avatar 2, it'll set a breakpoint the first time you launch it in the target. And then once the target is hit, it dumps everything that it can already know about.
So it doesn't dump the whole kernel because that would be huge. It just dumps like the current page and the breakpoints that we have. No breakpoints, sorry, all the registers that we have. And then once the harness wants something more, it still has its little state and its breakpoint and it'll just go there and fetch more memory as we go on.
On the other side, we have the AFL Unicorn harness and it'll just fork, and fork in Linux is a copy-on-write thing, so every page that we touch that is not changed will just stay the same, so it's pretty quick. It's still a syscall, so it's still slower
than if you would do something in process, whatever, but it's actually pretty quick, I'll show you. There's a demo. So what would you do? If you use our tool, if you go to GitHub and download it, at first you download it, obviously. Then you run all the setup scripts that we have. There's one optional one for debugging
and one optional that sets your kernel up for fuzzing to be quicker. And then there's also some helper scripts that we use internally to spawn up QEMO VMs to fuzz kernels. Then you find a parser. That's the biggest manual task. There's lots of manual analysis involved
because you don't know where a parser is. It's this huge blob, so you drop this huge kernel into something and look for something that looks like a parser. It takes input, you know where the input goes to, and it gets an output, right? And then there's a config for our tool.
The config needs where to break and where to stop fuzzing, basically, like where the parser ends. And then there's a function, a Python function that you have to implement that drops the data coming from AFL into its right position inside the kernel memory. For example, if you would fuzz Open vSwitch,
you would take the input and then drop it. This is like this really weird setup because Open vSwitch doesn't take just a buffer. It takes an SK buff, which is an internal Linux kernel structure for socket buffers. And if we would just drop the input anywhere
instead of the SK buff, then we would overwrite all the pointers and they need to be aligned. If we overwrite a pointer with zero, of course it would crash. But in the real world, Linux would never put a zero at this pointer address, so we would find loads of false positives. So instead, what we do, we go and just drop the data where we actually wanna put user,
where the user could also put data so that we have minimal false positives. And then we start the probe wrapper. It'll wait, it'll set the breakpoint, wait, and then once the breakpoint is hit, we can fuzz. And then, yeah, start AFL, starts AFL. And afterwards, we have a nice debugging setup
kinda where you can then see what happened. So let's see what happened. Since I just rebooted my machine, let's see if it actually happens. So there's the virtual machine here. This is inside the virtual machine. It says, oh wow, it's super small.
It's a lot better, right? I guess. Sure, sorry for that. Why is this here? I think white background maybe, this one. Sorry, sorry for that. Thanks. Right, so this is the virtual machine.
And then this is still small. This is inside our unicorn thingy. We can look in the config that we set up. So there's, we set the architecture, we set where the GDB port lives. We just need some addresses that you don't have to care about these.
Then we set the break address. This is where the harness will, where the probe wrapper will break. And then we set where it should stop fuzzing. And then we have an init function that's called before fuzzing. So everything you can do here is called before. So what I did here was, I just knocked out the function at this address,
which is, I can show you in, okay, probably that takes long now. Well, you have to believe me that this would be kprintf. So it just takes forever to just print something. I don't think it would ever return
because it needs some console syncing, and we don't have console syncing in an emulator. There's no interrupts and nothing. And then this is the place input function. This one is a lot easier. This just takes up to 512 bytes. If it's more, we just immediately exit. And then we read rdi,
which is the parameter that we wanna, that is just a buffer. And then we map the page there, so we make sure that there's actually something that we can write to. And then we write the input. The input comes from here, and this is just called by afl magic unicorn. And then this is the length
that we actually have to set right, so the parser knows how much it has to read from that. Oh, it worked pretty well, actually. Did I copy this address? No, okay. Well, it's kprintf. You can, I think you believe me. Okay, so let's do the probe wrapper.
This will set a breakpoint. And then we insert this machine. We should start this function. And now it just stops doing things. It's paused now, the halted voodoo machine. And this guy says, okay, I'm initially done complete.
I'm listening for requests from harnesspy. So let's spawn up harnesspy. Okay, let's spawn up harnesspy not. Let's spawn up afl directly. Let's see what happens. Okay, so this starts afl. And then it starts fuzzing.
I mean, some people may have seen afl before. Who has seen afl before? Sweet. So you see that it finds paths, which means that it's actually instrumented. So the emulator reports back if it finds new basic or jumps between basic blocks. You see that it's not super fast. Before I had like 100 per second,
I think reboot broke something or something. But it's a really slow laptop that we fuzz on now, and it's probably super hot out in the sun. It's fine. Okay, so it starts, it's crawling, it's looking for new paths.
And let's see if it finds something. I think there should be something to find. It's like an easter egg hunt. But of course it's not deterministic, so it might happen any time. Still waiting for new paths, waiting for new paths.
Okay, new paths, fingers crossed. One minute.
Damn it. Oh well, that's fuzzing, you know. Sometimes you don't find something. Okay, let's continue as if we would have found something. Come on, come on. Too bad. Well, I found something earlier, so that's good.
That's live demos. Okay, so anyway, we can continue as if we would have, say we would have found something at this point. Then we could do harness pi minus t, AFL outputs, let's see if, oh, it should have, no, there's no crashes.
So let's say we already found something before at the same place, and then we can do, run it with minus t, which will trace every single instruction, and at the end we find that it tries to read address zero,
and address zero, of course, cannot be read, so it doesn't work. It crashes at this point, which is good, which is what we want. So that means the kernel would also crash at this place. And then we can do it with minus d, which starts the debugger, which is uddebuck, and it's specifically written for a unicorn. That's pretty nice, it does all this,
it looks a bit like your famous favorite gdb shell. You can just step through every single function and you see all the registers. So if we continue here, at some point it'll show us invalid memory read, you see read un-mapped, so we can't map this thing, and we see here the function is at this place,
eight, six, and eight, six, we see there's a move from the address of array x to edx, and the address of array x at this place is zero. So there's a null pointer that tries to de-ref. So that's a nice bug that usually, if I would have found by now,
oh, it did, nice! Oh yeah, so it just didn't wait long enough. So after two minutes, it found the bug again. So that's good. Cool, and then one more thing, just to see that I'm not bush hitting, let's kill this.
That's the probe worker, so we're back in our little thing here, and now we do this one, and then it'll just reboot, and kernel offset, it just panicked, so it crashed. That is the real kernel now, this is not in the emulator.
This is just taking the input from AFL, re-running it as an actual network input to the kernel, and then the kernel crashes at this place. Cool, so this is your little bug. And it works, let's see on what else we have. Cool, so speed, as you've seen,
ah, actually, it could be faster after restart, because then the pages are already there. Oh, it found a new bug, no, it's still only three unique ones. This time it should be faster, actually, because the next time around, it'll already pre-map before fork all the pages, and then, yeah, exec speed should be a lot better.
Okay, yeah, now it's more than four times as quick. So now we should find the bug in less than the time. Anyway, yeah, we found the ASN1 parser bug, that was an ASN1 parser bug. Of course, the Linux has ASN1 parsers also, and of course, ASN1 is never working, so that broke.
And yeah, the fastest we found with the proper machine was the fastest we could, was like four times as fast, because my machine is quick and not that quick, and it's still like 10 times slower than proper AFL, if you would make and port it, and then even slower if you would use something
like lip fuzzer, that would never respawn the process. But it's okay, you know? Problem is, you won't find state-dependent bugs, so something that you need to set up before, you know, some syscalls that need to happen before, or something, you won't find these. But on the plus side, you know, there's no timers, race conditions, nothing,
and yeah, the speed could be better in Unicorn, and lots of manual analysis. Yeah, so Unicorn, where's gsbase stored? X86, 64, just like a pop quiz to the crowd, anybody?
Cool, so yeah, nobody, okay, so gsbase is a register, and Unicorn also doesn't know, or I don't know, they know, but you can't write it directly, usually you can interact pretty well with Unicorn, in this case, that's why we need the scratch addresses, you need to do a workaround for everything.
So there's many things that Unicorn can't do right, hence, you know, that's also why the ARM target is not done yet, because there's also bugs, but it'll happen at some point. The nice things, though, we can now fuzz many things that are not fuzzable easily. And we can reproduce the bugs perfectly,
because, yeah, that's something in syscaller, it's kinda hard, like, they got it now down, but if you have many syscalls and races and everything, it's usually hard to replay those, and that just works now. And then, you know, future work, ARM target, MIPS target, and so on and so forth.
Also one thing, oh yeah, just refined the bug, obviously. One other thing would be the anger. Okay, it's not, anyway, I'm working on a symbolic execution in that thing also, that would be nice to find more paths, and so on and so forth.
So it finds bugs, I think I'm already past my time. We did find this denial of service and some of our stuff, kernel things. Speed could be better, could be worse. And it's now open source, and you can download it and run it and try to find your own kernel bugs. So.