最近写Pixeval的时候部分功能需要抓包,发现现在的Android不好抓了,首要的问题就是Pixiv本身不信任Fiddler的证书,结果就是如果在Fiddler上开启了Decrypt HTTPS Traffics那么Pixiv的流量就只会显示SSL handshake成功,而请求本身则会因为证书校验失败而失败,在Fiddler的Log里可以看到相应的请求失败异常信息:

!SecureClientPipeDirect failed:
System.Security.Authentication.AuthenticationException
A call to SSPI failed, see inner exception.
< An unknown error occurred while processing the certificate for pipe
(CN=<host>, O=DO_NOT_TRUST, OU=Created by http://www.fiddler2.com).

解决这个问题首先要知道他的来源,这个问题来自Certificate Pinning,是一种安全机制,大意是让应用程序只去接受一个特定的证书或由该证书所颁发的证书,这样的话即便你把Fiddler的证书加入了CA,让系统信任了,但是由于应用使用Certificate Pinning,因此依然不会信任该证书。
  面对该问题,我所知道的解决方法有两种,第一种是在Fiddler的设置里取消勾选Decrypt HTTPS Traffics,但是这样显然是属于“解决提出问题的那个人”这种类型的方式,因为取消勾选之后也就完全起不到抓包的作用了。第二种方法就是把apk拆开,然后通过修改一些文件来达到这个目的
  在介绍第二种方法以前,需要知道Android的应用清单文件AndroidManifest.xml中的<application>项有一个叫做android:networkSecurityConfig的属性,这个属性指向文件res/xml/network_security_config.xml,而这个文件里配置了该Android项目的网络安全相关信息,其中有一栏叫做<debug-overrides>1,我们可以在这一栏里指定调试模式下应用信任的证书库,也就是说,我们可以在这下面把FiddlerRoot.cer所属的user证书库加入到应用的信任证书库中。
  当然,在上述描述中有一个很明显的问题就是调试模式,默认状态下应用是不会处于调试模式的,我们需要回到AndroidManifest.xml文件中,在<application>一栏添加属性android:debuggable="true"2,才可以开启调试模式。

解决方法:

  1. 首先获取Pixiv最新的apk文件,可以前往apkmirror或者自行把手机上的应用分享给电脑
  2. 下载apktool,打开控制台并且cdapktool所在的目录,输入命令
    .\apktool.bat d pixiv.apk
    

    这会在同目录下生成一个`pixiv`文件夹,里面包含了解包后的内容,接着删除掉这个`pixiv.apk`,我们已经用不到它了

  3. 定位到pixiv/res/xml文件夹,打开network_security_config.xml文件,在<network-security-config>一栏,加上如下内容
    <debug-overrides>
          <trust-anchors>
              <certificates src="system"/>
              <certificates src="user"/>
          </trust-anchors>
      </debug-overrides>
      
  4. 回到pixiv文件夹,打开AndroidManifest.xml文件,在<application>一栏加入android:debuggable="true"
  5. 此时要做的修改都完成了,键入命令
    .\apktool.bat b pixiv -o pixiv.apk
    

    这会把pixiv文件夹中的内容重新打包到pixiv.apk中,接着需要对该压缩包进行签名,输入命令

    keytool -genkey -v -keystore my-pixiv.keystore -alias pixiv-key -keyalg RSA -keysize 2048 -validity 10000
    

    来生成一个keystore,注意该命令使用到了JDK的bin目录下的工具keytool.jar,使用该命令之前需要先安装JDK

  6. 2022.7.30 特别鸣谢HappyLive6发现该问题并邮件联系我,特此添加该步骤以作指正
    正常来说,下一步的步骤应当是对apk文件进行重签名,然而,如果在重签名以前没有使用zipalign对重打包的apk进行对齐,则可能会导致重打包失败,zipalign的详情页同样提到这一点:

    Caution: You must use zipalign at one of two specific points in the app-building process, depending on which app-signing tool you use:

    • if you use apksigner, zipalign must only be performed before the APK file has been signed. If you sign your APK using apksigner and make further changes to the APK, its signature is invalidated.
    • If you use jarsigner, zipalign must only be performed after the APK file has been signed.

    因此,在重新签名之前,应当先使用zipalign -p -f -v 4 pixiv.apk pixivcrack.apk来对齐pixiv.apk (注意输入输出文件名不同)

  7. 第5步的命令会在同目录下生成keystore文件,接着使用Android SDK提供的工具apksigner对apk签名(apksigner就在Android SDK目录下,需要先下载Android SDK):

    apksigner.bat -ks my-pixiv.keystore pixivcrack.apk
    

到此为止,对apk的重打包大功告成,可以正常的使用Fiddler对其抓包了

Reference

  • [1] redice.(2015).How to capture HTTPS(TLS 1.0) communications from Android App with Fiddler4?[Online] answer. Available: https://stackoverflow.com/a/33390831 [2015, Oct 28].

  1. https://developer.android.com/training/articles/security-config#debug-overrides ↩︎
  2. https://developer.android.com/guide/topics/manifest/application-element#debug ↩︎

欲少留此灵琐兮,日忽忽其将暮