Table of Contents
- The setup
- First attempt: instant fail
- Fix: swap in modern Magisk
- Second attempt: rooted the wrong thing
- The actual problem: two SDKs
- Third time's the charm
- Lessons
- Next steps
So I wanted a rooted Android emulator for some security testing. Frida, Burp, the usual suspects. Easy, right? Just grab rootAVD, point it at the ramdisk, done in five minutes.
Reader: it was not done in five minutes.
The setup #
I had a fresh Android Studio install with an AVD running an Android 17 preview image. Specifically: sdk_gphone16k_x86_64, API 37, with 16KB memory pages. Brand-new stuff. The kind of system image you create when you click "latest" without thinking about it.
rootAVD is the go-to script for rooting Android Studio emulators with Magisk. It moved from GitHub to GitLab back in 2023, and the last real update was October 2024. That last-update date turned out to matter a lot.
First attempt: instant fail #
[*] Finding a working Busybox Version
[!] Can not find any working Busybox Version
[!] aborting the script
Cool. Turns out the rootAVD repo ships with Magisk v26.4 baked in. Current Magisk is v30.7. The bundled busybox binaries inside that old Magisk zip couldn't execute on a 2026 system image, so the script gave up before doing anything useful.
Fix: swap in modern Magisk #
The README actually documents this you can replace the bundled Magisk.zip with whatever version you want. Magisk APKs can be renamed to .zip and used directly:
1mv Magisk.zip Magisk.zip.old
2curl -L -o Magisk.zip https://github.com/topjohnwu/Magisk/releases/download/v30.7/Magisk-v30.7.apk
Re-run, and now busybox is happy:
[!] Found a working Busybox Version
[!] BusyBox v1.36.1.1 topjohnwu (2024-10-06 01:38:43 PDT)
Progress.
Second attempt: rooted the wrong thing #
Script completed. I cold-booted the AVD all excited, ran su, got:
/system/bin/sh: su: inaccessible or not found
Bruh.
Buried in the rootAVD output:
[-] This AVD = 6.12.58-android16-6-...
[-] Ramdisk = 5.15.119-android13-8-...
[!] Ramdisk is probably NOT from this AVD
Translation: I'd pointed rootAVD at system-images/android-33/google_apis/ramdisk.img because that's what the help text showed in its examples. But my running AVD was the Android 17 image. I patched a completely different ramdisk file sitting on disk, and the AVD booted from its own untouched image.
The actual problem: two SDKs #
1find ~/Android/Sdk/system-images -name "ramdisk.img"
2# /home/me/Android/Sdk/system-images/android-37.0/google_apis_playstore_ps16k/x86_64/ramdisk.img
3
4find $ANDROID_HOME/system-images -name "ramdisk.img"
5# /opt/android-sdk/system-images/android-34/default/x86_64/ramdisk.img
6# /opt/android-sdk/system-images/android-33/google_apis/x86_64/ramdisk.img
Two Android SDKs on my machine. Android Studio uses ~/Android/Sdk, but $ANDROID_HOME pointed at /opt/android-sdk (probably from a package manager). rootAVD reads from $ANDROID_HOME, so when I ran ListAllAVDs it only ever saw the API 33/34 stuff. The Android 17 image was invisible to it.
Fix:
1export ANDROID_HOME=~/Android/Sdk
2./rootAVD.sh system-images/android-37.0/google_apis_playstore_ps16k/x86_64/ramdisk.img FAKEBOOTIMG
Third time's the charm #
This run:
[-] This AVD = 6.12.58-android16-6-gccafb60de224-ab14828483
[-] Ramdisk = 6.12.58-android16-6-gccafb60de224-ab14828483
[!] Ramdisk is probably from this AVD
Kernel hashes match. We're patching the actual running image's ramdisk. The Magisk app launched, I picked "Install" → "Select and Patch a File" → navigated to Downloads → tapped fakeboot.img → hit the Let's Go button. About ten seconds later Magisk wrote out a magisk_patched-30700_xxxxx.img, rootAVD's polling loop picked it up, and the script finished cleanly.
Cold boot from the AVD Manager. Then:
1adb shell
2emu64xa16k:/ $ su
3emu64xa16k:/ # id
4uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
context=u:r:magisk:s0 is the one I wanted to see. That's the SELinux context Magisk creates for root shells not a misconfigured root, not a half-baked workaround, the real deal.
Lessons #
A few takeaways that would've saved me an hour:
rootAVD's bundled Magisk is old. If your AVD is anything recent, swap Magisk.zip with the latest APK from topjohnwu/Magisk releases before your first run. It costs nothing and pre-empts the busybox failure.
The ramdisk path you pass has to match the SDK rootAVD is reading from. Set ANDROID_HOME explicitly to whichever SDK contains your target image, then use ListAllAVDs to confirm rootAVD sees it. If it doesn't show up there, you're patching the wrong file no matter what command you run.
Always check the kernel-mismatch line in rootAVD's output. If it says "Ramdisk is probably NOT from this AVD," stop and figure out why before cold-booting. Saves a confusing reboot.
Don't pre-emptively avoid preview images. I almost gave up and fell back to API 33. Turns out the Play Store 16KB-page Android 17 image roots just fine with current Magisk rootAVD's logic is more flexible than the maintenance schedule suggests.
The FAKEBOOTIMG flow is honestly elegant. rootAVD generates a fake boot image, launches the Magisk app, you patch it in the GUI like a real device, and the script reaps the patched file. No funky kernel module compilation, no manual ramdisk surgery.
Next steps #
Now the fun part frida-server, Burp CA install, and seeing whether modern apps' root detection catches a properly hidden Magisk install on an Android 17 emulator. That's a different post. For now: enjoy the dopamine hit of a green uid=0.
If you're trying to do the same thing, the actual two-command version of this whole post is:
1# in the rootAVD folder
2curl -L -o Magisk.zip https://github.com/topjohnwu/Magisk/releases/latest/download/Magisk.apk
3export ANDROID_HOME=~/Android/Sdk # or wherever Android Studio installed it
4./rootAVD.sh system-images/<your-api>/<variant>/x86_64/ramdisk.img FAKEBOOTIMG
Then patch the fake boot image in the Magisk app, cold boot, and run adb shell su -c id. Done.
Big thanks to newbit for building and maintaining rootAVD the script does a lot of unglamorous shell-scripting work so the rest of us can root an emulator with one command. Repo lives at gitlab.com/newbit/rootAVD.