Freeing my tablet (Android hacking, SW and HW)

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:

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).

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...

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):

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:

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.

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.

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:

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...

...and to my utter amazement, I saw this:

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.

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):

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?...

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.

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:

The capabilities bounding set

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:

(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).

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?!?!

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:

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.

(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).

Finally, I streamlined the process with a fake 'su' that I placed under /system/xbin:

/# cat /system/xbin/su#!/system/bin/shecho "========================================================="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.12323

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".

Notes

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!"

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.

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.

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.