 I want to bring up a doctor and doctor who are going to talk about, uh, the, the, the job rocket. Yeah? Let's give these gentlemen a big round of applause. Alright, thank you very much. Alright, thank you. Um, welcome everyone. Uh, as mentioned, we're gonna be introducing and talking about the job rocket. Uh, and so in a few minutes you'll learn about the supremely wicked tool for job gadget discovery. With me is Dr. Bramwell Brizendine. He is the creator of the job rocket. Uh, you'll find more information about the job rocket at jobrocket.com as well as the github and uh, I don't see it here but it's a link later on in the slides so we'll get to it in a moment. Uh, Bramwell's an assistant professor at Dakota State University and um, you can see his contact information at the bottom. My name's Josh Strostein. I'm also an assistant professor at Dakota State and was the chair for Bramwell's dissertation which is where this work was uh, really focused and conducted under. My contact information is also at the bottom of the slide. A couple of quick acknowledgments. Uh, Austin Babcock, undergraduate research assistant at DSU as well. He's studying cyber operations and he put together the job exploit that you'll see here towards the end of our presentation. Um, he is looking for any opportunities for internship and work. So if you're looking for a very talented student, please feel free to contact him or reach out to Bramwell and myself and we'll be happy to put you in contact. Um, we also would like to thank Dr. Jared Damott of VDA Labs. Um, he is a part of the dissertation committee as well as a well-renowned security researcher so a big thanks to him. So what are we going to talk about today? Quick and 20 minutes. Uh, we're going to spend a few moments on ROP. ROP is important to understand in order to understand job. Uh, we're going to get into job jump oriented programming. More importantly, you'll get to know the job rocket a little bit better. Some of the finer points of job exploit development and then it'll be time to take a ride on the job rocket itself. And I'm going to leave that up to Bramwell. So this begs the question, uh, did this work invent job? It did not. There is some references in the literature that goes back about a decade. However, it was sparse. There aren't a lot of tools or, um, other frameworks that are available to help further learn, explore or utilize job in your daily exploit endeavors. Um, so this work really endeavors to fill that gap to provide more literature. And in addition, it also will do this in the windows environment. So, um, again, not a lot of information there for doing job on windows. Uh, what is job? Well, simply put, it creates a side door. If you're having trouble with your exploit chains with ROP and the ROP heuristics being detected, then job may allow you to bypass those mitigations and ultimately get shell code to execute. We're not trying to oversell the job rocket though because job is just another category of code reuse attack. It is not another category of exploit. A little background, uh, you can go back to the late nineties with the return to libc, uh, ret to libc. Uh, that opened the door for ROP return oriented programming. Um, ROP borrows little chunks of code that end in RETs. And there's a couple of important concepts that come along with this. Uh, we have gadgets, which are instructions or a series of instructions that end in a RET. And then we have our chains. And those chains, uh, simply are then a series of gadgets that do something practical, like call a function in the windows API. Um, important thing to note here is that these, uh, with ROP, we're really dependent upon the stack in order to control the flow, the execution of a ROP chain. That changes a little bit with, with job. Um, come some prevalent tools. Uh, ones that likely you have all used before, uh, would be MONA by the Coraland team and Peter Van Neckout, as well as the ROP gadget. Here's an example of a ROP chain generated by MONA. Uh, as you can see the addresses that are gonna be placed on the stack as part of the payload. Um, those are the addresses that are gonna be, uh, the fetched, um, after the, the gadget itself is executed and ends in a RET. So again, going back to the stack in order to control the execution, the flow of that entire chain. So jump oriented programming or job differs, uh, and that we are using jump and call instructions in order to control the flow. So job is really just ROP without the RETs. Uh, while the stack is not available for the control flow, it is still, it is still necessary to use the stack in order to set up and make calls to the windows API. Because remember, we're focused on the windows API here. A couple of different paradigms. We have the dispatcher gadget, the dispatch table. We're gonna do more details here in just a few minutes. The job rocket does use both of those. That's the approach that it's taken. Um, there's also some different techniques available with job that you can use in your everyday ROP. So, uh, a pop jump and where you pop into a register and then jump to that register in order to, uh, go back to the stack, for example, if you're having trouble finding, uh, you know, your ROP gadgets. So you can job and then go back to ROP. So, about those two paradigms that we just, or that I mentioned just previously. Uh, the dispatcher gadget and the dispatch table. The dispatcher gadget is the instrument of change. It moves things forward and backwards in that dispatch table. It ideally should be short and sweet. And it should also be predictable. It should predictably modify the register holding the address to that dispatch table. Uh, the dispatch table then has entries that lead to the addresses of the functional gadgets. And the functional gadgets are what really, um, allow us to, to modify registers and set up the stack in order to make our Windows APL, API calls. Here is a, maybe somewhat oversimplified control flow diagram. You have the dispatcher gadget, which controls flow into the dispatch table, which then dereferences and calls those different dispatch gadgets, uh, or functional gadgets, excuse me. Um, from there, instructions are executed that will feel a bit like ROP. Uh, and then you'll jump or call back to the dispatcher gadget. And the cycle will continue to repeat until if you've accomplished whatever functionality that you're out, uh, to get. That's, my part was brief. So, uh, I'm gonna let Bramwell take it from there. Thank you, Josh. So all of this kind of begs the question of why is Jop not much used? Uh, in fact, uh, in 2015, one person even claimed that Jop had never been used in the wild. Of course that was wrong. It has been, but only very, very rarely. So some of the reasons for that, uh, lack of proper tooling, we just don't have tools to find Jop. And if you're trying to do Jop, that, that's a serious problem. Jop is also much trickier. It's less well understood, whereas with ROP, it's very well documented. Uh, great literature that exists, great tools that are available to facilitate that. There's difficulty in finding Jop gadgets. Uh, from a couple of perspectives. First, uh, just the number of Jop gadgets relative to ROP gadgets is much, much fewer. So that makes it much more challenging to, to find the right gadgets. Uh, secondly, if you don't have a dedicated tool, then it can make it, uh, difficult or even impossible to find enough, uh, gadgets. And the reasons for that is opcode splitting. So our, our ROP tools, our Mona, so on and so forth, will do the opcode splitting. But if you try to just use general purpose reverse engineering tools, it's not going to, uh, very easily readily, readily allow you to, to do that. And so then it would be a kind of a manual process that could be tedious and time consuming. Just like it would, the same would be if you tried to do it with, with ROP if you didn't have a tool such as, as Mona. So we've got to be very grateful for, for those, uh, different tools. So Jop, yes, it is a little bit more complex. Um, folks don't really know too much about it. Uh, don't know how to use it. And that's, that's understandable because there's not much that's written about it. There's some that's written in the academic literature. Uh, and additionally there, I mean if you try to search for, uh, uh, articles on how to use it in Windows, you just won't find anything, uh, for the most part. Uh, so that's perfectly understandable. Uh, with Jop you also have to pay attention to registers that are being used for the dispatcher gadget for the dispatch table. And those, if you tie those registers up, then you can't use them for other purposes. So that, uh, just adds to the complexity, adds to the chaos. We need the dispatcher gadget too. It's a very rare, very scarce gadget. If we can't find it, then we can't do the dispatcher gadget, uh, paradigm. So that can be problematic. Of course you can still try the pop-ex, jump-ex, uh, paradigm. And if you're even temporarily do ROP and then do a little bit of Jop, that's entirely possible. So many of you are probably familiar with ROP, you may be masters of ROP. The good news is a lot of that can carry over. So, uh, some of those ROP techniques will also apply to Jop as well. So at this point we want to, uh, introduce the Jop rocket, uh, honor the sacrifice that, uh, ancient rocket cats made so many centuries ago to deliver their malicious payload. Uh, so a little bit of history lesson, I guess in 1300s there'd be, there were, uh, so-called rocket cats that would have explosives, uh, strapped to their back and they would, uh, be able to, uh, sub-divert, subvert, uh, the defenses of a well-defended castle to deliver their payload. Jop rocket tries to do the same thing. Uh, we can get past, uh, ROP heuristics. Um, so very sophisticated tools, a Python script, uh, has dependencies that are required, can run in a Windows environment, can, uh, run in, uh, Linux. Um, it is static analysis, uh, and the only reason I did that is simply from a programming standpoint, it made it more challenging, more difficult to, to write it rather than something that would integrate with an active process. You can take an executable or a PE, you can scan it, as well as all of its associated modules and DLLs. Uh, the Jop rocket features, uh, command line, uh, user interface, uh, accepts brief, uh, keyboard shortcuts, uh, very easy to memorize, very easy to quickly utilize them. It also has a convenient get everything option, uh, which we'll talk about in a little bit here. So some of the features, uh, the Jop rocket, uh, tremendous flexibility in terms of how we can discover the different gadgets, um, both functional and dispatcher gadgets. So, there are reasonable defaults, but if you're not finding what you want, you can enlarge or you can narrow the scope. Uh, as it goes through and, uh, acquires the gadget, it performs classification into dozens of categories based on the operation. For instance, is it adding? Is it doing sub? And also on the registers that are affected, so that you, as the, uh, user can be very specific in, about, you know, what you, uh, want, want to acquire. Also as an option to get everything, uh, printed as a CSV. Uh, so that can be incredibly useful if you want to gain insights into whether or not a specific binary would have enough gadgets to perhaps, uh, support Jop. Uh, it does feature opcode splitting. Uh, the challenge with opcode splitting is, if you do it from a return or to a program and you go for the, the C3 or the red or one of the variations, a disassembled backwards, enumerate everything, with ROP, you're looking for the, uh, op codes for many different indirect calls or indirect jumps. So there's a lot more to, uh, consider there. Contributions of the Jop, uh, rocket, just from a, a standpoint of how it's, uh, built and how it's put together. It does a lot of things in kind of an original unique fashion and the reason for that is it's not wanting to ape or mimic the, uh, contributions of others, but just to try to do something, uh, in my own fashion, but maybe not particularly interesting in terms of how to, uh, perform Jop. So how do we, uh, utilize the Jop rocket? Uh, it is again a static analysis tool. Uh, we do run it from the, uh, command line. Uh, it can, uh, support any platform that has the necessary dependencies. Um, since it is targeted towards windows, if you are doing it in a Linux environment, as you're gonna miss out on the ability to scan the, uh, the modules, cause, you know, some of them simply won't be present. Um, now how do we do it from the command line? We can do, uh, Python, Pro, and then the, the file name. If it's a local file, if we do it that way, uh, it's just going to get the image executable. Otherwise, you want to provide the absolute path which we can supply and input text file. Uh, and it needs that to enumerate the different, uh, modules. So a number of different options, uh, associated keyboard shortcuts. I won't spend too much time on that. Um, and there is more as well. So how do we use the Jop rocket? Uh, again lots of many, many different features, but by design a very minimalist user interface just to make it a little easier to use, a little bit more friendly. So the first step we want to establish the registers of interest. Are we looking at EAX? Are we looking at EBX? That's the first step. And then we establish scope. Do we want call or do we want jump? Keep in mind if you do call then you're adding to, to the stack and so if you're trying to load windows APIs then that can be problematic. But you can compensate for that of course. Uh, additionally are you looking for modules and DLLs? Which you probably are. Or are you just looking at the, uh, image executable? Once the selections have been made then we just hit G for go and it will get those gadgets. Uh, and then we go to the printing submenu and we can print the, uh, what it's found to, to files. Uh, many, many different options based on classification, based on the operation, based on the registers that have been, uh, affected. So you can be very specific, very granular. Um, and of course if you need to you can, uh, enlarge, uh, the scope or narrow it. And there, there are many, uh, specialized, uh, options that we won't discuss that can allow you to, uh, kind of finagle, uh, some of that. Uh, again the option to do everything as a CSV just to get a broad overview of whether or not, uh, binary may support that. So how do we get the, uh, dispatch for gadgets? First step is to select the registers of interest. Uh, and then D for dispatcher gadgets we go and acquire those and then we go to the print submenu. We can print those out. Uh, if you want to use call on the dispatcher gadget that can be problematic because it's constantly, uh, interfering with the stack. But you know, it's an option. So a couple screenshots here. Uh, very minimalist, uh, UI. Um, now we're going to discuss a job exploit, uh, to try to gain a kind of an understanding of, uh, how all this comes into play. So this is a, uh, a wave reader, uh, prints out or gets some information on a wave file. We provide it with a malformed, uh, wave file. Initially we have, uh, an overflow just to set things in motion. And then we set up our, uh, job gadgets. Uh, we set up the dispatcher gadget. We set up the dispatch table. Uh, and then we do our job change. So we're gonna bypass depth data execution prevention. We call virtual protect. We call write press process memory. The second one is not necessary, but we do it anyway. And then we do our knob sled and then our shell code and then profit. So some basics here. Uh, the register for, uh, dispatcher address is edx. And then edi will contain the address of the dispatch table. And then we serve dispatcher gadget instructions. There we're adding c or 12 at base 10 to the, uh, dereferenced, uh, edi. So, uh, we can see a nice little diagram of our exploit that we're about to, to do momentarily. We have the dispatcher gadget which allows us to advance forward by 12, taking us to the dispatch table. Uh, and then we have padding in between, um, and then the functional gadgets which are similar to ROP. And then it swings right on back to the dispatcher gadget that then advances, uh, to the next entry in the dispatch table. So setting things up here, uh, we have the initial overflow. We want to set up the dispatcher gadget. Uh, we're doing call edx. Um, we do a little bit of exclusive or action and we provide the two different, uh, values for edx and edi or dispatcher gadget and dispatch table. And then we call edx the dispatch, uh, gadget. Uh, after that we can then start crafting the function calls. To do that we move ESP to a known location. It just makes things a little bit easier. Uh, then we're calling, we're calling, uh, the API functions. We're setting up virtual protect. We, we provide the necessary parameters. That's good. And then we do write process memory. We provide those, uh, parameters. Uh, so with virtual protect we can then make it so that, uh, memory is rewrite executable rather than just simply, uh, rewrite. So supplying values for those functions, we get ECX to a known value. It doesn't really matter what it is, but what we're going to do is we're going to modify it with exclusive or. Then we pop a value into EAX. We do the exclusive or on it. And then we pop another value into EX. And now we have two values that we can push onto the, the stack. Uh, and then so we do that. Um, and then we need to compensate for, uh, ESP. Uh, we do dereference virtual, uh, protect pointer. Um, so we go ahead and do that and we will utilize that a little bit later on. Now the goal here is to do purely job with a dispatcher gadget paradigm. And since we're doing two windows API calls, well, uh, an API call is a function, a function ends in a ret. So that takes us out of job. So we do insert one ret to get us right back into job. Again, we have the option to call. We just need to do provide compensation by adjusting the stack. So it's not big of a deal. Uh, getting right process memory. Uh, that one is a little bit more, uh, challenging. There's not a direct pointer to it and the binary unlike with, um, virtual protect. But since we have dereference it, we can do a little bit of finagling with, uh, by analyzing the DLL and do some hex math and, uh, then we can, uh, thereby reach that, reach that. Uh, we can also jump to other registers if we want to shuffle around the, uh, address of the dispatch, dispatcher gadget. That's not a problem. So let's go ahead and take a look at a demo. So first we want to establish the registers of entry. Uh, we go ahead and do that by typing R and then we're doing all. So let's gain all registers. Other options, but we're gonna bypass those. It goes and acquires those. We go to the print menu. Uh, then we select the registers to print. The registers affected. Uh, G for all. Uh, we look at all operations and Z. It then goes and acquires them. Uh, and we see some gadgets that it's found. Just one random, uh, example here. We see our initial, uh, overflow. Uh, we set that up and then we set, uh, our dispatcher gadget to EDX and then our dispatch table to EDI. Uh, and then we go ahead and get, uh, get it going there. Now we have our, uh, the wave file, wave file that we've read into memory. We have some shell code there. Then we have the, the header, just a traditional wave header. Uh, and then we're going to go ahead and make our virtual, virtual protect call and this is all purely job. So what we want to do is we want to provide it with the necessary, uh, job parameters. So we go ahead and do that. Let's see that in motion there. Okay, nice. And then after, after that, then it takes us to dispatcher gadget. We see that at EDI, uh, C and that'll follow, uh, every single, um, uh, functional gadget. We get ECX to a normal location just so we can do exclusive or action on it. Then we go ahead and, uh, so we get the first couple of parameters for virtual protect. Uh, we do some, uh, stack adjustments there. Um, then we go ahead and de-reference virtual protect. Keep in mind we will be utilizing that a little bit later on. Uh, and then we go ahead and do a jump ESP which now contains virtual, uh, protect. Uh, and then we have, uh, values for the pop instructions, uh, that will follow, uh, subsequently. And this part may be a little tricky to understand here, just, uh, utilizing, uh, the stack. So, um, there we go. And then we go to, uh, fix, we need to fix the registers after the call. We do our right process memory. Much of this is, uh, more or less the same we're providing parameters, uh, making stack adjustments. Uh, nothing too earth-shatteringly, uh, difficult. You can do a little bit of semi-tricky things like if you, like I guess it's not really that tricky, but if you want to use a call EDX that's fine. Just got to do a little bit of extra, uh, stack adjustment which you see right there, uh, in the next line. Uh, then we want to get to our right process memory. We remember we de-reference virtual protect because virtual protect is in kernel 3, 2, which, you know, ASLR, that can make it, um, you know, unpredictable. Uh, and so we get the, get that, we add the offset for right process memory so that we can then make a call to right process memory. Uh, and then we're all set to go. We just need to provide the necessary, uh, parameters for that. Uh, and then once we provide those parameters, uh, make sure that we get the stacked values then we're ready to go. We can then execute right process memory which we're right going to do and we got a note pad. We didn't do the calc but we got a note pad. So, um, that's it. Uh, if anybody has any questions, uh, we'll be down there. You can go ahead and reach out to us. Thank you.