collected: shiny ADB and root – the f*c**@! (:=easy) way
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/upgrade_check.sh):
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
sync
sync
e2fsck -dy /dev/block/mmcblk0p4
sync
sync
mv /mnt/sdcard/extsd/recovery.img /mnt/sdcard/extsd/recovery.img_old
rm /cache/upgrade/recovery.img
sync
sync
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 update.zip) 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/upgrade.sh you find these lines:
dump_ramdisk(){
....
busybox dd if=/cache/upgrade/uramdisk.img of=/dev/block/mmcblk0 bs=1M seek=6
sync
sync
....
}
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
>ls
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:
****init.rc*****
service adbd /sbin/adbd
--- disabled
+++# disabled
---------------------------
****default.prop****
---ro.secure=1
+++ro.secure=0
---ro.debuggable=0
+++ro.debuggable=1
---persist.service.adb.enable=0
+++persist.service.adb.enable=1
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 | initrd.img.uboot.org |
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 replace_initrd.sh
+++ 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):
#>nano replace_initrd.sh
+++#!/system/bin/bash
+++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!"
+++fi
#>chmod a+x replace_initrd.sh
Finally unmount the recovery-image and run a sanity check:
>cd ..
>sync
#>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 | recovery.img.org |
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?