 Hello. My name is Andrew King. I'm here to present reflective injection detection. Put together some Python C types in about a week that fairly accurately detects reflective injection, the vast majority of the time. It does have a couple of issues with false positives. But something to note about the title, I said defensive vendors in general. It's not exactly the case. Defensive vendors do have products that catch reflective injection. It's just not in your main line home user applications. So a couple things I thought I should know before I get started on the talk. One is I don't own any of the artwork. It's all Google images. There weren't any notices about, hey, you're going to get in trouble for using this artwork. So that's why I used it. As far as attributing blame to offense, defense or whatever, I think both sides are equally at fault. But that's just how it goes. My statements here don't reflect past present or future employers, obviously. I left the who and my page blank, but if you were really interested, you could jump to LinkedIn. But that's on the DVD. So why would I do a talk that's going to make people angry? I did a talk previously that made some folks a little upset and complaining about a problem often gets people up in arms. But I think it's something that should change. And if everybody just goes, well, it's old, okay, then why does it still work in most home user cases? So I think everybody knows what reflective injection is. You're just doing a huge allocation into memory. You're copying a DLL there and then through whatever method you want, you're stirring execution. Now, on the defensive side, programmers are lazy. Yes, but it's not just defensive programmers. It's offensive programmers to perfect example. I threw this code together in about a week and it's not, it's very procedural and not awesome as a stellar code example. So there's very little request specific and check going on with most of your, most of your exploitation frameworks, most of them are just going, hey, when I want to inject, I'm just going to request that you allocate a certain size and you get contiguous pages in memory and the base of those pages tends to be pretty sequential. So if you wanted to optimize your scanning for where reflect injected DLLs might be, one way to do it would be to use from a defensive perspective, intentionally insert yourself into another process and see where the allocation happens and then work backwards from there so that you're not trying to scan all of memory all the time. Just a possible optimization. So on the offensive side, what if they start trying to look for PE mapping code? The perfect example for that was I used it in a code obfuscation tutorial and one of the vendors wound up flagging it as malicious software when it printed hello, you know, if you actually ran it or dropped it in a disassembler or looked at the source. So there's a lot of just, if you customize your PE mapping code or you expanded it on disk and then moved it into memory, it would be a lot more effective and that I believe is what interpreter does. But another component to that is that it changes, the way that you map it changes where you have to look for PE headers in memory in order to actually find the reflect injected DLLs. Like in the case of, I couldn't figure out what I was doing wrong there for a second because when interpreter does the interpreter stager, it loads the entire DLL at once and the whole thing is rewrite execute. So you're looking in the executable space for the PE header, but if you're looking with the Joaquin botch code for reflect injected DLL, then you're going to be looking one page before executable space. So there is that, so you just have two pages to check instead of many. And yes, they're probably just mostly at this point looking for stager code. They're probably not looking for the injected code. And I think that's kind of a fail. But why does it still work? We could detect it at runtime as it happens, but we'd have to be monitoring all memory allocations and if you started doing that and just going, you know, look for the next copy to that allocation, then, you know, you could simply trick your way past that. And so it's very hard to do once, right? So it's a continuous looping through. It's probably why it's not implemented. It's really hard on resources. You're going to be having a really difficult time with making it detect almost immediately after run and not having a significant performance impact. Yes, we can scan memory for it. So from the defensive side of things, to find reflect injected DLLs, we could look for executable space and then walk backwards for that and look for PE headers. If they started finding ways around that, we could start looking for something that looks like cough signatures. Section tables are technically part of the PE header. Then you've got permissions. You're looking for anything executable that's not already inside of a DLL, which shouldn't happen, but some things use it, Java uses it, Flash uses it. But they're just bad ideas to begin with. Then we've got the predictable layout. And the predictable layout is speaking of where allocations happen in memory. So first you could build a white list. You could get a list of all processes, all modules in all processes. And that's essentially your exclusion list. And if you, and then you've got the rest of memory to check out and see if it's in use, see what permissions it has, see if it has simple headers or structures, then you can, you could automatically kill anything that you think is reflect injected. But that's, there's an issue with that. Or if you were to do it immediately, there's an issue with delay loaded DLLs where if, say you turn on Windows Media Player and you've got this running as hard as it can go and it scans for loaded DLLs, finds them, and then Windows Media Player loads another DLL in that moment, in between when you stand for new modules and to build the exclusion list and when you start checking memory space you can accidentally kill applications. So it has to, it has to happen a couple of times in a row for that to actually be viable. You've also got, so the things that you need to do this are just virtual query that you can find out a bunch of data about just about any, just about any memory area, just about any process. You can just save all that, you might need it later. Process of elimination, you're looking to find all your legitimate pages and then eliminate everything that's non, eliminate everything that's legitimate and then pick through from there. There are more criteria that you could use to eliminate other than just looking for executable sections in case somebody starts toggling permissions just when they, just when they want to go there. So I tend to do things like leave out mapped memory sections where files are mapped into memory but I guess you could execute from there. So now that you, now that you can find out if it's execute or not, you want to read it and find out if you actually have a P-like structure, you can't validate the entire P header fast enough to be viable so you're really just looking for two letters at the very beginning and you in some cases possibly have to build an exclusion there. So we could, if we wanted to validate the entire P header and possibly additional structures within the DLO, then we could check the probable allocation space only and go, hey, you know, if we request memory be allocated and it's probably going to be in this location then we can only check a certain number of allocations previous to that or a certain number of pages previous to that. So now that we found it, what do we do about it? Well, you could just flip access permissions so that threads that try and execute there, get an access violation and die. Could be a very serious problem with false positives if you had a false positive in some system service, which would be very bad. You could also suspend threads found to be operating there, but if you wanted to do that, since threads don't have attribution, you'd have to do, it's for just reflect injected DLLs, it's not horribly important to catch it immediately. If you diverted open socket or socket send, then you could find out what threads are actually touching the network and that would be important to know because you could back up on the stack and see if that came from your injected DLL. In this case, a simple example is interpreter, but that's just one example. You could dump it to disk, you could try and reverse the relocations to get yourself the original usable DLL. You could just add another DLL to the processes list and then edit the table of DLLs manually to in essence attach it to the process so that then any virus begins to see it again. That's much more viable than just killing things at random because it doesn't require that you make a judgment call, you just attach it to the process and let other tools do what they already do. That was pretty easy and not altogether new. They've been knowing for quite some time that executable space, or writable executable space is a really huge beacon, but that it has false positives in Flash and Java. Just that nobody said, hey, look in the previous two pages for a PE header and nobody's fixed the problem yet. So anyway, home user products, they're not attacking it at all. From the offensive side of things, so how could we beat it if they started detecting it? We could rewrite the PE header, it'd be really simple. You could just zero out MZ. You could load a large DLL into memory and then instead of doing virtual locks and copying the DLL into the allocated space, you could load some random huge binary and carve it out and just be inside that. So that would be relatively difficult to catch with signature. You could change permissions on the page with the header. You could set it to no access. As long as you don't have to touch it anymore, you're done. If some tools might change the permissions, check, change it to readable and then change it back when they're done looking at it. But I would think at least one would fail in that way. So why don't more developers open source? The reason I bring this up is because I'm giving the really nascent, not production grade code away. Just here, use it, make it better, general how I did the thing. And I think it's because some people, a lot of people build entire product lines on top of open source code and never donate back to the products. Great examples for open SSH, which I have a sneaking suspicion is the base for the SSH servers or clients for an incredible number of network appliances from all types of vendors. And then FFMpeg's wall of shame has been down for quite some time, but it's still there on an internet time machine and it still lists a ton of products. All right, so the demo. Oh, come on. Well, if it would launch properly, everything would be dandy. I'm not a fan of Unity, by the way. All right, there we go. Start that one and that one. Hopefully that's the only time that I upset the demo gods today. So we've got that. And all that's doing is sitting there listening. Oh, come on, break it across the barrier. There we go. And we've got the Windows box here. And you guys can't see the command prompt there at all, right there. It's just running, like I said, I took out the auto kill because it was having some issues. And we've got a little test executable right there. And all we want to do is give it a run. And this would be just simulating whatever caused, whatever caused the interpreter stage to go off. And it's finding it. And it could easily kill it, but you can see that the PIDs match. And that's all there is to that. I previously did really long demos where I showed killing the process and really looking at things. And I got the impression that that was a bad thing to do. So there, no long, hugest demo. I'm cleaning up all the Windows. All right, so if you stop worrying about reflecting, injecting things and started just because, say, they catch it, and you can't find additional ways to fight it because they just get really, really good at catching it, then you might just want to think about runtime obfuscation of compile binaries. And yeah, they're going to see the code, but there's, even if you don't do obfuscation, just not doing anything hinky means you could get away with it for quite some time. Both sides of the fence, can it be halted or slowed down? Yeah, I suppose it could be slowed down quite easily. Could it be halted? Probably not. Because there are too many ways that you could, that you can just try and continually change tricking things. Why isn't it being done? It's kind of processor intensive to catch quickly. There is some code that I'm given out that catches it pretty fast. It is just Python with C types. It's not very, it's not very heavy. You'll want to shim and nice thing up the processor if you plan on leaving it running in the background because it doesn't have any processor control at all. It's not pretty, but it works. Only works, only I only tested it on x86. There are issues that can happen with x64 because the way you query memory changes and some of the results you get can change. Doesn't have, doesn't have a lot of features. I did have auto kill and setting prejudice levels so that you could try and suspend threads and whatnot, but that became troublesome and I didn't want to have to field bugs on well, suspend, broke my system. I have a C port, but it's much slower because I used lists instead of maps. The other code that I'm just given away is an encoder thing that I put together a while ago for obfuscating C binaries. I had a bunch of people want a copy of it, so I'm giving it away. I had to strip out some things, but I am here, fine. I couldn't really in good conscience put a fully weaponized thing out there, so I did strip out some of the lists that it needs to operate, so you just have to populate those lists with assembly structures that you're choosing. What else am I working on? Some interesting things. There's some Python obfuscation stuff going on where you're taking PYCs and actually doing obfuscation on PYCs, which is fun and not horribly unexpected since it's default installed on everything but Windows at this point. And there's some guys in the audience that deserve a thank you for turning me on to the obfuscating Python thing and helping me out, trying to grow me on some of the stuff so I could be ready for questions. And questions, yes, I'll be around. We've got the Q and A room and evidently I didn't ramble on quite as much as I thought I was going to. All right, so we can take questions here if anybody has questions or they want to complain about my approach or they want to ask, when does it fail? Because I can think of random cases where it would fail. There's some things you can do with .NET that would cause it to have problems with loading DLLs. All right, so no questions. I'm sorry. Oh, all right, yeah, I could do that. Have I done any 64 bit mitigations? That's a good one. It does run on X64. There are a couple of specific reasons that it can fail. And it has to do with when you load 32 bit DLLs into a 64 bit process, then some things can come off the rails. And where is my pointer? All right, I just had an epic fail, guys. Probably sorry about that. I'll turn that off and I can step through the code, but that's horribly, that's just not good. I'm not sure what to do at this point. When I was doing this at home, I must have rambled on quite a bit. And here I'm talking quite quickly. What do you want me to do? All right. Well, that's essentially all the demo I have with the code that I'm giving out here. The other code is on a desktop that does the auto-kill and all that. Yes. I mean, just in general, as a screen engineer, what would you say, you know, like you would say every dev team should do this early in the cycle, I think that's just there. Whatever it might be. Would it not be? Oh, yes. In order to get past the developer's or lazy period component, what could we do early in the dev cycle to get past that? And constantly through the dev cycle to get past that. And that would be stuff like if you actually use a UML modeling tool to say these are the features we want and this is how we're going to break them up. And it leads to objective pretty code as opposed to procedural code. And instead of banging out a feature and then going back and making it object oriented and moving things around to fit what you want them to later, if you start with a top-down problem solving approach, then you can break it up and just not implement chunks or modules until you get around to needing that particular feature. But it's difficult because you expect to have a feature for another feature or if you're planning ahead, you need to plan how you're going to access all your features all the time, ahead of time, which is difficult. Does that, essentially what I was trying to get across was top-down problem solving with modular solutions and UML hopes with that a lot. You know, the given dev cycle outside of, because a lot of times what we do now are end up doing kind of the normal stuff we look at, it's tossed over and it's very sad to say, hey, make sure this doesn't suck. Is there something that could be even done even in a new cycle or a testing cycle outside of the UML pen testing or just maybe some high-level things like, yeah, these are really cool things to do at that time? Well, as far as, the question was during, I responded to the question about what things you can do during the dev side of the cycle, but what things can you do on the QA side of the cycle to try and make sure something doesn't suck as things progress. And on the QA side, it's the test early and test often and test in under the kind of stress that it's going to be operating under because if you've got some network appliance that's running some software and it runs just fine on your test cycle because you only run 5% of its maximum backplane, then when you max out the backplane, what happens? And that could really mess with features. The other part of it is the, that if you can break your testing down into individual features, that's nice, but you can't always break down testing into individual features because a bug could depend on one feature being activated and another feature happening at the same time. So that's, test-driven design is good, but test-driven design goes nowhere to catching that particular issue. Does that essentially address what you were asking on that one? Thank you. Thank you. Oh, thanks for having me. All right.