background

Android APK Signature Scheme V2 Signature and a verification tool based on Java environment. The idea is to check if the ZIP Central Directory of an APK contains the APK Signing Block that is required for V2 signatures, and if so, verify that its V2 signatures are authenticated.

After you have the tools to write, the official signature verification tools developer Alex email contact I told the official apksig is already offered a similar tool, corresponding to the source code for: android.googlesource.com/platform/to… “, but because the tools already exist, and communicate with him he said that the direct use of Android source code can also work, so I did not carefully compare the official implementation and their own scheme. The validation tool is not optimized against the official code.

Phenomenon of the problem

After the tool was written, I scanned the applications in the application library and found that many applications had problems. At that time, I judged that the tools I wrote were effective. Sampling inspection found that they could not be installed on devices above 7.0.

On my last day at work years ago, I got feedback from a developer and found that there was no problem with the application using the tool

➜ Java - jar ~ / lib/CheckAndroidV2Signature jar. / test. The apk {" ret ": 0," MSG ":" ok ", "isV2" : false, "isV2OK" : false}Copy the code

However, it cannot be installed on a machine running Android 7.0 or higher, causing an error

➜  adb install ./test.apk
Failed to install test.apk Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from /data/app/vmdl2077545153.tmp/base.apk: META-INF/YSDK.SF indicates /data/app/vmdl2077545153.tmp/base.apk is signed using APK Signature Scheme v2, but no such signature was found. Signature stripped?]Copy the code

There is a problem with using the official tool to verify after getting the APK of the application. The following is the result of using the official tool to verify:

$ANDROID_HOME/build-tools/25.0.0/apksigner verify. /test.apk DOES NOT verify ERROR: JAR signer ysdk. RSA: JAR signature META-INF/YSDK.SF indicates the APK is signed using APK Signature Scheme v2 but no such signature was found. Signature stripped?Copy the code

After unpacking the apK, the summary file in the meta-INF folder contains the following fields:

X-Android-APK-Signed: 2Copy the code

The signature summary file marks the app as using Android V2 signatures, but the APK Signing Block required for V2 signatures is missing.

Since the Spring Festival holiday is coming soon, there is not enough time to make detailed positioning of the problem, so we can only solve the problem temporarily. – Adjusted the validation scheme to check if an APK ZIP Central Directory contains the APK Signing Block required for V2 signatures or if x-Android-apk-signed is defined as 2 in the summary file. If there is a signature block or the signature is 2, it indicates that the packet is signed by V2. Then check whether the V2 signature verification succeeds.

Check the problematic APK after modifying the tool

➜ Java - jar ~ / lib/CheckAndroidV2Signature jar. / test. The apk {"ret":-3,"msg":"com.bihe0832.checksignature.ApkSignatureSchemeV2Verifier$SignatureNotFoundException: No APK Signing Block before ZIP Central Directory","isV2":true,"isV2OK":false}Copy the code

Well, although the reason has not been found, it seems that this kind of problematic APK can be filtered through this method. After using the optimized tool, I found that there was a very large number of applications with this problem. I suspected that there was something wrong with the tool for a while, but only after the sampling test verified that there was indeed something wrong with the tool did I feel relieved to go home for the holiday.

Problem analysis

Because found that almost all use the V2 signature but the inspection without the APK are because developers to use the old channel bag packaging, but did not understand the V2 signature and the application of the problem through the sweep out the quantity is very large, so the individual preliminary think this APK is supposed to be caused by using a special change package way, And it’s very popular among developers, it’s very widely used.

At present, the most widely used methods of content injection in APK mainly include:

Decompile and add content before signing it

In this case, the signature will not be affected in principle. Could it be caused by V2 packaging and Jarsigner signature after injection? So I chose a package made with V2, and checked it with the tool first:

➜ Java - jar ~ / lib/CheckAndroidV2Signature jar. / test. The apk {" ret ": 0," MSG ":" ok ", "isV2" : true, "isV2OK" : true}Copy the code

Then decompile APK

➜ Java -jar -duser. language= en-duser. home=$ANDROID_HOME/build-tools/25.0.2 ~/lib/apktool.jar d -f./test.apkCopy the code

Add the channel. TXT file to the Assets folder and repackage it and sign it with Jarsigner

➜ java-jar-duser. language= en-duser. home=$ANDROID_HOME/build-tools/25.0.2 ~/lib/apktool.jar b -o ~/ a.apk. /test/ 1 Jarsigner -verbose -keystore ~/lib/ysdk.keystore -signedjar./test.apk./a.apk 'ysdk' enter the password phrase of the keystore: adding: Meta-inf/manifest.mf Adding: meta-INF/ysdk. SF Adding: meta-INF/ysdk. RSA signing: androidmanifest.xml …………Copy the code

Then use the tool to verify

➜ Java - jar ~ / lib/CheckAndroidV2Signature jar. / test. The apk {" ret ": 0," MSG ":" ok ", "isV2" : false, "isV2OK" : false}Copy the code

That is, a package with a full V1 signature will not be a problem, so you can be sure that this is not the cause.

Add content directly to the comment section of the ZIP package

The Signing Block for this package does not break the APK Signing Block for the V2 package, and it can be verified using the first version of the tool.

➜ Java - jar ~ 1 / lib/CheckAndroidV2Signature jar. / test. The apk {" ret ": 0," MSG ":" get people failed, throw an SecurityException","isV2":true,"isV2OK":false}Copy the code

Through the scriptMETA-INFFolder injection content

This scheme is easy to implement and has strong operability, so it is widely used. Its core principle is to first generate a signed package, and then use a script to inject a file in the META-INF folder. The content or file name of the file is the information to be injected APK. Since injecting content into the META-INF folder does not break the APK signature under the V1 signature, this method and the above comment section addition method are widely used by developers in specific development. Let’s try this with a script:

The injection script is used to stream data into a channel_ file in the meta-INF folder, where the channel number is stored. Because injection is not the focus, we do not specify how scripts run.

#! /usr/bin/python # coding= UTf-8 import zipfile import shutil import OS import sys # targetApkNamePrefix = If len(sys.argv) < 2: if len(sys.argv) < 2: if len(sys.argv) < 2: print("\n\tplease enter the apk name as command para like:") print("\n\tpython MultiChannelBuildTool.py ./test.apk") os._exit(0) src_apk = sys.argv[1]; extension = os.path.splitext(src_apk)[1][1:] if extension ! = 'apk': Print ("first para must be the apk with extension name") src_apk_file_name = os.path.basename(src_apk) # Splitext (src_apk_file_name) # name without extension src_apk_name = temp_list[0] # Such as: Output_dir = 'bin_' + src_apk_name + '/' # Create if not if directory does not exist os.path.exists(output_dir): Os.mkdir (output_dir) # splice apk target_APk = output_DIR + targetApkNamePrefix + "_" + target_channel + "_" + TargetApkVersion + src_apk_extension # copy shutil.copy(src_apk, Zipfile = zipfile. zipfile (target_apk, 'a', Empty_channel_file = "meta-INF /channel_{channel}". Format (channel=target_channel) # Zipped. Writestr (empty_channel_file, target_channel + "\n") #Copy the code

After the script is OK, we select the test application and use the tool to check first. There is no problem

➜ Java - jar ~ / lib/CheckAndroidV2Signature jar test. The apk {" ret ": 0," MSG ":" ok ", "isV2" : true, "isV2OK" : true}Copy the code

Then run the command to inject the content:

➜ 1 Python./test.py./test.apk is packagedCopy the code

Use a script to validate the generated APK

➜ Java - jar ~ 1 / lib/CheckAndroidV2Signature jar. / bin_test YSDK - TEST_channel1_v1. 0.0 the apk {"ret":-3,"msg":"com.bihe0832.checksignature.ApkSignatureSchemeV2Verifier$SignatureNotFoundException: No APK Signing Block before ZIP Central Directory","isV2":true,"isV2OK":false}Copy the code

Magically, the problem recurs

*.SF file: *.SF file: *.SF file: *.SF file: *.

X-Android-APK-Signed: 2Copy the code

At this point the problem was finally determined, after finding a way to reproduce, the cause of the problem is easy to understand ~

The problem summary

When it is determined that the APK validation is invalid because of injecting content into the META-INF folder, it is immediately understandable why this is the case.

  1. The application uses V2 to sign out the package, so the entire package is a V2 package, and then in*.SFIs also recorded as using the V2 signature.
  2. The application developer uses a script to dynamically inject a file into the package after it is exportedMETA-INFThe APK Signing Block has moved the header position because the content of the file has changed, but this way it doesn’t change the starting position of the header
  3. The APK Signing Block was not able to be found, so the error was reported.

The solution

At this point, the problem has been identified and you can be sure that the modified script will solve all the problems.

  • For application developers, if they want to continue to use the second and third packaging methods above, they can only disable V2 Signature. Or use the newly developed injection method. At present, it is known that several teams have implemented the injection method based on V2, which is similar to the open source method of the comment team. Relevant documents can be referred to: Walle, a new generation of open source Android channel package generation tool

  • For channels, how to check whether the APK provided by developers uses V2 signature can continue to use the tools mentioned at the beginning of this article, and now individuals have completed the packaging of the official verification tool, or directly use the JAR that encapsulates the official verification tool, which are open source under the same GTIHub: Github.com/bihe0832/An…