
all right um yeah Welcome to our talk on uh forging chains the Java blacksmith uh what you're about to see is joint work uh yeah of um David who will also be speaking today then Ruben who see in the audience who won't be speaking today uh and then myself uh Fabian uh we um recently uh founded a company here in Cape Town Called worly labs and we're essentially doing security uh Consulting but with a heavy focus on uh bringing in our own uh code analysis tooling so essentially um we try to be quicker um by using a lot of the stuff that we've built in in the past years um what we're going to speak about today
um are Java deserialization vulnerabilities now I mean that's certainly not a new topic I think the big um deserialization Java deserialization apocalypse was uh sometime in 2016 uh with the yo serial work but um it's very troubling how uh people have dealt with the results of this and that's what we're going to be speaking about today um and for those of you uh who are not so much in that topic um this is just a very simple example um of what this would look like in the code so this is the kind of vulnerability we're talking about this is a um it's just a class that uh has an input stream object input stream and that stream um
that comes from an attacker so typically that's um something that comes in over HTTP for example so when you sniff uh on the interface or when you have your burp connected uh in between uh your Target and uh your browser you'll typically see that there's this binary blob in there but some of those names in there so some some um strings are in there that look like Java types when you you see that you know that there's a a Java object sent to the server and the other side so the server is about to deserialize it right and so that already um is a huge problem so it means that the attacker can now specify whatever object they
like and the other side is going to deserialize it now um just uh to clarify that from the beginning um this does not mean that the attacker can now just send uh whatever you know madeup class you know just create new code and then send it over and say please execute this right that's not how it works um but they can load anything that is currently on the class path so anything that's already inside the application and this is a setting that's surprisingly similar to uh you know what we've seen in memory corruption exploitation so in the exploitation of of buffer overflows for example um right in this in the start you know stack based buffer overflows you could
actually jump uh to code that you had just injected but that ended quite quickly the stack was made non-executable so you could no longer include your own code so all you could do was jump to code that was already there and you could start chaining little pieces of code to create your exploit exploit chain essentially um and um yeah this this technique uh well has a few different names uh it's been around for ages so return to lipy Borrowed Cod chunk technique and at some point Academia also um picked this up uh there were a large amount of papers about this and it all started with this one here with this beautiful title in 2007 the geometry of
innocent Flesh on the bone right so these little coat chunks that you use to now exploit the target that's the innocent flesh right and so each of these gadgets is completely harmless in itself there's nothing to patch here um they do ex it does exactly what it's supposed to do but by chaining that now and due to the vulnerability due to due to the ability of you being able to make that first jump right it becomes dangerous and so here's an example of what that looks like in memory corruption this is from a talk we give in 2021 uh on router exploitation so you can see some uh some uh gadgets for myips and you can see
they always end in uh jump um R so that's on myips right and on x86 um that would be a return and that's why it's called return oriented programming you're looking at these little you're looking at these little pieces of code that all end in return these are now your instructions these are the instructions for your weird machine as they say so machine that's there that shouldn't have been there that's the idea and as an attacker you now have control over some of the registers over memory locations and where to jump first that's all and from that you build your exploit now in the Java world we have a very similar setting so here now what we
look for are serializable classes these are the things that we can specify and um serializable classes in Java it's not always that easy to to to deserialize them again to to get them back into a valid state so um what you can do is you can install all of these custom handlers that are going to be called when the D serialization happens and that's your innocent flesh now right so these read object functions that you see there in the code they do some custom stuff and you can think that all of these functions are what I can call First and now I want to chain you know and now I want to go from here to the next thing
and here it's called property oriented programming so um yeah similar concept all right um yeah all fields are under your control so this is similar to the registers in the memory in the memory corruption case except for the ones that are marked as transient and the ones that I marked as static but that's yeah technical detail um yeah that's it so it's the same setting um I would say but the reactions to this have been completely different and that's why I think we need to talk about this again so in memory corruption things are actually okay right so people recognize that if you have a buffer overflow that is the problem you know you need to fix
that buffer overflow and nothing else so I think a good example is the man page of the of the gets function so there's a function um in in Lipsy called gets and there's no way of using it without it causing a buffer overflow it just doesn't do checks and so now this man page says because it is impossible to tell without knowing the data in advance how many characters gets will read and because gats will continue to store characters past the end of the buffer it is extremely dangerous to use it blah blah blah and then at some point it says oh yeah in the beginning it says that never use gets right just don't do it
okay and so here the world is okay now in the Java world it's completely different in the Java world this is this is um read object itself they say warning deserialization of untrusted data is inherently dangerous and you should be avoided untrusted data should be carefully validated right according to the blah blah and this and that right so by saying this last P oh yeah you can still validate this right when you go into an audit to a customer and tell them hey look you're doing you're you're using read object you have a big problem they say but can we carefully validated and things like that and the answer should be no right and this is why we're having
this talk today um it gets worse when you move slightly away from read object right so there's this thing called http invoker service exporter and it simply it pretty much takes all of your hdp end points and says okay let's use the calization for this first it says okay this is the recommended protocol for Java to Java remoting right and then it says warning beware of vulnerabilities due to unsafe Java deserialization this is already weird because the deserialization is the vulnerability it's not that there are vulnerabilities due to the Der serialization and so yeah this we don't want we hope that in 2030 uh the documentation says never dilize attack control Java objects you might as well
use gets or do Heron right um and then you hear people say but all the known chains they're patched so can I please deserialize my data and there's a bit of a fetish in the Java World about deserializing data you know you have RMI that was a big story and essentially this idea of oh we have all of these computers we just program them as if they were one and we don't care about the fact that you know they're actually other computers right that's where this comes from they really wanted de serialized data and now we kind of broke all of that right that's the problem now in memory corruption there's been this long stream of research which
is where people show okay here's a generic way of exploiting a buff overflow and then they started hardening the Heap right to make all the stuff um yeah harder to exploit to essentially patch the chain patch the way of exploiting this but nobody in their right mind would say on oh the Heap is hardened now uh we don't have to patch buff overflows anymore right nobody would say that but in the Java world that's exactly what's happening right so overly confident we stated um you know it's just super easy to find chains right let's just tell bides Cape Town that we can find these chains right and well then we got kind of scared because it's actually not that easy and
the talk was selected so now we're here um oh oh and uh luckily we found the chains so that's good um but uh I have read an awful amount of java code and it was quite traumatizing all right um this thing went off so I have no idea about the time um so the way we got started is to look at chains that existed in the past um and there's the Y so Sero projects that that's the one from 2016 and you'll find a lot of nice chains there but they all don't work anymore and that's not because they were bad to begin with that's because people started introducing patches you know just to make sure that that stuff uh doesn't
work anymore um and so I'll show you one of those chains um which is called The Groovy one chain just so you get a bit of a feel of um you know how do these chains actually work and then we'll look at how they patched it so um yeah you have this chain of priority Q comparator converted closure method closure method and we'll look at each one of them really briefly so a priority Q as the name says is a q where some elements have have some sort of um priority over other elements that means you need to be able to compare the elements in that now if you have a queue like that you want to reconstruct it you
are going to have to check whether um the order is still Cor correct so you need a comparator and the comparator is going to have to be called on der serialization so that little e that you see here that's the comparator that you can include so you know that if you take a priority q and you ask somebody to deserialize it your comparator do compare function is going to be called so that's the first Chunk in your exploit chain the first Gadget second Gadget is Java Dynamic proxies and that is a really weird thing but um the way it works is um in Java you can actually have a class definition um generated on the Fly you know as the
deserialization happens and as an attacker you can specify which interfaces it's supposed to implement comparator in this case and um you can say which invocation Handler is supposed to be called every time a call is made to any of these methods of that interface right so it's a proxy in the sense that you get to catch all the calls and give them to your Handler and so that's the second thing we use we create this proxy and we pass it on to the third Gadget which is the converted closure and the converted closure is just one of those invocation handlers so a function that catches all the calls and then um calls a closure what's a
closure is a fancy word for a function in groovy right so now we can call groovy functions essentially closures and then there's a closure that allows you to call any method Java method or the method closure and so now you intercept that and then pass it on to any method again right and that's the entire chain um yeah there's a comment there in the code it'll become interesting in the moment um but yeah that's essentially how it works so now when we look at the patch that's really crazy that really blew my mind of course they you know you can't just patch out these different gadgets because actually they do exactly what they're supposed to do so they only
patched out one of the gadgets which is this method closure they said yeah method closure is a closure so it needs to be serializable but we can't think of any you know legitimate reason to ever do that so maybe let's just throw an exception when somebody tries to do that right and that's what happened here right so so here you have the patch the patch is also wrong so the patch now says you can still choose to deserialize this if you want to then you can set a variable called allow resolve and then you will deserialize the object but in either case you throw the exception so even though they still enabled it for legitimate use it's obvious that
nobody's using this because otherwise they would have noticed that you cannot use this in anymore right so this is now broken um it's broken for attackers it's broken for everyone at this point right that that was the patch um and um yeah so that one was removed but the first three gadgets are fine we tried them out they work fine no problem with that one so then we thought does that mean that we can still call any groovy method um and we then looked for well groovy closure we looked for different closures and um I found one that just says print line right so that we could just see can we print anything we like
um and then we started we we used that Gadget chain we plugged in that print line closure and we got an exception and it said no signature of method um they want to call do call and they want to put two arguments in there which is f and bar but um all we have is a do function with one argument so that doesn't work so then you think okay well then I'll just use one argument well the problem is the arguments that you see here Fu and bar so those are the elements in a priority Cube if you only have one argument then the comparator is never called because you don't have to compare one element
with anything right you you need at least two arguments so at that point that seemed broken so we thought okay is there is there another Gadget that we could find here that would resolve the situation for us and so what we need is a method that is called with two arguments right two arguments because something needs to be compared um and receives a closure and then calls that closure only on one of the arguments or on one at a time and you actually don't have to read a lot of code to come up with the answer here but the truth is I read a lot of quote until I eventually found out and then I
thought this is really this you should have thought of this and the answer is order bu all right so if you call order Buy on something then the thing that you're going to be passing in is some function that's supposed to uh do the ordering and that one is only evaluated on one of the things right it's just it gives it assigns a number to the thing that you're going to be ordering and yes it's a comparator right and so here you see the code of order by you can see it's a compare function like we want to call and you can see it has a closure and it calls the closure once on the
first object and once on the second object and now it's bridged now it works now the whole thing is open again now we can call any groovy closure with either one argument or two arguments also with three now because the limitation with two was only there because we need at least two to call the comparator right and so this is the code that will um create a serializable object called q and if you write that Quee out you take that binary blob and you give it to that server it will output you are owned right so that was the first working exploit now I hear you saying okay well now you can only print stuff who cares
um there are a lot of closures in there like a lot um in groovy pretty much everything is a closure so here's a nice one um I just GED over the quote bit to just find a few nice ones so this one allows you to set any system property that's very interesting because we have another Gadget that would work if we were able to set a system property I'm not going to show you that one now but um the point here being um you can use this to control all sorts of things where normally you would say well this can be trusted right now suddenly you cannot trust your system properties anymore or this one here it will load an
arbitrary class and called not Constructor on it right so now you can execute any static initializer block and any Constructor with zero uh arguments and usually in these uh static initializers if you can only call a static initializer that's not much fun because you don't control any of the input but together with this one where you can set the system properties now you control system properties that are often processed within those static initializers so you can see this gets worse and worse the more code you read well the worse it gets for the Target and for yourself right I mean it just gets worse and worse right um and then this last one here um you can add URLs
to your url class class loader this means you can say oh there's another jar over there right this also contains nice code that you might want to load right so this is this is definitely um dangerous stuff I would say and uh Warren's saying that uh well you know this is not patched right you can't just take out the method closure and then and then that's patched any anybody can come along uh get another um Gadget and um and the whole thing is open again right and so what I'm trying to tell you is um in real well first of all as I said you can you can call all of these closures in real code bases you can also
call the closures of the actual application you're not limited just to the library so anything that somebody writes you got to think of this like this your programming and any closure you write you have to uh you have to think about okay what happens if an attacker just calls this right I mean that's insane right um and when you look at the chain it's it's only two elements the priority q and the order buy and both of these both of these gadgets they do exactly what they're supposed to do there's nothing to patch here the only thing we patching here is like our general attitude towards usage of read object all right over to you
David all right so um I'm David uh and now where we come in is how do we do this at scale so faon read a lot of code and much of it is what I gave him um but this is sort of the Journey of the research and development of this tool and starting with the research so we have this cauldron of things that lead to these chains or create these chains and one thing we really were exploiting a lot in these Gadget chains and being able to call stuff like comparator and you know if someone overrides compare there all these little methods that come along with you know object or other things that you're implicitly inheriting and
this is going to sound a lot like a CS 101 lecture but um yeah it might not be obvious that something is serializable again you know there's long chains of on the hierarchy but uh anything that happens to inherit serializable is a payload for us um so that is essentially one of our sources and um a lot of in these groovy closures you see a lot of side effects being called um method calls being jumped to here and here it's a lot of uh classes that aren't initially serialized and especially with the proxies you know you can start to manipulate things uh dynamically and a simplified example that's very popular in this is also um
something from closure so if you thought gy was bad it happens everywhere else um so the closure language had these uh also instead of calling them CL like these functions and these were all serializable as well and um highlighted are sort of the important parts of it so you have the abstract table model which uh has a bunch of closure functions and it overwrites hash code so already we have a magic method um and then we start to pretty much anything that inherits function is uh more potential payloads and in a simplified way the hash map or the payload example on the left shows what the kind of vulnerability you're going to construct looks like so we wrap it in a hashmap
because we know that we want to call Hash code and when you're reconstructing a hashmap but all the keys need to be hashed again so it'll then call whatever in our attack controlled um closure function map field uh that will start to have then all of its values hashed and what we defined that behavior was is invoking everything in I function and one of those invokes a value and one of those is a value so we just set the value to our payload and say use the executor um and similarly there was a patch on one of the gadgets to make it throw an exception um and you can see the sort of patent forming of you can
you have the rest they're still serializable but there's one that you can't and uh you can still do a lot of other interesting things um another one that was briefly touched on was reflection um and there are many forms of this kind of uh behavior that we can reach via sterilization detalization uh but briefly Java Reflection uh allows us to read write to Fields but also execute methods using references um new versions of java they limit uh what you can use reflection on built-in but um ultimately you can still change you open a you know hex editor and you can still manually write things and um an example on the right is one class that controls um well they
serializable and gives us a bunch of hooks into a side effect that will'll declare methods we can say Define the method we can Define the class we can Define the command and uh the non- serializable class can be our Target so um you know maybe you have a predefined dictionary of a bunch of classes that can do this and then you just uh generate a whole bunch of bar classes that have those various payloads and see what comes out um method proxies this was something that was brief briefly touched on so it does get worse um there's a more uh sort of uh in-depth example on the right where or you you really need the main
limitation of this is you need the interface so for example we have a Fu interface and we have a Fu object instance and we're going to wrap that object with the proxy so that any calls in that object are going to have be proxied and as also we've seen some of these handlers can be attack controlled serializable so we can Define all of that behavior but then they said this is too limiting we want to handle any Clause so that's where CG Li comes in and that allows us to instrument the bite code dynamically so you're effectively rewriting code while the program's lifespan is happening and um you know you get things like aspect oriented programming that you see in uh
spring spring aop and you know that's used for injecting dependencies and that kind of stuff and that's really CG lib running in the background so if you have spring on your class path you have CG lib on your class path and you better hope that spring isn't dzing attack Control Data so now that we we have a few ingredients um how are we going to actually approach designing uh sort of mass automation of these kinds of things so one of the constructs we depend on is the type hierarchy because again it's an object oriented program so we need to model the classes interfaces polymorphism all that kind of stuff and um this is more about ingredient one
where we need to understand uh what our possible callers are uh a lot of these chains follow call trees and stacks and we need to be able to sort of uh follow those and this is a little example of um some Java this is some standard CS 101 kind of stuff so we have class A which implicitly uh extends object which means it also extends hash code two string uh Etc so that's already on that class and then you have B extends a doesn't overwrite anything so it's effectively some kind of duplicate and then final Class C C and final means you can't inherit from C and it overrides Fu so um that's a whole new call in the call
graph that brings us to the call graph um so before we head on to what that example looks like in the call graph let's look at the three sort of main uh method invocations we want to model so static is pretty pretty chilled it's kind of like see you know you only have one instance you have a class and you say call this function and it's pretty easy to validate and from compile time you see there's only one call that can be made virtual comes from object instances object instances is where a lot of this hierarchy stuff comes in you're inheriting different methods and if you're defining a parameter that's really high up in the hierarchy it could
refer to a call from anyone who inherits it but at the same time it's still a finite set we can still look at all the classes who inherit from it and say it's maybe one of these five calls but with reflection ingredient two we can write code on the Fly um that call could go to code we Define at any point so this is a little bit tricker to uh model and how do we analyze the call graph for the example so let's use an example of this main uh function takes in the three types as the parameters and calls F in all of them um and let's just also use Define some components so the
call sites are the callers the targets the call Le um are the methods and we need the type hierarchy on top of this to define or see what is that finite set of things we can call in the case of virtual um calls so yeah we're going to have multiple call that's one challenge reflection is difficult because we have to potentially track arguments that go in there but we can also approximate certain calls an example of something we approximate is that when you call default read object you're calling read object in all your Fields um we can draw that line manually um and also this representation of its own of just calls is not a call
graph not a control flow it's not a data flow graph so we just see a bunch of calls um so it's not very precise but um it does tell us a lot and is a good starting point um and here's just an example of that source code and the kind of thing we'll see in the call graph so the first two will call uh both FS or potentially both FS uh we don't know unless we see what is actually given to main but C it's pretty safe to assume it just calls food. C and no one can inherit from C so yeah that's a simple simple one but you can see once we Traverse These Chains there can be
quite a state explosion um as they sort of fork onto many potential calls so do we have enough to sniff out Gadget chains well again one challenge we don't have is flow so we could on the path in in the code on the right we have a bunch of attack Control Data being serialized but when we look at something like that sanitizer function can we statically verify that it is being 100% sanitized or can we still get to that file right um and that's a sort of the challenge of static analysis and false positives and all that kind of thing um but it is also a bit more expensive to start doing that kind of
analysis um but we do have y so Y is sort of the uh big open source project that we maintain and it is a really granular static analysis tool that can do t t analysis uses a graph database and you can writes like re nice queries um to see what's happening in the program and also model flows but it is very expensive Ive it's very granular um and you know when you start to call these magic methods like hashmap and stuff like that you're really going deep into the jdk and if you have all that in your analysis you got gigs in memory so let's not go there yet um and a lot of these chains can be much deeper than say
four calls deep so starting you know from scratch let's see what we can do um for bsides so this is where I rub Ruben in I said Ruben we got to make a tool um that can find chains and we basically ingest bite code and we iterate around it and say are there any missing types you know that we haven't seen are they on the class path you know this will often be the JRE classes and we just sort of recursively get these dependencies in we construct the gadget graph which is just a type hierarchy and call graph we look at the payloads which are serializable classes with controllable fields and potentially side effects in the read object behavior and
then our syns will be our like runtime exec and all that kind of stuff or maybe the start of a new Gadget um perform a bread first search and we have these you know basically just call graph chains but they're not very precise so we give that subset of the program to Y and we say can you please validate if these are true or not and then we have a nice list of refined chains that are potentially exploitable um and this is where we present one of the big exploits that we found um again the notion of this is it's not a vulnerability um but if you do have this uh artifact on your CL
class path and you Red deiz Data uh here's something fresh um status I'm disclosed but I did was to try Google and no one has assigned any cves to this so consider this um a Christmas gift from us to you guys so what about what is ZK so they describe themselves as the best open source Java framework for building Enterprise web and mobile apps they say Enterprise twice here so you know it must be big uh in this slide they say Enterprise another two times and describe that JavaScript is bad and they do this business Logic on the serface side so server size UI generated and given to the client um cool our report lit up and
I was like Hey Fabian something looks pretty fishy here and he pointed out yeah there's a lot of weird serializable classes here it's called like scripts and sessions that are serializable interpreters that are serializable um and then I was like okay let's look at the Docks so the docks have this describ this feature this this Z script tags everything is kind of like this XML or HTML extension and you can Define you know custom behavior that generates um UI elements and we've seen this kind of templating before um but usually there's s like tags and they for loops and that kind of thing um but z uh zscript is pretty hardcore there like straight up any language you want you
know Pyon JavaScript brought like a whole you know sub program within your your your script so cool um what's the well we looked at the page implementation class which renders most of the uh UI elements and we found that they just again like the Java do said uh it it's serializable but don't just don't do it um sotally say this is a good place to start um and when you looked at the distalization hook there was a lot going on and a lot of side effects and this was great so starting at top default read object all fields are just you know straight up serialized note checks and then they have addition they expect additional um by code one of them is the
language that you want so we're telling them what language you want to execute uh they do a lookup uh if they have a language definition and an Associated interpreter for that um but you can also send interpreters to it tell it which objects that on the class path uh you want to interpret for certain languages and this renders the page so it immediately executes those interpreters on the scripts that are also tag controlled and looking further into this yeah I mean that's just code execution right so let's craft up halad um it wasn't as simple as choosing your own language um Bean shell was the only serializable interpreter uh but that's still fine um we could use a lot of
builtin defaults and nulls in a lot of places um they're quite null tolerant and we could say here's some Java um we want to Java use this Bell interpreter for Java when you see it and um there were some things we had to set because otherwise you know they don't expect some everything to be null but some you know so we set some basic parts and um you think okay if I use CK really I can disable execution and well yes you can um it is enabled by default and as we showed if you have groovy in the class path we can also control system properties so just don't put those two on the class path
um and actually let me go to the demo so let's see if I can increase that font size okay that's the shortcut uh let's see in any case let's hope that is good um but just the basic description we have on the build the latest version of um ZK and known for the vulnerabilities as you can see there's something unrelated on the class path they bring in um transitively but this essentially all just uh is Java Reflection writing the payload that I described and we're going to open the calculator um so let's run that it is going to generate a file payload.bin now we have payload.bin and we see all these Java words and stuff come up and a bunch
of uh nulls and whatever uh let's look at the read so the read is straight up um file input stream input uh object input stream and the big bad read object so let's read that and we've got an yeah' got a calculator and one thing about these um uh you know big Enterprise um Frameworks they advertise the clients but in this instance they're also advertising potential victims so if you want the payload I can send it to you can start sending it to these guys maybe you know see what comes back just like um plug it yeah just see what happens um and yeah so with conclusion um patching the code doesn't really make sense again it is like buff overflow um
signing cves doesn't make sense uh which is maybe why the ZK thing doesn't have a cve yet or whatever but um you know one could also ask why don't they just write all that to a j file or protoy file um and yeah we didn't we decided not to do vendor communication because it's not really a vulnerability every the file the page renders the page and it's doing exactly what it does but um if you're going to read objects then that's a problem and we didn't find that ZK automatically reads objects so that still needs you know extra gadgets or you to actually intentionally read objects um so our position is that it's too easy to craft new chains um and and
we found a whole bunch we can only present so many in this talk um we have yeah some more if you want to talk to us afterwards um and are there vulnerabilities that can't be exploited um like the old wiso serial ones that did get patched um yes some of them are no longer you know available for us to exploit on uh the newer versions of those libraries but that's also true for buff overflows um not all of them work the same ways that they used to but generic chains are not needed um application specific ones work just as well and a lot of these are open source projects ZK is open source so I could
also um read it but and one thing Atul does do is also in the report give us uh decompile Java so that's the benefit of um when I had to look at all of the whole data set that Ruben M from Maven you know not everything was open source but we could decompile it um and ultimately recording read object is the vulnerability as you could see we can do some pretty wild stuff um and with that we open to questions um here's some more further reading uh if you'd like at the bottom of work in this field in Academia and other hack conferences check out y it's open source you can build your own Gadget tool um and
yeah that's
it cool any questions sure same thing um you mentioned that they just sort of they threw an exception on one method call um
with on here we go yeah so I noticed that they patched out um or they threw an exception for the one method call in the Y serial chain um can you tell us about how they patched the other chains that that's sort of what I'm curious about was it was it equally as like yeah so I I reviewed quite a few of the wio serial ones and um a lot of the times people try to um make the entire class non-s serializable but that's not always possible because um you might be inheriting from some interface that just needs uh or some some Base Class that just needs to be serializable so for that closure that you saw closure you
know is serializable right so all closures are serializable so the only thing you can really do is throw that exception um the patches in general are pretty soft I would say um and it's quite common that uh only one particular piece in that chain is patched and I think that's also because the code is actually doing what it's supposed to do right so you're just you're just create uh creating these small differences that don't impact the functionality much but essentially um Target that particular exploit okay thanks thank you can I ask one more question yeah do you so a lot of this work was manually finding alternative change right like you had to actually search through the
stuff um I I think analogously with the r chains at this point we are having just from what I read we're having like symbolic execution automatically split out R chain is that where this is going you think yes so a lot of the ideally our follow-up work would be either to for example um we're using data flow to valid static analysis to validate but they have been other approaches at fuzz they have been proach approaches that use um symbolic execution um and there's also another aspect of automatically um patching these so CG lip could be used for good in that case yeah so that's kind of the future work we want to look at this um in this
direction okay
thanks cool right thank
you