During the last few days a lot of nice Remote Exploits have been released over at Exploit-DB by one of my followers Harold aka superkojiman targeting applications by EFS Software Inc. First of all: Kudos to Harold, you did a really nice job :-)!
As I were looking through his releases, I noticed a special one which immediately drew my attention: Easy File Management Web Server 5.3 - Stack Buffer Overflow - especially the technique used to achieve code execution - according to one of the comments:
`# only second byte changes in the stack address changes, so we can brute``# force it`
I’ve tested this exploit multiple times against my WinXP VM, but unfortunately I noticed that the bruteforce-scenario wasn’t quite reliable, as the application crashed sometimes and it doesn’t work on Windows 7/8 - the application does not crash at all.
So I thought that there has to be a way to execute some code without the need of brute forcing the stack-address. Here’s the write-up on my exploit that works reliably on all MS OS up to 8 :-)
Method #1 - Brute Force the Stack Address
Before moving on, let’s just have a quick look at the vulnerability itself and the reason why you could brute-force the stack address. Taken from the exploit comments:
`# By setting UserID in the cookie to a long string, we can overwrite EDX which``# allows us to control execution flow when the following instruction is``# executed:`
A quite common buffer overflow scenario :-) - in means of assembly:
Due to the oversized UserID value, the attacker gets control over EDX, which is afterwards used in a pointer call at 0x00468702. This may result in a possible redirection of the application flow and EDI points to somewhere inside the overwritten stack-part. Please notice the addresses of the overwritten stack-part:
The reason why to use a brute-forcing method is simply the following: If you restart the application and try to exploit the same flaw a second time, the location of the overwritten stack-part may have changed:
So if you try to build an exploit that relies on the stack-address, the brute-forcing method may be the only solution to solve this problem.
Method #2: Feed the Call Pointer with Something Trusted
The second method is quite simple in its idea: Do not use a stack address in your exploit! :-D :-D …. Instead use trusted code segments (that don’t change their address in memory - they’re not rebased!) and/or use only relative exploiting methods like ROP :-).
Enough gibberish. Let’s have a look at the technical details.
Instead of feeding the CALL DWORD PTR DS:[EDX+28] at 0x00468702 with an address from the stack, let’s feed it with a pointer to an address within the .text segment of ImageLoad.dll, which finally should do the stackpivoting. After a really long search for a usable pointer, I found this one using lovely mona.py:
All you have to do is find a string in the .text segment of ImageLoad.dll which is before and of course near to (more about this later) the stack pivot address at 0x1001d89b.
Searching for the string “\xD8\x01\x10” results in a perfect match at 0x1001D8F0 that contains “\x7A\xD8\x01\x10”, which is due to little endianess 0x1001D87A:
The code starting at 0x1001087A up to the start of the stackpivot (0x1001D89B) is:
This is a quite good match, because there are only a few instructions between the .text segment pointer and the stackpivot instructions! And that’s the reason why you should pick an address that is close to your stackpivot, otherwise there may be instructions that change major parts of your stack or even jump to undesired memory locations resulting in loss of application flow.
Now that you have an address for the CALL DWORD PTR DS:[EDX+28] instruction from the .text segment, notice that 28h are added to EDX, which means you have to substract it: 0x1001D8F0 - 28h = 0x1001D8C8
Feed it! Great the application flow was successfully redirected to 0x1001D87A!
Ok, just a few more problems to solve. The application flow was redirected but the application crashes due to an access violation at 0x1001D881:
The content of ESP-264 is MOVed to EDI and afterwards the contents are copied to BL. So you need an address which is readable (for the MOV instruction) and which can be used to pass the JNZ instruction at 0x1001D891, otherwise the JNZ instruction will take your application flow control. To achieve this, you simply need a 0-value in BL:
There’s a usable value at 0x10010125, which contains \x00\x00\x00\x00! This results in EBX being zeroed out and the Zero-Flag is set (due to the TEST BL,BL at 0x1001D884):
This means that the JNZ instruction at 0x1001D891 is not taken and the application continues to execute the stackpivot up to the RETN. Then it would move on to a pop/pop/ret instruction at 0x10010101:
ROPing to the Shellcode
The following diagram shows how the further ROPing leads to the executing of the shellcode.
This is the first RET after the stackpivot. ESP+25C contains 0x10010101, which is a simple p/p/r instruction set:
It pops the following two values at ESP+260 0xA445ABCF and at ESP+264 0x10010125. Now the value at ESP+264 is already familiar to you, because it’s used to set the Zero-Flag in the TEST BL, BL instruction at 0x1001D884, so you can POP that somewhere.
The value 0xA445ABCF is used to craft a JMP ESP call on the stack. So why that? As every \x00 would break the Exploit and there are only two JMP ESP instructions in non-OS modules:
And both are starting with 00, you need to craft the value for one of them directly on the stack. That’s by the way the same reason why you have to stick to the ImageLoad.dll during the whole ROPing, because it’s the only module that does not start with a 0x00!
The instruction at ESP+268 (0x10022AAC)
moves the value of EBX (0xA445ABCF) into EAX for some more crafting magic. The included p/p/r just moves two dummy values 0xDEADBEEF to ESI and EBX, because I haven’t found any shorter instructions sets.
Here’s the crafting magic. The instruction at 0x1001a187 is a simple:
It adds 0x5BFFC8822 to EAX which contains 0xA445ABCF. The result of this addition is: 0x00457452, which contains the JMP ESP from Step #1.
The instruction at ESP+278 (0x1002466d):
PUSHes the crafted JMP ESP value from EAX onto the stack and RETs (executes it).
ESP is now pointing to the nopsled:
and it executes the shellcode resulting i a poped calc.exe:
Pwned. Reliably pwned.
Have fun! :-)