androidSigning

📌What is Signing?

Android application signing refers to the process of digitally signing Android app packages (APKs) using cryptographic keys. This is an essential security practice in the Android ecosystem to ensure the integrity and authenticity of apps distributed through the Google Play Store and other app distribution channels.

📍Why do we need this process?

  • Imagine you have an application that wants to check if there is a new update on Google Play Store

    How can we make sure that this update is for the same application?

    The package name? Of course not, because the package name is only a unique identifier for the app on our device, not on the Play Store. So, how can we ensure that this app is from the same developer? Here comes the role of signing.

    The developer creates a private key and uses it to sign the app. This process distinguishes the application from any other app. Now, when the application checks with the Google Play Store for updates, the Play Store can verify that both the installed app and the update are signed with the same key. If they are, it confirms that they are from the same developer and have the same package name, allowing the update to proceed.

  • Exchange data based on the signing process

    • Some developers don’t make components "exported." Instead, they enable applications signed with the same certificate to share data with each other.

📍How is signing done?

Here's how the process generally works:

  1. Key Generation: When you develop an Android app, you generate a pair of cryptographic keys: a private key and a corresponding public key. The private key is kept secure and should never be shared, while the public key is included in the app.

  2. Signing the APK: Before releasing your app, you use the private key to digitally sign the APK. This process generates a cryptographic signature that is embedded within the APK. This signature is unique to your app and your private key.

  3. Distribution: The signed APK is then distributed to users through platforms like the Google Play Store. When users download and install the app, the Android operating system verifies the signature using the public key embedded in the app.

  4. Verification: The Android system verifies that the signature matches the app's content and that it was signed by a trusted source. If the signature is valid, the system knows that the app has not been tampered with (will) and is the same version that the developer released.

📍How to sign an application

Remember the spacepeng game we used in the decompiling section?

After rebuilding the app using apktool, a new application was generated. However, when you tried to install it, you struggled and couldn’t.

This is due to the signing process—the application has no signing certificate.

So, what do we need now to sign our application?

  • Steps to follow:

    1. Decompile the app: apktool d app.apk

    2. Make modifications: Edit the app as needed.

    3. Rebuild the app: Once modifications are complete, rebuild the app with apktool b app.

    4. Sign the app: Use tools like keytool, zipalign, and apksigner to sign the app.

    5. Install and use the app

📍 Let’s put our hands on this

  1. We have our rebuilt APK base.apk, but we can’t install it.

  2. Using keytool, create a certificate and store it in a keystore file keystore.

  • Command explanation

    • keytool: The Java tool to manage keys and certificates.

    • genkey: Generates a new key pair.

    • v: Enables verbose output. (it's printing a certificate in a human-readable form.)

    • keystore ./my-release-key.keystore: This specifies the name and location of the keystore file you're creating. In this case, it's named my-release-key.keystore and will be saved in the current directory (./).

    • alias space: Sets the alias name for the key (used for referencing).

    • keyalg RSA: Specifies the key algorithm as RSA.

    • keysize 2048: Sets the size of the key to 2048 bits.

    • validity 10000: Sets the validity of the key to 10,000 days.

    • sigalg SHA1withRSA: Specifies the signature algorithm as SHA1 with RSA.

  1. Use zipalign tool to optimize the alignment and memory usage of Android app packages (APKs).

    • Command explanation

      • zipalign: Aligns APK file data to improve runtime performance.

      • v: Enables verbose output.

      • 4: Specifies the alignment value (4 bytes).

      • base.apk: The input APK file.

      • out.apk: The optimized output APK.

  2. Use apksigner to sign the optimized APK out.apk with the certificate created using keytool.

  3. Now install the signed APK


📌META-INF directory

The META-INF directory contains information about the certificate and application signing, located at the path original/META-INF. It contains these three files:

1- MANIFEST.MF file

  • This is the manifest file.

  • It contains the names of all the files in the app and their SHA1 digest values.

📍Let’s take the file assets/music/game.ogg as an example.

The value pAkhCMRnbpC6yEF6jlfAH+J01pQ= appears to be a Base64-encoded hash.

Output:

To produce a plain hex dump of this binary value, we can use the xxd command with the -p flag:

Now we have the SHA1 hash value of the file assets/music/game.ogg.

To confirm this, let’s calculate the SHA1 hash of the file directly and compare it with the value in the manifest:

The output matches the Base64 value in the manifest file, indicating that the file has not been tampered with.

2- The signature file SPACE.SF

  • Contains a list of names/hashes of the corresponding lines in the MANIFEST.MF file.

  • The purpose of this file is to ensure that the application or its files are intact and not tampered with or corrupted.

  • At first glance, this file appears similar to the MANIFEST.MF file, as it has the same structure with file names and SHA1-digests.

  • However, there’s a key difference:

    If you compare the SHA1-digests for the same file (e.g., AndroidManifest.xml) between the .sf file and the MANIFEST.MF file, you’ll notice different hash values.

    This is because the SHA1-digest in the .sf file is calculated from the hash of the name and SHA1-digest pair in the MANIFEST.MF file.

The .sf and .mf files are critical for tamper detection and file corruption detection in Android applications.

3- The signature file SPACE.RSA file

  • This file contains the public key and the signature of SPACE.SF.

  • It holds public information, which means these data cannot be directly used to modify or tamper with the application.

  • To view the contents of this file, use the following command:

  • Output:


📌 Blue box master key vulnerability

  • What would happen if we modify an existing application by changing the application content but keeping the same original signature?

    • If we change any value in the APK’s file and try to install it again, an error will occur due to changes in the file content.

    The error here occurs because of the MANIFEST.MF file.
    • What if we calculate the new hash value of the file, update it in the MANIFEST.MF file, and modify the .SF file accordingly?

      • If we try to install it again, an error will appear, but this time it will not be because of the MANIFEST.MF file.

      • The issue lies with signature verification since the system detects that the app has been tampered with. This cannot be fixed without the developer's private key.

    When an app is signed by its developer using a private key, a unique cryptographic signature is generated and embedded within the APK. This signature is computed based on the contents of the APK and the developer's private key.

What Happens If We Add a New File to the Application?

  1. Adding a completely new file:

    • Adding new files doesn’t work because they are not included in the hash and signature validation.

  2. Adding a file with the exact same name:

    • For example, if we add a new classes.dex file, the file size changes, meaning the file has been overwritten. This method does not work either.

  3. Adding a file with a different name and modifying it afterward:

  • Let’s say we add a new file named classez.dex while keeping the original classes.dex.

  • Then, we open the APK file in a hex editor like ghex and replace all occurrences of classez with classes.

  • After this step, the APK contains two files named classes.dex, and our modified file will override the original one.

  • By doing this, an attacker can introduce completely new source code into the application.

The vulnerability lies in having two files with the exact same name in the ZIP archive. When this happens, the system installs the last file added (the one added by the attacker) and ignores the original file. This allows attackers to inject malicious code into the APK.


Last updated