Apktool

repository·main·Indexed 12 days ago

https://github.com/ibotpeaches/apktool

A specialized reverse engineering tool for third-party, closed, binary Android applications. It allows users to decode resources, modify them, and rebuild APKs, facilitating tasks such as localization, debugging smali code, and platform customization. Supports Apktool 2.x and 3.x releases.

Tokens
2.6K
Snippets
9
Records
15
Agent score
98%

What's inside Apktool

  1. Overview of Apktool

    main

    Apktool is a reverse engineering tool for third-party, closed, binary Android applications. It allows developers to:

    • Decode resources: Convert Android resources back to a nearly original form.
    • Rebuild apps: Recompile modified applications.
    • Debug smali code: Facilitate step-by-step debugging of smali code.
    • Automate tasks: Manage project-like file structures and automate repetitive tasks like building APKs.

    It is intended for legal purposes such as localization, adding features, or adding support for custom platforms.

  2. Build modified aapt2 binaries

    main

    To build the modified aapt2 binaries used by Apktool, you must first obtain the AOSP source and integrate the modified frameworks/base repository. The frameworks/base repository contains specific changes (like disabling optimizations) to ensure Apktool keeps APKs as close to the original as possible.

    1. Get the modified frameworks/base repo

    Use the platform_frameworks_base repository. Branches follow the Android version naming convention (e.g., apktool_7.1 for Android 7.1).

    To include the modified package in your AOSP source:

    1. cd frameworks/base
    2. git remote add origin git@github.com:iBotPeaches/platform_frameworks_base.git
    3. git fetch origin -v
    4. git checkout origin/apktool-{x} (replace {x} with the target version)

    2. Prepare AOSP Source

    Download the AOSP source (requires 150-250GB). To optimize the clone size, use:

    # Partial clone
    ~/bin/repo init -u https://android.googlesource.com/platform/manifest -b android16-release --partial-clone
    # Sync only the current branch
    repo sync -c

    3. Build the aapt2 binary

    Steps vary by operating system. Ensure you have performed the initial AOSP build first.

    Linux / Windows

    source build/envsetup.sh
    lunch aosp_cf_x86_64_only_phone-aosp_current-eng
    m aapt2
    strip out/host/linux-x86/bin/aapt2
    strip out/host/linux-x86/bin/aapt2_64
    strip out/host/windows-x86/bin/aapt2.exe
    strip out/host/windows-x86/bin/aapt2_64.exe

    Mac

    Note: If building on a recent macOS, you may need to patch build/soong/cc/config/darwin_host.go by adding your current SDK version to the darwinSupportedSdkVersions array.

    export ANDROID_JAVA_HOME=/Path/To/Jdk
    source build/envsetup.sh
    lunch aosp_cf_x86_64_only_phone-aosp_current-eng
    m aapt2
    strip out/host/darwin-x86/bin/aapt2_64

    4. Verify Static Builds

    To ensure dependencies like libc++ are built statically and not shared, verify the binaries using:

    • Unix: ldd <binary_path>
    • Mac: otool -L <binary_path>
    source build/envsetup.sh
    lunch aosp_cf_x86_64_only_phone-aosp_current-eng
    m aapt2
    strip out/host/linux-x86/bin/aapt2
  3. Configure Maven publishing for Apktool

    main

    Apktool supports publishing to Maven, allowing plugin authors to integrate it directly. To enable this, create a gradle.properties file in the root directory with the following structure:

    signing.keyId={gpgKeyId}
    signing.password={gpgPassphrase}
    signing.secretKeyRingFile={gpgSecretKeyRingLocation}
    
    mavenCentralUsername={sonatypeUsername}
    mavenCentralPassword={sonatypePassword}

    Setup Requirements:

    • Generate a secret key ring: gpg --export-secret-keys -o ~/.gnupg/secring.gpg
    • Generate a Maven password via Sonatype User Token.

    To execute the release to Maven, run:

    ./gradlew build shadowJar release publish
    signing.keyId={gpgKeyId}
    signing.password={gpgPassphrase}
    signing.secretKeyRingFile={gpgSecretKeyRingLocation}
    
    mavenCentralUsername={sonatypeUsername}
    mavenCentralPassword={sonatypePassword}
  4. Build the Apktool binary

    main

    Building Apktool and publishing Maven artifacts requires JDK 17+.

    To ensure a clean build, start by running gradlew clean. Then, build the new binary version using the following command:

    ./gradlew build shadowJar proguard release

    Verify that the build output matches the version specified in your recent commits. The output should look similar to: Building RELEASE (main): 2.2.2

    ./gradlew build shadowJar proguard release
  5. Tag a new Apktool release

    main

    To release a new version, you must first update the versioning in build.gradle.

    1. Locate the version and suffix variables in build.gradle.
    2. Keep the version variable as the target version (e.g., 2.2.2).
    3. Remove the SNAPSHOT value from the suffix variable so it is blank.
    4. Commit this single change with the message: version bump (x.x.x).
    5. Create a signed git tag using the following command format:
    git tag -a vx.x.x -m "changed version to vx.x.x" -s

    Example for version 2.2.1:

    git tag -a v2.2.1 -m "changed version to v2.2.1" -s
    git tag -a v2.2.1 -m "changed version to v2.2.1" -s
  6. Use Gradle tips and tricks for Apktool builds

    main

    When developing or building Apktool, use these Gradle commands to optimize your workflow.

    Fast builds (skipping tests)

    To perform a quick build without running the test suite (which typically takes 2-4 minutes), use:

    ./gradlew build shadowJar proguard -x test

    Debugging the test suite

    To enable the debugger on the test suite (starts the debugger on port 5005 for connection via IntelliJ):

    ./gradlew test --debug-jvm

    Running specific tests

    To run a specific test within the apktool-lib project, use the --tests flag with a wildcard pattern. This is useful for isolating new tests.

    Run a specific test:

    ./gradlew :brut.apktool:apktool-lib:test --tests "*BuildAndDecodeTest"

    Run and debug a specific test:

    ./gradlew :brut.apktool:apktool-lib:test --tests "*BuildAndDecodeTest" --debug-jvm
    ./gradlew build shadowJar proguard -x test
  7. Push release changes to remote repositories

    main

    Once the release is prepared and tagged, push the changes to both GitHub and Bitbucket:

    # Push to GitHub
    git push origin main
    git push origin vx.x.x
    
    # Push to Bitbucket
    git push bitbucket master
    git push bitbucket vx.x.x
    git push origin main
    git push origin vx.x.x
    git push bitbucket master
    git push bitbucket vx.x.x
  8. Verify binary integrity with MD5 and SHA256 hashes

    main

    After building the binary, name the jar file using the pattern apktool_x.x.x.jar (e.g., apktool_2.2.2.jar).

    Before uploading to any distribution platform, you must record the local MD5 and SHA256 hashes to ensure all remote copies match. Use md5sum and sha256sum on Unix systems:

    md5sum apktool_2.2.2.jar
    sha256sum apktool_2.2.2.jar

    These local hashes are the source of truth. All versions uploaded to Bitbucket, GitHub, or mirrors must match these exactly.

    md5sum apktool_2.2.2.jar
    sha256sum apktool_2.2.2.jar
  9. Reporting Security Vulnerabilities

    main
    If you discover a security vulnerability within Apktool, do not report it via public issues. Instead, send an email directly to Connor Tumbleson at connor.tumbleson(at)gmail.com to ensure the vulnerability is addressed promptly and privately.
  10. Manage Apktool frameworks

    main

    Apktool uses framework files to decode resources correctly. You can manage these files using the following commands:

    • if or install-framework <apk-file>: Install a framework from an APK file.
    • cf or clean-frameworks: Clean the framework directory.
    • lf or list-frameworks: List all installed frameworks.
    • pr or publicize-resources <arsc-file>: Publicize resources from an .arsc file.

    Framework management flags:

    • -p, --frame-path <dir>: Set the path for framework files to <dir>.
    • -t, --frame-tag <tag>: Suffix framework files with <tag> or use files tagged with <tag>.
    • -a, --all: (For cf and lf) Include all framework files regardless of tag.