Structured Exception Handling (SEH)Based Buffer Overflow Vulnerability w/ Restricted Characters
Windows Vista
Vulnerable application: vulnserver.exe (LTER)
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:
Github: https://github.com/pyt3ra/SEH-based-Buffer-Vulnerablity-128-Restricted-Hex-Characters-
~~~~~//********//~~~~~~
Here we can see our 4 bytes getting decoded at address 00D0FFBF
...we carve out the next 4 bytes
...and follow the instructions being decoded
~~~~~//********//~~~~~~
Fuzzing
Fuzzing with boofuzz
We open the boofuzz result using SQLite browser
Recreating the crash with our Proof-of-concept
As usual, we examine the crash using Immunity Debugger and see that our SEH handler address has been overwritten with our buffer
Calculating Offset
We use Metasploit's pattern_create.rb and pattern_offset.rb to generate unique characters and calculate the offset.
Updated POC
The following values overwrite the SEH handler
...which then equates to the following offset positions.
Once again, we update the Proof-of-Concept with the following offset calculations and verify if we can see these values after the crash
Finding restricted characters
After running a few
test, it looks like anything over 7F is being subtracted by 7F as we can
see below in our dump….such that x80 -
x7F = x01
This means we will
not be able to use any hex characters over 7F
Allowed characters:
x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f
At this point we have successfully done the following:
1. Successfully produced a crash to the program with the buffer we provided
2. Calculated the offset values for address redirection
3. Found all the restricted characters
POP-POP-RET...the key to SEH Based Buffer Overflow Vulnerabilities
I will be using the same POP-POP-RET address from the Vulnserver.exe (GMON) write-up
Updated the POC with the following values...I also added some nopes for the other 4 bytes
We cannot forget about the restricted characters (hex 80 to FF)
We
get a crash, however, we can see that our POP-POP-RET address has been changed
to 625010B4 to 62501035 where the last byte has been changed (B4 - 7F = 35)
Also note, that our 90s have been changed to 11 (90 - 7F = 11)...we will worry about this part later
We found another POP-POP-RET address
Again, we update the POC with this new POP-POP-RET address
We fire up the POC and set a breakpoint in immunity. As we check the SEH chain plugin, we can confirm that we were able to redirect the SEH handler to the address 6250120B
We allow the execution and hit our breakpoint
We
step through the POP POP RET instructions, and we hit our first entry (x90s) or
in this case, x11s (90 - 7F)
First Jump
After we are redirected to the pop-pop-ret address we are then sent to the 4 bytes right before it. We will have to use these 4 bytes to get our first jump
For
the first jmp we will use the jnz conditional jump and fill the extra bytes
with inc eax. With GMON we used EB 09 or jmp 9
bytes, however, EB is unusable since it is one of the restricted characters.
At this time, eax is currently 0x00000000 so I used the inc eax (41) to disable the ZF. Then do the jump-if-not-zero (jnz) instruction
This jumps pass our SEH handler address…also, note that if we follow it in the dump that we can see we only have 48 bytes of address space…not enough for a reverse/bind shell.
Second jump
Now we have 48 bytes
that we can use to do our second jump while keeping in mind the restricted characters
To circumvent the restricted characters, we will be 'carving' our shellcode with SUB instructions
More info about shellcode carving can be found here: http://vellosec.net/2018/08/carving-shellcode-using-restrictive-character-sets/
First, we
will need to realign our stack so that we will know where our decoded jump will
show up. In this case, we want our decoded jump opcodes just below our first jump at the following
address:
Before we carve it out, we have to realign ESP to address 00E9FFF8 which can be done with the following instructions:
(1)
push esp
pop eax ;move the value of esp to eax
add ax, 0d75 ;add 3445 to eax
add ax, 0465 ;add 1125 to eax
push eax ;push new eax value to the stack
pop esp ;move the value of eax to esp
Note that after we do this, we will need to zero out eax for shellcode carving to work
There are multiple ways to zero out eax (i.e. xor eax, eax), however, this will not work due to restricted characters
We will use the AND operator using the following values
(2)
AND 554E4D4A = 101 0101 0100 1110 0100 1101 0100 1010
AND 2A313235 = 010 1010 0011 0001 0011 0010 0011 0101
--------------------------------------------------------------------------------
=000 0000 0000 0000 0000 0000 0000 0000
(3)
For our second jump, we will be using a reverse short jump: EB 80
In order to carve out EB 80 we use the following values:
\xeb\x80\x90\x90 = 6464 7F15
0 - 909080EB = 6F6F7F15
32103355 + 32103355 + 0B4F 186B = 6F6F7F15
0 - 3210 3355 - 3210 3355 - 0B4F 186b = 909080EB
We will do SUB operations with these values then push the result to the stack
After everything is said and done, our second jump will look like this
We execute our updated POC and trace code execution in immunity debugger
Here we can see that our second jump instructions starts at address 00EFFFD1 and then the EB 80 instructions are carved at address 00EFFFFA
Once we take the jmp short 80h, we get another 72-byte address space that we can work with. This can be seen in our hex dump at address 00EFFF7C
Third Jump
After the second jump, the address space is still not big enough for reverse or bind shell...which means we will need to do another jump.
As usual, we will need to realign ESP to set where are decoded instructions will be saved. In this case, ESP currently points at address 00FAFFFD and we would like to point it to 0FAFFAE.
After we store the value of ESP to EAX we execute the following SUB instruction
SUB AL, 4F (00FAFFFD - 4F = 0FAFFAE)
We then pop this address back to ESP
After
we run the following instructions, we can see that ESP points to address
00FAFFAE…this is where our decoded jump instructions will be stored
For the third jump, we will be using the following instructions:
\x81\xec\x48\x0d\x00\x00
(SUB ESP, 0DA0)
\xff\xe4 (JMP ESP)
00FAFFAE - 0DA0 = 00FAF20E
00FAF20E is the address that is just below the beginning of our buffer....this will give us about 3400+ bytes worth of address space for our final shellcode
We will be carving 4 bytes at a time beginning at the lowest 4 bytes (since this will be pushed into the stack in LIFO manner)
As usual, we zero out EAX first then carve the instructions using SUB instructions before EAX gets pushed into the stack
Here we can see our 4 bytes getting decoded at address 00D0FFBF
...we carve out the next 4 bytes
...and follow the instructions being decoded
This completes our
third as we can we have success decoded our next jump instructions @ address
00D0FFBB:
SUB ESP, 0D48
JMP ESP
We continue code execution to get to our SUB ESP and JMP ESP
Here
we can see that after the SUB instruction, our ESP point 00D0F273
We
take the JMP ESP and we are provided with 3000+ bytes of address space for our final
shellcode
Final Shellcode
At this point, we can use MSF to create a reverse shell encoded with alpha_mixed.
Also, note that we need to add BufferRegister=ESP to get rid of some restricted characters at the beginning of the shellcode.
More info about BufferRegister flag can be found here: https://www.offensive-security.com/metasploit-unleashed/alphanumeric-shellcode/
Comments
Post a Comment