
Go로 Android Studio 에뮬레이터의 ramdisk를 Magisk로 패치하여 루팅합니다.
avdroot는 AVD를 콜드 스타트에서 단 하나의 명령으로 작동하는 루트 셸까지
가져옵니다. 모든 작업은 호스트에서 이루어집니다: ramdisk가 압축 해제되고,
Magisk의 init이 /init을 대체하도록 재작성되며, 다시 압축됩니다. 이미지
빌드에는 셸 스크립트도, busybox도, magiskboot도, 에뮬레이터 내부에서의
코드 실행도 필요하지 않습니다.```
$ avdroot root
==> Target
Pixel_10_Pro_XL (the only AVD)
==> Preparing Magisk's environment
Magisk's files are not unpacked yet; writing them for 31.0 now
ok 14 files written for Magisk 31.0, before the restart that will use them
==> Patching
preinit device: vdd1 (read from the running emulator)
==> Restarting the emulator
booting cold, because a snapshot would restore the pre-patch ramdisk
==> Installing the Magisk app
ok installed com.topjohnwu.magisk (Magisk 31.0)
==> Granting su to the adb shell
ok uid 2000 allowed
==> Verifying root
ok Magisk 31.0:MAGISK:R is running
ok su grants root
root: uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
## 목차
- [왜 또 하나 필요한가](#why-another-one)
- [설치](#install)
- [빠른 시작](#quick-start)
- [명령어](#commands)
- [작동 방식](#how-it-works)
- [Magisk 릴리스 선택](#choose-a-magisk-release)
- [이 도구가 처리하는 함정들](#traps-this-tool-handles)
- [Chrome에서 HTTPS 캡처하기](#capturing-https-from-chrome)
- [플랫폼 지원](#platform-support)
- [출력 언어](#output-language)
- [개발](#development)
- [크레딧 및 라이선스](#credits-and-licence)
## 왜 또 하나 필요한가
[rootAVD](https://github.com/newbit1/rootAVD)가 이 기법을 처음 개척했고 여전히
이 기법의 레퍼런스이지만, 최신 Android 및 Magisk 릴리스에 맞춰 업데이트되지
않았습니다. Android 17 AVD에 대해 실행해 보면 문제점들이 명확히 드러나며,
각각은 여기서 해결되었습니다:
| rootAVD 동작 | avdroot |
|---|---|
| `bash`, `busybox`, `unzip`, `xxd`, `strings`, `dd`, `cpio`, 그리고 GNU `stat`/`sed`(macOS에서는 다름)를 요구 | 하나의 정적 Go 바이너리. cpio, LZ4, gzip, xz 모두 프로세스 내에서 구현됨 |
| 스크립트와 바이너리를 에뮬레이터로 복사한 뒤 그 안에서 자체 실행 | 이미지를 전적으로 호스트에서 빌드 |
| 매 실행마다 `ramdisk.img`를 백업하므로, 첫 패치 이후에는 "원본" 백업 자체가 패치되어 `restore`로 순정 상태로 되돌릴 수 없음 | 한 번만 백업하고 절대 덮어쓰지 않으며, 기존 백업이 패치된 것으로 판명되면 경고 |
| Magisk의 예전 `magisk32`/`magisk64` 레이아웃을 패치 | Magisk 26+ (`magiskinit`, `magisk`, `init-ld`, `.backup/.rmlist`)를 구현 |
| ramdisk 경로를 인자로 붙여넣어야 함 | SDK, AVD, 이미지를 자동으로 탐색하며 `--sdk`/`--avd-home`으로 재정의 가능 |
| 무조건 재부팅하고 기대에 맡김 | 콜드 부팅을 강제하고 `su`가 실제로 `uid=0`을 반환하는지 검증 |
## 설치
**미리 빌드된 바이너리** — [Releases](https://github.com/ejfkdev/avdroot/releases)에서
사용 중인 플랫폼에 맞는 아카이브를 받으세요:```sh
tar -xzf avdroot_linux_amd64.tar.gz
chmod +x avdroot_linux_amd64
sudo mv avdroot_linux_amd64 /usr/local/bin/avdroot
Windows 및 macOS 아카이브에는 단일 실행 파일이 포함되어 있으며, macOS에서는 quarantine 속성을 지워야 할 수 있습니다:```sh xattr -d com.apple.quarantine avdroot_darwin_arm64
모든 릴리스는 `SHA256SUMS.txt`도 함께 게시합니다:```sh
sha256sum -c SHA256SUMS.txt --ignore-missing
Go 사용 시 (1.24 이상):```sh go install github.com/ejfkdev/avdroot@latest
Go 1.24가 최소 요구 사항인 이유는 이전 툴체인은 `LC_UUID` 로드 명령을 생성하지 않으며, macOS 26의 `dyld`는 그러한 바이너리 실행을 거부하기 때문입니다. Go 1.21과 1.22도 `minos 26.0`을 기록하므로 두 가지 측면 모두에서 실패합니다.
**소스에서:**```sh
git clone https://github.com/ejfkdev/avdroot
cd avdroot
make build # host binary
make all # every release target into dist/
또한 adb와 에뮬레이터가 포함된 Android SDK와 google_apis 또는
AOSP 시스템 이미지가 필요합니다. Play Store 이미지는 이 방식으로 루팅할 수 없습니다. 이들은
adb root를 거부하므로, patch와 root는 몇 분 후에 실패하는 대신 즉시 이를 거부합니다.
avdroot list # what exists, and what state it is in avdroot root # patch, restart, install the app, grant su, verify
그게 전부입니다. `root`는 AVD가 하나만 존재할 때는 AVD 이름이 필요 없고, 한 번 확인을 요청하며, stdin이 터미널이 아닐 때는 질문을 완전히 건너뜁니다:```sh
avdroot root Pixel_10_Pro_XL --yes # named AVD, unattended
단계별로 진행하고 싶다면:```sh avdroot patch # patch only; the emulator need not be running avdroot patch --dry-run # show what would change, write nothing
avdroot install && avdroot verify
되돌리려면:```sh
avdroot restore # restores ramdisk.img.backup
| 명령어 | 설명 |
|---|---|
avdroot root [target] | 패치, 재시작, 설치, su 권한 부여, 검증 — 무인 실행 |
avdroot patch [target] | ramdisk만 패치; 쓰기 전에 확인을 요청 |
avdroot restore [target] | ramdisk.img.backup에서 복원 |
avdroot list | AVD, 시스템 이미지 및 해당 패치 상태 |
avdroot status [target] | preinit 장치를 포함한 단일 대상의 세부 정보 |
avdroot verify [target] | Magisk가 실행되고 su가 uid=0을 반환하는지 확인 |
avdroot install | 실행 중인 에뮬레이터에 Magisk 앱 설치 |
avdroot magisk info | 어떤 설치 프로그램이 사용될지, 그리고 무엇을 지원하는지 |
avdroot magisk fetch | 릴리스 다운로드 (--list, --version, --prerelease) |
avdroot trust-chrome | Chrome이 가로채기 CA를 수락하도록 설정 (--cert, --clear) |
avdroot doctor | 모든 경로가 어떻게 위치되었는지 설명 |
대상은 AVD 이름, 시스템 이미지 경로 또는 ramdisk.img의 경로입니다.
avdroot <command> --help는 각 명령어의 예시를 보여줍니다.
다음은 모든 명령어에 적용됩니다:
| 플래그 | 효과 |
|---|---|
--sdk PATH | 감지가 잘못된 것을 선택했을 때 Android SDK 루트 |
--avd-home PATH | AVD 정의가 있는 위치 |
--serial SERIAL | 여러 장치가 연결되어 있을 때 사용할 장치 |
--magisk PATH | 특정 Magisk 설치 프로그램 사용 |
--abi ABI | 감지된 ABI 재정의 |
--compress FORMAT | ramdisk 압축 재정의 (gzip, lz4_legacy, lz4, xz) |
--preinit DEVICE | preinit 블록 장치 재정의 |
--lang | 출력 언어 (en 또는 zh), 시스템 로케일 재정의 |
--no-adb | 실행 중인 에뮬레이터에 연결하지 않음 |
--no-download | Magisk 설치 프로그램을 자동으로 가져오지 않음 |
| 플래그 | 명령어 | 효과 |
|---|---|---|
-y, --yes | root, patch | 확인 프롬프트 건너뛰기 |
--dry-run | patch | 계획을 표시하고 아무것도 쓰지 않음 |
--force | root, patch | 이미 패치된 ramdisk를 다시 패치 |
--no-install | root | Magisk 앱 설치 건너뛰기; 루팅은 이에 의존하지 않음 |
--no-restart | root, trust-chrome | 에뮬레이터나 브라우저를 그대로 둠 |
--timeout 10m | root | 부팅을 기다리는 시간 |
--keep-verity, --keep-forceencrypt | patch | 둘 다 기본적으로 켜져 있음; 비활성화하면 fstab 옵션을 제거 |
--recovery-mode | patch | 복구용으로 패치 (API 28에서 암시됨) |
--cert PATH | trust-chrome | 신뢰할 CA; 생략하면 자동 감지 |
--clear | trust-chrome | 브라우저 신뢰 취소 |
--list | restore, magisk fetch | 실행 대신 목록 표시 |
최신 시스템 이미지의 ramdisk.img는 gzip, lz4 또는 xz로 압축된 cpio newc 아카이브입니다. Android 11+ 이미지는 종종 하나의 압축 스트림 안에 두 개의 아카이브 — 일반 ramdisk와 벤더 ramdisk — 를 연결합니다. 패치는 다음을 의미합니다: