 My name is Chris Eagle, thanks for coming, and clearly nothing better to do on a Sunday afternoon at DEF CON, but okay, I'm not good with microphones, okay. Again I'm Chris Eagle, and this talk is titled Creating Genetic Mutations to Survive the Vulnerability Window, and there's zero scientific knowledge in here, better subtitle is Stupid Hex Editor Tricks, or creating nipples in the gene pool, I guess, or just nipples in the pool, was suggested from the crowd, and you know, you might like some of that better than this talk. Well, we'll see. So again, Stupid Hex Editor Tricks, this is not deep, deep stuff, alright, and anything I say has nothing to do with who I work for, or who I know, or no guilt by association stuff there. So the stuff I'm going to talk about is really born from ideas developed out of playing CTF for the past couple years, where your threat model is, you have an application that has vulnerabilities, and it needs to survive for three days, okay, with some pretty serious people looking for holes in this thing, but perhaps, well, we'll get to the more general use case, maybe. Again, no source code available. You have to run the service for whatever reason that might be, there are business cases like that, and in our case, the patch needs to survive less than three days, okay. In the real world, you may not know how long the vendor will take to patch the thing, so we'll just go from there, three days. I'll use x86 examples as I go through this stuff, I think it could be easily adapted to other platforms. It's pretty generic techniques, again, there's nothing really deep going on here. So a while back, Dan Geer talked about the problem with the software monoculture in which a large number of platforms all running essentially the same software are, you know, provide for this the capability of mass propagations of worms and such. The idea is that in order to mitigate this sort of monoculture problem, you've got to address the similarity in all the software some way, you know, short of getting everybody to migrate to different operating systems and so on. This is, again, one novel approach perhaps or not to go about that. So talk about a couple of things. The idea, the notion of a vulnerability window, you can talk about it a lot of different ways, but basically spans the timeframe from the discovery of a vulnerability, whether it's disclosed or not, up through the time at which a patch becomes available and then you could extend that through the delay for lazy system administrators getting the patch applied and that's sort of a different problem. Two components so you can break the window into two or as I view it, you have discovery time to disclosure time, which, you know, if nothing ever gets disclosed that could be forever, but so your vulnerability in that window is a lot more difficult to pin down. Obviously if you can spot the fact that you're vulnerable then the thing has become somewhat public, requires cooperation of the discoverer in order to make this thing known, sometimes difficult to get, or it propagates wide enough that eventually it leaks out to someone who is cooperative. And during this window you have very little defensive capability. If you run in a vulnerable application and, you know, it's accessible remotely or by whatever means, then you are probably vulnerable, obviously the vulnerable application in this default configurations. Then you have the time window from disclosure to the availability of a patch and that can last differing amounts of time depending on the disclosure model used by the discoverer. And during this window you might have defense by mitigation. If you know how to mitigate the attacks, you know, the most severe would be secure in the service, but there may be other techniques and that's sort of what I'm going to talk about. And the idea here is that we want this window to be shorter than the time it takes to automate that vulnerability and turn it into, say, a worm, okay, because of course then all hell breaks loose and that's where the monoculture comes into play. But if we can keep that short, then maybe we can survive through there. So in that window what do we do? Okay, if we're waiting for the vendor supplied patch, you don't have a whole lot of options. There might be a patch offered up by the discoverer. We don't see this too often. Okay, often in cooperative disclosure the discoverer will coordinate with a vendor and details will be released when the patch becomes available. Alternatively the discoverer will just throw this problem out there and offer you no real means to fix it in your life to your own devices to understand the nature of the problem and secure the whole. Alternatively, and we don't see this too often, but we have seen a couple interesting cases in the past year or so where independent researcher provides a patch, not the person necessarily who discovered the whole, and they make this thing available. You have Ilfak Guilfanov's WMF patch that came out last year widely tatted by SANS as the way to fix that hole. And I think EI came out recently with Internet Explorer patch for some client side vulnerabilities there. They can be controversial because who do you trust? What's the software QA process that goes on these things? And what are all the interactions that they may cause with the application that they claim to patch? So there's also some controversy that goes along with these things. So if we take, you know, I don't want to turn anything into disclosure debate unlikely to happen here today, but personally I don't care whether you disclose or not, that's up to you. I don't care if you coordinate with a vendor or not, that's up to you. They're probably not paying for your time anyway. And I just kind of in the school that says if you do choose to disclose, it'd be nice if you told people how to protect themselves. They don't offer a patch necessarily, but telling you why, you know, not just, hey here's my O-day, but maybe here's what you can do to prevent it. And maybe that includes shutting down the service, but maybe there are some other things that you can get, that you can do. And that's kind of where I fall on all that. And I don't think it's worth getting into. There's enough of that going on. So before I get any further, there have been a few patching talks that have gone on through Black Hat and Def Con, I guess. And they've been kind of interesting. They've talked about the new Microsoft hot patch, hot patching features where with certain compiler switches, you basically have built-in room at the beginning of every function to kind of hook in, divert the function call and inject patches that way. And that's not what this is all about. This is what I'm talking about here is simple changes, relatively simple changes to a binary to alter its runtime characteristics, not necessarily its behavior, sufficiently enough to foil automated exploitation attempts. Okay? Sometimes doing this is a lot easier than fixing the problem behaviorally, which may require addition of, you know, injection of an additional code to perform any kind of boundary checking, error checking, whatever it might be that you would like to do to fix the problem. Uncheck string copy. We need to add some kind of check on the length of the buffer that's going to get copied and so on. And adding those checks takes space. Space is sometimes at a premium inside a binary and creating that space, obviously without the source code to be able to recompile it is probably, you know, a sophistication level above what I'm going to talk about here. And so finally these things are basically security through obscurity. So again I do not tout them as a way, as a long-term fix. Obviously you're interested in getting the problem patched at the behavioral level, not just at the sort of characteristics level. So with that also they are not necessarily, in most cases, not unexploitable. They are just exploitable in a different way than the rest of the monoculture out there. So the point is once a worm hits the streets, if they, let's say, are very good and build a worm to sort of brute force their way through every machine they attack or just those that they're unsuccessful against, then perhaps the worm will give you a try and just pass on by. So again they remain not a long-term solution. Ultimately the patch is what we're after. So some assumptions I guess that automated exploits are generally built for specific target layouts. I mean they may understand a few different target layouts. So we got the sort of things that will hit Win2K, WinXP, various service packs and so on, but they tend to look for specific features on each of those and or exploit common functionality across all of the platforms. So if you look different than your stock Win2K service pack 4 box or whatever they're at these days, then maybe even these things will not hit you. And that's the goal. Most automated attacks aren't smart enough to evolve. These things are out there looking for the low-hanging fruit, scanning for a target list and then iteratively hitting each target on the list and when they fail to propagate to a target they often just move on. Now your dedicated, serious attacker out there who's after you individually specifically might realize that their stock attack is not working against you and may then take the time to try to brute force their way into your system and ultimately they may make your way through. So this is and this is not probably the protection that is for you if that's your threat model. Again patches are the best bet. Okay, so into binary patching which is ultimately where we're going. Again it's really stupid hex editor tricks. So it's not for everybody. It's something of a black art. You need to have some familiarity at least with the assembly language level, maybe some binary auditing, some executable file format layout issues, things like that to understand what your opportunities are with any given binary. Is there room to add code? How much room? Can I create room? Can I divert the flow of execution to some other location where there is some room and so on? And then what code needs to be moved to accommodate any behavioral checks that you would like to add? And unfortunately compilers are often concerned about the size issues not all the time but often and don't generally too much free space. You can find some. Sometimes you can create some if you're willing to dig into program headers and sort of spread things out. But as soon as you start messing with the virtual address layout of the binary then you're adding an additional level of complexity on top of all your changes. And ultimately if we want to add some new behavior and we need to use additional functions that may not be included like a safer version of string copy which includes checks and so on. If that function was not imported by the original binary then you have the additional task of adding the capability of the function to locate, of the binary to locate that function and so on. So we have all these sort of cascading problems. So some simple mutations that maybe we can deal with. The ones that are easiest involve stack mutations and stack mutations simply alter the stack layout to something other than the stock stack layout. And I'll talk about what that is and again they're the simplest to perform. There are some simple heap mutations that you can do without having to add a whole lot of extra code or change too much. And the goal again is to just alter the heap layout so that it looks different than what the attacker expected since some of these things require very specific knowledge of where overwrite code will land. Format string mutations, these are again harder and evolve more to changing the characteristics so I don't spend a lot of time there. And then uninitialized stack variables in which we hope to sort of alter the stack layout to move the uninitialized variable again and that's kind of up with stack mutations in a different sort of vein. So I'll start with stack mutations and the basic idea with stack mutations, a very simple idea, is to simply grab more stack space in the function prologue. A lot of functions start off with grabbing some local variable space and you can see the code that does it there. If you set up a stack frame and adjust for your local variable storage, in this case the first prologue there grabs 34-byte hex bytes on the stack for some local variables. And that's often done as a one-byte constant so that has some implications later on but if you want more space, grab more space. Subtract 80 hex bytes and that builds you just in this case 50 hex bytes or 80 bytes of space to kind of rearrange a layout of the stack. In the second case they're grabbing a much larger chunk of stack space, in that case just over 1k worth of stack space and that constant happens to be larger. And so you can make significantly larger adjustments in that case to grab a significantly larger amount of stack space and have larger variance in your rearrange of things. In a sense this is poor man's address space randomization when you start doing these kinds of things just because again your stack layouts, offsets, return addresses end up getting shifted around so that the stock exploits don't work. Once you grab the extra stack space you need to sift through the code and just adjust pointers into the stack frame which tend to be relative offsets from a frame pointer or the stack pointer itself. So in stack pointer based frames there, ESP based frames, then in actuality ESP based frames there's no adjustment needed for local variables because everything just remains relative to ESP it's just higher up in the stack space. And you've built a gap buffer of sorts at the bottom of the stack that just remains unused. And of course we have to also assume that we don't care too much about memory consumption or not start grabbing too much stack space just for the hell of it. The only thing that does need to be adjusting in the ESP based stack frames is the depth to the function arguments sitting under the return address as mentioned there. So you don't have to adjust any references to local arguments because everything floats with the stack pointer which is just higher up and you have to dig deeper in that stack frame to get to your function arguments. When you have a frame pointer based stack frame like an EVP based stack frame then you need to adjust all your local variable arguments because they're higher up in the stack so we have to subtract a greater offset off of EVP but there is no adjustment required for your function arguments. The first case is usually easier because there's typically more local variables declared than there are arguments so there's fewer changes perhaps. So here would be a simple example where you see a stack layout where they basically grab about 1K of stack space up there and you see some variables declared in the stack including that of our 3F8 which is about a 1K stack based buffer which is perhaps susceptible to a buffer overflow. And you can see that the declaration or the way they access that is using a relative offset from EVP there in the last line of the text where that equates to EVP minus 3F8. You can see the offsets over in the left margin. So that might be the default layout. Now if we can inject say 2K of code into that buffer obviously we have a stack based buffer overflow corrupting EIP and allowing perhaps remote code execution. So we can make a quick adjustment here and instead of subtracting 414 hex we changed one byte in the code. We are now subtracting 814 hex. So now our buffer in the stack is about 2K and everything just shifts up. It requires us in this case I shifted everything up in the stack to remain the relative relationships among all the stack variables. And from for all intents and purposes you can still treat the form of our 3F8 which is now bar 7F8 as a 1K buffer. It's just a 1K buffer that has about a 1K padding area beneath it. So if somebody was overflowing with something slightly over 1K they don't reach EIP. It's that simple. And we have to go in and change that subtraction operation where we allocate our locals. That's a one byte flip right there. And we go in and change any references, EVP based references to all of the local arguments that are sitting up there in the stack. So we end up with EVP minus 7F8 and that still reaches the start of the buffer. Again, not terribly sophisticated stuff. Does it remain vulnerable? Yes. Is the stack layout the same as the rest of the monoculture? No. So again maybe you survive that vulnerability window just a little bit longer. An alternative would be to simply move the buffer entirely where we don't move any of the other stack based variables and we again grab all the extra space and just change the offset to that single variable, the stack based buffer. Which moves to the top of the local variable space, still a 1K or a 1016 byte buffer if I did math right. Followed on the tail end by a bunch of local variables and another thousand bytes of padding. Same sort of effect. There's a side effect here that now in order to get to EIP, the attacker also has to write through a lot of other local variables. Some of which, hopefully none of which, it's poor man's canaries. If you corrupt any of these variables, you may cause or the function may error out in a variety of different ways, hopefully cleanly. And if we error out cleanly, perhaps we'll avoid any activation of the stack based buffer overflow. So this gets sort of a small demonstration of permutations of these variables. If you can rearrange your buffers, move file descriptors or something like that below an overwriteable buffer, then you start to get perhaps some error conditions that might crop up that prevents things from getting triggered as well. The variations on this theme are, again, sometimes you rely on offsets into the stack. Things are more sophisticated these days where we try to get addresses to things like a jump ESP or jump to a known register. But when people do rely on known addresses in the stack, if we can change where things lie, where's your shell code, for example? If you have to point your shell code for any reason, if we can just move the location of the shell code, then you're not going to hit it. Even though you might trigger the overflow, you don't land in your shell code. So simple ways to move the shell code around just involve grabbing more stack space for main on up. If main grabs more stack space than it needs, regardless of whether it has any stack based buffers, then all the stack addresses for every local variable allocated by functions called from main change. So it's, again, poor man's stack randomization, I suppose, is the best way to put it. No, I went backwards, I guess. Reordering local variables, I mentioned briefly that one and just place additional locals between buffers and save return address and so on. Mutations, there's less we can do here without getting into the behavioral modification of the program. The easy change is that when a heap overflow occurs in fixed size buffers, so what you're looking for here is when the object that is getting overflowed out of is a fixed size object in memory, malloc with a fixed size constant, change the constant, grab more space. These are more particular to the layout of the memory because you have to have the right alignment for all your pointers to line up and the unlink operation and all that. So if we can, if your object is 40 bytes that gets overflowed out of, ask for 90, ask for 100. Get a larger size chunk and then you build a little bit of padding on the backside and the attacker has a harder time finding that next frame or that next chunk in memory and lining up the pointers correctly. If the size of the chunk is computed by some mathematical operation, then you have a little more difficulty because you're going to have to influence the math there to try to grow that size out to grab more space than you need. Again, we want to do these things where memory is not necessarily a premium and grabbing more space can be done without bringing the system to its knees. So the idea here is we mutate to increase the amount of space requested so that the overflow out of the heat buffer doesn't quite behave the way the attacker might want it to. Again, we're still not unexploitable. So this is just silly. Hex edit, if you have a 16 byte object that's just a data buffer or something, you copy into that, grab 64 bytes. The attacker doesn't know you did it unless they start brute forcing things and they get their pointers to line up beyond there, then hopefully they'll move on to the next target. Again, computed size mutations, if they're computing the size a little more difficult because you have to influence the size of the argument to malloc, which even if you just want to add an arithmetic operation, you may need as many as 5 bytes in there to do that. Format string mutations, harder to do. If it's a format string vulnerability, what you want to do is substitute your own format string in there, which often involves pushing an extra argument to a format string that you can specify. You can build format strings almost anywhere you want. Usually you can find space to do that. Use any old string that you hardly ever use. Terminate things like copyright notices and just overwrite it with a format string and then get your pointer to the format string pushed on the stack. Just point at that string that you edit in the binary virtually anywhere. Again, as long as you can create the space to do that, you can craft format strings just anywhere in memory. Overwrite some important things. Modified post return stack adjustment. Oh yeah. Anytime you try to push extra arguments when you have C standard calling conventions, you're going to have to clean up after yourself. So don't ever forget to do that. Uninitialized stack variables. Halvar spent some time talking about this over the past year or so. You had this variable in the stack that doesn't get initialized by the function and the exploitable condition is to make some function calls that grow the stack space through that variable, leaving a value that you can predict in the uninitialized variable and hope that it gets used in a manner that's exploitable. So the idea here is move your variable. Permute the stack. That way the attacker, when they're trying to lay that one value into that memory location through some sequences of calls that grows and shrinks the stack, then their picture of your uninitialized variable where they think it is is different than where it actually ends up. So even though you still don't necessarily get to initialize the thing, it's not where the attacker thought it might be. So he doesn't get to initialize it with what he had hoped either. He's got to spend some time perhaps brute forcing through memory to try to figure out that you've done this, or again hopefully move on. The idea here again is to hopefully not be the low hanging fruit. I'm still fruit. You're just not hanging so low. Okay, going quick. So a couple simple demonstrations. This is not a real technical talk. It's just some ideas thrown out there from CTF World. That's really light text. People read that or is that too light in the back? Too light? Let me see if you don't mind if I edit my slides here on the fly. What's that? Kill the lights? Oh man, don't do that. Can't see my keyboard. No, that didn't work. It got like bigger too, sorry. Okay, is that better? Of course it's darker too, so. Okay, so here's a couple simple examples. Simple examples that if the demonstrations go right, they'll work. And if not, then sorry, I wasted an hour. So this is basically the area out of the SQL server that was responsible for the SQL slammer worm. And you can see that Microsoft is using the sprint def function call here. Always known to be a poor choice. And the idea is that if you can see the snippets of strings over there in the right margin, they are sandwiching some static text around. I'm going to see which is it. This var, let me see which one. Okay, I don't have a pointer unfortunately. Right above the sprint def call, there's a push EAX. That is your buffer that's going to be the destination for all of this stuff. Okay, so if we can get a large value into that buffer represented by var24c8 at the top, all that text gets squeezed in between the two static text snippets. One being your format string and the other one that ends up on the tail. So that's a problem because if you can see the math there, that destination buffer is, what, 84 Hex bytes above EBP and so on, what's that? 120, 132 bytes, not a big buffer. Okay, so if we can fill up that top buffer with enough stuff, obviously we have a buffer overflow. Okay, and so the idea is on the left you have the original stack layout with that poor little buffer pony right there down at the bottom. And with some stack pointer manipulation when we allocate our local variables we can reorient or relocate pony up to the top of the stack and allocate it even some extra space and now it's not where the attacker expects it to be. So here is the mutated code. I don't show you the stack adjustment up front but the mutated code basically places a pony, the buffer all the way up at the top of the stack. And that's the basic idea. Now, not wanting to unleash slammer on myself, Metasploit has an exploit for this vulnerability and here's a VMware image. We'll see if this will all work out for me. You can see I've got a SQL server running on here and we'll come out to the Metasploit console where I have and the box that we're looking at as you can see is unpatched. Trust me. All right. And I've got the Metasploit exploit all set up to go which only takes seeing the keys to type. Thank you. Okay. So it's all set up to go against that particular target I hope and so we run it and Metasploit is always exciting when it doesn't work. Run two Windows VMs on a doggy Dell laptop. Please work. Okay. There's the command prompt on the unpatched system. Thrilling, right? We can all do this in our sleep. So here's our other system. Okay. Which is running, which is a host named patched and it is also running SQL server and I'm going to go over here and grab my canned text. I don't know if that'll be useful. Okay. For that host. Because I don't like typing and I can barely run Metasploit in front of the console. So we get out of this guy and paste in some text to, as you can see, change the host name over here and unfortunately we don't end up with a command prompt. Okay. And you have to trust me that was patched. Okay. And we go back and SQL server even managed to survive the attack. Okay. That patch takes all of, I don't have. Oh, it's four bytes. As I mentioned here. Okay. It's a four byte patch. Doesn't change any behavior. All it does is modify the stack layout and now you look different than everybody else. And sometimes that's all we're trying to hope for. Okay. So if we're just on running those vulnerable applications before the patches are out, then maybe this can help. Again, it's not unexploitable. Okay. But it introduces a lot more complexity to the attacker. Because the layout of the stack is significantly different and to get to the return address down here, they still have to go through a substantial number of other local arguments. Okay. 8k worth of stuff to blow through because we've moved that buffer very far away from the stack and there's a whole lot of other local variables in there. So the complexity to the attacker is increased significantly. Okay. So that's an idea where a simple change might help you survive against a worm propagation. Again, sophisticated attacker. He has a challenge of not knowing what your binary looks like anymore because he can't do a stock SQL server install and that's all. So at least he has that added complexity. It doesn't mean they can't brute force you remotely but that gets to be a noisy operation and hopefully you'll spot that one coming. Okay. The other one I'm going to try to do here is RPC decon. A little bit more recent, a little bit less opportunity to modify things. You see on the left, there's a, I don't know how Microsoft writes their code sometimes, but it's allocated, it's only like 32 bytes allocated on the stack and that array receives the machine name, the host name for the host running the service or the host lookup. And ultimately, if you go through the rest of the function, which I don't identify here, but obviously this stuff is public, that host name getting copied into that buffer results in the buffer overflow that yields the exploitable condition. In this case, we don't have quite as much ability to change. They are only using a small amount of stack spaces, the one byte subtraction, you have to be carefully say, well, you know, I can subtract all the way up to FF. Okay, there's a problem with that when you deal with the offsets because the offsets generated from EBP will also be one byte offsets and they're treated as signed integers and when you start subtracting EBP from that, you're going to have a lot of randomness in this issue. So restricted to about the best we can do is to change this up to about a 7C, I think, is where we start to reach the limits of EBP's ability to reach this variable without running into a one byte signed issue. But that simple change, that small change, obviously there's not a lot of randomness left there or available there, but the attacker can say, you know, where do you maybe play around with things? You use alternate alignments. Instead of changing this, just following the top, we're going to keep stack pointer aligned on a four byte boundary, but we might adjust string one to start instead of 7C, 7B. So then any alignments, any pointers to things, or fall off by four bytes when you pop them into EIP, okay, because they're trying to get addresses and they're expecting a particular alignment in this buffer as they overwrite EIP, if you shift it off by one, they don't get quite what they had hoped for, so just other opportunities. So I'm going to try to wrap this up and we'll see if RPC-D-COM is still running on some of these boxes. Okay, and let's go back to the unpatched box and try our Metasploit code and bam, that was quick. Okay, everybody sees at the bottom I have a command prompt on the unpatched system. Okay, exit out of there and I kind of like Metasploit in that respect. They clean up very nicely after themselves. They leave RPC-D-COM up and running and you can come right back into the system. Okay, that's far more food than I possess. Okay, we will give the unpatched system a try. I can't promise you D-COM is not already whacked on that box, so it's not a very good demonstration if we don't even know it's running. What's a quick command line to show that D-COM is running? RPC. Anybody know? Metstat? That works. What's our favorite port number for RPC-D-COM? UDP 445 right there? Okay, TCP 445? Okay, so we'll assume that D-COM remains up and running. I apologize for not getting that checked out. And we switch to okay, we give it a go. Couldn't mind. Okay, so that simple little fix defeats the stock Metasploit exploit to get into RPC-D-COM. And we hope that the authors of the Metasploit payloads and the exploits are a little bit smarter than the average Walmart though. Okay, since they're probably cutting and pasting that stuff anyway. They're right out of Metasploit. So we go back to the box and give it a go. And I think, well, it's still showing as running. Yeah, I think it's probably been whacked. Okay, I'm not sure we can connect to it anymore. But that's the basic idea. And I think I'm at 10 minutes and that's probably going to roll into questions. Again, it's like silly hex editor tricks. Okay, something you can do at home. Okay, if you're not a coder. You don't have to again inject new code into binary, change the binary, build new DLLs, use Microsoft's hot patching compiler techniques or wait for some third party necessarily to offer up a behavioral hot fix. Okay, if this is something that you're interested in. Works in CTF? Okay, may not migrate to the real world that well. So with that, I thank you for coming and I'll take any questions that anybody may have. Is somebody standing back here? Yes. I think there's some possibility. I've pondered that and the idea is the problem is if you come out and say, hey, here's a mutation and you make the mutation public then everybody uses the same mutation and we'll write back where we started from. So yes, you want a way to build like a mutation generator and you generate the mutation so that hopefully it's fairly unique or at least randomized to your circumstances. And once you again, some of these patches, these patches are only like four and seven bytes in these two cases and not behavioral, you know, strictly layout wise. So once you understand where the bytes need to go you can probably specify a range of values and you need to understand the relationships among the values. If I modify this, if I subtract off here I need to add over here and I can subtract, here's the range I can subtract off of and once you pick that then you can probably spit out a mutation automatically, yeah. So there's probably some opportunity, obviously the more you want to do the more complex it gets. So yes, Ryan. The quality of disassembly you have to do and the level of detail you have to grok, the stack layout here to be able to do these patches is just a couple of steps shy of spotting the vulnerability in the first place and probably being able to patch it directly. Is that correct? Yeah, and that's where I don't know where the skill level separates. I personally think it's easier to look at assembly than to take that extra step and understand the implications of trying to inject new code or shift code or even then dig into modifying PE headers or things like that. I think that is a it's probably a fine line. I think again this is probably a lower technical skill level and obviously I think changing bytes in a binary and shipping it say and run this code is difficult in either case but I think you can be more confident that these will work without breaking your code sooner than getting the patch in. What happens when the vendor issues the official patch? Do you have to go back and revert to what it was before? I suppose that depends on the vendor's patching mechanism. I don't know if they verify whether the MD5s or whatever on the original, on the DLL that's going to be replaced because it depends on the patching technique. If the vendor is going to give you a whole new DLL then the overwrite will just kill this fix and incorporate the vendor fix. If the vendor is going to come into your DLL and do a hot fix over the top of it then you have issues. You might have to roll this back so that they are hot fixing the known quantity that they had back in their development shops. That's a good question. Thank you. A lot of vendors are moving toward co-signing as a means of protecting against root kits and trojans and that sort of thing. In that circumstance it wouldn't be generally possible for the user to modify a binary on their own because they wouldn't be able to get it signed. Are there any dynamic techniques that could potentially be used along these same lines to maybe hot patch something that would be able to get around the co-signing? I haven't really thought about it. The only thing that comes to mind is if you could modify it in memory in place the signature checks take place when the binary is initially loaded into memory and I don't know that they periodically recheck the integrity of the binary in any way, shape, or form. If you want to do it in a hot fix way you'd have to have direct write access to process memory space which is tough on some processors although if you've seen Joanna's stuff on Vista root kits there's some opportunities there perhaps. Thanks. Any other questions? Okay, I think I'm out of here on time and thanks for coming.