Skip to content

Dealing with BLOBs found in APK signing blocks

This is a continuation of #475 (closed), especially this comment chain. SigningBlock BLOBs are now recorded to the apkcheck.db silently, but how should they be dealt with? Summing up, there are two kinds of them:

Payload BLOBs

For now we know about the MEITAN_APK_CHANNEL_BLOCK, which is used it for payload. This should be considered a no-go for inclusion. Luckily, no app in the repo yet was found to have it.

Google BLOBs

The others are by Google, and only of interest for their Play Store:

GOOGLE_BLOCKS = dict(
    DEPENDENCY_INFO_BLOCK=0x504b4453,
    GOOGLE_PLAY_FROSTING_BLOCK=0x2146444e,
    SOURCE_STAMP_V1_BLOCK=0x2b09189e,
    SOURCE_STAMP_V2_BLOCK=0x6dff800d,
)

The DEPENDENCY_INFO_BLOCK can easily be avoided by using apksigner to sign APKs, which doesn't include it at all. Apart from Google itself, Android Studio and IntelliJ IDEA are known to include them, where this can be disabled via build.gradle / build.gradle.kts:

android {
    dependenciesInfo {
        // Disables dependency metadata when building APKs.
        includeInApk = false
        // Disables dependency metadata when building Android App Bundles.
        includeInBundle = false
    }
}

As its name suggests, that BLOB is supposed to be just a binary representation of your app's dependency tree. But as it's encrypted with a public key belonging to Google, only Google can read it – and nobody else can even verify what it contains.

Also suggested by it's name, the GOOGLE_PLAY_FROSTING_BLOCK is only useful for Google's Play Store (and most likely applied only with Google-Signing).

The frosting block is added by Play Store, so it proves that particular file was downloaded from Play Store, but not all APKs have it yet - APKs that were not updated recently are missing it.

Curiously, the frosting includes a metadata chunk encoded using protbuf. The structure is rather complex, it contains data like signing timestamp, versionCode, minSdkVersion and many more.

(source)

SOURCE_STAMP_V2_BLOCK and its companion are referenced in SourceStampVerifier.java:

SourceStamp improves traceability of apps with respect to unauthorized distribution.

The stamp is part of the APK that is protected by the signing block.

The APK contents hash is signed using the stamp key, and is saved as part of the signing block.

Quoting another source:

For apps uploaded as app bundles, we will improve this security by introducing what is called a source stamp. This source metadata is inserted into the app’s manifest by bundletool. When the APK is generated on Play’s server, it’s also signed with a Google key in addition to your app signing key.

This means the security metadata cannot be removed or tampered with without invalidating the Google signature. This gives a high confidence signal that unmodified APKs containing the source stamp must have come from Google Play.

So it's clear this is only used by Apps that "have come from Google Play".

How to deal with those?

  • at the very least, app authors should be made aware of them and suggested to keep them out of FOSS distributions like this repo.
  • The Maituan one (and similar ones should they be found) must be considered as a show-stopper
  • all of them should probably made transparent (as it's currently already done with permissions, sensitive flags and sensitive intent filters)
  • anything else?