local mobileme = require "mobileme" local stdnse = require "stdnse" local tab = require "tab" description = [[ Sends a message to a iOS device through the Apple MobileMe web service. The device has to be registered with an Apple ID using the Find My Iphone application. ]] --- -- @usage -- nmap -sn -Pn --script http-icloud-sendmsg --script-args="username=,password=,http-icloud-sendmsg.listdevices" -- nmap -sn -Pn --script http-icloud-sendmsg --script-args="username=,password=,deviceindex=1,subject='subject',message='hello world.',sound=false" -- -- @output -- Pre-scan script results: -- | http-icloud-sendmsg: -- |_ Message was successfully sent to "Patrik Karlsson's iPhone" -- -- @args http-icloud-sendmsg.username the Apple ID username -- @args http-icloud-sendmsg.password the Apple ID password -- @args http-icloud-sendmsg.listdevices list the devices managed by the -- specified Apple ID. -- @args http-icloud-sendmsg.deviceindex the device index to which the message -- should be sent (@see http-icloud-sendmsg.listdevices) -- @args http-icloud-sendmsg.subject the subject of the message to send to the -- device. -- @args http-icloud-sendmsg.message the body of the message to send to the -- device. -- @args http-icloud-sendmsg.sound boolean specifying if a loud sound should be -- played while displaying the message. (default: true) author = "Patrik Karlsson" license = "Same as Nmap--See https://nmap.org/book/man-legal.html" categories = {"discovery", "safe", "external"} local arg_username = stdnse.get_script_args(SCRIPT_NAME .. ".username") local arg_password = stdnse.get_script_args(SCRIPT_NAME .. ".password") local arg_listdevices = stdnse.get_script_args(SCRIPT_NAME .. ".listdevices") local arg_deviceindex = tonumber(stdnse.get_script_args(SCRIPT_NAME .. ".deviceindex")) local arg_subject = stdnse.get_script_args(SCRIPT_NAME .. ".subject") local arg_message = stdnse.get_script_args(SCRIPT_NAME .. ".message") local arg_sound = stdnse.get_script_args(SCRIPT_NAME .. ".sound") or true prerule = function() return true end -- decode basic UTF8 encoded strings -- iOS devices are commonly named after the user eg: -- * Patrik Karlsson's Macbook Air -- * Patrik Karlsson's iPhone -- -- This function decodes the single quote as a start and should really -- be replaced with a proper UTF-8 decoder in the future local function decodeString(str) return str:gsub("\226\128\153", "'") end local function fail(err) return stdnse.format_output(false, err) end local function listDevices(mm) local status, devices = mm:getDevices() if ( not(status) ) then return fail("Failed to get devices") end local output = tab.new(2) tab.addrow(output, "id", "name") for i=1, #devices do local name = decodeString(devices[i].name or "") tab.addrow(output, i, name) end if ( 1 < #output ) then return stdnse.format_output(true, tab.dump(output)) end end action = function() if ( not(arg_username) or not(arg_password) ) then return fail("No username or password was supplied") end if ( not(arg_deviceindex) and not(arg_listdevices) ) then return fail("No device ID was specified") end if ( 1 == tonumber(arg_listdevices) or "true" == arg_listdevices ) then local mm = mobileme.Helper:new(arg_username, arg_password) return listDevices(mm) elseif ( not(arg_subject) or not(arg_message) ) then return fail("Missing subject or message") else local mm = mobileme.Helper:new(arg_username, arg_password) local status, devices = mm:getDevices() if ( not(status) ) then return fail("Failed to get devices") end if ( status and arg_deviceindex <= #devices ) then local status = mm:sendMessage( devices[arg_deviceindex].id, arg_subject, arg_message, arg_sound) if ( status ) then return ("\n Message was successfully sent to \"%s\""):format(decodeString(devices[arg_deviceindex].name or "")) else return "\n Failed to send message" end end end end