collected: shiny ADB and root – the f*c**@! (:=easy) way

posted by on 2013.06.26, under linux, collected, security

I AM SO STUPID. I was looking for a way to exploit that little thingy by using some buffer overflow or some other coding mumbo jumbo… the hard way. And there is a script that writes the whole recovery image on the shine without any checks… the f*c**@! way. Telekom, sometimes I love you for your lack of… …and it gives us an open Tolino Shine WITHOUT the need of opening the device. Gotcha!

These are the lines I’m talking about (system/bin/

elif [ -e /mnt/sdcard/extsd/recovery.img ] || [ -e /cache/upgrade/recovery.img ]; then
    echo "---> Programming partition RECOVERY ----------------------------------"
    busybox dd if=/mnt/sdcard/extsd/recovery.img of=/dev/block/mmcblk0p4 bs=8M
    busybox dd if=/cache/upgrade/recovery.img of=/dev/block/mmcblk0p4 bs=8M
    e2fsck -dy /dev/block/mmcblk0p4
    mv /mnt/sdcard/extsd/recovery.img /mnt/sdcard/extsd/recovery.img_old
    rm /cache/upgrade/recovery.img
    am start -a android.intent.action.ACTION_REQUEST_SHUTDOWN

Yes. If there is a file recovery.img on your external SD card it is written to the shine. Without any check. Be careful! If you broke something the next step is to open your device to recover the SD image. If you boot the shine in recovery mode, mmcblk0p4 becomes the root-fs…

Kernel command line: console=ttymxc0 ... init=/init root=/dev/mmcblk0p4 ...

ADB (+root) is locked by init.rc and default.prop – inside of the initrd. So we must rewrite that part of the SD card.

What to prepare:
1. rework the initrd (uramdisk.img in the so ADB is enabled
2. put the new initrd inside of the recovery.img
3. change the init.rc in the recovery.img so it writes a initrd to the SD card

How it works:
1. put the changed recovery.img on a external SD card, plug it into the shine
2. boot the shine – the recovery image is updated silently (after that the shine goes down)
3. boot while holding POWER&HOME
4. wait for END of the script – reboot
5. the shine is free.

Lets extract some data to play with… in /system/bin/ you find these lines:

busybox dd if=/cache/upgrade/uramdisk.img of=/dev/block/mmcblk0 bs=1M seek=6

The initrd is expected to take place at 0x600000 on the SD card – the loader header starts at 0x5ffff0, containing the well known magic number (FF 5F AF FF) and the size information (0x23701 = 145153 bytes, size=uboot-header+image-data=64+145089). The initrd itself is encapsulated in a u-boot-header (note the magic number 27 05 19 56 at the beginning).

Get the initrd out of the backup-image:

>dd if=backup_internal_sd_shine_after_sys_recover.img of=initrd.uboot.img bs=1 skip=6291456 count=145153
>export PATH=$PATH:/home/devel/projects/tolino_shine/own_uboot/uboot-imx/tools/
>devel@bigplay:~/projects/tolino_shine/backup_tolino_sd$ mkimage -l initrd.uboot.img 
Image Name:   ntxinitramfs
Created:      Tue Feb  5 06:38:45 2013
Image Type:   ARM Linux RAMDisk Image (uncompressed)
Data Size:    145089 Bytes = 141.69 kB = 0.14 MB
Load Address: 70308000
Entry Point:  70308000

Now we stript the u-boot header so we got the pure image file:

>dd if=initrd.uboot.img of=initrd.img bs=1 skip=64

The initrd.img is still compressed and packaged with cpio. To get the content of the ramdisk run

>mkdir initrd ; cd initrd
>zcat ../initrd.img | cpio -id
data          dev   init.freescale.rc  init.rc  sbin  system                ueventd.goldfish.rc
default.prop  init  init.goldfish.rc   proc     sys   ueventd.freescale.rc  ueventd.rc

Fire your favorite editor and change the following files:

service adbd /sbin/adbd
---      disabled
+++#     disabled

Repacking the initrd goes the other way around:

>find ./ | cpio -H newc -o > initrd.cpio.adb
>gzip initrd.cpio.adb
>mv initrd.cpio.adb.gz initrd.adb.img

_note: the new image is only 144858 bytes – 231 bytes smaller then the original.

Now add the u-boot header:

>mkimage -A arm -O linux -T ramdisk -C none -a 70308000 -e 70308000 -n "Tolino+ADB" -d initrd.adb.img initrd.adb.img.uboot
Image Name:   Tolino+ADB
Created:      Wed Jun 26 12:02:02 2013
Image Type:   ARM Linux RAMDisk Image (uncompressed)
Data Size:    144858 Bytes = 141.46 kB = 0.14 MB
Load Address: 70308000
Entry Point:  70308000

Half way done. Now lets write that new initrd to the SD card to check if ADB is enabled after boot…

#>dd if=initrd.adb.img.uboot of=/dev/SDCARD bs=512 seek=12288

_note: seek=12288*512=6291456=0x600000

After power on start ADB shell and be happy:

devel> adb devices
List of devices attached 
20030394  device
devel> adb shell
# id
uid=0(root) gid=0(root)

The images:

md5 size/mb file
c57b4edd33c92bf2f52179166fcd289a 0.14
95c435c2339820eefe1bd06d81a5ddb0 0.14 initrd.adb.img.uboot

Yes, now we have ADB as root. But replacing the initrd this way that is only possible if you open the Shine… not good. But by the power of the recovery.img we will solve that problem. First get the partition that holds the recovery image. After having some trouble using kpartx and dd from the loops/mappings I decided to go the good old way…

#>sudo fdisk /dev/sdb
Command (m for help): p
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb4         7185411     7709699      262144+  83  Linux

_note: 7709699-7185411=524288 -> *512 (block size) = 268435456 bytes

>mkdir recovery; cd recovery
#>dd if=/dev/sdb of=recovery.img bs=512 count=524288 skip=7185411

Make a copy to keep the original file. If everything is okay we could mount it…

>mkdir recoverymnt
>cp recovery.img recovery.img.initrd
#>mount -o loop recovery.img.initrd recoverymnt
>cd recoverymnt

Now copy the initrd with enabled ADB into the recovery image and add a line in the init.rc script (before the line that contains service recovery /sbin/recovery):

#>cp ../../initrd/initrd.adb.img.uboot .
#>nano init.rc
---service recovery /sbin/recovery
+++service adbroot
+++   oneshot
+++service recovery /sbin/recovery

_note: documentation of android init script syntax: readme.txt

Next step: add a little script that does the replacement job for us (and make it executable):

+++if [ -e initrd.adb.img.uboot ] ; then
+++busybox echo "replace initrd with given image... this may take some seconds."
+++busybox dd if=initrd.adb.img.uboot of=/dev/block/mmcblk0 bs=512 seek=12288
+++busybox sync
+++busybox rm initrd.adb.img.uboot
+++busybox echo "initrd replaced. Reboot device and enjoy ADB+root!"
#>chmod a+x

Finally unmount the recovery-image and run a sanity check:

>cd ..
#>umount recoverymnt
>fsck.ext4 recovery.img.initrd 
e2fsck 1.42.5 (29-Jul-2012)
recovery: clean, 420/65536 files, 109353/262144 blocks

Now place the recovery.img.initrd on a micro SD card, plug the card inside the Tolino and boot.

_note: remember to rename the recovery.img.initrd to recovery.img and do a sync before pulling the card

The copy process for the recovery.img starts and runs in the background – do not try to do something useful with the device during the (hidden) copy process – it will hang. After the copy is done the scripts causes a shutdown. This basically means: plug the card into the shine, start it and wait till it is off again.
Now start the shine in recovery mode by pressing the HOME and POWER button together… and the magic happens as soon as init.rc is executed… wait till the shine asks you to restart or reset the device and reboot. Now ADB (as root) is enabled – persistent.

Here you can download the recovery images I used. Attention: use them on your own risk. I’m not responsible if you brick your device (but I can give you advices how to open it). If something is fuXXed up: I am not responsible! (Maybe someone else with an already opened shine should try that first, and again, and again…)

md5 size/mb file
43096205380ffe22f40aa251fdfcb34a 256
12b632ccda3d5ad0bee4b04606d6bf5b 256 recovery.img.initrd

Have fun!


I opened the device and followed the first part of this blog, changing the init.rc and default.prop files in the initrd at 6MB on the internal SD card as described. After rebooting, the system works as allways but I don’t get the „ADB“ connection to work.

What I did was to download the adb tool from google, connect the device via USB, touch „Freigeben“ on the device when asked and then run „adb device“ from the command line on the host PC. But the device is not listed. The list is empty. I tried that on OS/X and Ubuntu GNU/Linux and got the same result on both systems. What am I doing wrong?

Patrick ( 21/01/2014 um 20:40 )

    Have you added the device in /etc/udev/rules.d/51-android.rules? If not -> just search the blog for it.
    Since you already opened the device I suggest to solder 3 wires to the serial connector on the left side
    of the board and use a FTDI/or somewhat serial-2-usb adapter to get a permanent serial console with root privileges.
    Beside the fact that you can get root even with the latest updates (cause you have hardware based root access) it also
    eases the pain if you had killed your ADB accidentally…

    Is your device hardware generation 2?

    hecke ( 21/01/2014 um 22:00 )

Please Leave a Reply