To track an eventually stolen laptop, I try to set it up to periodically send a security e-mail to myself.
This should happen as invisible and with the least intervention possible.
The following script assembles a message containing (thanks to jj!) the machine’s SN and current WAN IP number.
How could that be sent, regardless the kind of e-mail client, and without user intervention…?
set the_sn to text 2 thru -2 of (do shell script "ioreg -l | grep serial-number | awk '{print $4}'")
set {t, IPnr} to {do shell script "curl -s http://checkip.dyndns.org/ | grep 62 | awk '{print $6}'", ""}
repeat with i in characters of t
if "<" is in (i as string) then exit repeat
set IPnr to IPnr & i
end repeat
repeat
set inputText to (the_sn as Unicode text)
set exitOK to true
if (inputText's length) mod 2 ≠0 then inputText to "0" & inputText
set hexchars to "0123456789ABCDEFabcdef"
copy inputText to temp
repeat with i in inputText
if (offset of i in hexchars) = 0 then
set exitOK to false
exit repeat
end if
end repeat
if exitOK then
exit repeat
else
display dialog "Invalid data!" & return & return & "You must enter an even quantity of hex digits..." with icon stop buttons "OK" default button 1
end if
end repeat
set rr to my hextoString(inputText)
set sn to ""
repeat with i from 1 to count of characters of rr
if character i of rr is in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" then set sn to (sn & character i of rr) as string
end repeat
set cpu_name to do shell script "hostname | awk -F. '{print $1}'"
open location ("mailto:abc@def.net?subject=StatusMsg?body=" & cpu_name & "__" & sn & "__now_at__" & IPnr) as string
on hextoString(t)
set z to ""
repeat with i from 1 to t's length by 252
try
set z to z & (run script "«data cstr" & ¬
text from character i of t to character (i + 251) of t & "00» as string")
on error
set z to z & (run script "«data cstr" & ¬
text from character i of t to character -1 of t & "00» as string")
end try
end repeat
z
end hextoString
some “shortcuts” to get the machine informations (with Panther and Tiger):
set WAN_ip to word -7 of (do shell script "curl http://checkip.dyndns.org") -- Tiger
set WAN_ip to word -6 of (do shell script "curl http://checkip.dyndns.org") -- Panther (I don't know why, it's the same command)
set serial_number to word -1 of (do shell script "ioreg -l | grep IOPlatformSerialNumber")
set host_name to do shell script "uname -n" -- Bonjour name
i agree with stephan that you’d be well served by the built in mail program, but i think one problem you may run into is how to find an email server that will forward your email along the line (SMTP server). what you may need to look into is a DNS query, specifically for MX (mail exchange) records for whatever location the laptop is in and then use that information to send an email.
i’ll look into this a bit later and see if i can suggest some specifics. it’s a difficult problem.
I like the original idea a lot. The way I envision setting it up is by creating a guest login option that doesn’t require a password. A startup program for this account would then execute the above script. As the thief is likely to try various login options with only one not requiring a password I think this might work perfectly (especially when it is named ‘guest’). As I don’t know how to script unix mail as well, a bit of help would be appreciated. Or did Eelco find a way to do that already? Additionally, wouldn’t it be great to have iSight make a snapshot and attach that to the email (no clue how to do that either)
As for the abovementioned mail server problem, wouldn’t it be easiest to use an provider-independent SMTP server, like Gmail?
Yep, I am!
(not from Amsterdam anymore, so the issue is slightly less pertinent…)
However, I found the way to use Unix sendmail that does work for me.
Did not check if it also works from a new (clean) account, though.
set WAN_ip to word -7 of (do shell script "curl http://checkip.dyndns.org") -- Tiger
set sn to word -1 of (do shell script "ioreg -l | grep IOPlatformSerialNumber")
set host_name to do shell script "uname -n | awk -F. '{print $1}'" -- Bonjour name
send_mail_sbr("Status of " & host_name, ("At " & (current date) & return & host_name & " (" & sn & ") was at " & WAN_ip), "yourname@yourISP.com")
do shell script "sleep 2"
tell application "System Events" to keystroke return -- to eventually "OK" Little Snitch outgoing
on send_mail_sbr(subj, body, addr)
do shell script ("echo \"" & body & "\" | mail -s \"" & subj & "\" " & addr)
end send_mail_sbr
I already found iSightCaptur too and came up with the following script which seems to work fine here.
If only I could keep Mail.app hidden throughout the process…
-- This script sends an email to a specified address either through Unix mail or through Mail.app (or you can use both too)
-- When using Mail.app, an iSight image capture will be added as attachment
-- This script requires iSightCapture which can be downloaded from http://www.intergalactic.de/hacks.html
-- For this to work, the script requires that the shell script 'iSightCapture' to be located in the same folder as the script
-- This script must be saved as an application to work properly
set WAN_ip to word -7 of (do shell script "curl http://checkip.dyndns.org") -- Tiger
set Serial_Number to word -1 of (do shell script "ioreg -l | grep IOPlatformSerialNumber")
set host_name to do shell script "uname -n | awk -F. '{print $1}'" -- Bonjour name
set theName to "John Doe" -- change to whatever name
set theAddress to "john.doe@provider.com" -- change to preferred email address
set theSubject to "Status of " & host_name -- change as preferred
set theBody to "At " & (current date) & return & host_name & " (" & Serial_Number & ") was at IP address " & WAN_ip
set theSender to "jane.doe@provider.com" -- change to preferred email address
tell application "Finder"
set thePath to container of (path to me) as string
set theAttachment to thePath & "isightimage.jpg"
set shPath to POSIX path of thePath
end tell
--send email through Unix mail; doesn't attach iSight capture
do shell script ("echo \"" & theBody & "\" | mail -s \"" & theSubject & "\" " & theAddress)
do shell script "sleep 2"
tell application "System Events" to keystroke return -- to "OK" Little Snitch outgoing in case it is installed
--send email through Mail.app; includes iSight photo as attachment
do shell script "cd " & shPath & "; ./isightcapture isightimage.jpg" -- Take iSight photo
tell application "Mail"
set newMessage to make new outgoing message with properties {subject:theSubject, content:theBody & return & return}
tell newMessage
set visible to false
set sender to theSender
make new to recipient at end of to recipients with properties {name:theName, address:theAddress}
tell content to make new attachment with properties {file name:theAttachment as alias} at after the last paragraph
end tell
send newMessage
end tell
while i do think you could mail an attachment, it seems complicated. however, nothing is stopping you from sending an email and then following up with a “put” FTP command to a write only drop box for the screenshot. a good solution might include attempts to use multiple services in case of firewall blockage. perhaps a file could be sent to a .mac account…
→ the iSight picture was sent. However, the attachment received is only 0.1 kB and cannot be decoded with uudecode in Terminal.
do shell script ("uuencode " & quoted form of fpath & " jpg.sit | mail -s \"" & subj & "\" " & addr)
→ attachment can not be decoded by either Stuffit (format unrecognized) or uudecode (“Does not start with “Begin””)
However:
do shell script ("uuencode " & quoted form of fpath & " x.jpg | mail -s \"" & subj & "\" " & addr)
→ Mail attachment now indeed is the iSight snapshot, 43kB x.jpg readable in Preview, it apparently never got uunencoded or Stuffed anyway. The picture is quite dark though (making myself an even better suspect than intended
This is on a plain OSX 10.4.8 machine with no Unix frills - apart from Apple’s.
Here is my latest script. Though it’s not needed at all, I left in the Mail.app routine, just in case someone likes to use it.
The script sends an email through Unix containing both a logentry and a uuencoded snapshit from iSight. For most email programs uuencoded files is not a problem, they often automatically decode them so it seems as if the image is an attachment. There are probably some smarter routines to use, but for me this works as I want it too.
The main features:
checks whether an internet connection is available, if not, just logs the time and location
if connected, takes a pic from iSight, logs the location and time and sends this by emaill to specified address (using either Unix mail or Mail.app). Time and location are also logged on the computer
once sent, the culprit/finder gets to see himself in preview, a warning is read out and appears on screen.
if (s)he clicks OK on last dialogue box, an email to the owner is generated for a save return
(Edit: cleaned it up quite a bit)
-- This script sends an email to a specified address either through Unix mail or through Mail.app (or you can use both too)
-- This script requires iSightCapture which can be downloaded from http://www.intergalactic.de/hacks.html
-- For this to work, the script requires that the shell script 'iSightCapture' to be located in the same folder as the script
-- This script must be saved as an application to work properly
-- You can use this script to track the theft of your laptop
-- I suggest to create a login account "guest" without password protection and use the script as a startup program for that login account
-- For the Mail.app script it is necessary that a working mail aount has been set up for the user
-- Change these variable to fit your needs
property UseMailApp : false -- if True, both Apple Mail and Unix mail will be used. If False, only Unix mail will be used
property ShowPicPreview : false -- if True, a preview of the image will be shown to the 'finder' of the computer
property ShowWarning : false -- If True an audio warning will be displayed and a warning message appears on screen
property PrepareMail : false -- if True, an email message to you from the lost computer willl be prepared.
property WAN_ip : word -7 of (do shell script "curl http://checkip.dyndns.org") -- Tiger
property Serial_Number : word -1 of (do shell script "ioreg -l | grep IOPlatformSerialNumber")
property host_name : do shell script "uname -n | awk -F. '{print $1}'" -- Bonjour name
property theName : "John Doe" -- change to whatever name
property theAddress : "john.doe@provider.com" -- change to preferred email address
property theSubject : "Status of " & host_name -- Header for mail message; change as preferred
property theMessage : "At " & (current date) & return & host_name & " (" & Serial_Number & ") was located at IP address " & WAN_ip -- Body for mail message
property theSender : "john.doe@provider.com" -- change to preferred email address
property AlertMessage : "A picture of you was made and the location of this Macintosh has been recorded. These were sent to a central location. Please return this Macintosh to its owner. A finder's fee will be given to you in return. If not, the police will be alerted" as string --Any text here
property Found_Header : "Found your computer" -- header text for email from finder
property Found_Body : "I have found your computer and would like to make sure you get it back safely. Please contact me at (insert contact infomation)."
property TheReturnKey : ASCII character 13
global thePath
global PosixPath
--log all events in eventlog.txt
tell application "Finder"
set thePath to container of (path to me) as string
set PosixPath to POSIX path of thePath
set MessageEntry to theMessage & TheReturnKey
do shell script "echo " & quoted form of MessageEntry & " >> " & quoted form of PosixPath & "eventlog.txt"
end tell
-- Test connection status; if not connected script won't run
set testIP to chkUP("http://www.apple.com") or chkUP("http://www.google.com")
if testIP then
SendAlert()
end if
to chkUP(theURL)
return (count (get ((theURL as URL)'s host & {dotted decimal form:""})'s dotted decimal form)) > 0
end chkUP
-- The actual alert script
on SendAlert()
tell application "Finder"
set thePath to container of (path to me) as string
set theAttachment to thePath & "isightimage.jpg"
set old_Image to thePath & "isightimage.jpg"
if exists file old_Image then
do shell script "rm " & PosixPath & "isightimage.jpg"
end if
set old_Event to thePath & "concat.txt"
if exists file old_Event then
do shell script "rm " & PosixPath & "concat.txt"
do shell script "touch " & PosixPath & "concat.txt"
end if
end tell
do shell script "cd " & PosixPath & "; ./isightcapture isightimage.jpg" -- Take iSight photo
set LogEntry to theMessage & TheReturnKey & TheReturnKey
--send email through Unix mail
do shell script "uuencode -o " & PosixPath & "camcapture.jpg " & PosixPath & "isightimage.jpg camcapture.jpg" --encodes the image for Unix mail
do shell script ("echo " & quoted form of LogEntry & " >> " & quoted form of PosixPath & "concat.txt")
do shell script ("cat " & quoted form of PosixPath & "camcapture.jpg >> " & quoted form of PosixPath & "concat.txt")
do shell script ("cat " & quoted form of PosixPath & "concat.txt" & " | mail -s \"" & theSubject & "\" " & theAddress)
do shell script "sleep 2"
tell application "System Events" to keystroke return -- to "OK" Little Snitch outgoing in case it is installed
if UseMailApp is true then MailApp()
if ShowPicPreview is true then ShowPreview()
if ShowWarning is true then ShowAlert()
if PrepareMail is true then MailHome()
end SendAlert
-- send email through Mail.app; includes iSight photo as attachment
on MailApp()
tell application "Mail"
set newMessage to make new outgoing message with properties {subject:theSubject, content:theMessage & return & return}
tell newMessage
set visible to false
set sender to theSender
make new to recipient at end of to recipients with properties {name:theName, address:theAddress}
tell content to make new attachment with properties {file name:theAttachment as alias} at after the last paragraph
end tell
send newMessage
end tell
end MailApp
--Shows the captured image in Preview on screen
on ShowPreview()
tell application "Preview"
activate
open theAttachment as alias
end tell
end ShowPreview
--alert the finder/culprit that information and a picture was sent to a central location"
on ShowAlert()
say AlertMessage
display dialog AlertMessage
end ShowAlert
-- Predefines an email to be sent to the owner by the finder
on MailHome()
tell application "Mail"
set newMessage to make new outgoing message with properties {subject:Found_Header, content:Found_Body & return & return}
tell newMessage
set visible to true
make new to recipient at end of to recipients with properties {name:theName, address:theAddress}
end tell
activate
end tell
end MailHome
I am currently in the middle of doing this myself and the easiest way I found to send an email is php. If you work for a company they likely have a web server running php so you can easily have a txt file containing the serials of all the stolen laptops and have curl read it like so:
do shell script "curl http://www.website.com/stolen.txt
read out each paragraph and if the serial variable is in there then have it collect system information & post it to a php page on the same web server ie:
do shell script "curl [url=http://www.website.com/theftmail.php?ip=]http://www.website.com/theftmail.php?ip="[/url] & _ip
adding in as many variables as you want.
<?php
//gets the variables passed from the URL
$mac = $_GET ['MAC'];
$ip = $_GET['ip'];
$anc = $_GET['anc'];
$serial = $_GET['serial'];
$hostname = $_GET['hostname'];
$vip = $_SERVER['REMOTE_ADDR'];
// mail function
$to = "me@website.com";
$subject = "Stolen Laptop Recovery System";
$message = "The following information has been emailed to you because the laptop with serial number " . $serial . " has been found in the database of stolen Laptops \n
The machines ethernet mac address is: " . $mac . "\n
The machines current external IP address according to dydns.com is: " . $ip . "\n
The machines active network connection is: " . $anc . "\n
The machines serial number is: " . $serial . "\n
The machines hostname is: " .$hostname . "\n
The machines current external IP address according to visitor IP lookup is: " . $vip ;
$from = "me@website.com";
mail($to,$subject,$message);
// prints it on the webpage if visited
echo "The following information has been emailed to you because the laptop with serial number " . $serial . " has been found in the database of stolen Laptops \n
The machines ethernet mac address is: " . $mac . "\n
The machines current external IP address according to dydns.com is: " . $ip . "\n
The machines active network connection is: " . $anc . "\n
The machines serial number is: " . $serial . "\n
The machines hostname is: " .$hostname . "\n
The machines current external IP address according to visitor IP lookup is: " . $vip ;
?>
this is 100% silent and doesn’t require you to setup any mail functions and it also has the added benifit of being able to use the $vip = $_SERVER[‘REMOTE_ADDR’]; which gives you their external ip address without having to query dydns.org and read it out form the html.
Hope this helps someone and if anyone wants a copy of my finished thing feel free to contact me