Bypassing ASLR on Windows into a Reverse Shell
I referenced some of myprevious exploit‘s work throughout this post, so I’d suggest you check it out. I’m also going to mainly focus on the new stack environment we have here, and how to structure a payload to bypass ASLR. This is slightly different than my previous post, and the change is by Alex’s request.Exploring windows stack environment Compared with linux, Windows has a slightly different stack layout (why wouldn’t they?). Apart from a different stack layout, Windows also has different calling conventions. In a bit, I’ll explain what that means for us, but before then understand that on the stack, depending on the environment, either the method that calls another method, or the called method is responsible for cleaning up everything they put on that stack. This is called caller/callee and is important because it adds content to our stack. Back on linux, we operated under the caller paradigm, which means that the method which calls another method pushes the proper instructions onto the stack to be called when the other method returns to clean everything up. However, on windows, we’ll see that this is a callee paradigm, which means the method that is called is responsible for cleaning up the stack. So, still similar to our previous image of a stack in the Linux environment, but modified slightly:
We’re left with this image, where EIP is follow by something and then ESP brings up the rear. Well, the something that comes before ESP is in fact the cleanup code that is inserted due to these calling conventions I was talking about. This is important for later because when we’re writing our exploit and we will want to make sure we account for this gap.
And that’s basically it! The Windows stack is surprisingly similar to the Linux stack from our perspective―at least when figuring out how to structure our input. The only other hiccup is that the Windows stack features ASLR, meaning that every new stack frame is placed on a random location on the stack. Ultimately this is the mechanism we’re attempting to bypass with this exploit, so here lies our challenge.
The original plan is to override EIP with an address to the stack where we placed our shellcode (usually just NOP sleds because we can’t be super exact). But this poses a problem as soon as stack randomization (ASLR) is applied. Essentially, whenever a new stack frame is allocated, the operating system randomizes the last portion of the address (varies with OS). This means that we can never be sure where our shellcode is on the stack. Well, you’ll see throughout this blog post that so long as we structure our input correctly, and with just a bit of extra work, we can replace EIP with something different. Instead of the return address to our code, we can put an address that points to the op codes which instruct the computer to jump to ESP. Since ESP is always pointing to the bottom of the current stack frame, it doesn’t matter where in memory we are, we have a relative address to work with. This is the basis of the exploit, and throughout this blog, you’ll see how we find this information.Structure of the malicious input
Well, very similarly to the RedHat8 exploit, we will be chiefly concerned with a buffer overflow. The exact length of that buffer will be decided later, but we at least have enough information right now to decide on the actual structure of the buffer.
Let me first address the issue of bypassing ASLR. We use a simple mechanism known as jmp esp which allows us to jump to where ESP is pointing to, regardless of the location. That means we get a relative jump without knowing the specific address ESP is pointing to. This is a good thing! It means that despite our stack frame being placed randomly on the stack, there will always be a pointer to the end of our stack, and that pointer can be reached with just a simple op code.
Perfect, so as long as we can find the jump esp instruction, we can just place it into EIP on the stack (remember, whatever EIP points to will be executed). That just leaves the little bit of cleanup code I discussed earlier. Well after speaking with Alex, I don’t know the very fine details of when this code is placed on the stack―all we need to concern ourselves with is just ensuring our payload begins after that code ends. This can be achieved with our good friend the NOP sleds. We’ll just insert a fair amount after we override EIP to make sure that we extend beyond the cleanup code.The last issue is found again in the encoding of our shellcode. Similar to the RedHat8 exploit, our shellcode will be transmitted, which means we need to encode it. And thus when the shell code is executed, it could potentially expand from the decoding. The solution to this is simply move ESP further up the stack so that any operations our shellcode does, won’t mess up the stack for ESP. Finally, that leaves us with this goal stack in mind:
Determining the parameters used in the malicious input
For starters, I should note that Windows 7 is in fact, little endian. I only know this by Googling it, but it’s important for how we structure our return addresses, like the jump esp instruction.
The first thing I did was determine our buffer length, or the length that we have to fill before we override EIP. This was done in a very similar fashion to the RedHat8 machine. Namely, we use ./pattern_create.rb 5000 and send it to our server. I chose 5000 after a simple test of first sending A’s to the server and checking when it finally crashed. There’s really no better way than just guess and check for something like this. Next, we check the debugger and note the part of the pattern that overrode EIP and run it through ./pattern_offset.rb PATTERN . This tells us the length of the input which will override EIP, and in our case it is 4093.Next, we need to find the location in memory, probably in shared library, since those don’t tend to move, that will provide us the jump esp instruction. This is accomplished with Narly, listed above. First, attach to the Apache.exe process and type !load narly . Then !nmod to list all of the packages stores on the stack. We’re chiefly concerned with the packages that are listed without ASLR because we want to ensure it is as static as possible. It should look something like this:
I chose to search one of the DLLs with the dbg command for search, namely: s 6a6b0000 L?6a6dd000 ff e4 . All this does is search through memory starting at the first address, and continue until the second address, and it searches for patterns matching ff e4 which is simply the op codes for jump esp . If everything goes right, you’re greeted with a long list of possible addresses, and simply choose one and write it down. Note that this address is not in little endian form, so we do need to change that. Referencing the goal stack, this value is what we’ll override EIP with in an attempt to jump to ESP, a bit further down the stack. I picked the value 0x0fbb1477 . Which avid readers may recognize as a little endian form, and if you’ve been following along will also realize that this address points to ASLR’d shared libraries. I could never get narly to list things out in non-ASLR memory, which is frustrating and most like the reason why my exploit doesn’t work.Finally, we need to figure out the op codes to shift ESP, because, remember, otherwise we could corrupt our stack when unpacking or executing the shellcode. We don’t want that to happen. Luckily there is a website called
本文系统（linux）相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统