shizuku-privileged-api.md (19182B)
1 --- 2 title: "Shizuku Privileged API" 3 section: "Mobile" 4 sectionSlug: "mobile-pentesting" 5 sourcePath: "src/mobile-pentesting/android-app-pentesting/shizuku-privileged-api.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/mobile-pentesting/android-app-pentesting/shizuku-privileged-api.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Shizuku Privileged API 14 15 Shizuku is an open-source service that **starts a privileged Java process with `app_process`** and exposes selected **Android system APIs over Binder**. 16 Because the process runs with the same **`shell` UID capabilities that ADB uses**, an app that is explicitly authorised by the user can proxy Binder calls to system services **without rooting the device**. 17 18 In practice, this means a Shizuku-enabled app can often exercise the same primitives as `adb shell`: package management, `appops`, `settings`, `cmd connectivity`, log collection, and many other shell-allowed Binder transactions. It is still **not root** and it is still constrained by **Android permissions, Linux UID checks, SELinux policy, Android version, and OEM-specific restrictions**.<sup>[[1]](#references)</sup> 19 20 Typical use cases: 21 * Security auditing from an un-rooted handset 22 * On-device package management, debloating and split-APK installation 23 * Collecting logs, package metadata and shell-visible network/process state 24 * Building PoCs or helper tooling that need **ADB-grade** access but not a full root chain 25 26 --- 27 ## 1. Starting the privileged service 28 29 `moe.shizuku.privileged.api` can be started in three different ways. The Binder interface exposed to client apps is the same, but the effective privilege depends on whether the backend is **ADB/shell** or **root**. 30 31 ### 1.1 Wireless ADB (Android 11+) 32 1. Enable **Developer Options -> Wireless debugging** and pair the device. 33 2. Inside the Shizuku app select **"Start via Wireless debugging"**. 34 3. The session survives until reboot unless the OEM ROM kills wireless debugging or revokes the debugging authorisation. 35 36 ### 1.2 USB / local ADB one-liner 37 ```bash 38 adb shell sh /sdcard/Android/data/moe.shizuku.privileged.api/start.sh 39 ``` 40 The same script can be executed over a **network ADB** connection (`adb connect <IP>:5555`). 41 42 ### 1.3 Rooted devices 43 If the device is already rooted run: 44 ```bash 45 su -c sh /data/adb/shizuku/start.sh 46 ``` 47 48 ### 1.4 OEM quirks that matter during testing 49 * **MIUI / HyperOS** often requires **USB debugging (Security settings)** in addition to the normal USB debugging toggle. 50 * **ColorOS / OxygenOS** commonly requires disabling **Permission monitoring** or equivalent security wrappers. 51 * On Android 11+, **Disable adb authorization timeout** reduces random Shizuku loss during long test sessions. 52 * If wireless startup keeps failing, allow Shizuku to run in the background; several OEM ROMs suspend local-network discovery when the app is backgrounded. 53 54 ### 1.5 Verifying that it is running 55 ```bash 56 adb shell dumpsys activity service moe.shizuku.privileged.api | head 57 adb shell service list | grep shizuku 58 ``` 59 A successful start returns a running service and exposes a Binder service related to `moe.shizuku.privileged.api`. 60 61 --- 62 ## 2. Binding from an application 63 64 A Shizuku-enabled app does **not** use the raw Binder returned by Shizuku as if it were `IPackageManager`. The normal flow is:<sup>[[2]](#references)</sup> 65 1. add the Shizuku API permission and `ShizukuProvider`, 66 2. wait for the Shizuku Binder to appear, 67 3. request Shizuku's runtime-style authorisation from the user, 68 4. wrap the target system-service Binder with `ShizukuBinderWrapper`. 69 70 Manifest requirements: 71 ```xml 72 <uses-permission android:name="moe.shizuku.manager.permission.API"/> 73 74 <provider 75 android:name="rikka.shizuku.ShizukuProvider" 76 android:authorities="${applicationId}.shizuku" 77 android:multiprocess="false" 78 android:enabled="true" 79 android:exported="true" 80 android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" /> 81 ``` 82 83 Minimal Binder-wrapper example: 84 ```java 85 Shizuku.addBinderReceivedListenerSticky(() -> { 86 if (Shizuku.checkSelfPermission() != PackageManager.PERMISSION_GRANTED) { 87 Shizuku.requestPermission(1000); 88 return; 89 } 90 91 IPackageManager pm = IPackageManager.Stub.asInterface( 92 new ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package")) 93 ); 94 }); 95 ``` 96 97 That wrapper is what causes Binder transactions to be forwarded by the Shizuku service process instead of being executed with the caller app's normal UID. 98 99 ### 2.1 UserService: when you need more than a single Binder call 100 For anything more complex than direct Binder transactions, modern Shizuku development prefers **UserService** instead of the old `newProcess` helper. A UserService runs **your own Java/JNI code** in a separate process as **UID 2000 (`shell`)** when Shizuku was started via ADB or **UID 0** when backed by root.<sup>[[2]](#references)</sup> 101 102 ```java 103 Shizuku.UserServiceArgs args = new Shizuku.UserServiceArgs( 104 new ComponentName(this, AuditService.class)) 105 .daemon(false) 106 .version(1) 107 .processNameSuffix("audit"); 108 109 Shizuku.bindUserService(args, conn); 110 ``` 111 112 This is useful for offensive tooling that needs long-lived state, JNI helpers, or repeated Binder operations without paying the cost of spawning shell commands over and over. Remember that the service is **not a normal app process**: some `Context` methods do not behave like they do inside a regular Android application. 113 114 ### 2.2 Boundaries that still apply 115 * **ADB/shell and root are different privilege levels.** `Shizuku.getUid()` returns `2000` for shell-backed sessions and `0` for root-backed sessions. 116 * Shell permissions **change between Android releases** and can also be trimmed by OEMs. 117 * Shell still cannot directly read another app's private sandbox such as `/data/user/0/<package>`. 118 * Hidden API restrictions still apply to code running in the normal app process; if you need non-SDK interfaces extensively, move the logic into a UserService or use a dedicated hidden-API bypass. 119 120 --- 121 ## 3. Rish - elevated shell inside Termux 122 The Shizuku settings screen exposes **"Use Shizuku in terminal apps"**. Enabling it downloads `rish`, which opens a remote privileged shell backed by Shizuku. 123 124 ```bash 125 pkg install wget 126 wget https://rikka.app/rish/latest -O rish && chmod +x rish 127 128 # start elevated shell (inherits the binder connection) 129 ./rish 130 whoami # -> shell 131 id # uid=2000(shell) gid=2000(shell) groups=... context=u:r:shell:s0 132 ``` 133 134 Useful detail for Termux-heavy workflows: when Shizuku runs as ADB/shell, `rish` intentionally avoids preserving Termux's environment by default because the shell user usually cannot traverse Termux-private paths. 135 136 ### 3.1 Useful commands from the `rish` shell 137 * List running processes of a given package: 138 ```bash 139 ps -A | grep com.facebook.katana 140 ``` 141 * Enumerate listening sockets and map them to packages: 142 ```bash 143 netstat -tuln 144 for pid in $(lsof -nP -iTCP -sTCP:LISTEN -t); do 145 printf "%s -> %s\n" "$pid" "$(cat /proc/$pid/cmdline)"; 146 done 147 ``` 148 * Dump every application's logs exposed to shell: 149 ```bash 150 logcat -d | grep -iE "(error|exception)" 151 ``` 152 * Bulk debloat (example): 153 ```bash 154 pm uninstall --user 0 com.miui.weather2 155 ``` 156 * Inspect users and profile layout before multi-user abuse: 157 ```bash 158 pm list users 159 dumpsys user 160 ``` 161 162 ### 3.2 Modern abuse patterns enabled by shell-backed Shizuku 163 164 #### AppOps and special-permission tampering 165 Shizuku-enabled managers such as App Ops or App Manager are effectively wrapping shell-authorised `appops` and package-manager Binder calls. From `rish`, the same primitive can be used directly: 166 167 ```bash 168 cmd appops get com.target.app 169 cmd appops set --uid com.target.app RUN_IN_BACKGROUND ignore 170 cmd appops set com.target.app SYSTEM_ALERT_WINDOW allow 171 ``` 172 173 This is useful during pentests to validate whether an app or MDM agent actually tolerates aggressive AppOps manipulation without requiring root. 174 175 #### Per-app network isolation without VPN or root 176 Recent Shizuku-based tools such as ShizuWall use the `connectivity` service's **chain-3** controls to block networking for selected packages:<sup>[[3]](#references)</sup> 177 178 ```bash 179 cmd connectivity set-chain3-enabled true 180 cmd connectivity set-package-networking-enabled false com.example.agent 181 cmd connectivity set-package-networking-enabled true com.example.agent 182 ``` 183 184 For assessments, this gives you a fast way to test how a target app behaves when a competing security, telemetry or management package is selectively cut off from the network while the rest of the device remains online. The state is cleared on reboot. 185 186 #### On-device advanced installs and split APK workflows 187 Modern Shizuku installers such as InstallWithOptions or InstallerX-Revived use shell-backed `PackageInstaller` access to perform operations that are otherwise awkward from a normal app: split APK installs, test-only packages, batch installs, and some Android 14 package-install flags.<sup>[[3]](#references)</sup> 188 189 From an offensive-testing point of view, the important part is not the GUI but the primitive: **Shizuku turns package installation back into an on-device shell-authorised action**, which is useful for persistence tests, downgrade checks and rapid deployment of helper payloads on a non-rooted handset. 190 191 #### Work-profile and secondary-user boundaries 192 Shell-backed Shizuku is still subject to Android's user restrictions. On managed profiles you will often hit errors such as: 193 194 ```text 195 INSTALL_FAILED_USER_RESTRICTED 196 Shell does not have permission to access user X 197 ``` 198 199 If you are specifically testing work-profile bypasses or required-app replacement, keep that material in the dedicated page instead of duplicating it here: 200 [Android Enterprise Work Profile Required-App Replacement](/hacktricks/mobile-pentesting/android-app-pentesting/android-enterprise-work-profile-bypass) 201 202 #### Accessibility-assisted local Wireless ADB pairing and Shizuku-style helpers 203 204 Android 11+ supports Wireless Debugging pairing by code, and the paired host remains authorised until the user forgets it or revokes ADB debugging authorisations.<sup>[[6]](#references)</sup> 205 206 Some Android RATs now replicate the **Shizuku architecture** instead of waiting for the user to start Shizuku explicitly. The interesting part is the **attack chain**, not Shizuku itself:<sup>[[4]](#references)</sup> 207 208 1. A rogue [Accessibility service](/hacktricks/mobile-pentesting/android-app-pentesting/accessibility-services-abuse) navigates Settings, taps the build number seven times, enables **Developer Options -> Wireless debugging**, opens **Pair device with pairing code**, and reads the code directly from the UI tree while an overlay hides the workflow. 209 2. An embedded ADB client then pairs with the same handset's own `adbd` over **`127.0.0.1`**, so the phone becomes both the **ADB host and target** with no PC or USB cable involved. 210 3. After pairing, the malware launches a helper process under **UID 2000 (`shell`)** and talks to it over **Binder IPC** exactly like a Shizuku-enabled app would talk to a shell-backed UserService. 211 212 A protocol-level variant automates the pairing dialog itself: Accessibility launches `Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS`, enables Wireless Debugging, and polls the **Pair device with pairing code** modal for both its dynamic port and six-digit secret. An embedded client then connects to `127.0.0.1:<port>`, establishes TLS, performs the PIN-backed SPAKE2 exchange, authenticates its generated ADB key pair, exchanges peer metadata, and finally submits ADB commands in the `shell` context. This is **not root**, and the exact post-pairing commands must be recovered from the sample or runtime traffic because the public analysis did not publish them.<sup>[[7]](#references)</sup> 213 214 That gives the malware a non-root but still highly privileged execution context that can usually: 215 216 - run arbitrary shell commands as `uid 2000` 217 - grant itself `WRITE_SECURE_SETTINGS` and modify `Settings.Secure` / `Settings.Global` 218 - silently install or uninstall APKs 219 - grant runtime permissions without normal user approval flows 220 - call shell-reachable Binder APIs and capture low-level input events 221 - stream the screen through shell-accessible capture paths instead of depending only on MediaProjection consent dialogs 222 223 This matters during assessments because a previously one-time Wireless Debugging approval can be converted into an **on-device privilege broker**. If the malware stores ADB pairing material, a `BOOT_COMPLETED` receiver can restore Wireless Debugging, reconnect to local `adbd`, and respawn the shell helper after every reboot. 224 225 Observed keep-alive enhancements around this pattern include **1x1 foreground activities**, silent `MediaSession` playback, `WakeLock`s, two services in different processes that rebind each other with `BIND_AUTO_CREATE` / `onServiceDisconnected()`, periodic restart alarms, writes to `/proc/<pid>/oom_score_adj`, and `mlock()` to pin hot pages in RAM. 226 227 #### Build-specific kernel exploit staging and KernelSU late-load handoff 228 Another practical pattern is to use **shell-backed Shizuku only as the staging bridge** for a **build-specific local kernel exploit**, then hand the post-root workflow to **KernelSU/ReSukiSU**.<sup>[[5]](#references)</sup> 229 230 A robust wrapper usually does all of the following **before** launching the native payload: 231 232 1. Collect an **exact target profile** from JNI / shell-visible sources such as `getprop`, `/proc/version`, `uname`, `getconf PAGESIZE`, and `ro.build.display.id`. 233 2. Match **codename + build ID + kernel version + ABI + page size** against an explicit allowlist (for example an embedded `profiles.json`) and **abort on mismatch**. 234 3. Use a Binder-bound **Shizuku UserService** or similar helper to extract the matching native payload into **`/data/local/tmp`** and execute it as **UID `2000` (`shell`)**. 235 4. If the exploit succeeds, immediately convert the one-shot kernel primitive into a **reusable local root channel** such as a privileged daemon or **Unix-domain socket** (for example `temp_su.sock`) so later steps do not need to rerun the kernel exploit. 236 5. Stage a `ksud` binary matching the target **KMI** and late-load KernelSU: 237 238 ```bash 239 getprop ro.build.display.id 240 getconf PAGESIZE 241 uname -a 242 ksud late-load --kmi <kmi> 243 ``` 244 245 This pattern is useful because **Shizuku gives reliable ADB/shell execution and file-placement primitives on non-rooted devices**, while the fragile build-dependent exploit is kept inside a native payload selected only for the exact firmware. After the root channel is up, the workflow can verify KernelSU activation by checking artifacts such as **`/dev/kernelsu`**, **`/sys/kernel/kernelsu`**, and **`/data/adb/ksu`**. 246 247 The same design is also a good detection model: watch for **Shizuku-authorised apps dropping native helpers into `/data/local/tmp`**, launching shell-owned payloads, creating local privileged sockets, and then invoking **`ksud late-load --kmi ...`** or triggering a **soft reboot / `system_server` restart** to stabilize the new root environment. 248 249 --- 250 ## 4. Security considerations / detection 251 1. Shizuku needs **ADB debugging** or **root** first, so _Developer Options -> USB/Wireless debugging_ must be enabled on non-rooted devices. Unexpected enablement of **Developer Options**, **Wireless debugging**, or pairing-code dialogs on a production handset is already a strong signal. 252 2. The service registers itself under the name `moe.shizuku.privileged.api`. 253 `adb shell service list | grep shizuku` and `adb shell dumpsys activity service moe.shizuku.privileged.api` are reliable quick checks for benign tooling; malware variants may instead expose their own shell-owned Binder helper or native server. 254 3. Capabilities are limited to what the current backend has. On ADB-backed sessions, that means the effective attack surface is the one exposed to **`com.android.shell`** on that Android build, plus whatever SELinux permits. 255 4. A normal Shizuku session does **not** survive a reboot unless the device is rooted and Shizuku is configured as a startup daemon. However, malware that stores ADB pairing keys and can re-enable Wireless Debugging (for example via Accessibility + `WRITE_SECURE_SETTINGS` / `Settings.Global` abuse) may reconnect to local `adbd` after boot and recreate the shell helper without root. 256 5. High-signal detection ideas for this abuse chain: 257 - correlate Accessibility-driven taps on **Build number**, an `APPLICATION_DEVELOPMENT_SETTINGS` launch, Wireless Debugging activation, and immediate scraping of a six-digit pairing modal; this sequence is much stronger than any event alone.<sup>[[7]](#references)</sup> 258 - local ADB TLS/SPAKE2 traffic or pairing attempts against **`127.0.0.1`**, especially to a port just read from the Settings UI.<sup>[[7]](#references)</sup> 259 - shell-owned helper processes spawned from an app workflow (for example a native library acting as a local privileged server) 260 - unexpected writes to `Settings.Secure` / `Settings.Global` or silent grants of `WRITE_SECURE_SETTINGS` 261 - suspicious `BOOT_COMPLETED` receivers that restore debugging state or reload stored ADB keys 262 - persistence helpers such as `1x1` activities, silent `MediaSession` playback, `WakeLock`s, cross-process `BIND_AUTO_CREATE` resurrection, writes to `/proc/<pid>/oom_score_adj`, or native `mlock()` use 263 6. OEM "security" layers often break or silently reduce Shizuku functionality. If a command works via direct `adb shell` but fails through Shizuku, compare the current backend UID (`Shizuku.getUid()`), OEM debugging toggles, and whether the device trimmed shell permissions. 264 265 --- 266 ## 5. Mitigation 267 * Disable USB/Wireless debugging on production devices. 268 * Monitor for Binder services exposing `moe.shizuku.privileged.api`. 269 * Enforce work-profile or MDM restrictions that remove debugging features from managed users. 270 * Treat Shizuku-compatible tooling as **ADB-equivalent** during threat modelling; it is a post-exploitation force multiplier even when the device is not rooted. 271 * Treat the combination of **Accessibility + Wireless debugging + shell-backed Binder helpers** as a high-risk chain, not as independent low-severity events. 272 273 --- 274 ## References 275 276 - [1] [Shizuku Official Documentation](https://shizuku.rikka.app/) 277 - [2] [Shizuku-API Developer Guide](https://github.com/RikkaApps/Shizuku-API) 278 - [3] [awesome-shizuku - list of supported apps](https://github.com/timschneeb/awesome-shizuku) 279 - [4] [RedHook Returns with a Dangerous Upgrade](https://www.group-ib.com/blog/redhook-android-rat-upgraded/) 280 - [5] [Root My Pixel: Automated Temporary Root and KernelSU Late Loading on Google Pixel Devices](https://github.com/alex193a/Root-My-Pixel) 281 - [6] [Android Debug Bridge: Connect to a device over Wi-Fi](https://developer.android.com/tools/adb#connect-to-a-device-over-wi-fi) 282 - [7] [ToxicPanda Never Sleeps: ToxicPanda 2.0 Prepares Its Next Mobile Strike](https://zimperium.com/blog/the-toxicpanda-never-sleeps-toxicpanda-2.0-prepares-its-next-strike-on-mobile)