jump to navigation

Locate Your Mac Laptop If It Is Missing January 19, 2011

Posted by Robert Harder in : Utility , trackback

There are commercial services to help you locate lost laptops, but I wanted a feature that required less software to be installed and fewer Big Brothers helping me out along the way. Using a few free tools and shell scripts, I cobbled together my own LoJack-type system that notifies me whenever my laptop awakes (I can’t help you if your computer is turned off).

Tools Used:

Downloads:

Concept of Operations

Scenario: Laptop is forgotten or stolen. Third party opens laptop to snoop or legitimately try to identify owner. Third party sees password prompt (you have that turned on, right?) and wonders. If laptop is still connected to a known wireless network, or if Third Party has plugged in a network cable, laptop determines its latitude and longitude and sends notification. If you don’t have a password prompt, then suspect helpfully connects your computer to a network in order to use it, and you get notified. (You might be imagining a possible problem here; discussed below)

Step 1: SleepWatcher

First we need the ability to run a script when the laptop wakes up, and the SleepWatcher tool is a great way to run commands when certain events happen. According to the man page, the following events can be used as triggers. When the computer…

I used the example files included in the distribution and made a file at /Library/LaunchAgents/de.bernhard-baehr.sleepwatcher-20compatibility.plist

?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>de.bernhard-baehr.sleepwatcher</string>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/local/sbin/sleepwatcher</string>
		<string>-V</string>
		<string>-s /etc/sleepwatcher/rc.sleep</string>
		<string>-w /etc/sleepwatcher/rc.wakeup</string>
		<string>-D /etc/sleepwatcher/rc.displaydim</string>
		<string>-E /etc/sleepwatcher/rc.displayundim</string>
		<string>-S /etc/sleepwatcher/rc.displaysleep</string>
		<string>-W /etc/sleepwatcher/rc.displaywakeup</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>KeepAlive</key>
	<true/>
</dict>
</plist>

I used the sample rc.* files provided and added a line to rc.wakeup:

/usr/local/bin/log-location-to-notifo.sh

Step 2: Shell Script

The log-location-to-notifo.sh file looks like this (sorry about the long lines):

#!/bin/sh
# Author: Robert Harder, rob _ iharder.net
# Web: http://blog.iharder.net
# Date: November 2010
# License: Public Domain

# Example:
# <+37.19511210, -120.37831060> +/- 150.00m (speed 0.00 mps / course -1.00) @ 2010-10-22 11:10:09 -0700
PATH=/usr/local/bin:$PATH
LOCATION=$(LocateMe)   

# Parse Lat and Lon
LAT=$(echo $LOCATION | sed 's/<\([0-9+-\.]*\), \([0-9+-\.]*\)> \(+\/- [0-9a-zA-Z\.]*\) (.*/\1/' )
LON=$(echo $LOCATION | sed 's/<\([0-9+-\.]*\), \([0-9+-\.]*\)> \(+\/- [0-9a-zA-Z\.]*\) (.*/\2/' )
ERR=$(echo $LOCATION | sed 's/<\([0-9+-\.]*\), \([0-9+-\.]*\)> \(+\/- [0-9a-zA-Z\.]*\) (.*/\3/' )

# Log location right away
logger -t "$(basename $0)" "$LOCATION"

# Network Up?
function netup(){
NETUP=$(osascript - << EOF
try
	do shell script "ping -c 1 api.notifo.com"
	do shell script "echo Y"
on error
	do shell script "echo N"
end try
EOF
)
echo $NETUP
}

# Wait for network to be up
while [ "$(netup)" == "N" ]; do
	logger -t $(basename $0) Waiting for network to come up to report location $LOCATION
	sleep 1
done

# Get my external IP address
MYIP="$(curl -s http://whatismyip.org/)"

# Build a URL that will display a Google Maps page with useful info
URL="http://maps.google.com/maps?q=${LAT},${LON}($(hostname),+${MYIP},+$(echo $ERR | urlencode),+$(date | urlencode))&ie=UTF8&ll=${LAT},${LON}&t=roadmap&z=14&iwloc=A&mrt=loc"

# Log locally as well as calling notifo (another script)
# and logging its response.
logger -t "$(basename $0)" "$URL"
logger -t "$(basename $0)" $(notifo.sh -l "$(hostname)" -t "Current Location" -u "$URL" $LOCATION)

Step 3: LocateMe

The log-location-to-notifo.sh script calls LocateMe to determine your computer’s location and report it using, in this case, Notifo.

The LocateMe tool itself returns data provide by Apple’s GeoLocation API:

$ LocateMe
<+37.12357770, -120.45605097> +/- 197.00m (speed 0.00 mps / course -1.00) @ 2011-01-19 09:36:20 -0800

The relevant part of the shell script is this:

LOCATION=$(LocateMe)   

# Parse Lat and Lon
LAT=$(echo $LOCATION | sed 's/<\([0-9+-\.]*\), \([0-9+-\.]*\)> \(+\/- [0-9a-zA-Z\.]*\) (.*/\1/' )
LON=$(echo $LOCATION | sed 's/<\([0-9+-\.]*\), \([0-9+-\.]*\)> \(+\/- [0-9a-zA-Z\.]*\) (.*/\2/' )
ERR=$(echo $LOCATION | sed 's/<\([0-9+-\.]*\), \([0-9+-\.]*\)> \(+\/- [0-9a-zA-Z\.]*\) (.*/\3/' )

Step 4: Notifo

Another handy script that’s used within log-location-to-notifo.sh is notifo.sh which posts notifications to your Notifo.com account.

You’ll need to sign up and insert your own account and key in the notify.sh script:

#!/bin/sh
# Author: Robert Harder
# Date: September 2010
# License: Public Domain
# For use with notifo.com

# Provide your username and API key here
# Example
NOTIFO_USER=johndoe
NOTIFO_API_KEY=baf06f567ee7e30bc5ab5760b48ab748e7e30bcd3

# Default values
LABEL=$(hostname)
TITLE=$(whoami)
MSG=
URI=

function USAGE(){

    echo "Usage: $0 [-l label] [-t title] [-u url] [message]"
    echo "  -l label        The application sending the message"
    echo "  -t title        The title of the message"
    echo "  -u url          The URL to take the user for more information"
    echo "  message         The message to display to the user or STDIN if not supplied"
    echo "  -h/-?           This help message"
    echo "Example: $0 -l Log -t "Access Granted" A user has logged into your system."
}

# Process command line arguments
while [ "$1" ]
do
   if [ "$1" = "-l" ]; then
        LABEL="$2"
        shift 2
   elif [ "$1" = "-t" ]; then
        TITLE="$2"
        shift 2
   elif [ "$1" = "-u" ]; then
        URI="$2"
        shift 2
   elif [ "$1" = "-h" ]; then
        USAGE
        exit 0
   elif [ "$1" = "-?" ]; then
        USAGE
        exit 0
   else
        MSG="$@"
        shift $#
   fi
done

# Change command line to curl depending on whether the
# message is coming from command line arguments or from STDIN.
if [ -n "$MSG" ]; then
    MSGCOMPONENT="msg=${MSG}"
else
    MSGCOMPONENT="msg@-"
fi

#echo \
curl -s -k \
    -u ${NOTIFO_USER}:${NOTIFO_API_KEY} \
    --data-urlencode "label=${LABEL}" \
    --data-urlencode "title=${TITLE}" \
    --data-urlencode "uri=${URI}" \
    --data-urlencode "${MSGCOMPONENT}" \

https://api.notifo.com/v1/send_notification

echo

Step 5: Google Maps

Notifo lets us attach a URL to a notification, so we can create a Google Maps URL with the information we have discovered so far. The relevant portion of the log-location-to-notifo.sh script was this:

# Build a URL that will display a Google Maps page with useful info
URL="http://maps.google.com/maps?q=${LAT},${LON}($(hostname),+${MYIP},+$(echo $ERR | urlencode),+$(date | urlencode))&ie=UTF8&ll=${LAT},${LON}&t=roadmap&z=14&iwloc=A&mrt=loc"

Problems

Your wayward laptop can only notify you if it’s on a network, so if a thief does not connect to a network or wipes your computer clean before connecting, then you are out of luck. Also if your Mac cannot determine its position by its wifi signal, you also are out of luck. There’s not much you can do to get around that, but at least you are protecting yourself from some threats.

Comments»

1. SvenOnTech Reviews » Blog Archive » GadgetTrak Anti-Theft Software - January 21, 2011

[...] you can accomplish the same thing for free (free as in money, not free as in headaches) with some clever scripts, but for everyone else, GadgetTrak may be cheap [...]

2. Robert Harder » Bash Profile Sharing and Useful Scripts - March 17, 2011

[...] script as well as sundry scripts and command line apps that I want to share, such as my LocateMe app for finding my latitude and [...]

3. Dave JohnsonNo Gravatar - April 8, 2011

I built a homebrew version several years ago using IP-location, then augmented it when apple added the geolocation API in snow leopard. How you get around the “user wipes” issue, is just use filevault for your account, then have the system auto-log into an account on login.

I made the auto-log account name “apple” with “Full Name” of the account “password = apple” so that it would appear like the account was setup for use by apple technicians during service (and in fact, it is).

Unless I disable it (for instance, prior to sending into Apple for service), the system location info is emailed automatically every 20 minutes as long as the “apple” user is logged in. The thinking here is that anyone who finds a computer with Microsoft Office and Adobe Create Suite (I think the only 2 paid apps that I have other than shareware like SuperDuper!) will surely want to keep the system loaded rather than wipe it and loose those apps.

I’ve luckily not had my system stolen so haven’t had to test any of the recovery capabilities but I am pretty confident that a bogus auto-login account is a much better choice, but then, I take the performance hit of filevault (although my new 500GB Momentus XT hybrid drive has sped that up considerable), and keep all my sensitive information like tax, medical, and banking info on a small TrueCrypt volume inside that. Typically a petty compuer thief is more interested in hardware than delving into Federal crimes :)

4. Dave JohnsonNo Gravatar - April 8, 2011

ps- forgot to mention, the IP-location is super simple:

speedster@fiveangle[~]$ curl http://api.hostip.info/get_html.php?ip=`dig +short blog.iharder.net`
Country: UNITED STATES (US)
City: Scottsdale, AZ
IP: 208.109.218.230
speedster@fiveangle[~]$

5. Robert HarderNo Gravatar - April 8, 2011

@Dave I like how you set up the honey pot to get around the obvious weakness of these tools, which is that someone has to use the computer and put it on a network for any of this to work!

Does the apple user have admin privileges in your scenario? I guess you only need them to be comfortable enough that they log in to a network somewhere.

I’ve gone back and forth on File Vault. I have a thorough and secure backup strategy, but File Vault makes me nervous as far as potential fragility goes. I take it you’ve had no problems?

6. RobNo Gravatar - January 24, 2012

How would you turn on Location Services on via the command line

Have you found a way to do this?

7. CarlosNo Gravatar - March 13, 2012

Hey, i am surprised because i am trying to develop something like this. There are a couple of things you can do further. For example, it would be nice to be able to have an ssh connection and perform different actions like install keylogger and activity loggers, scp,…

But if the thief connects to internet with a router, you will have to use something like netcat to reverse open ports.

Also, the geolocation feature built in snow leopard sucks monkey’s ass unfortunately. It is way better google’s and more accurate (See, i am in Spain). Problem? you would need a browser (that supports geolocation) to get the coordinates for you. I am still working on how i could do this without being noticed.

If i ever finish it, i will post it.

Take care!