This is my post on how I managed to run a alpine chroot system on android without root 🌿
Intro
So, I was recently using Termux when a thought came to my mind 🤔.
It’s fascinating how Android has grown since KitKat era. We used to have terminals that looked like xterm without styling. Jackpal Android Term used to be what came along Kali Nethunter 😌.
The only ways to run Linux on android was chrooting (change root), on a rooted device. Linux Deploy one of very first apps that perfected it. It came Pre-installed on Kali Nethunter so you can run a Kali subsystem on android, very cool back in days 😌. Now…. Now we have Termux that works without root. You can now run Arch to Kali, heck even Gentoo without root 🤯.
How did we come this far? 🤨
Good Question 🤔, I strongly believe this is because of the simple tool proot
. That uses user-level resources to chroot into a rootfs. Termux project added patches that allowed them to make it more compatible for Android devices, and then Termux was born ✨.
Let Me Show You How 🪴
Required
- We need Android Terminal Emulator Suggested Terminals:
- Terminal by Alif Software - (recommended)
- TermOne Plus
- Jackpal Android Term
- Alpine RootFs tarball
- Busybox
Configs
Set this as initial command so everytime we start terminal we are at app_HOME folder 📂.
cd $HOME && clear
Then we setup a small rootfs for terminal emulator.
1
2
mkdir bin
cd bin
We need to add this bin
folder to PATH
, so we can access binaries inside it.
1
2
3
# Assuming we are at ./bin folder
EXPORT PATH=$PATH:$(pwd)
echo $PATH
Download Busybox
Downloading busybox is easy. We will use Busybox from Magisk-Modules-Repo which are compiled from (osm0sis Android Busybox Repo)[https://github.com/osm0sis/android-busybox-ndk]. We will download it with curl, because wget is not installed in android. I’m using arm64 binary, use binary according to your cpu. Use cat /dev/cpuproc
or uname -a
to find.
1
curl -o ./bin/busybox https://github.com/Magisk-Modules-Repo/busybox-ndk/raw/master/busybox-arm64
Now we should make it executable by giving it perms
1
2
3
chmod 755 ./bin/busybox
# or
chmod +x ./bin/busybox
We should now be able to run busybox tar -xvf
and it wont give us gunzip
not found error.
Installing applets is a nice addition, so we will install busybox applets as commands. To link applet to busybox we run:
1
ln -sf ./path/to/busybox ./path/to/applet/applet_name
Linking one command:
1
2
3
# Assuming we are in $HOME
cd bin
ln -sf busybox xargs
Next let’s link all applets.
But Busybox has so many applets, How do we install them all? :(
We use the busybox --install -s ./directory
command.
1
2
3
4
# Considering we are at $HOME directory
busybox --install -s ./bin
# Check
ls ./bin
Great! Now we can access all of busybox tools 👍
Getting Alpine rootfs
Go to Alpine Linux Downloads page and copy download link of mini rootfs according to arch. I’m downloading arm64 rootfs so i have to run:
1
wget -O alpine.tar.gz https://dl-cdn.alpinelinux.org/alpine/v3.15/releases/aarch64/alpine-minirootfs-3.15.0-aarch64.tar.gz
Isn’t it pretty cool that we can run wget now ✨! Anyway, now we use tar -x
to extract to alpine dir.
1
2
mkdir alpine
tar -xvf alpine.tar.gz -C alpine
Great! Now we have a alpine rootfs! :)
How to Chroot without root?
Now that we have a alpine rootfs, how do we chroot into it? 🤨
We use proot
, like termux.
Where do we get proot from? We don’t even have apt or pkg 😐
We download publicly available binaries.
One of the repos i found searching for ‘android proot binary’ was green-green-avk/build-proot-android. It’s a fork of termux/proot with little patches. You can also use termux/proot.
I downloaded and extracted the proot binary from the repo.
To Download proot:
1
curl -LO "https://github.com/green-green-avk/build-proot-android/blob/master/packages/proot-android-aarch64.tar.gz"
To Move binaries:
1
2
3
tar -xvf proot-android-aarch64.tar.gz
mv ./root/bin/* ~/bin/
mv ./root/* ~/
Great, proot android is installed. Try running it with proot
command.
I’M PROOT
Now time to proot into our alpine rootfs. To do so we need to do it in multiple steps. So i made a simple script.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/system/bin/sh
export PATH=$PATH:$HOME/bin
unset LS_PRELOAD
ROOTFS_PATH=$HOME/alpine
PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
proot \
-r $ROOTFS_PATH \
-p \
-H -0 -l -L \
-b /sys \
-b /dev \
-b /proc \
-b /proc/mounts:/etc/mtab
Lot’s of thigs going on here. Let’s go line by line.
#!/system/bin/sh
We First declare which shell to use when this script file is run.
export PATH=$PATH:$HOME/bin
We set the path so we can access proot (just in case) PATH
is not set.
unset LS_PRELOAD
Unset LD_PRELOAD
to prevent errors.
ROOTFS_PATH=$HOME/alpine
We set the folder of the alpine rootfs. Here its in ~/alpine so $HOME/alpine.
PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
We set the new path that tells proot where to look for binaries.
proot
-r $ROOTFS_PATH \
We run proot
with -r
root location.
-p \
We don’t have root access, so we use higher ports for binding.
-H -0 -l -L \
We hide files starting with .proot
with -H
. Give our user fake root -0
. We make current user group appear as “uid:gid” with -i
. We use correct size of lstats -L
.
-b /sys
-b /dev
-b /proc
-b /proc/mounts:/etc/mtab
Here you can see something you’ll be familiar as a linux user. As Common chroot practice here we bind hardware locations to new root.
and on running it we should get….
Objective Complete!
That’s It for this post. I’ll save cooler stuff for lated posts. Hope you learnt something new today.
Let me know if you liked / disliked the post by leaving a comment below! :)
~ **CypherpunkSamurai** Logs_Off....
Comments powered by Disqus.