Introduction to Windows User Mode Exploitation pt. 4

 Introduction to Windows User Mode Exploitation pt. 4


Continuing with our ongoing tutorials and practice on the windows user mode exploitation, we dive into another buffer overflow but this time we will be working on an SEH Buffer Overflow, 


SEH (Structured Exception Handler) : Unlike how the windows kernel works, in handling errors, the userland(mode) handles errors very differently, more so on the windows platform where this isn't shared with other operating systems. While handling of SEH exceptions is not a programmers 'fault' they tend to be implemented by the OS when a thread faults.

Since mostly this is for me to prep for my OSED exam, I will not focus on fuzzing (for now) but I will work on fuzzing way later on after my certification, I will also use decomplication hints to best understand the application logic, but primarily working on dissembled code would be of great benefit.


This will also be a longer post as some hints of me searching for commands on Vulnserver hinted heavily on it having EggHunters, I also will only pop calc and not a reverse shell as previously on my previous posts. the reason is very simple, I am a netbook when i find the time to work on this challenges so I am running the server on my local machine.

GMON command


`Function3` seems to be the vulnerable function just as the previous one, they do share the same issue of lacking bounds check of the the `strcpy` function the destination seems to only handle a max of 2008 bytes but we can send more than 3950 going by the check on GMON.


We start of by crafting a python script to send 5000 A's and see if we can access `Function3` : we get a crash and hence we will start to look for an offset pattern from here.


Sure enough we get our crash note a couple of items : the overwritten `EDX` register and also the access violation happens when EDX is moving to a pointed to by EDI : 

However we still don't have control of `EIP` , however if well noted, we have a `First chance violation` : which is first reported before its handled , this tells us we can give a go `g` command to examine further any second chance violations or will be handled by the program later.

SEH : What it is 


There's two types of exceptions as we mentioned earlier, Hardware and Software, for Hardware they are initiated by the CPU , typically the one above is this type (Hardware) , software exceptions are initiated by applications when execution reaches unwanted or unexpected items/code. 

Normally  the `try/except/catch` statements leverage SEH mechanism to handle unexpected events , this is implemented by Windows.

So for the OS to be able to handle SEH on per-thread level, each thread in a program is identified by its TEB (Thread Environment Block) structure (per respective thread), every time a **`try`** block is encountered during execution of a function in  a thread, a pointer to the corresponding exception handler is saved within the `_EXCEPTION_REGISTRATION_RECORD` structure, since there can be many `try` blocks executed in a function, these structures are connected together in a linked list.


After retrieving the `ExceptionList` the operating system will begin to walk and invoke every exception handler function until one is able to deal with the unexpected event, if none of the user defined functions cannot handle, it will be handled by the default exception handler, which is ALWAYS the last node in the linked list, this is a special exception handler that terminates the current process or thread.

Dumping the TEB for information


- `dt nt!TEB` this command dumps the `nt!_TEB` structure in WinDBG

 - `dt _NT_TIB` this command dumps the` _NT_TIB` structure in WinDBG
`dt _EXCEPTION_REGISTRATION_RECORD` contains two members : `Next` (this acts as a link between `EXCEPTION_REGISTRATION_RECORD` structures in the singly-linked list of registered exception handlers) which points to a o a `_EXCEPTION_REGISTRATION_RECORD` structure, and Handler, which points to an `_EXCEPTION_DISPOSITION` structure: 
  If the exception handler invoked by the operating system is not valid for dealing with a specific exception, it will return `ExceptionContinueSearch`. This result instructs the operating system to move on to the next `_EXCEPTION_REGISTRATION_RECORD` structure in the linked list. On the other hand, if the function handler can successfully handle the exception, it will return `ExceptionContinueExecution`, which instructs the system to resume execution.


A visual representation : 



`_EXCEPTION_REGISTRATION_RECORD` structures are stored at the beginning of the stack space. Because the stack grows backwards, the overflow will need to be quite large or begin towards the beginning of the stack in order for the attacker to overwrite a structured exception handler.


Back to Exploiting


So far we know we have a crash but we need to really increase our sent buffer in size so we can be able to overwrite the SEH.

- `!teb` Dumping the TEB in WinDBG



We can however skip the manual SEH dump by using `!exchain`  command to output the SEH chain  :


We have modified our script to the following after finding the offset to the handler :


Since we now have the handler we can check for bad characters: (we don't find any except 0x00 (Null Byte))

Looking for P/P/R Instructions


PPR `Pop Pop Return` why do we need PPR, so we can redirect the execution flow to our buffer. We have to however find modules that have SafeSEH off (a protection mechanism to avoid exploitation of SEH overflows) we use `narly` for this :



We use a script to search for the PPR 


and load it on WinDBG as `$><C:\find-ppr.wds`


We choose `0x625011ef` :  to which we succesfully access 


so our payload(message)  will be :
`payload = <3546 A's (we will put our shellcode here too)> + NSEH overwrite + SEH overwrite + filler`
we need to jump `JMP` back around 400 or so bytes to simply allow ourselves a shellcode of practical size: we only have 4 bytes to write this instruction which may prove difficult since :


`E96BFEFFFF` is 5 bytes in length, we need to figure a way to do this : we will use the 2's complement: `2’s complement = (<jump distance> ^ 0xff) + 1` so in our case `(70 ^ 0xff) + 1` , we chose to short jump , then we can increase our jump size as still 400 bytes will translate to a two complements that still needs 5 bytes.
we can do this with python: 


`JMP -70` becomes` \xeb\xba`, we have filled only 2 bytes we need to fill the other two with NOPs to make it a 4-bytes instruction. Lets update our python script. (if you need further reading on this, [here](https://thestarman.pcministry.com/asm/2bytejumps.htm) is a good reference)


Looking at our debugged code we can tell that we land 2 bytes away from our target:



The reason is provided as follows : 



We either need to fill the two bytes with NOPS or we need to adjust and send 70 bytes and add 2 more bytes to adjust accordingly. I choose the latter and we test this: 


With that we have 70 bytes to island hop and add our "big_shellcode"

current state of the script is adjusted to this:



We can now use the 70 bytes to set a short jump 500 bytes from that 


Lets make a shellcode to pop a calc : and we have our final script (which manages to pop calc.exe) as:


[Here](https://github.com/ke0z/VulnServer/blob/main/VulnServer_SEH_BufferOverFlow%20No%20ASLR.py) is the python exploit code. Onto the next challenges but this time with Egg Hunters, then we shall look at the same vulnerabilities but with protections enabled.

Comments

Popular posts from this blog

Introduction to Windows User Mode Exploitation pt. 1

Introduction to Windows User Mode Exploitation pt. 6

Introduction to Windows User Mode Exploitation pt. 5