Structured Exception Handling (SEH)Based Buffer Overflow Vulnerability
Kali Linux
Windows Vista
Vulnerable application: vulnserver.exe (GMON)
Vulnserver.exe is meant to be exploited mainly with buffer overflows vulnerabilities. More info about this application and where to download it can be found here:
~~~~~//********//~~~~~~
Once the application has been downloaded, we run it on our Vista Machine and start fuzzing.
Fuzzing
For fuzzing, I will be using boofuzz, and documentation can be found here:
First off, we connect to the application to test its functionality--specifically, we will be testing the GMON command as shown below
Here is the boofuzz template/proof-of-concept that I used for fuzzing:
We fire up this python fuzzer and get a crash.
With boofuzz, it generates a fuzzing result that can be further accessed using a DB application. For this, I am using a sqlitebrowser that provides a nice SQLite GUI.
We can see in this result (line 24) that our fuzzer sent 5013 bytes before the crash occurred
Proof-of-concept
Here's the original proof-of-concept that I will be using throughout the exploit development
We will begin by recreating the crash using this POC
We fire up this POC and examine the crash in Windows Vista using Immunity Debugger.
We successfully get a crash with our buffer of 41s.
Since this will be an SEH based buffer overflow, we look at the crash in SEH chain which shows that SEH handler address being overwritten with our 41s
Since this will be an SEH based buffer overflow, we look at the crash in SEH chain which shows that SEH handler address being overwritten with our 41s
After being able to successfully overwrite the SEH handler, we then need to figure out the correct offset. This can be done by feeding our POC with unique characters of 5100 bytes long.
We will be using Metasploit's pattern_create.rb as shown below.
We then update our POC with the following unique chars and again fire up our exploit.
The POC successfully crashes the vulnserver.exe program again and follow the crash in immunity.
Here we can see that SEH has been overwritten with the following values:
326E4531 & 45336E45
We can use these two values to calculate the offset using Metasploit's pattern_offset.rb
Note: Immunity Debugger's mona.py can also be used to create the pattern_create and pattern_offset
We get the following offset:
SEH: 3519
nSEH: 3515
We can use these offset values to update the POC one more time and recalculate our buffer
Again, we fire up the updated POC and examine the crash in immunity.
We can see that nSEH has been overwritten with x42s and the SEH has been overwritten with x43s
We can see that nSEH has been overwritten with x42s and the SEH has been overwritten with x43s
Redirecting the SEH Handler
At this point, we have successfully accomplished the following:
1. Fuzzed the vulnerable application given a long string of buffer
2. We have calculated the offset for the SEH Handler
One common way (or only way?) to exploit a buffer overflow vulnerability is using the POP-POP-RET
This is possible because when an application crashes and the SEH happens, our malicious buffer is loaded into the stack and the crash makes this buffer accessible using the POP-POP-RET sequence of instructions.
More information about POP-POP-RET can be found in this blog:
Bottom right of the immunity debugger crash below shows the current state of the stack after the crash
Our buffer is loaded at address 00FDF1F0 (note that addresses 00FDF1E8 and 00FDF1FC will need to be pop from the stack)
POP - 00FDF1E8
POP - 00FDF1FC
RET - 00FDF1F0 (returns our buffer)
Bad characters are no bueno
Before we look for a POP-POP-RET address and redirect our SEH Handler to it, we need to discover bad characters that will truncate or mangle our exploit.
Searching for bad characters can be accomplished by feeding 255 unique hex characters and follow code execution in immunity debugger to see it certain hex characters truncate or mangle our buffer
Again, execute our POC and trace code execution in immunity debugger.
Looking at the hex dump (bottom left), we can see the application took all 255 hex characters (0x01 to 0xff) which means that other than 0x00, all hex characters can be used.
Now we are ready to find any POP-POP-RET address. This can be done using the mona.py plugin in immunity debugger (I couldn't get it to work) or you can just do it manually by opening up the essfunc.dll and searching for these sets of instructions.
I found the POP-POP-RET at address 625010B4
Once again, we update our POC with the SEH Handler redirect address. We examine the crash by adding a breakpoint at address 625010B4 and see if we can hit the breakpoint for a successful redirection.
Note that the address has to be in little-endian format. Also, we added a first jump (EB 06) and 2 NOPs.
We get a another crash, examine the SEH chain which shows our POP-POP-RET address and if we allow the exception to happen, we are successfully redirected to address 625010B4
We step through the POP-POP-RET codes and we then hit our first jump (EB 06).
...once we take the jmp and hit the address 00EFFF7D. This gives us roughly about 70 bytes of address space. This space is not enough to get a reverse or bind shellcode however, we can utilize this space to further jump.
For our second jump, I am using the following instructions which were straight from the OSCE course.
These instructions basically moves the address of EIP to ECX then 8 bytes of ECX gets decreased before the jump is taken.
These instructions can be created to a nasm file then objdump can be used to generate the opcodes.
Below shows these instructions and their respective opcodes
Note that at this
point, ecx points to address 00EFFD87. We step through the instructions, take the jump and follow the new EIP
00EFFD87 in dump which gives us a bigger address space…512 bytes to be exact
00EFFF8B - 00EFFFD87= 512 in decimal
We update our POC once again with these jump instructions and now we are afforded an address space big enough for our shellcode.
SHELL TIME!
We create a reverse shell.
We update our POC buffer one last time
We execute our POC
again and follow code execution in our debugger
And after taking our
second jump, we hit our NOPs and if we follow the eip in dump, we can see that
our encoded shellcode is just right below it.
If we continue code execution, we hit our shellcode and get a reverse shell in kali
Final POC
Conclusion:
- Fuzzed the vulnerable application given a long string of buffer
- We have calculated the offset for the SEH Handler
- Determine if there are any bad characters
- Found a POP-POP-RET address to access our buffer
- Use the 4 bytes @ offset 3515 to do our first jump for a 70-byte address space
- Use the 70 bytes address space for the second jump which gave us 512 bytes of address space
- Add shellcode
Comments
Post a Comment