20145307陈俊达_安卓逆向分析_软件包签名研究

20145307陈俊达_安卓逆向分析_软件包签名研究

引言

写这篇文章的原因有两点,一,之前打算写两篇cydia逆向分析,可惜手机不能Cydia不支持5.0以上系统,无奈放弃。二,在写之前的博客的时候重新打包后传到安卓手机上的时候,出现了签名有问题,不能进行安装的问题,这就促使我想写一篇关于软件签名的文章。

start

安卓系统禁用更新签名不一致的apk,所以我们打包新的apk是肯定不能安装的。那么我们怎么来研究呢?推荐一款签名软件,鼎鼎大名的auto-sign,我们下载后进行解压,右键用VS code打开sign.bat文件。

同时readme文件也帮助我们又一个很好的理解,两个签名密钥信息加上一个jar文件是这个程序的核心。testkey.x509.pem这个公钥文件和testkey.pk8这个私钥文件对xxx.apk签名之后变为signed的apk

testkey.pk8 is the private key that is compatible with the recovery image included in this zip file
testkey.x509.pem is the corresponding certificate/public key

使用方法:
java -jar signapk.jar testkey.x509.pem testkey.pk8 update.zip update_signed.zip

那么我们来看看签名前后有什么变化,签名后多了一个叫做META-INF的文件夹,里面有三个文件,分别为 MANIFEST.MF 、 CERT.SF 、 CERT.RSA

我们用jd-gui工具打开signapk.jar,找到主函数 main 看看代码

  public static void main(String[] args) {
    if (args.length != 4) {
      System.err.println("Usage: signapk publickey.x509[.pem] privatekey.pk8 input.jar output.jar");

      System.exit(2);
    }

    JarFile inputJar = null;
    JarOutputStream outputJar = null;
    try
    {
      X509Certificate publicKey = readPublicKey(new File(args[0]));
      PrivateKey privateKey = readPrivateKey(new File(args[1]));
      inputJar = new JarFile(new File(args[2]), false);
      outputJar = new JarOutputStream(new FileOutputStream(args[3]));
      outputJar.setLevel(9);

      Manifest manifest = addDigestsToManifest(inputJar);
      manifest.getEntries().remove("META-INF/CERT.SF");
      manifest.getEntries().remove("META-INF/CERT.RSA");
      outputJar.putNextEntry(new JarEntry("META-INF/MANIFEST.MF"));
      manifest.write(outputJar);

      Signature signature = Signature.getInstance("SHA1withRSA");
      signature.initSign(privateKey);
      outputJar.putNextEntry(new JarEntry("META-INF/CERT.SF"));
      writeSignatureFile(manifest, new SignatureOutputStream(outputJar, signature));

      outputJar.putNextEntry(new JarEntry("META-INF/CERT.RSA"));
      writeSignatureBlock(signature, publicKey, outputJar);

      copyFiles(manifest, inputJar, outputJar);
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    } finally {
      try {
        if (inputJar != null) inputJar.close();
        if (outputJar != null) outputJar.close(); 
      }
      catch (IOException e) { e.printStackTrace();
        System.exit(1);
      }
    }
  }

addDigestsToManifest 这个函数,遍历 Apk 中所有文件,对非文件夹非签名文件的文件逐个生成 SHA1 数字签名信息,再 base64 编码。再写入我们之前提到过的manifest.mf文件中。

大概格式

Manifest-Version: 1.0

Created-By: 1.0 (Android)

Name: res/drawable-xhdpi/ic_launcher.png

SHA1-Digest: xxxxxxxxxxxx

Name: AndroidManifest.xml

SHA1-Digest: xxxxxxxxxxxx

如果你修改了apk的文件,那么它的sha1值肯定会对应改变,肯定是不会安装成功的。

接下来对之前生成的 manifest 使用 SHA1withRSA 算法, 用私钥签名,writeSignatureFile 这个函数,最后生成 CERT.SF 文件

总结

这篇文主要是一些理论的东西,没有太多的实践操作,所以我没有贴太多的图片,主要是三个文件结合保证了apk文件下所有的每个文件都有对应的密钥进行加密保证了唯一性,不会被其他的文件篡改。所以也就解决了之前的疑问,为什么会出现了签名错误的问题。下篇文章打算做一些实际的东西,实际的软件,实际的游戏,去hack it

posted @ 2017-06-12 17:01  20145307陈俊达  阅读(396)  评论(0编辑  收藏  举报