ng-dst / flashable-android-rootkit

Persistent backdoor for Android devices with unlocked bootloader. Runs as root in unrestricted SELinux context and can hide itself from anything except root
GNU General Public License v3.0
46 stars 3 forks source link

Installing without Recovery #2

Open DavidBuchanan314 opened 4 months ago

DavidBuchanan314 commented 4 months ago

Not an issue, but something I figured out for my self, so I thought I'd share.

The device I'm targeting doesn't have a working recovery environment, so instead I used https://github.com/ookiineko/magiskboot_build to build magiskboot for linux, which I used to repack the boot image off-device. Then all I needed to do to install it was reflash boot.

The only ramdisk patch I did was to replace init:

magiskboot cpio ramdisk.cpio "add 750 init magiskinit64"

I'm glad I found this repo because it's exactly what I was looking for, and it works great, thanks for making it! (btw, I tested it on the Rabbit R1, which runs Android 13 AOSP)

DavidBuchanan314 commented 4 months ago

Bonus update, my device has an insecure bootrom, so I was able to write a "bootkit" of sorts that bootstraps all the way from bootrom to rooted android, without touching the system or boot partitions on-disk, meaning the bootloader stays "locked" the whole time! (sorry, I hope you don't mind my ramblings here, feel free to close the issue)

ng-dst commented 4 months ago

Thanks for sharing! Did you really reflash bootloader in device's ROM? I thought the chip for primary bootloader is always made read-only. Or do you mean secondary bootloader / aboot? Either way, that sounds interesting

DavidBuchanan314 commented 4 months ago

I didn't reflash anything! It's like a "tethered jailbreak", there is no persistence. Once the device reboots, it's back to stock.

My target device has an insecure bootrom which accepts unsigned "DA" images over USB, directly into RAM, and executes them (see https://github.com/bkerler/mtkclient). From there, I was able to hook the rest of the bootchain all the way until linux boots.

The source is here https://github.com/DavidBuchanan314/rabbit_r1_boot_notes/tree/main/scripts/custom_da but it's pretty incomprehensible right now, and also hyper-specific to my target devices (hardcoded offsets etc.) I'll be doing a proper writeup soon.

DavidBuchanan314 commented 4 months ago

Writup is now live :) https://www.da.vidbuchanan.co.uk/blog/r1-jailbreak.html

ng-dst commented 4 months ago

Outstanding work! Congrats on successfully jailbreaking that thing :)

One small note on potential stealth issues with your TCP shell payload: this rootkit already implements some techniques to hide the injected service from any userspace apps / processes. So this might not be an issue at all!

I'm glad my tool was useful for your research. Thanks for the credits btw

DavidBuchanan314 commented 4 months ago

On the stealth front, I was mostly thinking about the app just trying to connect to localhost:1337 - if that succeeds then it knows it's been jailbroken!

ng-dst commented 4 months ago

That's what reverse shells are made for! But I get your point. Anyways, runtime detection is trivial to evade if you hook the entire boot process from the beginning!