 I've put together a number of different panel ideas. This year we wanted to do a little more in the technical side so that it wasn't all just script kitties. So I can take it by the attendance here that that was a good idea. All right. All right. I guess we'll keep doing that. Tomorrow we've got a pretty full session in all three rooms and we'll try to get things more organized. I certainly appreciate your patience. I know a lot of you have been waiting outside trying to get in here. I can tell you that typically Saturday was our big busy day. Today I think we broke all the records in one day of what we did last year so the attendance has been really great and we thank you all for making that possible and we hope we put together a good conference for you and a lot of party, a lot of fun. Hey it's Vegas. Fucking A man. You should have a great time. All right. So not to delay things any longer, try to keep a little bit on schedule if possible. New Hack City, the man himself, Jero, the one you've been waiting for. I'm going to turn the mic over to him and here you go. My name is Jero. I'm going to talk about advanced evasion of IDS buffer flow detection. This came about on a discussion on Pound CDC. I was talking with T-12 and Java Man about the way that IDSs are looking for strings and buffer overflows. Can you hit the slide? This is a little background on me. I worked in embedded systems. I'm working on IDSs right now. I've been a part of a New Hack City collective in San Francisco working on a couple different projects and of course we have t-shirts available. I'm going to start out with a brief overview of buffer overflows. I'm going to cover just as a refresher, like the stuff that was in the Alphan article just to get everyone up to speed in case I forgot something. Then I'm also going to go over the kinds of signatures that IDSs are looking for and then the techniques to code around the signatures so that you can bypass the IDS, get your attack through and no one will notice. You hit the next one. This is the stack on most computers and what you're trying to do is these local variables here. You're trying to overwrite up this way and overwrite the return address. Once you can get the return address to point back into your buffer, then you can execute your own code. This is the shell code that was provided in the Alphan article. I'm going to step through it a little bit and cover what's going on. At the top you have a jump with an offset that's going to this call instruction. The reason you need a jump in a call is that you have no way of knowing the current execution point or the EIP. You need to know the EIP because most of the buffer other flows you're going to try to execute a shell. The execv call requires a bnsh string in memory, a pointer to that string, the address of the string and a null. In order to insert these things in the proper registers, we're going to need to know the actual address. The first thing that happens is you overwrite this return address to point somewhere into here. You're usually going to pad this with no ops because you don't know the exact address. You're kind of just guessing here so the no ops provides some padding so you can guess in here. Usually your code will be maybe 50 bytes and this might be a 1K buffer. You have all kinds of space for a no ops so it's pretty easy to get in there. After you do the jump call, the address after the call is going to be pushed onto the stack. Then you get the address, you pop it back into ESI which is a stack index. You could really use any register in protected mode. There's no restrictions on base index so it was shown in the article but there's other ways to do it so it avoids the common signatures that are out there. After that, you put the address of this in the location right after the string. That's going to be your pointer to the string. Then you clear out EAX, you use the low byte AL and put that 7 locations after ESI after here so that's terminating the string. That's how you terminate the string. After that, you take EAX which still has zeros and put it 12 locations after this which there's nothing there and that'll be your null string. There's 4 bytes of nulls. After that, you move B into AL, ESI into EVX, load the addresses of the pointer into ECX and the address of the nulls into EDX. You do an interrupt 80. This is code specifically that Linux because that's how it handles it. That's the kernel interface. This does the exec VE call. This call right here is an exit in case anything goes wrong here. You can exit out and you won't keep pulling stuff off the stack. That's just basic overview. Here's some signatures from Snort. This is what it's looking for over the wire. This is a common overflow. This is 2.4.2 UFDP by ADM. These are the instructions it's looking for. This right here is an SUID call and here's another SUID call. It's looking for the instructions in the packet. Similar to here, this is, I believe, a jump. Here's one of the most common ones. Just looking for long strings of null ops. It usually means that someone's trying to overflow a buffer because they're using those for padding. We'll show how to go around that. This right here, lots of people use the slash bin SH to execute a shell. People are looking for this too. In order to avoid detection, you have to code a little differently. You can change the location and the order of the instructions you're using so that the signature is different. You can use different instructions and achieve the same objective. You can use different registers within the instructions. You can replace null ops with other 1 byte instructions. Or you can encrypt your payload. This code is copied from the code I showed earlier. You see that it's tearing it out here first. And all this being changed is the order of moving this into AL. So if you move it around, the signature would come out differently. Different instructions for the same objective. Instead of doing this type of call with a static offset, you can zero register, move that into the register, and call the register. You can also produce a different signature than the original one. Another thing you can do instead of using XOR to zero it out, you can use the subtraction to zero it out. These are all simple techniques that people have used before, but it only evades signatures. Well, go ahead and go back. The idea here is like, at the top of the buffer flow, there was a pop ESI. You could pop, let's say, EBX. And then the address of the string is already located in EBX, which you'd use for later. So it's actually optimizing the code. And it changes it around in a bit protected mode. It doesn't matter what registers you use. With certain limitations, you can't push into EIP and stuff like that. But most of the general purpose registers you can do anything you want with. A lot of people use, pretend this is not here. The idea behind the no ops is you're trying to provide some kind of padding to be able to jump into your exploit because you don't know exactly where it's at. So no ops are used because they don't do anything. You can use other instructions that are also one byte long that will not affect the outcome of your exploit. You could use like CLC, clear the carry flag, or set the carry flag, or set the direction flag, clear the direction flag. There's all kinds of one byte instructions you can use. It will not affect your exploit in any way, but it will avoid the signature that's looking for all no ops. That's, I'll cover that next. The types of encryption are really simple. All we're trying to do is avoid the known signature. We don't have a lot of space. So the first tile would be like some kind of ROT13-ish, just add a constant offset or subtract a constant offset. The second one would be an XOR with a constant. And the last one would be an XOR with a variable where your XOR is based on the outcome of your previous instruction. It will provide a little bit more protection. Self-modifying code, there's been a, like, I'm a exploit. You had to add a 50 byte offset to the BNSH to get it through. There's filters. Sometimes HTTP filters won't allow certain characters through. So people view self-modifying code. And someone pointed out this week, someone on this side right here wrote some encrypted shell code that would encrypt just the BNSH string at the end. But the rest of the payload is still detectable by signatures. This is the architecture that I chose. This is the decryption block, and this is an encrypted payload. So the decryption block is up here. First you start with a jump, and then you have a call. On your stack, you'll have the first address of the encrypted instructions. Then in here, you start reading in the data, either adding constant offset or doing an XOR with a constant and writing data back out. Once this drops through on this down, you jump into the first instruction of your payload and execute your exploit. This is probably really small to see, but it's the same thing I said. You start here, here's the jump. It goes to the call. This is the, this cover here is not encrypted for demonstration purposes, so you wouldn't be able to see what it was. And then you go back up, start decrypting, go through the loop, drop down, jump into the instructions. It's pretty simple. I have, I had a couple of demos working, working exploits have been converted to this, but we don't have the setup to have a live demo. I'm going to release the paper probably within a week. I had Spark code written, but it's not fully tested and needs a little more work. So either I'm going to release the paper in about a week with the X86 code, or maybe two weeks and have both X86 and Spark code examples. GCC sucks. You don't want to use GCC to code exploits. There's lots of instructions. It will not compile. It took me forever to figure out why I couldn't get the instructions to compile. The December GCC uses is called GAST. And they chose not to implement any instructions that have 8-bit offsets. And we're working with such a little code that we're never going to go past 8-bit offsets. So like a loop instruction can't use. So if you're going to write exploits, use NASM. NASM supports the full I3-6 instruction set. And this is one you want to use for optimization. Do you have a choice to do the GCC on Spark? The question is, you don't have a choice on Spark. I don't know how... I haven't looked into if Spark doesn't do all the instructions because all Spark's instructions are 32-bit because I haven't been writing anything for 64-bit stuff. But they're all 32-bit. They're all the same size. It's risk. So I'm assuming you support all the instructions. The common is GCC295 on Solaris does support all the instructions. What's that? On Solaris 8. And that's it. Is there any questions? The question is, how is this different from techniques virus riders use to evade detection? Like a portable execution compressor. I mean, I'm not saying that these are new techniques. I'm just saying these are things available that you can do to avoid detection. If you're looking to detect this, in the paper I'm writing, it's going to have a sample decryption header. So the best way it probably would be to look at the header, get a signature for the header, and look at that. But if anyone's writing an exploit and wants to go around detection, you just write your own decryption header and go around anything you want to. Any other questions? I couldn't hear the whole question, but I think it was how would you go about what if someone wrote a signature to detect the decryption technique? This is the standard decryption technique that I'm releasing, but if you write assembly, you can write your own decryption technique that will be different, that will have a different signature. Most of the signature-based IDSs are looking for known attacks that already exist, that they have problems finding new attacks. And what they try to use for new attacks is look for strings of no ops, look for slash bin SHs, and these little tricks to try to look for new attacks, but you can go around them. Any more questions? Go buy t-shirts.