 Good morning DEF CON. Yeah. How many of you guys went to the demon saw party last night? Anybody? Yeah, one guy. The fact that you're here means you didn't do it quite right. I was expecting no hands. Did you see McAfee last night? Yeah, I'm sorry. Alright, so one quick announcement. We're going to get started pretty shortly. About two minutes we're going to get this fine gentleman going. When you leave the room, please use the back doors. Not either side. They're pretty well marked. But back doors. We had some issues yesterday. The other announcement is yesterday we were told by hotel staff that there was some unusual traffic on their point of sale network. They have paid for a very, very high class monitoring solution just for DEF CON. And we have a very, very superb, I mean, I know it's DEF CON, but we have a very, very good standing with all the hotels and conference centers in the area for not messing with them too hard. POS system? Not cool. Please do not mess conference center or hotels network at all please. If you really feel like flexing some particular gray or black hat muscles, DEF CON network is there for a reason, bring it on. Alright, so we are right about, we are right on time. That is amazing. So without further ado, Benjamin Hollins, our first speaker of the day. Let's get a round of applause. Yes. Alright. Thank you everyone for coming today. So my name is Ben and today we're going to talk about a way to develop managed code root kits for the Java runtime environment. So just a little background who I am. I guess I would describe myself as a student. I've been a student for a really long time and probably will be for a little longer. So I've worked a few places and I come from Iowa State University. I see a few other people from Iowa State here. So yeah, represent. Alright. Okay. So a little background. First I just kind of want to show you a little taste of what's to come. So here's our simple hello world program. Everyone's probably written this program before, right? So let's go ahead and run it on our victim machine and see what happens. So let's go ahead. Okay. So we've got our just, it's just a Windows 7, latest Java update as of, so Java 8 as of like a week ago. We go ahead and run hello world. It just prints hello world. But we've got a session on this machine. We've got interpreter running. And we're going to load up this custom post module. Okay. And we're going to run this custom most module. I've got a dropper here. We'll explain what that is here. We're going to go ahead and manipulate the runtime a little bit. And then go back over to the victim machine and see what happens. So now when we run hello world it prints backwards, right? So we have the ability to manipulate the runtime. And what are we going to do with that? Well, we can talk about that today. Okay. So first of all, we should probably understand a little something about what the, you know, the runtime looks like at least from a high level. So we take Java code. Just plain Java source files. We feed that into the compiler. We spit out class files. We could run those. Or if we have a bunch of class files we just zip them up. And because we're Java we call it a jar. So that's just a zip file. We take that jar file and we run it on our host operating system. So that's Windows, Mac, Linux. And it seems to run the same on each one, right? So it's cross platform. That's really nice. But how do we do that, right? If you write a C program you might have to change things a little bit. But with Java at least it's, you know, it's standard. So the way we do this is we create a custom virtual machine for each host operating system. And that interprets the standard Java byte code and then runs it on the host operating system. So let's take a look inside those. We have the virtual machine and then we have the standard library, right? We have the definition of what's an object, what's a link list, all the different primitives inside this runtime jar. And what we're going to do today is actually just mess with that runtime jar, right? And because this runtime jar is actually just Java byte code itself, at least for the most part, that also has this nice property of being cross platform, right? So we can write one exploit and then run it everywhere. Okay. So there's a few advantages. First of all, I just want to make it clear that this is a post exploitation activity. So you've already gained permission on the box. You can write to usually these kind of protected directories. So program files on Windows is where they store the Java runtime. Of course, if you didn't store it in a good place, someone could just manipulate it without having administrator privileges. But the important part is that we're not manipulating the program itself, we're manipulating the runtime. So actually, we can affect every program that's running. So any, that Hello World program, we didn't touch that program at all. We touched the runtime and the Hello World program behaved differently because we modified the runtime. So, you know, there's some nice benefits of this. Typically, we audit the application code. We don't audit the runtime. So, you know, someone might overlook this. And we have a lot of contextual information about the application, right? So if we wanted to do something like grab the password field, we don't have to write an entire key logger. We could just key log maybe just password fields of applications. So we have some more contextual information at the application level. And of course, since we're manipulating the runtime and we're doing it, you know, at an object oriented language, these are full featured libraries. So we can write object-oriented root kits. We can use the standard library. We have lots of access to kind of some low-level things that you might not think are in there. So we can mess with key events, networking, all sorts of things. Okay. So there's been some pioneering work. I'm not the first to do this. And I'm not really expanding on kind of the main technique. I just want to expand on a new way to do this. And so Eris Metula gave me this book. And he's done a lot of work on this already. So if you're curious about, you know, kind of all the things you can do, you can check out his book. It's called Managed Code Root Kits. And he also released a tool called Reframewrker. It worked on .NET Runtimes. It was able to kind of specify XML tests of how to manipulate the runtime. And this uses an assembler and disassembler pair to make the modifications and has some deployment scripts. So it really kind of laid the framework, the groundwork for how we're going to do these. But when I started thinking about this, I wanted to do this for Java because I'm kind of a Java nut, as some of my friends know. And well, the previous tool was for .NET. So I thought, well, I have to extend this. But I have an opportunity to think about, you know, how am I going to modify the runtime? So there's a couple of different ways you could approach this problem. We have byte code. We could just try to manipulate the byte code right away. But this is, this is pretty difficult, right? It would work. But say you change a variable name or a method name, well, that has lots of references in the code. So we have to kind of change all those, those little references and the butterfly effect gets kind of a pain to manipulate. Also, we, you know, most people don't speak raw Java byte code code. So that's just kind of a pain. You know, ideally we could just decompile this, get the source, edit the source, recompile it and we're done. But if anyone's decompiled apps before, if you're lucky it that it even compiles, it's probably not even right to start with. So decompiling things is definitely a hard problem. Very hard and we're not going to have perfect decompilers. So people come up with things that are kind of in between. So we have these intermediate representations. They're used a lot in compiler optimizations. For Java, you can think about Smalley or Soot to Jimple, any of those representations if you played with those. But this is nice because we can decompile it to this kind of halfway point. It's not quite source code, but it is text, it is like, it is a source code but it's not Java source. And we can edit that and then we can recompile it. And we, and we, we come to this halfway point because we can guarantee that we can go back and forth between decompiled and compiled output. So, you know, these, the editing the byte code works, it's a huge pain. We can't really rely on decompiled source although we'd really like to work with that. And then working with intermediate representations was kind of my first approach and, you know, it has been kind of proven people have done this. But it's still tricky. You know, we, we learned to write code at the normal source level. We don't write code at an intermediate level. It's just kind of a, you know, it's just something we can, we can write tools for. But, um, yeah, but it's still tricky. So, I thought, I really, really want to, to just be able to, you know, lower the bar, the barrier to entry so that if you know how to write basic Java programs, then you can write a managed code root kit too. Um, so that's kind of the new, the new goals of the framework, right? I want to support the Java runtime environment. And I want this just really low, um, knowledge prerequisite. So, uh, just quick, show hands like who has ever written just a basic Java program? Okay, yeah, so you guys can all write a managed code root kit now. So that's fun. And also terrifying. Um, alright, so the other thing is we want kind of this natural development environment. If you've written a Java program, you've probably used Eclipse, right? You, you at least, whether or not you like it, maybe, maybe you like another, uh, IDE. But, um, it's, it's familiar, right? You know how to debug your program. You know how to, um, how to easily deploy your program. And again, if we can write something from high level and source, we don't, we can strive towards this portability. Um, and we don't have to worry about kind of low level details in the, the runtime. So, um, I want to, oh, yeah, I have this slide. Okay, so we want to write root kits and Java source. This is the tool itself. I called it JRE, ReframeWorker. Um, and that's kind of a rip off of Aira's, uh, Metula's, uh, ReframeWorker, um, just because kind of a, a common pattern is just to add J in front of a Java project. But then I noticed, oh, J, JRE, that's nice. So I, I kept it and I kind of attached to the name. Um, so, uh, it's an Eclipse plug-in so you can work right inside Eclipse. Um, we have, uh, an ability to, uh, export a way to drop the payload on the, on the victim machine. Um, so that's, that's all kind of abstracted away from you. Uh, it's open source, free, so you can play with it, hack on it, um, and, uh, have fun with it. So, um, there's been some early feedback on, on Twitter. Um, so some guys said, just what the internet is dire need of a well engineered malware development tool set. Um, I think he was being, uh, sarcastic, but I'm going to take that as a compliment because I like the idea of a well engineered, uh, tool, um, from me. So, um, I want to revisit that Hello World program. So this is, this is all the code that you have to write. Uh, and the idea is what we'll do is we'll extend, since it's object oriented, we'll extend the object that we want to manipulate. Um, and for now just assume that you can extend any object. Uh, so here I'm extending the print stream. Can I run the mouse? Yeah. Okay. So I'm extending the, the print stream and we have these little annotations that define how we want to manipulate the runtime. Um, and these are basically just notes to the tool, they won't end up in the final source. Um, so we're going to say we want to merge these two types. So we're creating a new class called backwards print stream. We're extending the print stream and we're going to merge this new behavior in. And what we're going to do is actually, uh, override the println method to just create a new string, reverse it and then print that string. Okay. Um, and so we have quite a few, uh, different annotations. Not, not too many I guess actually. Um, there's two main types. There's define and merge. Um, so a define type basically inserts or replaces the old behavior. Um, because sometimes you just want to completely blow it away and replace it with something new. But sometimes you want to preserve that old behavior and then, you know, maybe just hook into it or, um, or add a subtle difference to it, but then behave like normal in other cases. Uh, so that's what the merge type is. And you can put these on each thing. You can put it on a class, you can put it on a method, you can put it on a field. Um, and then we'll get to why we need these later, but we can also control the qualifiers on things. So if a class is final and you can't extend it, well you can basically just say, nope, no it's not. And then extend it. Okay. So, uh, I'm gonna do just a quick demo here of, of how to use the tool. Um, so that if you want to play with it, um, that you can. Okay. So let's go over here. Um, so I have a little bit of test code here. Uh, it creates a new file called secret file. It writes to that file, just writes the word blah to it. And then it checks to see if that file exists or not. And then just to clean it up, we delete it. So if I go ahead and run this, um, of course it works. Um, I just ran it with the normal runtime, nothing's changed. Um, but what we can do is actually override this. So I'm gonna extend the, um, file class. And, um, okay, so we've extended, we can use Eclipse to kind of help us out here. We need a constructor. Okay, no problem Eclipse, you can generate that for us. Um, I want to merge this. Let's see, uh, merge type. Okay. I want to merge this into the file class. And what I want to do is override the exist method so that if the file name is secret file, I'll just tell you it doesn't exist. Even though it does, we can still write to it, we can still read from it. Okay. So I'm gonna use another annotation. This is just a, a basic Java annotation. It checks to make sure that the, the method we say we're overriding is actually a method that we're gonna override. Um, and this is the exist method. So public Boolean exists. And, uh, we have to return something. So I'm just gonna return false for now. Okay. And, um, so let's, let's check to see if the file name is a secret file. So, let's see. Uh, let's, let's for say if it's a file, um, and not a directory, for instance, um, and the name is secret file. Then we'll just say, nope. No, it doesn't exist. Trust me. Um, otherwise, let's just use the default behavior. Right? So the default behavior, um, is the method that we're going to replace. So I'm just gonna return the original method. So I'm gonna use the super call for that. Um, so this will later get rewritten so that, um, all of this works. Okay. Uh, and then we also have to say I want to merge this method into the, uh, there we go. Okay. Um, now there's an eclipse builder built into it. Um, so, yeah, I guess I should first say you'll create a new project so you can do new, uh, other, and then there's a jerry reframe worker project. There's support, support for other things too. Um, and, uh, that'll set up the class path, everything like that. So as you're developing here, you're not actually, you'll be manipulating your runtime, but you're not gonna actually affect it. We're just gonna do it locally and then we'll just kinda hot swap it at runtime. Um, so I'm gonna go ahead and build this project here. Um, don't have a, uh, incremental builder yet so you have to do a build clean, but things are coming. It's a work in progress. Okay. So, um, we're building down here the progress. Um, hope it works here. Uh, pray to the demo gods. Okay. So we run it, uh, with the normal runtime it says true, but now we're gonna run it with our manipulated runtime. And it says false. So it worked. Okay. Um, but we know that that file exists because we wrote to it, right? So weird. Okay. Um, now let's take a look at what happened under the hood. So I'm gonna load up, uh, just a, uh, JD GUI, just an easy Java decompiler here. Um, and let's decompile the modified runtime just to see what's in there. So I'm gonna go to Java, file IO, um, go down to file, and I will search for, let's search for the exists method. Exists. Nope. Okay. So here's the original method, um, and all we did was rename it so that we can call it later. And then if we can find the other exists. Okay. So here's our new one, it's the code that we just wrote, and the recall to super now just calls our other method which we, um, made private so that nobody can see it anymore. Okay. So I'm gonna quit that, we'll go back to the slides here. Um, so really easy, right? We can test this, we can run it. Oh, I guess I could say, um, if we don't want, if we want to actually debug this, uh, in our test code, we could go back over here. Instead of invoking the file, we could just try our, our normal one. So if we want to set breakpoints, stuff like that, we can just debug it locally without actually manipulating the runtime. Uh, and then, um, once we're confident with it, we just change the target, manipulate the runtime and everything will work fine. Okay. So now we're gonna have a little bit of fun, right? We have a framework, we can just start manipulating things. So this is, um, this is just kind of a fun one. Um, what I'm doing is overriding the print stream object, uh, yet again. Um, this time we define a new field. Um, it's a integer called Beetlejuice. And, um, every time the println method is called, we look at the stack trace. So we're looking to see who called us, right? Um, and if there was a method named Beetlejuice, we increment that counter. And if the counter is three, then we call this call. And we'll see what that call does in a minute. So, we have to now think about what would trigger this code, right? So we have, um, a method named Beetlejuice, and we're going to, uh, invoke it three times. And, uh, we're going inside Beetlejuice, there's a call to println. So we'll trigger that code. And, uh, it'll go Beetlejuice, Beetlejuice, Beetlejuice. Um, if we run this normally, it's not very interesting. Um, because, actually let me skip forward just a little bit. Since we already explained all that. Okay. Uh, if we run this normally, uh, it's not very interesting. It just prints the hash code of the Tim Burton object. Um, I'm a fan of Beetlejuice. Anyway. Um, but if we run this with our modified framework. Yes. So someone has supported, uh, all of Doom to pure Java. And, uh, just as, um, just as, you know, a test, um, of how much complexity we can shove into the runtime, why not just shove the whole video game in there? Um, so about doubles the size of your runtime, but that's okay. Um, but what's fun is, um, you know, our client can have kind of fun little triggers, you know, of what, of what we want it to, um, of how we want to trigger it. So here's another one. Um, oh, okay. I'm gonna, I'm reordered my examples here. Okay. So, um, this one is just kind of, uh, to show off the other things. So normally if you call the string replace method, it doesn't modify the variable that it's operating on. Uh, so the receiver variable, it doesn't modify that. So in this case, demand replace sacrifice with puppy. Then, um, you know, it wouldn't do anything. So the, the, the normal behavior was, you know, it would just say Satan demands a puppy, or sorry, it demands a sacrifice. But if we make strings mutable, and we make this actually modify the behavior, then string replace works like how some people think string replace works, uh, and actually print Satan demands a puppy. So, um, this one's tricky, um, because a string is sometimes treated like a primitive object, so you shouldn't have to extend the string class. So they make it a final class, um, and you want to be able to treat it as mutable so you can make those assumptions when you're programming. Um, so they actually make the, the value of the string a protected, uh, sorry, a private field, and a final field itself, uh, so that you can't change it. But of course we control the runtime so we can easily, uh, update that. We just say nope, strings not final, nope, the value field is not final, and hey, let's make it protected so that we can actually manipulate it and play with it. Um, okay. So, uh, we can do all sorts of fun things. I just kind of went crazy. There's a whole bunch of modules that had to cut from this talk just for time reasons. Um, but I'll release them all on the, the GitHub repo right after this. Um, so this one, uh, is, it takes whenever someone loads an image like a JPEG or something in the, in a Java GUI, uh, they have to access the raw data of the image. So this just basically adds a hook that says, um, before you access that image, why don't you pixelate it for us? Um, and why would we want to do that? Well, for the glory of Satan of course. Um, and of course we control the pixelation so we can just make this as pixelated as we want. Um, here's another fun one I really like. Um, so this was, this came from a talk and was partially the inspiration for this talk. Um, was, I was trying to, to say, you know, what's the difference between, you know, how do we detect malware if we don't have a definition of malware? Um, so in this case I wrote a spell checker and the spell checker was just a normal spell checker and then I went through and I inverted all the logic, right? So what do we have now? Something that creates typos, right? It just creates kind of realistic typos, follows the same sort of rules, they're just all backwards. Um, and then what we can do is we can hook this into a key event, um, so that the faster you type, the more typos we create and then as you slow down, we start to behave again, right? So it's just kind of killing your productivity, um, and it's really annoying. Um, in fact the first time I, I tested this, uh, I didn't realize that Windows has two different run times, a 64 bit and a 32 bit and, um, I was trying this, I was trying this and I, I just couldn't get it to work, uh, and I was running on the command line, uh, and then I went back to Eclipse and I realized, um, it's working, it's just working on the run, wrong, wrong runtime. Okay, so I have, I have a demo of this, um, so you can, you can tweak the parameters. This one's actually better to run, um, in some sort of test harness so you know what typo is mine and which one's not because I'm trying to type as fast as I can. So when it turns red, it's typing, it's creating typos and then as I slow down, it starts to behave again, um, and, uh, and everything's fine. So, um, you can kind of play with, you know, with a sliding average to see how devious you want to be. There's lots of parameters there. Um, that one's kind of fun. Oops. Okay, back to this slide. Okay, um, so now, um, I really liked this idea. Um, so people will think about, um, you know, we have, we have a CVE and, um, you know, we want to create antivirus to detect the CVE or to detect the malware, right? But what is malware? Um, so I like, I like the CVE. I, I, I've gone through this a few times now and, and I really recommend if it, if anyone hasn't just picked a CVE and tried to just understand as much about that CVE as you can and, you know, go through, try to recreate it yourself. Um, it's a lot of fun and you learn a lot of things. So this one was, um, really popular. There was a Mesplate module. It worked on basically every platform. Uh, the original bug was in Oracle itself. So people like Apple, uh, copied it into their runtimes. Uh, and, uh, you know, it was exploited in the wild and people are just having all sorts of fun with this. Um, and I think that's, you know, probably one of the reasons Chrome doesn't ever let you run an applet anymore. But, um, so we have an existing exploit for this. Um, and, and I wanted, you know, I did an experiment a little while ago, uh, about two years ago just to see, you know, how could I, you know, just change this a little bit just to get it past AV. So we all know AV is bad, right? You know, it's, it's hard to write good AV, I've tried. Um, but anyway, so let's just see, you know, what are all the different antiviruses doing? So I created, um, you know, I took the original proof of concept, um, that was reverse engineered from the, from the, the malware in the wild. Um, I uploaded, so this is 2014. I uploaded it to virus total and, um, you know, 30 out of 55 people detected this and this is two years after, you know, after the exploit was out. So, you know, not, not great. Um, but then let's just start refactoring it a little bit. So start changing the class names, the variable names and we, we lose two people right off the bat, right? We lose two AV right off the bat. Uh, we start just obfuscating strings. So if, you know, we have a string, we just break it up and concatenate it. So, you know, now the AV has to kind of reassemble that or do some symbolic execution, something like that. We can change the control flow so we can start merging methods, splitting things into multiple methods, add dummy, um, if branches, stuff like that. Um, and that one didn't seem to do too much, so nobody was really looking too hard at control flow. Um, but then what we can do is start looking at, okay, well what are the key APIs that people are, um, you know, that people are keying off of? And let's just use reflection or another layer of indirection to call those, um, so that, um, you know, so we throw them off and we lose a bunch of people right away. But of course we, we can do way better. We could just, um, you know, put the whole class into a string, XOR, which is a simple key, just a one byte key, um, and then load it with a class loader at runtime and run it. And so nobody gets that. Um, okay, so not a big deal. Uh, if you guys want to play with this yourself, the, all the source there for all the different versions is online. Um, so I did this two years ago, which was two years after the exploit came out. I decided, let's just do it again one more time. Um, so I run it again and, uh, well we got a new antivirus in the game, um, and six more people found it, but it's, they're still, you know, like 20 people out there that I can't find this. Um, changing the class names, so we actually got a little bit better, right? Um, things like changing the class names, nobody's keying off of those sort of things anymore. Up-fee-skating strings still works a little bit. Um, the reflective invocation still helps, but still nobody can get the XOR anything. And that's, that's a hard problem, I don't blame them. Um, but it's just that easy, right? Anyway, um, so why don't, you know, I was kind of bummed out, this, this, this bug doesn't exist anymore. It was used lots in Java 1.7. Um, they fixed it, but hey, we controlled the runtime, so let's just put it back in, right? And so I called this the reverse bug patch. Um, so, yeah, so I, I'd love to, uh, automate this, um, and so, some day. Anyway, um, so the, the fix was really, really easy. Um, so, uh, I started first, I started, um, downloading all the versions of Java, um, and then, uh, I started doing differencing on them. And you see the fix is, um, they just add, uh, two calls in, um, in the class finder, uh, object to check package access. And this was because, um, basically someone was able to use reflection to avoid a security check by, um, kind of tricking, um, tricking the runtime into thinking that the call was coming from a different origin. So we just add this check and we're fixed. Um, there's another, another check that was added to method finder. This, this CVE actually consisted of two different vulnerabilities that were used together. So we had two separate bug patches. Um, and then they, uh, removed a, a field. Uh, I think this was just a, a case of refactoring later. They removed, uh, another method that we were using for the exploit. Um, so no big deal. We'll just put them back in for you. Uh, and, uh, of course, you know, if you want to upload malware to a target, yeah, that's fine. But why not just upload a vulnerability and then come back and exploit it again later? Right? Because if, if we know we can't detect the vulnerability, then we've lost ourselves kind of a nice backdoor. Uh, and we have lots of examples of great vulnerabilities that nobody's looking for. Um, so of course, I mean, this was expected. You upload this to virus total. They, you know, this modified runtime and, and nobody's going to detect this. So we're not looking for the vulnerabilities. We're looking for the exploits. Um, okay. So maybe some good uses, um, for this. So this was a, um, a master's project that, um, I helped a student with that I was state. Um, so he was looking at things like, can I take old, uh, SCADA HMI applications and secure them somehow? Um, and so if we have a SCADA HMI application, a lot of these happen to be Java applets, which would communicate with some backend server. Um, so he started creating things like, uh, kind of a smart, intelligent firewall, application level firewall, um, that would wrap the, wrap the server. But then we need a way to, if you know, if we want to do something like support two factor authentication, we need a way to, um, give some sort of feedback to the application so that the application can prompt the user for their, their token and then feed that back to the firewall. Um, and we can also do some things like add some profiling logic so we can do something kind of like active defense so, um, we can, we can, of course those could be disabled, but, uh, it's just nice to be able to, to add another layer of, of authentication. So in this case, um, we have this, this SCADA application, we don't have the source code to it, um, but that's not too hard cause we can just find the object, you know, maybe that controls this alarms list and say we want to add additional security around this alarms list, we can, uh, we can add, you know, um, the two factor authentication which, uh, lets you through the firewall, uh, just to access the alarms list data. Um, so in this case, um, it's just a real simple couple lines of code, um, with some JSON that passes the, the result back and forth, um, but we can add this prompt and secure this, this, um, this application. So, uh, I added support to jerry reframewrker to modify applications as well. Um, there's some really early basic support for android stuff, um, that one's really early cause you have to go through some additional tool chains. Um, but let's talk a little bit about the mitigation. So how are we gonna, you know, I'm trying to make this project, I'm, I'm making things a little bit worse by making it easy for everyone to write these. Um, so let's talk about the mitigations. Um, okay, so does anybody see anything wrong with this picture? This is our file example before. Okay, so, um, if we look at the line numbers, these are, these are added by the compiler for things like decompilers or debugging. Um, it's adding to the stack trace, you know, what line you crashed on. Um, but you can see in my framework, I wasn't too, too worried about being super stealthy, I just wanted it to work. Um, but when I inserted the new, the new method, you know, I didn't go back and recalculate the line numbers. So you can see at the end, we're at the, the end of the file and it's like line 2000 something. And now we go line to 18, 19, 21, and then we're back to like 2000 something again, right? So there's lots of fingerprints that, um, the runtime is gonna get added, uh, you know, if you, if you're not manipulating by, at the byte level, some tool is gonna add some fingerprints, um, as a, as a result of its manipulations. Um, so we can start to look for these things. Um, so the easiest way is probably, you know, have a baseline of all the files on your system and know when they should be changing. Did you run Java update? No? Then why the hash change, right? Um, but of course we can, you know, we've rooted the box, so it's kind of game over for you anyway. Um, because maybe I'll just backdoor the Java updater and after you update Java, I'll reminipulate things again. Right? Um, so we, we can have a lot of fun with this. Um, another kind of fun indicator was, um, the Java runtime is about 50 megabytes, but after I manipulate it, it's about 25 megabytes, which is weird, but it's just because I'm using a different compression ratio. So I could try to match the compression ratio of the original library, um, but it doesn't matter. The jar file is a zip file, so it still works. Um, but those, these are some of the indicators that you can look for. Uh, when you rename the, the methods, uh, to, to kind of preserve the old behavior, I'm just renaming methods, so, um, you could just look for that easy prefix. Uh, I have a preferences menu if you want to change that prefix and not use, uh, this default JRF underscore. Um, that's up to you, but, you know, there's still going to be kind of a pattern. You could count the number of methods and know the number of methods in each class file and expect, you know, it's going to kind of grow at this rate with each update. Um, and if you see a huge spike, then you should know why, right? Um, okay, and of course we can use all sorts of code complexity metrics, um, but yeah, we'll have fun with that later. So, the biggest thing is being aware of it, right? So if you're a forensic investigator, um, and things are behaving weirdly, you might want to look at something like this. Um, and this is generally an awareness project. Um, you know, Ara has talked about this about six years ago, and I was really surprised that nobody else had really done anything with this since. Um, so hopefully by, you know, lowering the barrier to entry, people can play with this more, uh, and will be more aware of it as a, as a community. Um, so my biggest point was, you know, if I could do this as an evening hobby, anybody could be doing this, right? And if we're not thinking about it, that's a problem. Okay, so I have some Q and A, um, and if I have tons of time left, I have more modules I can go through. Um, but I'm happy to take questions. Um, I just have this, this kind of closing poem by Robert Frost, which basically is my way of saying, um, there's a lot of work left to do on this. Um, I'd like to support quite a few more things. I'd like to look at other languages. Um, so the Java virtual machine itself, I'll come back to this, but the Java virtual machine itself, um, isn't just for Java. It supports lots of languages. In fact, there's, you know, invoke dynamic was, uh, kind of originally added, uh, to support things like Jython, um, with all their kind of, uh, dispatching. But, um, if we can manipulate the Java runtime itself, we can start to kind of branch out and start to consider other things. So things like JRuby will just call into the, the Java runtime jars to kind of reuse those languages so you can mix and match things. So if you have, um, a JRuby website, you can start to manipulate it that way. Um, and so I just want to say that it's not just about Java. Um, there's lots of managed languages out there and they're all going to have the same sort of issue. Okay, um, so the source code's out there. Um, if you're interested, please play with it. Make feature requests. I'm happy to support it. Um, and I'd like to keep working on this. Um, so thank you very, very much for coming. I'm happy to take any questions you have. Um, thank you. Yeah, that's fine. Hi. So if you're modifying skated devices, perhaps to improve the security by playing with their Java runtime libraries, then the opposite question comes up. How in the world do you discover whether somebody else did it? Yeah, um, so you're asking whether or not, um, so, so if, if, if you modified the, the, the application, how do we know if it was modified for good reasons or for bad reasons? Well, um, just arguing that the number one rule security is that it's easier for the good guy than the bad guy. Yeah, um, so I think this would be something you would want to do. I mean, you would do this in-house, right? You would have a specific need for this application that you, you don't have the source code to this for whatever reason and you want to, you want to add this feature or add this new building. This is a way that you could, sorry, you could, um, modify that binary and then sign it and, you know, keep track of that hash in your, in your deployment system. So it's, I mean, it's just, it's, I'm not necessarily advocating that you should do this, it's just that you could use it for this purpose. Okay, so I'd have to have like, um, uh, a standardized deployment. Yeah, I mean, if you're deploying this, if you're deploying this, this, already you should have some, some system in place for how you're going to deploy it. Um, you know, of course, if, if the application is signed, you're going to have to re-sign it with your own, your own application key and keep track of that because you're not, I mean, you're not going, you're going to violate the, the hashes in the, the manifest by doing this. Thank you. Have you tried to circumvent the, the requirement that cryptographic providers be signed? So you put in your own, like key generator class in the, uh, JRE? Have you tried to do anything like that? No, I haven't played with that too much. I, I basically just got it working and then played with a few modules. Um, are you talking about like the, the class loader stuff or like applet security? Um, where are you talking about with the key, the key-signing? Okay, if you're, if you're creating a, uh, security provider that provides like key generator. Yeah. And you want to use it. That has to be, uh, signed by Sun Oracle. Right. And so you have that jar in the JRE, Libby, XT directory and you have it in Java.security. Yeah. No, I, I haven't tried to, you know, bypass like the key signing on the manifest, anything like that. Um, what I did was, if it was signed, basically I just blow away the manifest, re-sign it with my own key. Yeah. Now you're modifying the JRE and not the application jar. Yeah. The JRE is actually not signed. Right. Yeah. So you could patch that and if key generate, there's key generator and key generator spy, which the security provider provides. Yeah. That would be interesting to have and try that. Yeah. That's a good idea. Hopefully not. Do you provide a way to modify the static part of the code? To modify the stack. So underneath it's using ASM. So, um, if there's things like, uh, say you add a, a parameter to a method, you've changed the, the stack size on the call. So in that case, you have, it recomputes the stack when it makes the modifications. So that part is handled by the ASM library. It's a pretty, pretty robust library. It's used in a lot of things. Can, can you ask it again? The static method of the class. Not, you cannot extend, right? So, oh, if you can't extend it because it's marked final. Yeah. So in that case, there's an annotation. I used to just call it, sorry, who's my voice? Um, I used to just call it not final. Um, but in this case, it's just a defined finality, true or false. So in that case, like string was marked final, you can't extend the class, but now you first run, you first mark it as, uh, not final and then, uh, compile it once. Now you can compile it against it again, uh, and extend it, add your feature, and then compile it one more time. So there's, you can have multiple passes if you want. It's not final, it's only static. Oh, yeah, you can, you can change the whether or not something static, um, well actually no you can't, um, because if it's not static, you've changed quite a few things. If you want it to not be static, I would either just declare a member variable, um, that you're gonna use for that. Uh, if you make something not static, you're gonna impact quite a few things. Um, not sure, I'm actually not sure what the use case for that would be. Um, but if you have one, I can look into, to make him that, yeah. Yeah, so right now I don't handle, um, the static initializers. So, um, you can, it just gets kind of tricky when you start playing with the supercalls. Um, it's, it's something, there's, there's actually this white paper right here, um, talks about one way that you can do that. If you want to merge, say, two constructors or, um, merge the static initializers of two different blocks, uh, two different classes, um, that's something that has been done before. Um, I just haven't, I didn't need it for any of the, the examples that I did today. Okay. Thank you. Yep. Okay. Well, thank you guys for coming. I appreciate it.