// HackTricks · Mobile

Shizuku Privileged API

Shizuku Privileged API

Shizuku is an open-source service that starts a privileged Java process with app_process and exposes selected Android system APIs over Binder. 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.

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.[1]

Typical use cases:

  • Security auditing from an un-rooted handset
  • On-device package management, debloating and split-APK installation
  • Collecting logs, package metadata and shell-visible network/process state
  • Building PoCs or helper tooling that need ADB-grade access but not a full root chain

1. Starting the privileged service

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.

1.1 Wireless ADB (Android 11+)

  1. Enable Developer Options -> Wireless debugging and pair the device.
  2. Inside the Shizuku app select “Start via Wireless debugging”.
  3. The session survives until reboot unless the OEM ROM kills wireless debugging or revokes the debugging authorisation.

1.2 USB / local ADB one-liner

adb shell sh /sdcard/Android/data/moe.shizuku.privileged.api/start.sh

The same script can be executed over a network ADB connection (adb connect <IP>:5555).

1.3 Rooted devices

If the device is already rooted run:

su -c sh /data/adb/shizuku/start.sh

1.4 OEM quirks that matter during testing

  • MIUI / HyperOS often requires USB debugging (Security settings) in addition to the normal USB debugging toggle.
  • ColorOS / OxygenOS commonly requires disabling Permission monitoring or equivalent security wrappers.
  • On Android 11+, Disable adb authorization timeout reduces random Shizuku loss during long test sessions.
  • If wireless startup keeps failing, allow Shizuku to run in the background; several OEM ROMs suspend local-network discovery when the app is backgrounded.

1.5 Verifying that it is running

adb shell dumpsys activity service moe.shizuku.privileged.api | head
adb shell service list | grep shizuku

A successful start returns a running service and exposes a Binder service related to moe.shizuku.privileged.api.


2. Binding from an application

A Shizuku-enabled app does not use the raw Binder returned by Shizuku as if it were IPackageManager. The normal flow is:[2]

  1. add the Shizuku API permission and ShizukuProvider,
  2. wait for the Shizuku Binder to appear,
  3. request Shizuku’s runtime-style authorisation from the user,
  4. wrap the target system-service Binder with ShizukuBinderWrapper.

Manifest requirements:

<uses-permission android:name="moe.shizuku.manager.permission.API"/>

<provider
    android:name="rikka.shizuku.ShizukuProvider"
    android:authorities="${applicationId}.shizuku"
    android:multiprocess="false"
    android:enabled="true"
    android:exported="true"
    android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" />

Minimal Binder-wrapper example:

Shizuku.addBinderReceivedListenerSticky(() -> {
    if (Shizuku.checkSelfPermission() != PackageManager.PERMISSION_GRANTED) {
        Shizuku.requestPermission(1000);
        return;
    }

    IPackageManager pm = IPackageManager.Stub.asInterface(
        new ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package"))
    );
});

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.

2.1 UserService: when you need more than a single Binder call

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.[2]

Shizuku.UserServiceArgs args = new Shizuku.UserServiceArgs(
    new ComponentName(this, AuditService.class))
    .daemon(false)
    .version(1)
    .processNameSuffix("audit");

Shizuku.bindUserService(args, conn);

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.

2.2 Boundaries that still apply

  • ADB/shell and root are different privilege levels. Shizuku.getUid() returns 2000 for shell-backed sessions and 0 for root-backed sessions.
  • Shell permissions change between Android releases and can also be trimmed by OEMs.
  • Shell still cannot directly read another app’s private sandbox such as /data/user/0/<package>.
  • 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.

3. Rish - elevated shell inside Termux

The Shizuku settings screen exposes “Use Shizuku in terminal apps”. Enabling it downloads rish, which opens a remote privileged shell backed by Shizuku.

pkg install wget
wget https://rikka.app/rish/latest -O rish && chmod +x rish

# start elevated shell (inherits the binder connection)
./rish
whoami   # -> shell
id       # uid=2000(shell) gid=2000(shell) groups=... context=u:r:shell:s0

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.

3.1 Useful commands from the rish shell

  • List running processes of a given package:
    ps -A | grep com.facebook.katana
  • Enumerate listening sockets and map them to packages:
    netstat -tuln
    for pid in $(lsof -nP -iTCP -sTCP:LISTEN -t); do
        printf "%s -> %s\n" "$pid" "$(cat /proc/$pid/cmdline)";
    done
  • Dump every application’s logs exposed to shell:
    logcat -d | grep -iE "(error|exception)"
  • Bulk debloat (example):
    pm uninstall --user 0 com.miui.weather2
  • Inspect users and profile layout before multi-user abuse:
    pm list users
    dumpsys user

3.2 Modern abuse patterns enabled by shell-backed Shizuku

AppOps and special-permission tampering

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:

cmd appops get com.target.app
cmd appops set --uid com.target.app RUN_IN_BACKGROUND ignore
cmd appops set com.target.app SYSTEM_ALERT_WINDOW allow

This is useful during pentests to validate whether an app or MDM agent actually tolerates aggressive AppOps manipulation without requiring root.

Per-app network isolation without VPN or root

Recent Shizuku-based tools such as ShizuWall use the connectivity service’s chain-3 controls to block networking for selected packages:[3]

cmd connectivity set-chain3-enabled true
cmd connectivity set-package-networking-enabled false com.example.agent
cmd connectivity set-package-networking-enabled true com.example.agent

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.

On-device advanced installs and split APK workflows

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.[3]

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.

Work-profile and secondary-user boundaries

Shell-backed Shizuku is still subject to Android’s user restrictions. On managed profiles you will often hit errors such as:

INSTALL_FAILED_USER_RESTRICTED
Shell does not have permission to access user X

If you are specifically testing work-profile bypasses or required-app replacement, keep that material in the dedicated page instead of duplicating it here: Android Enterprise Work Profile Required-App Replacement

Accessibility-assisted local Wireless ADB pairing and Shizuku-style helpers

Android 11+ supports Wireless Debugging pairing by code, and the paired host remains authorised until the user forgets it or revokes ADB debugging authorisations.[6]

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:[4]

  1. A rogue Accessibility service 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.
  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.
  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.

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.[7]

That gives the malware a non-root but still highly privileged execution context that can usually:

  • run arbitrary shell commands as uid 2000
  • grant itself WRITE_SECURE_SETTINGS and modify Settings.Secure / Settings.Global
  • silently install or uninstall APKs
  • grant runtime permissions without normal user approval flows
  • call shell-reachable Binder APIs and capture low-level input events
  • stream the screen through shell-accessible capture paths instead of depending only on MediaProjection consent dialogs

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.

Observed keep-alive enhancements around this pattern include 1x1 foreground activities, silent MediaSession playback, WakeLocks, 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.

Build-specific kernel exploit staging and KernelSU late-load handoff

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.[5]

A robust wrapper usually does all of the following before launching the native payload:

  1. Collect an exact target profile from JNI / shell-visible sources such as getprop, /proc/version, uname, getconf PAGESIZE, and ro.build.display.id.
  2. Match codename + build ID + kernel version + ABI + page size against an explicit allowlist (for example an embedded profiles.json) and abort on mismatch.
  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).
  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.
  5. Stage a ksud binary matching the target KMI and late-load KernelSU:
getprop ro.build.display.id
getconf PAGESIZE
uname -a
ksud late-load --kmi <kmi>

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.

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.


4. Security considerations / detection

  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.
  2. The service registers itself under the name moe.shizuku.privileged.api. 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.
  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.
  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.
  5. High-signal detection ideas for this abuse chain:
    • 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.[7]
    • local ADB TLS/SPAKE2 traffic or pairing attempts against 127.0.0.1, especially to a port just read from the Settings UI.[7]
    • shell-owned helper processes spawned from an app workflow (for example a native library acting as a local privileged server)
    • unexpected writes to Settings.Secure / Settings.Global or silent grants of WRITE_SECURE_SETTINGS
    • suspicious BOOT_COMPLETED receivers that restore debugging state or reload stored ADB keys
    • persistence helpers such as 1x1 activities, silent MediaSession playback, WakeLocks, cross-process BIND_AUTO_CREATE resurrection, writes to /proc/<pid>/oom_score_adj, or native mlock() use
  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.

5. Mitigation

  • Disable USB/Wireless debugging on production devices.
  • Monitor for Binder services exposing moe.shizuku.privileged.api.
  • Enforce work-profile or MDM restrictions that remove debugging features from managed users.
  • Treat Shizuku-compatible tooling as ADB-equivalent during threat modelling; it is a post-exploitation force multiplier even when the device is not rooted.
  • Treat the combination of Accessibility + Wireless debugging + shell-backed Binder helpers as a high-risk chain, not as independent low-severity events.

References