---------------------------------------------------------------------------------------
.
---------------------------------------------------------------------------------------
#Coding and administration articles by ttsiodras
IFRAME:
https://archive.org/includes/donate.php?as_page=1&platform=wb&referer=h
ttps%3A//web.archive.org/web/20221015134804/https%3A//www.thanassis.spa
ce/android.html
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
success
fail
About this capture
COLLECTED BY
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
walkthroughs.
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
find.
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
TIMESTAMPS
loading
The Wayback Machine -
https://web.archive.org/web/20221015134804/http://www.thanassis.space/a
ndroid.html
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.
Malta
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
idea).
And I trust Debian. Far more than I trust the Android ecosystem.
That was when it hit me; I searched, and searched, and searched...
Pain
...there was no open [2] rooting process for this tablet.
No TWRP, no CyanogenMod, nothing.
Nowhere.
(Gulp)
...
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.
Hmm.
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-12.16.1.12-user.zip
host$ unzip -l UL-K01E-WW-12.16.1.12-user.zip | grep boot.img
7368704 2011-03-22 11:21 boot.img
host$ unzip UL-K01E-WW-12.16.1.12-user.zip boot.img
Archive: UL-K01E-WW-12.16.1.12-user.zip
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
disabled
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
#!/bin/bash
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
fi
fi
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
issue.
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?
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
capacitance:
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
...
Well...
"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-12.16.1.12-user.zip
host$ unzip -l UL-K01E-WW-12.16.1.12-user.zip | grep aboot
1471540 2011-03-22 11:21 bootloader.aboot.img
host$ unzip UL-K01E-WW-12.16.1.12-user.zip bootloader.aboot.img
Archive: UL-K01E-WW-12.16.1.12-user.zip
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"
again.
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
guy".
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
knows...
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
oneshot
(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
/var/log/.
Silence.
(sigh)
I tried another form of spawning telnetd, suggested by an awesome
fireman - kudos, Kris!
But that one failed as well.
Hmm...
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
/sbin...
host$ adb shell
shell@K01E_2:/ $ /sbin/su
Permission denied.
Oh?
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
Enforcing
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),
1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),
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
d
1|shell@K01E_2:/ # ls -l /data/local/tmp
opendir failed, Permission denied
What?!?!
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
FINE.
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
blazing:
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
devices...
"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
them!
Why?
I am guessing the answer is closely related to patents and NDAs and
similar (expletive).
(sigh)
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
limited.
Where?
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
#!/system/bin/sh
if ! applypatch -c EMMC:/dev/block/platform/msm_sdcc.1/by-name/\
recovery:7847936:c8bd9025173cb3ab0f467f11291b10f517e95791; then
applypatch -b /system/etc/recovery-resource.dat \
EMMC:/dev/block/platform/msm_sdcc.1/by-name/boot:7368704:\
9c5998b970de2449b4c73b890c44f8e68b2a84da \
EMMC:/dev/block/platform/msm_sdcc.1/by-name/recovery \
c8bd9025173cb3ab0f467f11291b10f517e95791 7847936 \
9c5998b970de2449b4c73b890c44f8e68b2a84da:\
/system/recovery-from-boot.p && \
log -t recovery "Installing new recovery image: succeeded" \
|| log -t recovery "Installing new recovery image: failed"
else
log -t recovery "Recovery image already installed"
fi
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"
fi
/system/xbin/telnetd -b 127.0.0.1:2323 -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
rebooted:
host$ adb reboot bootloader
...
host$ sudo fastboot oem reset-dev_info
host$ sudo fastboot reboot
...
host$ adb shell
shell@K01E_2:/ $ telnet 127.0.0.1 2323
Entering character mode
Escape character is '^]'.
/ #
Finally!
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
/system/xbin:
/ # cat /system/xbin/su
#!/system/bin/sh
echo "========================================================="
echo "Feel free to run 'r' to get to a full Debian."
echo ""
echo "Telneting into the tunnel..."
echo "========================================================="
/system/xbin/telnet 127.0.0.1 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 :-)
Conclusion
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
hardware...
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
involved.
While malware authors still had to face pains like those I described
above.
(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
Notes
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.
---------------------------------------------------------------------------------------