Kaustuv 90
Platinian
When I modify an Android app which is not mine, I use apktool to unpack the APK, modify the smali, use apktool to pack it, and finally sign it using my own key. This works for most of the Apps. However, some Apps explicitly perform certificate checking in their code. The following code snippet illustrates such checking:
One way to fix this is by removing the “if” block, but it’s difficult to locate all such if blocks, especially in smali. A more convenient way is to hook the PackageManager.getPackageInfo() API and change info.signatures to the original APK’s signature. The following code snippet illustrates such hooking:
Three things need to be done here:
with
The smali code for PatchSignature can be easily obtained by writing a simple app with the java code and disassemble it. Now we have only one problem remaining, how to obtain the original certificate? I.e. what should we put in new Signature("...")?
Here’s what I found the most convenient way:
Code:
PackageManager pm = myContext.getPackageManager();
PackageInfo info = pm.getPackageInfo("my.package.name", PackageManager.GET_SIGNATURES);
String expectedSig = "308203a5...";
if (!expectedSig.equals(info.signatures[0].toCharsString()) {
quit();
}
One way to fix this is by removing the “if” block, but it’s difficult to locate all such if blocks, especially in smali. A more convenient way is to hook the PackageManager.getPackageInfo() API and change info.signatures to the original APK’s signature. The following code snippet illustrates such hooking:
Code:
PackageManager pm = myContext.getPackageManager();
PackageInfo info = PatchSignature.getPackageInfo(pm, "my.package.name", PackageManager.GET_SIGNATURES);
...
public class PatchSignature {
public static PackageInfo getPackageInfo (PackageManager pm, String packageName, int flags) throws PackageManager.NameNotFoundException
{
PackageInfo info = pm.getPackageInfo(packageName, flags);
if ("my.package.name".equals(packageName) &&
info.signatures != null && info.signatures.length > 0 &&
info.signatures[0] != null)
info.signatures[0] = new Signature("308203b6...");
return info;
}
}
Three things need to be done here:
- Change all PackageManager.getPackageInfo() to PatchSignature.getPackageInfo().
- Add class PatchSignature.
- Find out the correct signature.
Code:
invoke-virtual {PARAM1, PARAM2, PARAM3}, Landroid/content/pm/PackageManager;->getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;
with
Code:
invoke-static {PARAM1, PARAM2, PARAM3}, LPatchSignature;->getPackageInfo(Landroid/content/pm/PackageManager;Ljava/lang/String;I)Landroid/content/pm/PackageInfo;
The smali code for PatchSignature can be easily obtained by writing a simple app with the java code and disassemble it. Now we have only one problem remaining, how to obtain the original certificate? I.e. what should we put in new Signature("...")?
Here’s what I found the most convenient way:
Code:
openssl pkcs7 -inform DER -print_certs -in unpacked-app-using-apktool/original/META-INF/CERT.RSA | openssl x509 -inform PEM -outform DER | xxd -p