 Obviously, it's going to be on buffer overflows on the Spark. You're just treated to a great talk on basically advanced techniques you can do. I'm going to try and focus on this on doing overflows on other architectures, most notably the Spark. The Spark, for those who are unfamiliar or probably have just heard of them, is... Oh, well, this is what I'm going to talk about. Sorry, again out of order. I do a crash course on the Spark and Spark assembly. Just because I'm going to focus a lot on writing the shell code or the payload, because that's what differs the most between Intel and the Spark. And a lot of the techniques that were sort of talked about about how to deliver the shell code all equally applies here. There are some little nuances that will make it different, but as a general conceptual overview, it's the same. The stack is much funkier on the Spark, and I'll make sure I cover that. I'll cover some of the tools that I'm using to develop the shell code and examples. I'll be doing everything on a Solaris box, this one right here. Solaris is so nice to come with a wonderful debugger. ADB is called the Absolute Debugger. It's an assembly language level debugger. So you can step through, look at the registers, look at patch binaries. You can patch values in memory and do things a lot easier than you can with GDB. And that will speak up as everyone is motioning towards me to do. Then I'll discuss exactly what happens on an overflow and start discussing shell code and some methods of delivery. And I'll be giving some examples too, because I like doing that. Okay, the Spark. It's named for Scalable Processor Architecture, created by Sun in the early 80s. It was based on the risk designs out of UC Berkeley. And basically the whole philosophy was make the chip as simple as possible so it's blazing fast. And part of what this is is a 32-bit wide path. Everything in Spark is really pretty because every instruction is 32 bits wide. Your shell code is nice and square. It's really fun. It makes things just typically easier for calculating the size of your shell code and calculating jump addresses and stuff like that. There's a pipeline to architecture which I just had to mention because it will get you in some places. Every clock cycle, it basically executes one and a half-ish instructions where it basically prepares the second instruction. So you have to watch out when you're branching that when you branch, jump to another location and code, you will execute the statement after the branch. So just keep that in mind when you're writing your stuff. One of the other things to speed this up is the load store architecture. All logical and arithmetic instructions only operate on the registers. You can't just increment something in memory because that would involve making the chip smarter and slower. And the one thing unique to the Spark is this wacky invention called register windows, which I will cover in great depth because it's kind of crazy. Memory access, basically it's relatively simple. The only instructions that can access memory are load and store, and that whole family of instructions, load by half word, so on and so on. And all memory access is registered indirect, meaning that you have to write something in the value contained in a register, whereas each register acts like a pointer basically as they wouldn't see. So this chip was actually written for C compiler, so if you think and see you, the Spark will be very nice to you. All instructions are one word, very nice. The registers, risks, chips always have tons of registers, which make things really easy. At each given point in time, you have access to 32 registers. The chip may actually have more registers than that, more general purpose integer registers, but you can only see 32 of them at a time because of the register windows, which I'll talk about. You always have the global registers, you have eight of them, that are accessible across every function. You have the output registers, which you load up the arguments to a function to be calling. You have the local registers, which are local to your subroutine. The inputs, which are your caller's output registers. Things to note, the output register six is the stack pointer. That points to the bottom of your stack, bottom being the lowest memory address. The input six is the frame pointer, which is your caller's stack pointer, and also it points to the top of your stack space. Register windows work is a circular stack of 16 registers. The outputs and the locals, which are rotated among functions, so you don't have to worry about pushing arguments onto the stack or so on, and to speed up function calls because it was written for C, and that's what you do all the time. The caller's output registers become the input registers in the next function, and these are all handled by the save and restore instructions. The save and restore instructions allocate your new register set, and they also allocate the space on the stack, which we had to get the subroutine calling conventions. Basically, the caller's subroutine, very simple. You just place the arguments in the output registers, use the call instruction to actually jump to the location in memory containing the code for the function. The callee uses the save instruction to allocate a register window, and it will also allocate their stack frame. With that, they calculate the minimum space they need for the stack in addition to anything they need for local variables, as all allocated in one instruction. Interesting thing to note is that when you are allocating space on the stack for the register window, they're not actually written there. They're only written there when the system runs out of register windows, and when that happens, a trap is called that signals the operating system, that it needs to flush some of these registers out to the memory stack, and so basically what you're doing is you're saying, when you need to dump them, dump them here. So you're not actually guaranteed to have them written there, which is kind of difficult because the point of overflowing the buffer is to overwrite the return address, but if the return address is in a register, you have complications, and the callee does its thing, and at the end it does a ret, which is return to the caller, which just basically jumps to the value store in the input 7 register plus 8, because the 8 is added because of the register of the branch delay slot, that when it's called, it executes that instruction and the next instruction, so it has to go 8 back. A simple example. We have our main, just we'll call the function foo, and we'll set the upper register 0 to dead beef. This is executed because it is in the branch delay slot. Control transfers over to foo, which saves, the save instruction is interesting because the first argument, oh, one thing to note about Spark Assembly is the destination is always on the right, so it was save starting at the original stack pointer, and decrement the stack pointer by 96 bytes, which is the minimum stack frame needed to dump the registers, and store that value as the new stack pointer, and in between those is when the register window is rotated, so the value of the stack pointer at the first operand is now in the frame pointer register. Then it just loads the value stored at the memory address, stored in register input 0, and puts that value in register local 0, adds 42 to it, storing the result in register local 1, and similarly stores the result back in dead beef. Then it returns, and returns is transferred to control back, and because the branch delay slot, the restore flips the register window back, and the allocates the stack, so when transfer is controlled back, the caller thinks the world is right again. I want to define traps for you. These are typically called interrupts in other operating systems and architectures. They are transfers of control to supervisor software, meaning it's a request from the application, or from other supervisor code, or from the actual hardware for the operating system to get up and do something. These are handled for a window overflow and underflow conditions, where the operating system has to dump them to the memory stack, or restore them. The question is, why do we care? System calls. If you're familiar with Unix kernels, they are all based upon having tons of system calls that will do everything for you. These are all in the manual pages section 2, open, close, exec, fork, all these fun things are all there for you. To make a system call, all you do is look up in syscall.h, the system call number of the system call you want to execute, you throw that in global 1 and execute trap 8. A simple example here. We are going to set the output register to 0, because global 0 is basically the dev null register. It's hard coded 0. 23 is the index of the setUID system call. Move that to global 1, do the trap. Notice there is no branch delay slot after a trap. It's only on branches and calls. Now let's just execute setUID 0, which we'll see why we need to do that soon. The stack. Like other architectures, the stack goes downward and it reserves the space for the window in case of overflow and underflow. And basically, in the well-behaved convention obeying functions, all automatic variables are referenced by negative offsets from the frame pointer, because as my little art in the next slide will show you, the first part of the stack in the high memory address is space, if any, for automatic variables. You just index them that way. And then the bottom of the stack is stuff for the register windows. But you actually really don't need to reference those, because nothing is guaranteed to be there, so why would you want to do that? And here is, obviously, a struct representation of the minimum stack frame. And they do some interesting stuff here. You have eight words allotted for the local registers. Then you have six for the input registers. And notice these two are also the input registers. We have the frame pointer and the saved program counter, which is where we'll be jumping back to. Basically, you have eight locals and those next three lines form the eight inputs, which means you can only pass six arguments through the registers to a function. Then we have the structure return address for return and compound values. We decide to throw that in there for fun. So you could store a pointer on the stack instead of putting in a register. I'm not sure why. And then we have the argument dump area, which is so that the function being called, if it so chooses, can dump its arguments that it got on its input registers onto its stack. Okay. If you need more registers, you can do that and get them all. And then we have the arg x area. This is the argument extension. For more than six arguments to a function, this stack, this space just kind of grows as far as needed to place the arguments there. This is allotted with the callers save instruction, which I put those in there. They load them in. The function will know to reference them as negative to the frame pointer as yes. And that's how that works. We won't really be using that. But here's a nice ask your depiction of the stack. Stack goes this way, and I have it going left to right just so you can read it, and you can see the string buffers as they are. Locals inputs the structure return address point or the structure pointer. The argument dump area is 24 bytes of the sizes used by them up there. The argument dump area is that one byte is also sometimes referred to as the hidden word, which is used to make sure that the stack is double word aligned. The stack and the saved program counter must always be double word aligned or else your chip will get very angry with you. And we're going to make it very angry, but not so angry that it barfs. And then automatic variables restored here. Like right here in my example where I have a string pointer called buff of indeterminate size. It doesn't really matter. And then we have the frame pointer, which is the boundary between our next or our collars stack frame. There are his locals, his inputs, and our little asterisks. That's his saved program counter. That's our target. That's what we need to hit. And it's pretty easy to see that if the buffer grows outside of its boundaries, you just overwrite his registers and basically take him over. What actually presents the interesting thing is you're not overflowing and taking over the function that with the fixed length buffer in it, you are overflowing and taking control from his caller, which is very interesting because sometimes your caller can call the overflowable function, return, call another function, which will overwrite your wonderful stack frame and shellcode, and then basically you're screwed. But of course, you just attended the Greg Coglund's talk on how to do cool things with the stack and where you can put the code and stuff like that should not be a problem. But this is what's going to happen when we are overflowing the buffer. Just trying to trace through over how the register windows rotate the registers and how things change. Obviously, the previous stack frame's saved program counter is overwritten, as is all his other registers. The function returns, his frame pointer becomes the target address and his input seven register becomes the target address also. And the stack pointer is still valid. The stack pointer will still be the pointer to his stack, which has not been fully overwrite at this point. All of his values that he assumed to be safe have just been totally messed up, so he just freaks out hopefully getting an error condition immediately and returning. And if he does, he tries to jump to the input seven plus eight, our target address plus eight bytes, and that is where we would take over control. This is your stack on drugs. Basically, we have all these registers, or these areas on the stack are fine, and at our buff, we just overflow and write our target address off into the horizon. You can basically write as far as you want because nothing is going to behave well at this point. Yes. Thank you for reminding me. Okay, basically, you're told that we are not guaranteed that these values will be there. But what happens is basically, implementations of the Spark architecture, as is an open architecture, are allowed to have anywhere from, I think, eight to 40 register windows. Luckily, those register windows are always filled even in the lowest stages of the kernel, so you can basically assume that every time we do a save or restore, they will be restored from the stack, or saved to the stack and restored from the stack. So that when the overflowed function does a restore, we all assume that the registers that it thought it had in the register window were written to the stack, and so it restores them from the caller's stack. So basically what it does is we have our target address written all the way through there, and it just loads up its registers as it transfers control to the caller, loads up its registers with the target address. I'll do some examples, and I'll show you what this looks like when it's stepping through the program, and you'll see all the registers are just totally just spammed over. One of the very nice tools that Slayers comes with is just the disassembler. They ever looked into basically writing the shell code, writing the assembly code, and then changing it to the bytes, depending the but. But this makes it rather easy, especially when you just throw a Perl script on top of it, and it's a nice little chug, and you have a nice little header file you can use. There are freeware Spark disassemblers available. I just found the page about two hours ago off linuxassembly.org. It has a link to an FBSD, a link to some Spark assembly examples, and on this guy's page he has his own Spark disassembler and Spark assembler, and a couple others that you could use for linux and or BSD. All running on Spark, of course. Excuse me? Is it free? Oh, very nice. Okay. Well, I'm sure we can find that. If you want to give me the URL, I can throw it on here for people. Oh. I forgot who already, but someone has a really good free disassembler. Can you? Oh, wow. I was unaware that they had a disassembler. Well, I have done my research. Okay. And the other tool that we'll be using extensively is the absolute debugger, because this thing, correct me if I'm wrong again, I have not seen anything like this for any of the free operating systems. They tend to use GDB for their kernel debuggers and everything else, but I have not seen something that is as assembly language as this one is, as assembly level. Rather funky syntax to get used to if you're coming from the world of nice and pretty hand-holding debuggers. Arguments are address, height, iterations to do, and command and modifiers, as you can see. First instruction, it says starting at the address of main in the object file. The question mark means in the object file, the slash means in the memory image, whether it be a core file or the actual memory of the running process. What I'm saying on the first one is dump 10 instructions, or disassemble 10 instructions starting at main. One of the wonderful idiosyncrasies of this program is everything on this side of the question mark or slash is in hex. Everything on that side is in decimal. But there are modifiers you can use to put them either way, but we should all be very fluid with conversions, even though I'm not. The second example, just display the word stored at codebabe. That's not a real address, but I like it. We can also just query individual registers. Basically, you have a sudo redirection, the instruction that will say, give me the address of the stack pointer, assign it to the variable x, and it will print it out for you. The next instruction says, display 24 words starting at the stack pointer. That will give you the full minimum stack frame. And then from there, after that point, it will be automatic variables, if any, but every function must have at least those, and you can check them out. Here's a more interesting one. In the address of the frame pointer plus 3C, which I can't remember, I'm on the spot so I can't do math, that will be the saved program counter. Write the value, dead beef. And so then you just write the value, step through, and you'll see the program try and jump to it, or see the caller try and jump to it when it becomes time. The ADB will also do interactive debugging, some simple stuff like this so you're not really pertinent, but I threw it on there because I needed space. Wow, this is very difficult to see. This is a contrived session of using ADB to examine what happens when we overflow a program. I wrote a simple program called smash me, which I'll show you in a couple of minutes. They're basically just a fatal flaw. There's a stir copy or a stir cat into a fixed length buffer. And it just takes the argument on the command line, so I'm just saying run it with this argument. And I said, first, just set the break... Oh, there also is no prompt in ADB, so it's kind of hard to follow along. I said smash colon be me and set a breakpoint at the smash function, which is I have main and I call smash, which has the overflow. And then we run it with that argument, stops at the beginning of smash. We're stepping through. I'll get our stack pointer and we're going to store the value, go through. We're just stepping through watching it. It's going to call, I think right there at the bottom of your screen is where it calls stir cat. But right now we're going to watch... I can't remember how I did this. Oh, yes, I call stir cat. But first I look at our stack pointer and look at the frame pointer, our caller stack frame. And then I step over that instruction, which will call stir cat and we're going to watch what happens after that. The colon e means step to the next instruction, but don't follow any jumps or calls. As you can see, the saved program counter is overwritten, as is his entire stack frame. He's not happy. And then I basically just step through to the end and go right here to where he returns. And so when he returns, the stuff store on his stack is loaded off the stack into registers and using the restore instruction is flipped over to his callers, local and output registers. And so now we have them all loaded in back in control of main. They're all loaded in there. And we're going to step through the last instructions of main where it tries to do a return right here. And that says a bus error because the address 41414141 is not aligned. And you'll get that. It's the last way just to see when you've messed up, quit out of that. I'll run through that again later with a real-world example. I'm going to start talking now about how to write a similar code that we'll use as mobile code, as it's a new dependent code. We can just throw in there and it will just execute on its own behalf and take control of the process. Basically, two ways to write this is using your compiler, you can make an ASM block, which basically just says this is straight assembly code and you just write it in there, compile the program, you run it, and if it gives you a shell, you obviously know what's working. And then after that, I throw the function into a character array and then I cast that array to a function pointer, execute the function pointer as the final stress test. Here's my first example of some Spark shell code. This is somewhat brain dead in some ways as I'll explain. This representation does contain null bytes in it, so it's useless basically, but it's ordered in a simplest way. I'll show you just how we're going to write it. I write my shell code at first as if it's a well-behaved function, so I allocate in a new register window and I'm basically calling execs, so I'm creating the character array of the function to execute and I'm creating the arg value, the arg vector. Throw that in there, and just giving it a null for the environment pointer because, okay, it's a little bit messy, but it's not a problem. One very handy thing about Spark is that it's big Indian, and so you can write strings in a relatively straightforward way just straight to the stack. One way to do this is if you're lazy, almost the unixes will come with the octal dump program, and if you just do echo string, pipe, octal dump, slash x, forgive me, hexadecimal output, it'll give you a nice hex and you just basically just chop it into words and start storing them on the stack and you have a string. There are, I'm sure there are ways to do the cool little jumping thing that will actually load the address of the string so you can just write it straight, but that's a little over the top for now. And you can basically see I set 59 to the system call number, execute the system call. This can basically be looked at as a well-behaved function to just exec a shell. Then I chop it down a little more. It doesn't seem it's a well-behaved function. I am lying on that second line, ignore that. Basically, I chop out the saving restores and I just start using the current stack pointer because in the situation where the overflow occurs, assuming the well-behaved function assumes that you have valid stack pointers and frame pointers. You can get in situations where your stack pointer will be pointing to right behind your code and as you're storing memory, you'll be chasing your code as your code executes and you're overwriting behind it and you don't want to be there. So this code also will not work because it assumes that the frame pointer is valid, but as I discussed before, the frame pointer will be the target address and so you're stepping on your toes here. But this is another example of just chopping things down. And I can see I set the two words and two following registers to a stored double word instruction starting at the address of the frame pointer minus 16, so it writes the full 8-5 value down. And I basically am constructing in memory the string followed by a null so that I can use it for both the name of the program to execute and I build a pointer to that array of character pointers to use as the arg vector. If you've seen Aleph Warren's code in the expression of stack for front-end profit, he does this also. Very easy and straightforward way to do it. Here is my even better shell code. I'm not saying it's really great, but in writing this, there's an interesting caveat that is not addressed in smashing the stack for front-end profit. Under system v systems, the born shell, slash bnsh, when passed an effective UID of less than 100 will discard it so that the effective UID is triggered when the program has the suid bit set which means it keeps your real user ID saying this is who you really are, but effectively you're root. And then it calls the shell and the shell discards the effective UID and so basically you've found that you've exploited a suid program and you still have your own privileges and you're not very pleased. The second one. It contains a no-byte in this. Oh, thank you. Okay, the set is a synthetic instruction, meaning the assembler basically expands it for you. And of the set, because everything is 32 bits, how can you write a 32-bit value in the instruction? Because it splits it into two. It first writes the, is the set high instruction to write the first, the highest order, 13 bits to the register and then does an OR with the lower 13 bits, with the lower 8 bits to complete the whole value. And we'll see when I disassemble the shell code how it's changed over and I'm just lazy so I just do the set because it's easier to see the string there instead of in two words. But yeah, that will eliminate the no-byte. The no-byte will still be in the set and the OR but because of the way that the opcode for OR is aligned with the bits, it will not be on the correct boundaries to be a, in fact, no-byte. It'll be spread across. I don't have a diagram of that but you take my word for it or call me a liar and chase me out to the parking lot. It's your choice. Let's see, nothing else really changed here. You'll notice that I do not trust the frame pointer anymore because I've stepped through with you as I need a bug and I'm like, wait, why am I doing that? That is just whack. And so everything relative to the stack pointer, I waste four bytes before the stack pointer because storing straight to the stack pointer introduces a no-byte. And you'll notice when I'm trying to set a register to zero, I can't use the straight forward instruction by just setting to zero or moving the global register over because that introduces a no-byte so you just do something like XORs or there's a thousand different creative ways you can do that just to feel fun. I'm just going to talk a little bit about the delivery but not that much because it is basically treated well better than I could by Greg Hoglund. Same with other architectures either. You need to do the no-op sled and then the shellcode and then write the jump address off into infinity and let it jump back which has the problem of if the caller of the overflowable function calls another function, you're not necessarily toast, you're just basically dodging bullets. Or you can just write the jump address to overwrite the saved program counter then put the no-ops after it and the code after it so basically you're jumping backwards in the stack and beyond to the caller of the caller of the overflowable function the metacaller in this case. And basically because the register will be the saved program counter will be borked by that point, you don't have to worry about those stack frames they can just go to hell. Greg Hoglund talked a lot about this very well, am I not? Okay, some real-world examples if I can find a place to put this microphone. Can everyone see the shell? Okay. Let me do an example. Okay, first we're going to have our nice little simple smash me example. Here's a source code for that. Very, very simple. Smash with the argv1 stircat to 128 byte buffer. Now we run a min of smash me which will smash, smash me. One thing you'll basically always see is the calling function will get the value of its stack pointer because it'll calculate the offset from its stack pointer so it can try and guess the stack pointer of the function it's trying to overflow because it'll always be a defined number of bytes down the stack a certain number of function calls down the stack. And so basically what you're going to be doing is you're just going to be creating a very large string in this program what I do is I write I pass in the argument of the buffer size that I'm trying to overflow and so what I do is I write no ops all the way up to where the shell code must fit then write the shell code so it's all within the buffer and then just write tons of return addresses and the return address is calculated as an offset from the stack pointer of the meta smash me process. So I just calculate the egg size and it kind of just tells you what it's doing and writes like the no op I have here is I cannot remember what instruction that is just trust me that it's a basic instruction that does nothing essentially and just copy the memory into the egg and so the egg represents the entire string I'm trying to pass it with and I call the function so let's see what happens if we say the offset is zero notice that the shell code I'm using in this example has 64 bytes so we'll have 64 bytes of no ops and then the shell code so we don't have that big of a window it's not happy so fire parted bugger meta smash me and the core legal instruction to the registers notice how the registers are just basically splatted and so we can just check out our frame pointer see what they point to the point to themselves again because basically I did not go back far enough in the stack where I'm just pointing back at my target address so let's see minus 500 500 hex notice that is well beyond it okay so what I'm going to do is get my shell code I should all look at look at my no op I'll see that bite there and basically I'm going to search through memory for where that thing is and that'll basically calculate the offset for me so I'm going to say we'll start at 500 hex bytes down the stack from the frame pointer do a search for the 30 bit value alright okay search for that value show me the first occurrence of it is and now I'm going to do my poor man's hex calculator is that the value we want 980 so that right there is our offset so let's quit on that and let's put gdb at the test I'm going to smash me 128 bytes go back we have a shell we basically landed exactly at the first no op thank you but that's some precision that we don't really need basically we know that we have 64 bytes so basically we only have to be within 50 bytes or so so we can just go back and go try 1000 no not happy 1050 bingo and so the larger the buffer is basically you more leeway you have which will go and we'll see my libc example this is old this was discovered by onion I think in September 1998 or something like that and son took about a year to post a fix for it but so I just took all the patches off my system I'm feeling kind of vulnerable right now but it's for the greater good the details of this bug are there's an overflow in libc and it's parsing of the LC messages environment variable you can overflow that and basically so any sewer program becomes vulnerable to it so here's my little program right here I just ask what program to call how big the buffer is and what the offset is and I'll show you the program in a second pretty much the same thing as the last one just throws it in the environment you will have to you'll have to basically write a program to exploit each one you're going for typically just so you can customize it but it's not that big of a deal and what we can do is we can then I'm just going to try out let's go for bin rsh and I basically went through with Perl and basically kept giving larger larger buffers in LC messages until I got one that died it was somewhere around a thousand bytes that's what I'm going to assume the size of the buffer is start with offset zero it dies okay well I know now that because it is a thousand bytes of no ops 1,000 minus 64 I have a very gaping large window and so I'm just going to try offsets of 500 there we go and that basically gives me a root shell because in this the shellcode that I'm using I made sure to call set you 80 zero before I can bin shell so bin shell is happy and trust me and it's basically like that I can use any fluid program on the on the system at this point so okay anyone have a favorite you know I'll do bin password because that one's nice and easy but I basically just sat down today and decide which ones I could get and basically some of these didn't have the overflow in them because they didn't use the local support and libc to use it but the vast majority of them did so let's start with password and oh wow looks like they don't go very far down on the stack and then make it really easy for us so let's see what else do I have that's really fun to show you okay let's go for some really cool shellcode that mostly works I spent the last couple days on this a strange strange bug it's driving me nuts but here's an alternate way to develop shellcode instead of using the ass and blocks just write the assembly file and basically put you throw it through the create the object file and then I have a main function in a C program that just calls this function bind shell and that's a simple way for me to test it so I can go through here and mostly because the ass and blocks just makes emacs go hairy and I like emacs so don't throw anything okay what I'm doing oh let's see where's the source for this originally first I wrote basically what I wanted to do in C create a socket set it up bind it set the first connection dupe the file descriptors for send it in send it out send it error to the socket and run bin shell and I just kind of went through translated this into assembly because everything is just a system call so I do trap let's see right there is the socket call by 230 just look through these higher numbered ones will change from system to system so you'll have to look them up on if you're doing that in Linux or at BSD on there just straightforward assembly programming basically going through go bind store it all yada yada you compile and I just insert my standard shell code right there using the compiler to output assembly code will be very helpful and figuring out how the compiler does stuff but it is deceptive in a lot of ways because the compiler doesn't like telling you are in the various libraries that it's just doing system calls for all these so you'll go through six different layered functions underscore underscore socket underscore capital U that will finally say oh, I just do a trap but just look through syscall.h and you'll see what it really does it'll get angry at you but we test it I just compiled it and linked the two things together that's the bug for some reason when I run it straight it decides that it will not block and wait for it to accept it'll just kind of do something and the thread will just continue on and execute the shell but when I run it through the debugger and say what's it called bind shell where can I run it and I say yeah, continue nope and I just told it to bind to localhost part 2000 yes keep going I like to say it's about to exec something and things will change so I'll stop for you but just ignore that and basically we have a very mutated very ugly environment it's shell right here it says not found colon and you can get enough done from here to do what you need to do and obviously it's running as me because I just ran it from the command line but you just basically through the things I've showed you convert it to shell code and throw in the process and you'll have a bind shell to do so I have a nice little you here just to help me out with writing these I made my disk to H and so if I go through to my code let's see 3 what I do is I write 3.C test it out in there then I disassemble it to 3. well I disassemble it to 3.Disk which says diff main 3 little noise at the top so I just chop those off till I just have the disassembled code shouldn't hurt you to cut out 3 lines not with a script to do everything for you and then just simple like you know a filter you can do this and purl do this and whatever you want but I didn't see because it's fun 3.Disk type to that and gives you a nice little header file to include and this is a quick way to check for null bytes and just look at your code hand side by side and feel warm and fuzzy but basically with just a couple little tools you can just tinker around with in a writing shell code and stuff and then amazingly you will wake up and say wait a minute I'm actually decent at assembly programming now this is useful to be the example I didn't do class until I started doing this stuff and of course this semester it ended and now I know everything and can pay attention to class anyway so no no no grades me nothing I don't think I have anything else to show you and I think I'm out of time and I show you those oh yes some links to useful things linuxassembly.org obviously focuses on Linux and Intel architecture but they have some great info on there a little straight from the beaten path and show you some spark stuff some BSD stuff they have a nice little suite of basically the bin utility a lot of the small utility is written in assembly so you know your standard 100k executable is now like 3k because all they do is call the traps themselves it's not portable but it's really small and useful for boot disks shellcode.org I just saw come across see their bug tracker vulnerable some mailing list today currently down we'll have a lot of resources to various shellcodes for various operating systems Frack55 has a really nice article about writing shellcode on MIPS under iWix MIPS also being another of the pioneering risk chips very similar to this it's a very good read also and this stuff eventually will be on WSquad.net slash security whenever I finish it up and put it up there so you can look there but if you see a 404 don't have a heart attack