 All right, Defcon. So you're at the last talk of the evening. Please welcome Chris Eagle. Thanks very much. Can anybody hear me? Can't hear you? I'm Chris Eagle. Thanks for coming. We've got the Mr. Robot panel next door. Maybe you're all here to just stare at the sexy machines back here. I don't know. I'm about tired of them. Oh, where'd my sheep go? She wandered off. Okay. Wrong angle. Not her best side. Okay, I'm here to talk about a project that I've been working on for lack of a better name called School Debug. And it's about emulating various processors using the Unicorn framework for emulation that was released at Black Hat last year. And because it's kind of what I do, it's all baked into IDA. And we'll see if it's interesting and go through a couple of examples and watch things crash. And hopefully have some fun. I've got to say this. Everything I say today is my own opinion. Not that of my employer and certainly not that of DARPA. They don't let me talk on their behalf. A little bit about me if you don't know. These folks down here in the front row are filling seats to make the room look full. I'm a senior lecturer of computer science out at a place called the Naval Postgraduate School in Monterey, California. Doing security related stuff for a long time now. Do a lot of reverse engineering of various sorts. Play a lot of capture the flag. I'll be racing back over there right after this talk is over. And a performer of really stupid IDA tricks. Proving that just because it can be done doesn't mean it should be done. But that's what you're here to watch I guess. So this is really about CPU emulators. And they're useful in a lot of cases where you may not have a hardware to run a particular set of code on whether it's a well structured binary or just a small snippet of something like say a shell code. And you don't happen to have an ARM device or a MIPS device or a Spark device sitting around and you want to know how this thing behaves. So you're either going to become the world's best human MIPS engine. And you can interpret this stuff in your head and process it and figure out what's going on. Or you might want some help. And that's what I was looking for when I started thinking about baking emulators into things like IDA. Because in my particular use case IDA is virtually my desktop. I'm in it all the time. And I often have the desire to step out and execute something. Because perhaps my comprehension of the instruction set is not sufficient enough for me to understand what I'm reading. Or I just want to verify my suspicions about the behavior of a section of code. Like to run through it. Perhaps not an entire executable. Maybe I don't want to have to load up the elf and deal with the kernel loader and the operating system etc. And libraries and it's just a full blown execution environment just to run through five or ten lines of code. So I thought about this and decided if I could just run these lines of code anytime I wanted in some very stripped down environment wouldn't that be nice. We'll talk about how I got to that. I got there from here. You also may want to run code on obsolete platforms. Because you don't have real hardware to do it on. There's plenty of software emulators out there these days that do these kinds of things. But another use case for emulation. And there's another one I missed that I'm not going to go back. So emulators run the gamut from the simplest emulators that there are unicorns. In fact a fairly simple emulator. In fact it's not itself an emulator. It's not a standalone thing. It is an API that lets you point at instructions and execute instructions one or more at a time. Okay receiving some signals along the way. You can you can hook into it and get call backs and so on. And I'm really not going to talk about the inner workings of unicorn but I would encourage you to go out and try to find some of the slide decks that they've posted following Black Hat last year. There's some other presentations they've given at a variety of conferences. And dig into the project if you think you have a use for baking an emulator into anything. It is sort of to execution of instruction sets. What capstone was to disassembly of instruction sets. A fairly general purpose framework across many architectures that lets you script up things very quickly. And in this case we're going to execute things in just a few lines of code. That's the basics of unicorn. All I'm going to get into. But there are some fairly sophisticated emulators out there. I will refer to those later on. But unicorn is literally pointing at an instruction and update the internal state of unicorn and that is it. If that instruction manipulates hardware you're not going to get anything like that. Okay so the notion of a full blown emulator like a QEMU isn't what you're going to get out of unicorn. So the idea with this project was to build a lightweight CPU emulator available in a static reverse engineering context. I didn't want to have to go full on dynamic analysis with debuggers and processes and hardware operating system. Any of that stuff. I just wanted a very lightweight emulator that would let me step through code. And we can expand on it from there and I'll go into a little bit about the history and what led me here again in a couple slides. The idea is you're looking at some code. We step out of that static context. We go execute through some instructions in this emulated manner and then we take the knowledge that we gained by observing the execution state either to enhance our understanding of the binary or maybe incorporate some of that information back into our static picture to perhaps improve a disassembly, make some annotations, what have you. Maybe something as simple as utilizing a simple loop that you see in some code to decrypt, decode, deoptescape, whatever it might be. Whether that itself is code, self-modifying code or whether it's some data, some strings, anything like that and then bring that data or that information back into our static analysis without having to continue execution. Okay. And so the end result is what I'm going to talk about today. It's this lightweight emulator that I baked into IDA because if it's not in IDA I'm probably not going to use it. And that provides my static analysis side, my disassembly side and then the emulator as I mentioned previously is going to be based on this unicorn framework. I imagine if you're sitting in this room today you're probably familiar with IDA. So if you're not, okay, it's a commercial disassembler. There are some other disassemblers out there. We're seeing new ones every day. Binary Ninjas is a new one that was just released and maybe we can take this project and integrate it with that someday. But for now I'm primarily working in IDA. Supports a lot of different processor families and so that to me made it attractive to marry up with unicorn which also supports a lot of different processor families. Not as many processor families as IDA does. But more than one, more than two, more than three, I don't know, six or so. I'll list them out here in a minute. But it meant that IDA could understand all the code that I would ever want to emulate in unicorn. Okay. Because the processors that IDA supports are a superset of the processor architectures that are supported by unicorn. It's got IDA itself has integrated debugging support. So actual dynamic analysis let's fire up a process attached to it and pull in state. For x86 and ARM targets and it can do some remote debugging on some other targets. It also has a decompiler for 32 and 64 bit x86 along with 32 and 64 bit ARM. That's not entirely relevant to our talk today. Unicorn as I mentioned was introduced at Black Hat last year. Comes again out of the same group that did Capstone, the disassembly framework and now they have a tool called Keystone. In fact they may have talked about it at Black Hat. Anybody at Black Hat did they do Keystone this year? Yep. So they talked about their new project Keystone. I hope these guys keep coming back. That's like three years in a row. Capstone, unicorn, Keystone. They're all pretty useful projects. And Keystone is their assembly framework. So now we have a disassembly framework and assembly framework and an emulation framework. And you start to roll in these things together and you get a pretty powerful reverse engineering capabilities. There's the link out that their site is up there on the slide. It as an emulation framework is actually based on QEMU. So if you've ever used QEMU you know that it also supports a large number of architectures. And you might say well why do we have unicorn if QEMU supports a large number of architectures and in fact unicorn is based on QEMU. Isn't this just the same thing all over again? The answer is not quite. QEMU has a lot of support all the way down into hardware shims that lets you do full blown system emulation. We can boot Linux, we can boot Windows in the QEMU environment because it has that support for hardware interfaces and virtual devices and so on. The unicorn folks were not interested in any of that. All they wanted to do was be able to emulate processor instructions. They don't want the hardware interface. They're not trying to provide you network and video drivers or any of that stuff. They just wanted to help you emulate instructions. What does it do? Let's see. We run it in the emulator. What they did was they tore into QEMU, they ripped out all of that hardware abstraction layer and were left only with effectively the processors, right? The software CPUs that they then layered on top of. We instantiate a processor, we give it some state that it can manipulate and they give you access to that processor state and nothing more. Expose some of that up to a couple of different types of APIs and there you have it, right? A scriptable emulator. Supports the process of families that you've seen here, X86, about 32 and 64 bits, same for ARM, Spark, MIPS, and Motorola 68000. That's not all of the processor families that are supported by QEMU. But it's a start. It does take a fair amount of work to provide the interface to a given processor architecture. But I don't think it would be a stretch to add in some of the other processor families that are supported by QEMU if you wanted to enhance the capabilities of Unicorn. A number of projects, this is just one of them, have come along which make use of Unicorn. Some of them are pretty amazing and baked into a lot of very interesting analysis frameworks. I'll post a link at the bottom because you may be more interested in those than Unicorn itself because they provide somewhat more finished products. These are things that you'd make use of right out of the box if you did not intend to bake, if you didn't have a need to script an emulator of your own. So you can go find those out there and play around and so on. So I picked Ida and I picked Unicorn. There are some other emulators, as I mentioned, I talked about QEMU already, I talked about, I haven't talked about box. Box is another one. It is a pure x86 emulator. These are blurbs off of each of their project pages. Box is a highly portable open source 32-bit x86 emulator. While QEMU is more general, a generic, more processors open source machine emulator and virtualizer. It's a little bit more sophisticated than box. But it's also, there's a lot more to it than box. So could have gone with either of these, I suppose, but they really weren't geared to script around and just access just the processor bits. So this is sort of where I've been with this project. It's been kind of a long road. Unicorn came along and filled the need that I had and actually fulfilled a vision that I had back in 2003 when I built a tool called Ida x86 emulator. Where I wanted to do exactly what I described. I wanted to sit in Ida and I just wanted to emulate things. And use that to either transform my static analysis picture or enhance my understanding of the behavior of something. So I did that and at the time that I did that, I looked at those emulators, primarily box and QEMU back then, and thought, can I rip into this, strip out the bits I don't need and take just the emulator. And I looked at it and I'm lazy and I said, hell no, because they're way too big. So 13 years later, 12 years later, somebody did it for me. And so then I revisited this project and retooled and that's again why I'm here talking today. Somebody did all the heavy lifting by stripping out all the unnecessary stuff out of QEMU and dropping it in my lap. Along the way, the HexRays folks did an integration between HexRays and Box. They did it in a slightly different way. I'll do two quick demos later on of what these things look like and the different approaches that you might take as you think about doing emulation in combination with a static analysis. And so they released a box debugger module that Ida could communicate with. And if you're familiar with Ida, you understand what the debugging views look like in contrast to the pure static analysis views. And we'll see that here in a few minutes. I did a similar thing for the MSP430 processor, which was the processor that got used for the micro corruption challenges. If any folks have seen that, they're a lot of fun. And they were, that was a pure MSP430 implementation and I didn't want to deal with their clunky user interface through a browser. So did this emulator. It was in a style very similar to Ida x86 MU. And then along came Unicorn. And it took me a while, but I finally decided to integrate it into Ida to see if I liked it better or provided, proved more useful than some of these other combinations of tools. As I mentioned, I looked at QAMU in box briefly, but there was going to be a lot of work. I didn't have the time to do it all. And again, somebody else came along and did it. And their approach, because we finally get QAMU involved in this whole thing, it gives us a lot more processors, right, than my particular approach, which was specifically an x86 emulator. And so I got that one narrow architecture and I've never had another architecture. And I've never wanted to do another architecture because doing an architecture from scratch was just more work than I wanted to get involved with. So this was a nice marriage for me. Now, to the implementation. In implementing this, I had to make a couple of choices. Again, hopefully people are somewhat familiar with Ida and what it looks like. Okay. With Ida, you get your standard disassembly view. And then there's this debugging view. But you have to do a little bit of work to integrate what you learned from the debugger back into the disassembly view. And oftentimes it involves overriding a lot of information in your disassembly view. So you might go into the debugger and learn something, but it's fairly transient in nature because you're starting a process and eventually that process is going to terminate. And the information that you learn vanishes with that process. There are ways to migrate some of that information back into Ida, overriding your original data in Ida. But you'd have to automate some of that and it's not necessarily a very clean approach. So the alternative approach is you don't jump out into a debugger and you find some way to incorporate emulation right there alongside your static analysis view. In order to do that, your emulation has to be able to maintain state. So you're either maintaining state entirely separately from what you're looking at in Ida. In Ida, you get to see an entire disassembly through the various portions of a program, your code, your data, etc. What you don't have are things like a stack or a heap, any of your virtually allocated memory. But you need that in the emulation. So you either start modifying your database and adding all of that, those bits and pieces in there so that you expose them and make them available to view and navigate through. Or all of that information remains buried in the emulation and you have to come up with some way to propagate just what you want up into the static analysis view when you're ready to consume it. When you decided that you've learned what you wanted to learn and you're ready to annotate that static analysis. When I did x86 MU, I took the first approach and you're literally emulating on top of an existing Ida database. So as you do the emulation, your database gets modified. And there are some advantages and disadvantages to that approach. The disadvantages is obviously that it's destructive. So once you've modified something, if you're an Ida user, you know there's no undo in Ida. So once you've modified it, there's no going back. So if you want to see what it used to look like, you're either maintaining a separate database, a lot of snapshots, and it becomes a headache. But there, I have found it to be useful in many cases. The alternative approach is to take a debugging sort of approach. And generally speaking in Ida, that means you're launching a process and you're attaching to it in the way that a standard debugger would attach to that process, controlling the process, viewing the state of the process using Ida as a viewer. So you see what the running process state is. It gives you access to all the things you'd have in a typical debugger. And in this case, you're not manipulating your static view at all. That Ida database doesn't get changed at all unless you absolutely want it to. Your view is strictly into that transit process. And again, when it's done, you're done. Perhaps you learn something, perhaps you use it to update your state. The way you use that is entirely up to you. This is the approach that the HexRace folks took when they integrated box into Ida. Ida shells out the box. They created some IPC links between Ida and box. Ida pushes the state into box, including the code, the data that are being represented in that Ida database, and then tells box to go. It gives it an initial register state and then single steps or allows it to run freely as you see fit. Then pulls the data back out of box and shows it to you in Ida's debugger view. But again, once you're done, you're done and none of that updates your static analysis state. As I mentioned, there are some ways to pull state back into Ida, but it's entirely up to you how you're going to do it. I'll show you some demonstrations. I'll show you the two approaches and you can use that to understand what I did with Unicorn. In the case of Unicorn, the approach I ended up taking was the debugging approach because it just felt a little bit cleaner. I didn't want to get into updating databases and wanted to leave things flexible for the future. Might come along and implement it differently, but in order to implement it outside of a debugger, Ida doesn't provide you any tools to display something like registers, for example. Any of that execution state, while you're in a static analysis state, registers have no values, so you have to invent that user interface yourself. So that's one of the hard parts about doing it outside of the debugger state. My wife's probably sitting up here and not liking the slide, I don't know, or agreeing with her. In any case, I took on this task, trying to integrate Ida with Unicorn. A lot of unhappy development time. A supportive wife. A lot of time dealing with a mostly undocumented Ida interface. Dealing with a particular style of plug-in known as a debugger plug-in. Again, for those of you who know Ida, you know the state of its documentation. So I spent a lot of time reverse engineering Ida to try to learn how their debuggers actually work. Because there isn't much to go on there. At the same time, I was trying to integrate a piece of software that was really, I say, beta, that's kind of generous. At the time I was doing this, it was more like pre-alpha. So you never know where the problems lie. Is it Unicorn? Is it Ida? Is it me? And that's what led to bullet number one. But in the end, I was able to subclass Ida's debugger type to provide debuggers for all of the supported Unicorn processor families and end up with a debugger style interface for any one of these architectures that you could use to emulate code wherever you are. So if you're using Ida on Windows and you're running Unicorn and you open up a MIPS binary, you don't have to go find a MIPS platform anywhere. You can just pop out into the debugger and emulate through your MIPS code. And if you want to, you can utilize Ida's features for pulling some of that information back. Same is true for Spark or ARM, what did I say, 68k, x86, 64-bit x86 on the 32-bit platform or vice versa. So I got exactly what I wanted 12 years ago with a lot more flexibility. As it's doing this, you can go anywhere from basic, I've got five lines of code I want to emulate to trying to emulate through an actual process. If a code is formatted in the form of an executable like an L for a PE, the debugger plug-in tries to load that up and map that into an address space that is roughly what you get if you were to run it on the actual architecture the binary was intended for. There's a lot of challenges with doing that. Don't get to emulate through the kernel. We don't have a system call interface although I'll talk about later, one of my goals is to add the capability of hooking system calls so you can stub out some of the more common ones perhaps and provide some fake results back up into your emulation. So the debugger includes very basic loaders for PEs and ELFs that load those two file formats into Unicorn's state into the Unicorn emulation before you start up your emulation. It gives you stacks and so on. If you don't have a format that Unicorn recognizes or the school debug recognizes then all it does is takes the entire content of your Ida database and just copies it out into map sections in the Unicorn emulator. So however it's mapped in Ida, that's what you get out of Unicorn. It usually throws in a stack because that's something that you're going to need that you don't ever see in Ida but stacks are pretty useful and a lot of instructions make it useful. Some of the issues with doing all of this, if anybody's used Unicorn you might have some familiarity with building that. Ida is a 32-bit executable. Even though you may see well there's this 64-bit version of Ida out there, all that means is that it can understand 64-bit binaries. It is still a 32-bit native executable when you go to run it. That means that if you want to integrate with it you've got to build 32-bit libraries. So when you build Unicorn you've got to build it in the 32-bit library of Unicorn for the platform you're running Ida on. Whether that's Windows, Linux, or Mac. Unicorn unfortunately doesn't have very good support for building 32-bit libraries. They sort of assume that everybody's doing 64-bit stuff these days. Why would you want to build 32-bit binaries anymore? So we had to fix that up a little bit and they're getting better at being able to build 32-bit binaries. Doesn't also have, also does not have very good support for building on Windows. And that's primarily related to QEM use dependence on G-Lib. Which is not found on Windows platforms unless you reach out and you get things like SigWin, right, or Ming and install the requisite libraries out of those particular utilities. So this complicates Windows builds. In fact they don't have Windows built into their continuous integration. When you go observe how the project is, the state of the project out on their GitHub site. So it makes building on Windows a little bit tough. But it can be overcome. And in the end you're able to integrate Unicorn into Ida on all the platforms for which Ida is available. It's about all I'm going to talk about at a high level. It's pretty straightforward. Here's a disassembler. Here's an emulator. And it either works or it doesn't. So we'll see. I'm going to go through some demos and show you what it looks like. I'm going to start off with some simple de-opfuscation stuff. I'm going to show it to you in a couple different ways. I'm going to go through it fairly quickly. I'm not going to try not to get bogged down into the details of Ida isms or how to use Ida or things like that. I'm just going to show you what each of these things do, what they look like, and let you form your own opinions as to the utility of each and perhaps whether you prefer one approach to another. So if this all works out I'm going to use this old style emulator. Let's see. I've got to pick the right version of Ida. And we'll do this one. So you may recognize the section name. This is just a UPXPAC binary. And if all goes well here, I'm going to bring up this old emulator. Please work. It's coming. My machine's slow. This is an example of the original X86 emulator that I did in Ida. Good jokes. And what you're going to see here, assuming this works, is a crude like debugger console that's going to come up. We're not going to leave Ida's static user interface. I'm not happy with this. And we're going to be able to emulate through Ida without leaving its common interface here unless it never comes up. While that's going on, we may as well start the other one. Behind this door, we're going to try and do this with box. Ida's integrated box plugin. So in order to do that, we've got to switch our debugger over and you see Ida offers a number of debuggers. It's context aware, what platform you're running Ida on, and the nature of the binary that you're loading up. So you can see one of these is a local box debugger. And assuming I haven't messed this up either and still have box installed properly. If I choose box as a debugger, that doesn't do anything, we got to actually run it. So I'll set a break point at the beginning of the code here. I'll set a break point down towards the end over here. We're not going to jump out and execute any of these function calls because they jump out into Windows libraries. We'll just set a break point down here at the end. Maybe bring up a strings view. Try to convince you that it's actually doing work. All these strings, I don't know if that shows up at all. But these are the obfuscated strings that are part of the binary. You can see bits and pieces of strings but it's not fully de-obfuscated. And if box lets me do this, then we can start debugging. And this is going to toggle into maybe a segue back to the other demo. No, there's box starting up. I got too much going on in this machine. And so I just started off box. It's got this IPC channel between the two. And now Ida gives us a debugger view. We're not really running the process. All the emulation data has been stuffed into box. And box is going to do its thing. But this is a standard Ida debugger view. If you were running a process and actually attached to it, this is what you'd see. It's not the best user interface in the world. It's probably the number one knock against using Ida as a debugger. It's user interface is not great. But we can step through it. And the register state updates up here and so on. And we can let it run. And we should hit our second break point at some point down there. And we can go back and look at the strings on the binary. And maybe if I did this right, you're just going to have to trust me. I need one of those things. Yeah. Wow. It's got to pull these strings out of box memory. All right. Let's see how our other thing is doing. Look at that. It's like a cooking show. We've got a couple of things in the oven at a time. So this is back to the emulated view, right? Ida x86. You totally different view. We never leave the normal Ida interface. And you got this tiny little panel that pops up. It's very specific to x86. So taking this approach with other architectures, you would have to come up with your own interface, right? And replace all the x86 registers with whatever registers you have for that particular architecture. It lets you do some things like manipulate memory. Memory is really just the database. Everything you're manipulating is just a change to the database, right? And you're just, that's your memory store. You fetch bytes out of the database. You emulate them. You modify the database if that's what it says to do. But again, it's destructive, right? So we can sit here and I can click on, you know, step. Step. And it's hard to see, but if you watch the blue here and it doesn't really highlight, that blue is stepping through various instructions and we'll jump down and it follows through and so on. And I can reach down to the same part of the binary, which is down here before these function calls. Set a break point and say run. And this is much slower than box because actually it's, all of the interactions with the Ida database are pretty slow. But we hit our break point and we can go back to our strings window and set this thing back up again. And we should have lots of interesting strings, right? Like this. And this is just an old IRC bot, but we got all these strings out of it because it's mostly de-obfuscated. And then you say you're done, right? We close this up and you go back here and in fact what was formerly empty space is now code that we can go and disassemble, right? We didn't hop into a debugger. We've destroyed our database, right? It doesn't look like it used to look, okay? But we've got de-obfuscated code and we just continue at this point doing static analysis, okay? So it's a quick in and out. And I consider that approach but for the user interface aspect of it, hey, I might have gone that way. Now let's see if box is behaving for us. And over on the box side, hey, we got hopefully the same strings somewhere. Yeah, we got all this library code. I have no idea where that's even coming. Oh yeah, here we go, right? And so here are the, again, it's an IRC bot and you can see registry keys in there that it's going to reference and so on. So we get the same result but we haven't modified the Ida database at all, okay? So it's like a running process, okay? And I would have to then extract this from box back into Ida if I wanted to make this data permanent, okay? So this is again the approach that I took and now we'll go do this a different way. This is where we thought those demos were bad. See how we do here. Set a break point up here. Try to set a break point same place down here. And this time I'm going to switch my debugger over and if it's installed appropriately it'll show up as school debug. So we do this and we go back up here to the beginning and we try to kick this off. Hopefully I hit my first break point, okay? And then the plugin looks a lot like box, right? So, but this is Unicorn handling this particular emulation, okay? So you get register state over here, right? Just like you do in box, okay? And any other debugger and so on. And at this point, all right, we can just step through and it tracks along and I can let it run and we'll do the whole strings trick. See if we get anything interesting, okay? Right now there's not much but names of the couple libraries that get imported and we go back over here and we let it run. Just hit go here, hit our break point, come back, rerun strings, okay? And like the other two emulators, now we've got all of these, right? Strings extracted from memory and if we go down to the bottom of the self-decoding loop, we can jump up and very much like box, right? This is the extracted code which we can then turn into code up here in our emulator or in the debugging session. But again, I don't have that back in my database and when I go to quit this, okay? I'm right back where I started from, okay? And I don't have any strings and if I follow the jump, right? Up here, you can see it's empty, right? Because this is the region in the binary that it unpacks itself into, right? So it's very much like a debugger and not a static, you know, overwrite or whatever you might want to call it. So that's it emulating on 32-bit x86 code on 64-bit Windows. Let's see what else I think I'm going to do, okay? Local ARM emulation, so Windows platform, no network connections, no ARM hardware. Somewhere I've got an ARM binary open. Let's see where this one comes from. There we go. Okay. It's an ARM binary from an old DEF CON capture the flag. Shout out to legit BS, right? Okay. One of their first CTFs. But ARM, ARM binary on Windows, okay? And actually it's not going to offer me any debuggers because IDA has no clue what to do with this, right? ELF binary, ARM, Windows, right? Don't do ELF, don't do ARM, okay? But the debugger recognizes the architecture at least so it says I'm available and it's the only debugger that says it's available. So IDA has already selected it up there and we can kick this off and now we're debugging ARM more or less, emulation. Don't worry about that. Awesome. We'll see what goes on. So there's some memory mapping problems there. Let's see if, yeah, not going to work. Clapping for my crash. We'll just pass all these exceptions down and it looks like it's advancing and maybe it's even updating registers. Okay. R2 is actually equal to one at this point. Okay. I left this open and it had some stale state and I think it's not happy with me. Okay. But that's the idea, right? We're in a debugging session and we can jump in and out of this without having to fire up an ARM environment, okay? Do any remote communications to a remote ARM device and then when we're done we step out and we're back in our IDA disassembly session. Okay. What else? Oh, now MIPS. Let's see. MIPS, I don't even have any idea how to read. So somebody out there probably says that's MIPS. I don't know. IDA thinks it's MIPS. Again, no MIPS debugger on IDA. I can't switch my debuggers. There's no other debugger option but you can see that. No, don't do that. School debug is selected. Okay. So we try to hit go here and hopefully we hit our break point from which maybe we can step. Okay. Although I don't have a stack. This is probably a bad choice. Let's see. Step, step, step, step. Right. And we're emulating our way through MIPS code. Okay. Yes. Five minutes. Great. Because I am tired. Okay. So we hop out of that and we're again back to our disassembly view. Okay. And I'm not going to go into the ways you integrate, you know, what you have available in your disassembly view and what you have available in your static view but suffice it to say there's ways to pull information back across if you decide that it's useful for augmenting what you have on the static side. And last thing I'm going to do is take a look at one of the challenges from DEF CON qualifiers this year. Okay. And what this was was a binary that they gave you a thousand of them. Okay. And when you went to interact with the competition, they asked you had one minute, right, to craft an exploit for one of these thousand binaries that they gave you the file name for. So you downloaded a thousand binaries and you had a minute to craft the exploit. So it's going to take a long time to do all that by hand. Okay. So you want to automate this and you want to have an answer in your hip pocket when they say give me your exploit for binary number one. Okay. So how do you automate? Well, it turns out that all of these binaries have roughly the same pattern. And I'll describe it not by looking at the code but by looking at the stack and there's two buffers in here. Okay. And all of the binaries differ in the location of that user input buffer in the stack relative to the save return address, the size of that user input buffer in the stack, and then the content that gets placed into what I've called a canary string right there. So they gave you a free overwrite out of that user input buffer but you have to figure out how much do I have to overwrite to clobber EIP. Okay. And after you've done that, right, which is not a problem, there's nothing hindering the overwrite, but they come back and verify that the canary string matches the original canary that they placed in there. So as you do your overwrite, you've got to rewrite the canary in there and it better match their original string. But all thousand binaries have a different canary and it's not always obvious exactly the way they set it. They compute it, they copy it in one byte at a time, they do a string copy, they do it a lot of different ways. Okay. But they always end up doing a string compare at the end. So if you can put a break point at the string compare, right, and hit it, it doesn't matter what you filled the buffer with, you can do some other computations to figure out the distance from the start of your buffer to save the EIP, set a break point on the string compare, right, look at the required argument that's sitting on the stack and pick that out and these become your parameters. What's my canary got to be, right, how long is it from EIP all the way down to the buffer and there's a couple of other constants that you needed to pick out. But I didn't want to do this a thousand times by hand, nobody did. And there's some good write ups about using some other automated systems to solve this. But what I did was I scripted up this emulator and the emulator, let's see, somewhere the script exists down here. You see things, because this is implemented as an IDA emulator, right, you get all of IDA's debugger scripting, I'm sorry IDA debugger, all of IDA's debugger scripting can be used to drive this thing. Right, so we write the script, we load the debugger, we set some debugger options to break on start, we run to the start address, right, we do some things, okay, we get the value of EIP and I'm picking out all of the arguments, all of the bits and pieces from a dynamic environment, although I'm not actually running a process, I'm just emulating through it. And by the time I get done down to the bottom, I picked out a bunch of parameters that I'm going to need and what I did was I just took those parameters and wrote them out as a Python dictionary entry and so I had a dictionary of parameters when they told me what binary do you want to exploit, I said, well, I named it, my key into my dictionary is the name of the binary, I pick out the parameters, right, and I craft my buffer and fire it out. And what that looks like is this, okay, we run IDA in batch mode and then I'll be done, I promise. We got this one and we've got which one? This one. Okay, so I got two windows right here, I'm tailing an output file on the bottom, okay, I'm going to use IDA in batch mode, you can see the long command line there and what I'm going to do is I'm going to run that script that I wrote and I'm going to run it against one of these thousand binaries, well in this directory there's 300 of them and they all scroll up like that and we'll see if this will work and make sure I clear out some stale files. Namely I got to kill that IDA session because it's going to get in the way of the batch run and we'll try this out. Now you'll see IDA flash, you have to look in the background if everything works, so IDA is coming up in batch mode, we're in debugger mode, it's done, you can see the output down on the bottom, right, that quickly it got into an emulation on that elf binary, okay, ran through main, picked off the parameters that needed and dumped them out to me, now I wrap that in a loop, do it for every file in the current directory and I've got my thousand exploit parameters and I'm ready to connect to the remote side. Okay, so for the future and very quickly, a better user interface when launching the emulator would be nice to be able to specify some register state, right now I just take a guess, right, where do you want to start your emulation, do you want any registers to have particular values, so I'd like to have that done up, some options for mapping into particular memory regions or loading other regions, if you're familiar with IDA and debuggers there's a very useful interface called app call that just, that actually lets you incorporate functions or call them almost natively from IDA Python, right, call out and have your function run and then spit the value back to you in your scripts, I'd like to have a hooking library to be able to hook various functions and do things maybe other than what the emulator's doing or provide shims for library calls or system calls, things like that and I'll also perhaps add the option to go ahead and pull in all of the shared libraries that a dynamically linked binary might link to so you can follow the library calls down into a shared library function and emulate your way through those if you wanted to do so rather than writing all the shims for them. It's out there on GitHub, it's out there today, I will push all the latest changes shortly after the con but if you're interested, I'm always interested in feedback, if you want to collaborate I'd love to hear from you, if you have ideas on features that might make it more useful and you don't want to implement them, at least share them with me and maybe I'll get around to them or find somebody who might like to implement any of your ideas and that's it and I'm happy to take questions and if not, if no questions please enjoy the rest of your con. Thank you. Do we have microphones somewhere for questions? Yeah, I'm supposed to direct you to a microphone so it gets picked up, you can come up here. Microphone is, oh it's right here, it's right over here. Drink, don't forget your drink, that's right. Hello. A couple slides back, you mentioned the two console output windows, that's the wrong way. How do you recognize what magic 4 bytes over IEIP and how do you deal with bad characters? When I was doing the scripted demo, so what I did was in the scripted demo, what I had to do was I had to study a couple of the binaries manually, right, not a thousand of them but I looked at two or three of them, looked at the first one I said, well this is clearly an easy stack overflow, I understand if it was just this one exactly how I would exploit it, then I looked at another one I said, oh this one is subtly different, what's different about it, and can I develop an analysis that walks through the program and at certain key points in the program picks off certain things for me, okay. So what are the parameters, where is that buffer getting copied really, the string or the string compare gives it all away, it tells me the start of the user buffer and the start of the canary buffer and from there what I can do is do some math to figure out where saved EIP was, okay. Third binary, all of these things again looking similar and so I took what I learned from looking at three binaries, developed an automated process that I would apply to the three binaries and then it extended nice and neatly to the thousand binaries which was roughly what they intended and what they wanted to do was force you to do it quickly, right, so you weren't gonna be able to, if you tried to reverse engineer all thousand to develop these answers you wouldn't have finished in the weekend. So I don't, does that answer your question? Yeah, yeah, now I'm assuming that's the logic you have to hard code into the program or does it auto detect that? That's the logic that you have to bake into the script that you write. So through here, right, are some various things that I was looking for, right, extracting some register values, I'm stepping one instruction at a time, I'm asking, you know, am I at certain types of instructions, I'm counting the number of calls that I've encountered because the third call down, the chain was gonna be the stir copy and when I got to the stir copy or the string compare, you can see what I'm doing is I'm picking some arguments off the stack, right, that have been placed here that are passing to the string compare and then I'm using that to derive all the information I need to craft the exploit parameters. Okay, awesome, thank you. Sure, any other questions? You trying to get me out of here? I think we're done, thanks very much. I'd be happy to talk to you off to the side of the stage, thank you.