www.thanassis.space, 2022-10-15 | Main page
Saved from web.archive.org, with Lynx.
   #Coding and administration articles by ttsiodras


   Wayback Machine
   https://www.thanassi Go
   34 captures
   07 Nov 2016 - 15 Oct 2022
   Aug              OCT  Nov
   Previous capture 15   Next capture
   2021             2022 2023
   About this capture
   Organization: Archive Team
   [Archiveteam.jpg] Formed in 2009, the Archive Team (not to be confused
   with the archive.org Archive-It Team) is a rogue archivist collective
   dedicated to saving copies of rapidly dying or deleted websites for the
   sake of history and digital heritage. The group is 100% composed of
   volunteers and interested parties, and has expanded into a large amount
   of related projects for saving online and digital history.

   History is littered with hundreds of conflicts over the future of a
   community, group, location or business that were "resolved" when one of
   the parties stepped ahead and destroyed what was there. With the
   original point of contention destroyed, the debates would fall to the
   wayside. Archive Team believes that by duplicated condemned data, the
   conversation and debate can continue, as well as the richness and
   insight gained by keeping the materials. Our projects have ranged in
   size from a single volunteer downloading the data to a
   small-but-critical site, to over 100 volunteers stepping forward to
   acquire terabytes of user-created data to save for future generations.

   The main site for Archive Team is at archiveteam.org and contains up to
   the date information on various projects, manifestos, plans and

   This collection contains the output of many Archive Team projects, both
   ongoing and completed. Thanks to the generous providing of disk space
   by the Internet Archive, multi-terabyte datasets can be made available,
   as well as in use by the Wayback Machine, providing a path back to lost
   websites and work.

   Our collection has grown to the point of having sub-collections for the
   type of data we acquire. If you are seeking to browse the contents of
   these collections, the Wayback Machine is the best first stop.
   Otherwise, you are free to dig into the stacks to see what you may

   The Archive Team Panic Downloads are full pulldowns of currently extant
   websites, meant to serve as emergency backups for needed sites that are
   in danger of closing, or which will be missed dearly if suddenly lost
   due to hard drive crashes or server failures.

   Collection: Archive Team: URLs

   The Wayback Machine -

   Freeing my tablet (Android hacking, SW and HW)
   submit to programming reddit

   (October 2016)

Freeing my tablet (Android hacking, SW and HW)

   Born free, and life is worth living; but only worth living, cause
   you're born free
   For the TL;DR crowd: I wanted to run a Debian chroot in my tablet; and
   there was no open-source rooting process for it. That triggered me
   enough to have a deeper look at Android, and eventually completely
   dominate my tablet.

              Caveat - a long read... involving both HW and SW;
                ...but you'll probably learn a thing or two.

The backstory...

   Two years ago, I left my country. There's a sad story there, but let's
   just say that I chose to spend some time in Malta, working remotely for
   a nice Irish startup - while living in an apartment 30 meters by the
   sea :-)

   After finishing my work everyday at 16:00, 15 minutes later I would go
   for a swim.

   I miss the glorious Mediterranean sun...

   I would then enjoy long afternoon walks by the beach, listening to
   music and catching up on my favorite online forums (Reddit/programming,
   Hacker News, Slashdot, etc) - using my tablet.

   Until my tablet died. Suddenly.

   A cruel and unusual death that involved noise, a bad smell
   (electrolytic capacitor bidding farewell?) and then... total silence.

   I could have had a look into it - but I knew it was high time I got a
   new one anyway.

   I started looking at the various offerings, and being a nerd of a
   frugal nature, decided to only look at the best HW bang for the buck,
   completely ignoring the SW aspects.

   "Software? Bah, I'll sort that out later" - Famous Last Words (TM)

The main actor...

   I ended up with this:
   My tablet

   Asus MemoPad 10" ME103K

   In August of 2015, 175 Euros got me a tablet with a 10 inch screen, 1GB
   of RAM, a quad-core Qualcomm Snapdragon, and 16GB of storage - with
   more space available if one needed it via an SD card slot.

   In my preliminary use, the tablet was quite fast in web browsing (with
   ad blocking of course - otherwise the ads bring down even desktop
   browsers to their knees). That's what I mostly expect from my tablet -
   adequate browsing, and reading PDFs while listening to music.

   Oh, and running Debian in a chroot of course. Many benefits there; I am
   a Linux/Unix/BSD/embedded guy, living my life in the command line - and
   I need to be able to do everything that I do with my main computers, on
   my tablet as well (like running Privoxy, dictd, my local Flask servers
   that are accessible only from the tablet, tunneling via local SSH's
   SOCKS tunnels to tether beyond the idiocy of providers... you get the

   And I trust Debian. Far more than I trust the Android ecosystem.

   That was when it hit me; I searched, and searched, and searched...

   ...there was no open [2] rooting process for this tablet.

   No TWRP, no CyanogenMod, nothing.




   I spent my free time over the next weeks studying Android. Not from an
   application developer standpoint, mind you; only from the low-level
   aspects that an embedded software engineer cares about.

Understanding the Android boot process

   An Android device boots from a soldered-in flash chip, that acts as a
   "hard disk". The kernel sees it usually as device /dev/mmcblk0, and it
   is split in various partitions.

   In my tablet, after starting an adb shell, I can see this...
shell@K01E_2:/ $ ls -l /dev/block/platform/msm_sdcc.1/by-name

lrwxrwxrwx. 1 root root 20 Oct  8 23:11 ADF -> /dev/block/mmcblk0p9
lrwxrwxrwx. 1 root root 20 Oct  8 23:11 APD -> /dev/block/mmcblk0p8
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 DDR -> /dev/block/mmcblk0p28
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 aboot -> /dev/block/mmcblk0p14
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 abootb -> /dev/block/mmcblk0p20
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 abootu -> /dev/block/mmcblk0p23
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 boot -> /dev/block/mmcblk0p16
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 cache -> /dev/block/mmcblk0p25
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 fsg -> /dev/block/mmcblk0p10
lrwxrwxrwx. 1 root root 20 Oct  8 23:11 m9kefs1 -> /dev/block/mmcblk0p5
lrwxrwxrwx. 1 root root 20 Oct  8 23:11 m9kefs2 -> /dev/block/mmcblk0p6
lrwxrwxrwx. 1 root root 20 Oct  8 23:11 m9kefs3 -> /dev/block/mmcblk0p7
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 m9kefsc -> /dev/block/mmcblk0p30
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 metadata -> /dev/block/mmcblk0p31
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 misc -> /dev/block/mmcblk0p26
lrwxrwxrwx. 1 root root 20 Oct  8 23:11 modemst1 -> /dev/block/mmcblk0p2
lrwxrwxrwx. 1 root root 20 Oct  8 23:11 modemst2 -> /dev/block/mmcblk0p3
lrwxrwxrwx. 1 root root 20 Oct  8 23:11 persist -> /dev/block/mmcblk0p4
lrwxrwxrwx. 1 root root 20 Oct  8 23:11 radio -> /dev/block/mmcblk0p1
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 recovery -> /dev/block/mmcblk0p27
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 rpm -> /dev/block/mmcblk0p15
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 rpmb -> /dev/block/mmcblk0p21
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 sbl1 -> /dev/block/mmcblk0p11
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 sbl2 -> /dev/block/mmcblk0p12
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 sbl2b -> /dev/block/mmcblk0p18
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 sbl3 -> /dev/block/mmcblk0p13
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 sbl3b -> /dev/block/mmcblk0p19
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 ssd -> /dev/block/mmcblk0p29
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 system -> /dev/block/mmcblk0p24
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 tz -> /dev/block/mmcblk0p17
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 tzb -> /dev/block/mmcblk0p22
lrwxrwxrwx. 1 root root 21 Oct  8 23:11 userdata -> /dev/block/mmcblk0p32

              Golly gee, Mr Google, that's a lot of partitions

   My ME103K starts it's booting process by verifying the aboot partition
   is not tampered with. There's some sort of signature verification going
   on there, so even if you obtained root access and dd-ed over a tweaked
   version of the aboot partition data, you'd end up with a 175 Euro brick
   (unless you can desolder the flash chip, extract it from the PCB,
   re-program it, and solder it again. Not my cup of tea - huge respect to
   those that can, though).

   aboot is what is officially called the bootloader. Once it is verified
   and starts running, it will perform the same song and dance for the
   boot partition; checking that it is nice and proper, loading its
   contents and executing them.

fastboot oem unlock

   In principle, this is where Android vendors are supposed to allow you
   to hijack the process, and boot your own boot image, using...
host$ adb reboot bootloader

host$ # tablet reboots into aboot, and pauses just BEFORE
host$ # loading the boot partition data

   Bootloader snapshot
host$ # Actually, please load my own bootable image
host$ fastboot boot myDamnImage.img

   But to be able to do that, the bootloader must be unlocked; that is, it
   must allow you to load your own boot images.

   Some - but not all - devices, allow you to do this:
host$ fastboot oem unlock

   Mine did (thank god).

   I do believe though that when you do this, the tablet is supposed to be
   wiped automatically... since by allowing booting of a custom image, an
   external entity can pretty much gather every data residing inside the
   tablet - and completely violate your privacy.

   My MemoPad didn't.


Creating my own boot image

   It was time to create my own boot image. I wish I could dd the boot
   partition over from the flash chip and start from there - but I was not
   root, and therefore not allowed to dd from partitions.

   Looking for a fallback, I checked the last Over-The-Air update sent by
   Asus to these tablets. I was quickly able to extract the boot image and
   the accompanying file system from inside it (initrd, in Linux terms):
host$ ls -l
total 803592
drwxr-xr-x 2 ttsiod ttsiod      4096 Oct 21 01:22 ./
drwxr-xr-x 6 ttsiod ttsiod      4096 Sep 25 23:34 ../
-rw-rw-r-- 1 ttsiod ttsiod 822861864 Aug  7  2015 UL-K01E-WW-

host$ unzip -l UL-K01E-WW- | grep boot.img
  7368704  2011-03-22 11:21   boot.img

host$ unzip UL-K01E-WW- boot.img
Archive:  UL-K01E-WW-
signed by SignApk
  inflating: boot.img

host$ mkdir contents
host$ cd contents
host$ abootimg -x ../boot.img

writing boot image config in bootimg.cfg
extracting kernel in zImage
extracting ramdisk in initrd.img

host$ mkdir rootfs
host$ cd  rootfs
host$ zcat ../initrd.img | cpio -ivd
4040 blocks

host$ ls -l

lrwxrwxrwx 1 ttsiod ttsiod     13 Oct 23 08:30 charger -> /sbin/healthd
drwxrwx--x 2 ttsiod ttsiod   4096 Oct 23 08:30 data
-rw-r--r-- 1 ttsiod ttsiod    350 Oct 23 08:30 default.prop
drwxr-xr-x 2 ttsiod ttsiod   4096 Oct 23 08:30 dev
-rw-r--r-- 1 ttsiod ttsiod  37014 Oct 23 08:30 file_contexts
-rw-r----- 1 ttsiod ttsiod   1242 Oct 23 08:30 fstab.qcom
-rwxr-x--- 1 ttsiod ttsiod 235904 Oct 23 08:30 init
-rwxr-x--- 1 ttsiod ttsiod   2614 Oct 23 08:30 init.class_main.sh
-rwxr-x--- 1 ttsiod ttsiod   1284 Oct 23 08:30 init.environ.rc
-rwxr-x--- 1 ttsiod ttsiod   6758 Oct 23 08:30 init.qcom.class_core.sh
-rwxr-x--- 1 ttsiod ttsiod     88 Oct 23 08:30 init.qcom.diag.rc
-rwxr-x--- 1 ttsiod ttsiod   5604 Oct 23 08:30 init.qcom.early_boot.sh
-rwxr-x--- 1 ttsiod ttsiod  24602 Oct 23 08:30 init.qcom.rc
-rwxr-x--- 1 ttsiod ttsiod   3563 Oct 23 08:30 init.qcom.sh
-rwxr-x--- 1 ttsiod ttsiod   2838 Oct 23 08:30 init.qcom.syspart_fixup.sh
-rwxr-x--- 1 ttsiod ttsiod  38327 Oct 23 08:30 init.qcom.usb.rc
-rwxr-x--- 1 ttsiod ttsiod  22527 Oct 23 08:30 init.rc
-rwxr-x--- 1 ttsiod ttsiod   8346 Oct 23 08:30 init.target.rc
-rwxr-x--- 1 ttsiod ttsiod   1927 Oct 23 08:30 init.trace.rc
-rwxr-x--- 1 ttsiod ttsiod   3902 Oct 23 08:30 init.usb.rc
-rwxr-x--- 1 ttsiod ttsiod    301 Oct 23 08:30 init.zygote32.rc
drwxr-xr-x 2 ttsiod ttsiod   4096 Oct 23 08:30 proc
-rw-r--r-- 1 ttsiod ttsiod   3138 Oct 23 08:30 property_contexts
drwxr-xr-x 3 ttsiod ttsiod   4096 Oct 23 08:30 res
drwxr-x--- 2 ttsiod ttsiod   4096 Oct 23 08:30 sbin
-rw-r--r-- 1 ttsiod ttsiod    746 Oct 23 08:30 seapp_contexts
-rw-r--r-- 1 ttsiod ttsiod     76 Oct 23 08:30 selinux_version
-rw-r--r-- 1 ttsiod ttsiod 177701 Oct 23 08:30 sepolicy
-rw-r--r-- 1 ttsiod ttsiod  10468 Oct 23 08:30 service_contexts
drwxr-xr-x 2 ttsiod ttsiod   4096 Oct 23 08:30 sys
drwxr-xr-x 2 ttsiod ttsiod   4096 Oct 23 08:30 system
-rw-r--r-- 1 ttsiod ttsiod   8349 Oct 23 08:30 ueventd.qcom.rc
-rw-r--r-- 1 ttsiod ttsiod   4617 Oct 23 08:30 ueventd.rc

   Hello - lots of stuff here.

   The Linux kernel starts /init, which in the case of Android reads what
   actions to perform from init.rc - which includes other init.* to setup
   the various SW and HW subsystems.

   init.rc includes actions like spawning adbd - allowing us to connect to
   the tablet over adb:
host$ less init.rc
# adbd is controlled via property triggers in init.<platform>.usb.rc
service adbd /sbin/adbd --root_seclabel=u:r:su:s0
    class core
    socket adbd stream 660 system system
    seclabel u:r:adbd:s0

   And what we usually have in /etc/fstab in other Unixes, resides inside
   fstab.deviceName in Android (in my case, fstab.qcom):
host$ cat fstab.qcom
/dev/block/platform/msm_sdcc.1/by-name/system   /system           ext4 ...
/dev/block/platform/msm_sdcc.1/by-name/userdata /data             ext4 ...
/devices/platform/msm_sdcc.3/mmc_host           /storage/MicroSD  vfat ...
/devices/platform/msm_hsusb_host                /storage/USBdisk1 vfat ...
/devices/platform/msm_ehci_host.0               /storage/USBdisk2 vfat ...

   This part looks interesting as well; in principle, I can edit this file
   and have e.g. the /system partition point to my external SD card, which
   I CAN control (i.e. plug it in my laptop, write anything I want in it,
   then plug it in the tablet and reboot).

   But I can't read the current /system partition to do this - since I am
   not root, I can't take a snap, and store it in an external SD card.

   Not yet :-)

   Anyway - since the filesystem in the boot image is being modified,
   might as well cross-compile busybox and add it in. I copied it under
   /sbin and created all the symlinks:
host$ cd sbin
host$ ls -l
lrwxrwxrwx 1 root root       9 Sep 28  2015 addgroup -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 add-shell -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 adduser -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 adjtimex -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 ar -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 arp -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 arping -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 ash -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 awk -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 telnet -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 telnetd -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 xz -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 xzcat -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 yes -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 zcat -> ./busybox
lrwxrwxrwx 1 root root       9 Sep 28  2015 zcip -> ./busybox

   Busybox is very useful - allowing running tons of stuff from inside the
   tablet, even without chrooting.

   This modified filesystem needs to be placed back in a boot image:
host$ cd rootfs/
host$ find . | cpio --create --format='newc' |  \
    gzip > ../initrd_busybox.cpio.gz
host$ cd ..
host$ abootimg --create ../new_boot.img -f bootimg.cfg  \
    -k zImage -r initrd_busybox.cpio.gz

   Now, since busybox was added in, this image is bigger than the original
   one - so abootimg will fail here, with...
updated is too big for the Boot Image (8441856 vs 7393280 bytes)

   Editing bootimg.cfg and updating the expected length in field bootsize
   is simple enough - but since I will be doing lots of experiments with
   many attempted boot images, I had to automate this a bit:
host$ cat bootimg.cfg | grep bootsize
bootsize = 0xDEAD

host$ cat autoboot.sh
cd rootfs/
find . | cpio --create --format='newc' | \
    gzip > ../initrd_busybox.cpio.gz
cd ..
abootimg --create ../new_boot.img -f bootimgBig.cfg \
    -k zImage -r initrd_busybox.cpio.gz >log 2>&1
if grep 'updated is too big' log ; then
    SIZE=$(grep 'updated is too big' log | awk '{print substr($10,2,7);}')
    HEX=$(echo -e "obase=16\n$SIZE\n" | bc -l)
    cat bootimg.cfg | sed "s/DEAD/$HEX/" > bootimgBig.cfg
    rm -f log
    abootimg --create ../new_boot.img -f bootimgBig.cfg \
         -k zImage -r initrd_busybox.cpio.gz | tee log
    if grep 'updated is too big' log ; then
        echo Failure...
        exit 1
echo Rebooting...
fastboot boot ../new_boot.img
exit 0

   And there it was, the 1st step - the tablet was now "equipped" with
   software that I provided myself:
host$ ./autoboot.sh
host$ adb shell

shell@K01E_2:/ $ telnet
Usage: telnet [-a] [-l USER] HOST [PORT]

Connect to telnet server

        -a      Automatic login with $USER variable
        -l USER Automatic login as USER

   Almost there! Right?

Nope, not quite

   At that point, I noticed something.

   I was able to boot my custom images just fine - issuing adb reboot
   bootloader afterwards, and once my tablet reached fastboot stage,
   preparing and booting my next image... Always trying to become root.

   But I noticed that when I tried rebooting the tablet ON ITS OWN, it
   ended up in the bootloader menu.

   I believe the Android community calls this "stuck in fastboot".

   Oh-oh - the tablet was no longer bootable on its own! It needed to be
   tethered to a PC, where a fastboot boot whatever.img would solve the

   Not that I take my tablet on long trips or anything, but I found it
   rather annoying. Why did this happen? I didn't do anything wrong, did

   I needed a way to see what the tablet was saying during it's boot
   process. But... there's no way to do that in the Android world. No
   standard way, that is - every OEM has some method of its own.

   Why Google didn't mandate logging the boot messages via some form of
   the fastboot protocol (e.g. fastboot logcat), I will never know.

   What I do know, is that after Googling some more, I found out that
   Nexus devices have a serial port in their headphone jack.

   And Asus manufactured some Nexus devices. Just as it manufactures
   ME103Ks (which are NOT Nexus, mind you).

   Say, maybe they re-used the same hardware in my tablet...

Diving into hardware

   In Nexuses, if you feed 3.3V in the microphone input of your
   headphone's TRRS plug, the left and right channels switch to carrying
   the serial port's TX and RX channels.
   Sending 3.3V to the MIC input

   I used my Raspberry PI TRRS-to-TV cable to get access to the 4 places I
   needed: GND, MIC, L and R. The cable was not supposed to be doing
   anything else except exposing the 3 signals (MIC,L,R - each one paired
   with GND) in the three corresponding cables (red, white, yellow).

   I then used my recently acquired BitScope to probe between the TX (tip
   of white cable in picture) and the common GND (brown probe at the
   bottom of picture). I also used two probes (red and blue one) to "feed"
   3.3V from my USB/TTL chip (a PL2303HX plugged in my laptop) to the MIC
   (red) tip.

   Upon rebooting the tablet, I indeed saw what was unmistakably a serial
   signal at 115200 (peak-to-peak of 8 to 9us), but with lots of

                  There you are! Come out, little serial...

   BitScope also told me that the signal was at 1.8V - so my PL2303HX (a
   3.3V USB/TTL) could not possibly decode it. I needed a shifter.

   The signal also looked indecipherable, to my "amateur at electronics"
   eyes; the edges were surely too slow for any UART to pick up. I asked
   the Electronics Stack Exchange guys what they thought, and they
   recommended probing on the jack itself - so I stripped the tablet down
   to its PCB, and probed all over... Nope, same capacitance-riddled
   signal, and I couldn't find it anywhere else on the PCB.

   But if after booting, I used stty to lower the speed to 9600 baud, then
   all was crystal clear - nice square pulses:
shell@K01E_2:/ $ stty -F /dev/ttyHSL0 9600
shell@K01E_2:/ $ while true ; do echo UUUUUUU > /dev/ttyHSL0 ; sleep 0.1 ; done

   Much better at low frequencies

   I considered giving up, but Chris Stratton, in one of the few Stack
   Exchange comments I got, claimed that "...a good shifter can cope even
   with this kind of capacitance-riddled signal".

   Might as well try!

   As good an opportunity as ever to start rebuilding my electronics "war
   chest"... In the meantime, I had left Malta and gotten a job at the
   European Space Agency in the Netherlands, so I made my first on-line
   order from Dutch electronics' shops.

   3 days later, I got a bunch of cables, a breadboard, a soldering iron
   and a level shifter: a BSS138.

   After a bit of lousy soldering and jungle-cable-breadboarding, with my
   heart beating unusually fast, I tried spawning minicom...
   Adding a shifter

   ...and to my utter amazement, I saw this:
   Data at last

   Unbelievable - after BSS138 "lifted" the signal from 1.8 up to 3.3V,
   that miserable, capacitance-riddled signal was actually decoded! I
   could finally see why my tablet was stuck at fastboot.

   Update, 2 weeks later: I ordered a TRRS breakout (to connect a
   male-to-male headphone cable from the tablet to the breadboard) and
   cleaned up the tiny design - it is, after all, a useful circuit to
   keep. Besides connecting the TIP and RING1 to the shifter, I also used
   a voltage divider to create 1.8V out of the PL2303HX's 3.3V output -
   and fed it in the LV input of the BSS138.
   Cleaned-up breadboard

Back to software hacking

   This is the complete transcript of what came through the serial port
   (if you are using a slow device, you may want to use your
   desktop/laptop to watch this):

   Now after watching this ASCII cast (thanks, asciinema!), I am sure you
   are wondering where the heck I found those "magic" oem-specific
   commands (in this case, ME103K-specific):
host$ sudo fastboot fastboot oem device-info
(bootloader) Device tampered: true
host$ sudo fastboot oem reset-dev_info
host$ sudo fastboot fastboot oem device-info
(bootloader) Device tampered: false


   "Normal" firmware (for various values of "normal") can be asked to
   actually list the oem commands it supports - but...
     * in my case it just got stuck when I did, and
     * it can always choose to not report, erm, some interesting commands.

   So I went back to that Over-The-Air update...
host$ ls -l
total 803592
drwxr-xr-x 2 ttsiod ttsiod      4096 Oct 21 01:22 ./
drwxr-xr-x 6 ttsiod ttsiod      4096 Sep 25 23:34 ../
-rw-rw-r-- 1 ttsiod ttsiod 822861864 Aug  7  2015 UL-K01E-WW-

host$ unzip -l UL-K01E-WW- | grep aboot
  1471540  2011-03-22 11:21   bootloader.aboot.img

host$ unzip UL-K01E-WW- bootloader.aboot.img
Archive:  UL-K01E-WW-
signed by SignApk
  inflating: bootloader.aboot.img

host$ strings bootloader.aboot.img | grep ^oem
oem reboot-recovery is called!
oem unlock
oem device-info
oem lock
oem gpt-info
oem fuse_blow
oem check-fuse
oem reset-dev_info
oem grant
oem off-mode-charge 1
oem off-mode-charge 0
oem uart-on
oem uart-off

   I wouldn't touch those 'fuse' things with a ten-foot pole; I don't want
   to brick my tablet.

   But reset-dev_info?

   Come on, I just had to try that :-)

No longer in a fastboot-loop, time to become root

   So, what did we learn, Palmer?
     * We CAN boot our own boot images on the tablet, but ASUS keeps a
       note somewhere: "this is a bad person, booting his own boot image.
       We will no longer boot for him normally."
     * We CAN clear our record afterwards and make the tablet "normal"

   If I can only temporarily become root with a custom boot image, so be
   it - I will do so, and then try to exploit something on the /system
   partition; and finally "re-brand" myself as "an ASUS-compliant, good

Flashing a boot image and then resetting dev-info?

   But just in case... could one, say, flash a boot image... and then
   pretend it never happened?...
host$ sudo fastboot flash boot new_boot.img
host$ sudo fastboot oem reset-dev_info
host$ sudo fastboot reboot

   Nope - same 'stuck in fastboot' behaviour.

   NOTE: I already had a backup of the boot partition when I tried this -
   I did it AFTER I became root and was able to dd a pristine copy of the
   full boot partition for restoring. It was also interesting to note that
   the dd copy of boot did NOT match the boot.img in the Over-The-Air
   update form - maybe there are signatures at the end of that partition
   that are checked for correctness. With closed-source systems, one never

Spawning telnetd and also trying su

   So, back to becoming root via a custom boot image.

   Some of my research told me that if you are in control of the boot
   image, all you need to do is spawn telnetd from within init.rc - it
   would be spawned with root privileges, so anyone telnet-ing inside it
   is the equivalent of a Digital God.

   I tried various forms of this, but to no avail...
host$ cat init.rc
service telnetd /sbin/telnetd -l /sbin/bash

     (Remember that I had placed busybox and all its symlinks (including
                             bash) under /sbin)

   Nothing - there was no telnetd in the ps output after the boot.

   And no log of this failure anywhere... Nothing in dmesg, no logs under



   I tried another form of spawning telnetd, suggested by an awesome
   fireman - kudos, Kris!

   But that one failed as well.


   Maybe I can try one of the classics, and place an su under /sbin?
   Cross-compiled it, and placed it (with the proper setuid bit set) under
host$ adb shell

shell@K01E_2:/ $ /sbin/su
Permission denied.


   Denied by whom?

The 800-pound gorilla

   SELinux - the 800 pound gorilla

   Reading some more, I realized that SELinux was standing in my way:
host$ adb shell

shell@K01E_2:/ $ getenforce

shell@K01E_2:/ $ setenforce 0
setenforce:  Could not set enforcing status:  Permission denied

   I clearly couldn't disable it - not in the default state of my tablet.

   But since I control the filesystem bundled in my boot image, maybe
   there was a way to tell SELinux to get off my lawn? That is, to allow
   my shell user to control its state?

   In the root folder of my boot image's root filesystem, I eventually
   found this:
host$ ls -l sepolicy
-rw-r--r-- 1 ttsiod ttsiod  177701 Oct 23 08:30 sepolicy

   And - this took me ages to find - Joshua Brindle provides the source
   code of sepolicy-inject; a tool that allowed me to tell Android that
   the SELinux policy I want is one where my shell user has the power to
   kill the gorilla:
host$ ls -l
drwxr-xr-x 2 ttsiod ttsiod   4096 Oct 22 16:05 ./
drwxr-xr-x 4 ttsiod ttsiod   4096 Oct  4  2015 ../
-rw-r--r-- 1 ttsiod ttsiod    349 Oct 22 15:42 Makefile
-rw-r--r-- 1 ttsiod ttsiod   1088 Jul 17  2013 README.txt
-rw-r--r-- 1 ttsiod ttsiod   5851 Jul 17  2013 sepolicy-inject.c
-rwxr-xr-x 1 ttsiod ttsiod 293912 Oct 22 15:42 sepolicy-inject*

host$ ./sepolicy-inject -Z shell -P /path/to/original/sepolicy \
        -o /path/to/custom.rootfs/sepolicy.jean.let.me.in

   I packaged this new sepolicy in my root filesystem, packed a new boot
   image, and after fastboot-ing with it, I saw this:
host$ adb shell

shell@K01E_2:/ $ /sbin/su

shell@K01E_2:/ # id

uid=0(root) gid=0(root) groups=1004(input),1007(log),1011(adb),
    3003(inet),3006(net_bw_stats) context=u:r:shell:s0

   YES! I am (G)ROOT!

   And I can chroot - right?
shell@K01E_2:/ # chroot /data/local/tmp

chroot: can't change root directory to '/data/local/tmp': Operation not permitte
1|shell@K01E_2:/ # ls -l /data/local/tmp
opendir failed, Permission denied


   What kind of a root user can't list a folder?!

   I asked the Gods again for inspiration - but as usual, the Gods don't
   respond to mortals.

The capabilities bounding set


   Remember this part?
host$ abootimg -x ../boot.img

writing boot image config in bootimg.cfg
extracting kernel in zImage
extracting ramdisk in initrd.img

   So far the only modifications were applied on the root filesystem
   contained inside the boot image (that is, in initrd.img) - the kernel
   (zImage) was left as-is.

   To debug why the chroot system call (and the listing one!) fail, I
   decided to compile the kernel (ASUS thankfully provided the source
   code), and then sprinkle it with printk statements to see EXACTLY where
   the system calls fail.

   After a LOT of work, I found out about the 'capabilities bounding set'.

   To cut a long story short, the kernel allows you now to limit the kind
   of things ("the amount of damage") you can do from a process. The
   children spawned by it, can only limit things further - they can't get
   BACK what they (or their parents) lost.

   Then again, I controlled the kernel code - so I went all in, guns
static long cap_prctl_drop(struct cred *new, unsigned long cap)
    if (!capable(CAP_SETPCAP))
        return -EPERM;
    if (!cap_valid(cap))
        return -EINVAL;

    // ttsiodras: come in, everyone, the water's fine!
    //cap_lower(new->cap_bset, cap);
    return 0;

   (Yes, yes - I know, this is basically allowing everyone and their
   grandmother to do anything; capabilities are NEVER droped. But I don't
   care - remember, the plan is that I will use my temporary root powers
   to mess with my /system partition, and then revert back to a pristine
   boot image).

   After building this kernel and packaging it in...
host$ adb shell

shell@K01E_2:/ $ /sbin/su

root@K01E_2:/ # chroot /data/debian/ /bin/bash

root@localhost:/# cat /etc/issue
Debian GNU/Linux 8 \n \l

   Root at last

   If you are wondering how the /data/debian came to be, I first created
   the relevant folder in my host machine (via Debian's instructions) and
   then used ADB's port forwarding powers - and netcat:

   In the tablet:
host$ adb shell

shell@K01E_2:/ $ /sbin/su

root@K01E_2:/ # cd /data
root@K01E_2:/ # mkdir debian
root@K01E_2:/ # cd debian
root@K01E_2:/ # nc -l -p 9999 | tar xpvf -

   In the host:
host$ adb forward tcp:9999 tcp:9999
host$ sudo -i
host# cd /opt/chroot-armie
host# tar cpf - ./* | nc localhost 9999

Cameras - and doing it properly

   I enjoyed my newfound powers by setting up the chroot-ed Debian to do
   my bidding - and as it always does, Debian worked perfectly. I did some
   bind-mounting before chrooting to make sure it had access to everything
   in the tablet (and not just under the chroot-ed folder), which allowed
   me to e.g. process my recorded videos and images from within the tablet
   with ImageMagick and ffmpeg and mkvmerge, and...

   Oh wait a moment.

   The camera isn't working?!?!
   What?! No camera?!?!

   Googling about it... and look, I am not alone: tons of people all over
   the world are reporting a common thing about rooting their Android

   "I don't use rooting because afterwards the camera isn't working".

   Now I know more than enough about this to be 100% sure: rooting has
   NOTHING to do with the camera! The simple thing is, the kernel sources
   that I just compiled obviously have no device drivers for the camera in


   I am guessing the answer is closely related to patents and NDAs and
   similar (expletive).


   BTW, this means there is no chance to compile a CyanogenMod
   distribution for my tablet; best-case scenario, I would succeed but
   lose the camera functionality in the process. And God knows what else -
   the GPS, etc :-(

   I have to go back to my original plan - boot from the pristine boot
   image burned in the tablet, and become root ONLY through modifications
   to my /system partition.

   Which I can modify now - but modify what?

Game over

   Accomplishing rooting with the pristine boot image, means doing so with
   full SELinux and capability bounding sets in place.

   Which can only mean one thing - I needed to find a way to run something
   as root BEFORE the parent process that spawns me ends up severely


   This took me even more time to find... but eventually, I noticed that
   the tablet upgrade (the Over-The-Air update from Asus that moved the
   tablet from KitKat (Android 4.4) to Lollipop (Android 5.1), left
   behind... a gift for me:
host$ adb shell

shell@K01E_2:/ $ /sbin/su
root@K01E_2:/ # cd /system/bin
root@K01E_2:/system/bin # cat install-recovery.sh

if ! applypatch -c EMMC:/dev/block/platform/msm_sdcc.1/by-name/\
        recovery:7847936:c8bd9025173cb3ab0f467f11291b10f517e95791; then
  applypatch -b /system/etc/recovery-resource.dat \
        9c5998b970de2449b4c73b890c44f8e68b2a84da \
    EMMC:/dev/block/platform/msm_sdcc.1/by-name/recovery \
        c8bd9025173cb3ab0f467f11291b10f517e95791 7847936 \
            /system/recovery-from-boot.p && \
            log -t recovery "Installing new recovery image: succeeded" \
                || log -t recovery "Installing new recovery image: failed"

  log -t recovery "Recovery image already installed"

   Hello - what's this?

   This code clearly needs to run with god-like privileges - it is
   supposed to patch the recovery partition with the new recovery image
   contained in the update, and it obviously needs to do this rather early
   in the boot time.

   Can I hook stuff in here?
root@K01E_2:/system/bin # vi install-recovery.sh
root@K01E_2:/system/bin # cat install-recovery.sh
  log -t recovery "Recovery image already installed"
/system/xbin/telnetd -b -l /system/xbin/bash

   (Notice that I copied all the busybox stuff from under /sbin - that is,
   from the modified boot image - to under /system/xbin ; since the plan
   is to boot from a normal boot image, that won't have anything under
   /sbin except what Asus placed in there).

   And there it was - I added the proper music in the background and
host$ adb reboot bootloader
host$ sudo fastboot oem reset-dev_info
host$ sudo fastboot reboot
host$ adb shell
shell@K01E_2:/ $ telnet 2323

Entering character mode
Escape character is '^]'.

/ #

   I WIN

   Oh God, no one will get the reference - I am too old... :-)

   Finally, I streamlined the process with a fake 'su' that I placed under
/ # cat /system/xbin/su
echo "========================================================="
echo "Feel free to run 'r' to get to a full Debian."
echo ""
echo "Telneting into the tunnel..."
echo "========================================================="
/system/xbin/telnet 2323

   So my tablet, in pristine boot condition, with no tethering
   requirements whatsoever, was finally rooted; in an open-source way,
   with no mysterious dependencies on external servers [2], and with the
   camera still working.

   And is now proudly running a Debian chroot, of course :-)


   There were many points during this journey that I felt really sad. It
   was as if Android creators absolutely HATED people like me, and did
   their best to make us suffer; because they group us together with
   malware authors; and add multiple layers of checks that don't
   distinguish between the owner of the machine and the developers of
   applications that run in the machine.

   I am NOT a bad guy!... I just want to remain in full control of my OWN

   What makes this sad is that "security" and "freedom" are not mutually
   exclusive - and Google already knows that this dichotomy is a false
   one. Their Chromebooks used to have hardware switches that the user had
   to set by hand, in order to enter "developer mode". This meant the
   owners of the machines had the freedom to root them, install chroots or
   native Linux distros, and generally do whatever they want with the
   hardware they purchased - if they chose to do so and accept the risks

   While malware authors still had to face pains like those I described

   (Not that it stops them, BTW...)

   I shudder to think what I will face the next time the HW of my Android
   tablet or phone dies. The way things are going in the Android
   ecosystem, freedom to "tinker" will be gone; sacrificed forever in the
   delusionary altar of "safety-uber-alles".

   And if we are going that way... Android might as well be called iOS.

   Discussions in Slashdot - Reddit/programming - Reddit/Linux -
   Reddit/ReverseEngineering - Hacker News - Hackaday


    1. I wish the process was as smooth as I described it in the storyline
       above. In reality, as you can see in my two questions to Android
       Stack Exchange, and the one in Electronics Stack Exchange, the
       process is completely chaotic - there is no plan; you just try to
       make sense of all the complex factors that affect what is
       happening. As far as mental exercises go, this one was just as hard
       as the toughest ones I've ever met, and stretched my debugging
       muscles to their breaking point (which is good; that's how they get
       stronger). Huge thanks go out to the many people out there that
       work on this kind of thing and offer the resulting open-source
       tools and rooting instructions to mere mortals like me - probably
       without ever getting a "thank you" in return. I hope this page will
       act as my way of saying: "I now know what you guys go through -
       thank you so much!"
    2. Well, there are some closed-source "one-click roots" that seem to,
       er, communicate with servers in China; supposedly to obtain the
       "proper" kernel exploit. Much as I respect the hacking power behind
       this... I am sorry, but I can't trust that you guys won't install a
       keylogger, or steal my GMail credentials, or make my tiny tablet a
       part of the ARMies of Mordor that have been known to recently be
       used in DoS attacks.
    3. The details of Android rooting keep changing of course, as versions
       of Android constantly evolve. What I described above is most likely
       no longer applicable to any tablet or phone running Android 6.x.

   profile for ttsiodras at Stack Overflow, Q&A for professional and
   enthusiast programmers
   GitHub member ttsiodras
   Index  CV Updated: Sat Oct 8 20:33:36 2022

   The comments on this website require the use of JavaScript. Perhaps
   your browser isn't JavaScript capable or the script is not being run
   for another reason. If you're interested in reading the comments or
   leaving a comment behind please try again with a different browser or
   from a different connection.
Saved from web.archive.org, with Lynx.
Main page
© 2022 Matei. No cookies®