Executive Summary and Motivation
This article is currently a mess and a work in progress. I'm trying to iterate on it quickly so check back soon.
Pre-requisites
- a rooted Android device
- a terminal application like jackpal
- the busybox command installed
- a Debian based system
Installing Multistrap on the Debian based machine
Installing Multistrap
sudo apt-get install multistrap
What we're doing is pretty much the Embedded Debian multistrap instructions [2].
- Installing the Debian 'archive' keys for apt
- Creating a Multistrap config
For the exhaustive Debian multistrap documentation see [1].
Entering the Chroot
Need to mount some virtual filesystems and the devices internal storage:
- /sys (virtual filesystem of your computers hardware)
- /dev (filesystem of device files for hardware devices)
- /proc (virtual filesystem of processes, stats and settings)
- /dev/pts (virtual filesystem of allocated terminals)
- /dev/bus (found I needed this for USB device access)
- /sdcard (mount internal storage of the device)
MOUNT=<path to root of the chroot> mount -t sysfs sysfs $MOUNT/sys mount -o bind /dev $MOUNT/dev mount -t devpts devpts $MOUNT/dev/pts mount -o bind /dev/bus $MOUNT/dev/bus mount -o bind /sdcard $MOUNT/mnt
Also basic environment variables need to be set to make your life easier:
HOME=/root PATH=/bin:/sbin:/usr/bin:/usr/sbin SHELL=/bin/sh export HOME PATH SHELL # And finally enter the chroot /system/bin/chroot $MOUNT $SHELL
This step must be done the first time entering the chroot to setup many packages.
export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true export LC_ALL=C LANGUAGE=C LANG=C /var/lib/dpkg/info/dash.preinst install dpkg --configure -a
Setting up a User Account in the Chroot
Android generates user accounts for each application that is installed, counting up from 10000, the name of the account is 'app_#' where the # is the remainder from the 10000 base (uid % 10000).
Inside of the chroot we can use the UID of the terminal application for our user account UID. This way we can piggyback on the terminal apps permissions and avoid running everything as root.
Another easy, and fun, way to do this is to take the running process ID of the Android shell currently running, and look at the UID of the owner in the /proc filesystem. It is important to remember this must be done outside the chroot, we're just gathering information for the chroot.
# Below $$ evaluates to the process ID of whatever calls it, here the shell. # You must run the below code as the terminal application user, not root. app_88@android:/ $ cat /proc/$$/status | grep Uid Uid: 10088 10088 10088 10088 # Take the UID, 10088 in this case, and save it for later. # To use this variable in the chroot enter it using this same terminal. export TERM_UID=10088 # no spaces in the variable declaration
Android controls access to system calls by group membership, the same way access to a sound card is often controlled in GNU/Linux. The twist is the every application is a "user" that applies for group memberships, at installation time (when Google Play, or another market, asks you to confirm the permissions).
Anyway to have any fun with our renamed terminal user inside the chroot, we're going to want to be able to open network sockets, so we need to make a group inside the chroot matching the Android 'socket' group outside the chroot.
groupadd --gid 3003 sockets useradd --uid $TERM_UID -m -G sockets --shell /bin/bash debian # Boom! From root you can now change to a regular user in the shell, with # sufficient but not excessive permissions--for IRC, VNC or other purposes. su debian whoami
TODO: add bit explaining sockets group and source of GID.
Bibliography
TODO: Sources still need to be cited here. They are forthcoming.
[1] | Debian Multistrap |
[2] | EmDebian Cross Debbootstrap |