长亭百川云 - 文章详情

APP抓包方法总结

零鉴科技

164

2024-07-14

APP抓包方法总结

零鉴科技

First

在对app进行https抓包的过程中,总会遇到无法抓取有效数据包的情况,本篇文章就这个问题,收集并总结了一些常用的解决方案。

问题分析

0****1/

抓包工具无法抓到包,app可正常联网使用

  1. 使用非http协议,直接通过tcp协议或私有协议进行数据传输,比如qq,微信

    这一部分app在进行数据的传输时,大多使用自己实现的一套解析 / 解密流量的算法。若要尝试对这类app进行抓包和分析,那么则需要通过逆向app等较复杂的方法来提取其中的算法。

  2. app内部设置了不走系统代理的选项

    解决方案:可以使用一些第三方代理app(如Http Canary),通过使用系统vpn来强制app的http协议走代理流量,从而实现抓包。

0****2/   

抓包工具无法抓到包,app无法联网

这类问题,大多数情况下可以归结为证书信任的问题。如果需要使用类似于burp或者fiddler之类的中间人抓包工具对https流量进行拦截和分析,那么势必要让app能够信任此类工具自带的证书,这样流量才能以明文的形式展现。因此,本文的后续内容主要分析在https下如何解决app的证书信任问题。

03/

证书信任

涉及到证书信任问题,不外乎以下几种情况:

  1. 客户端和服务端均不对证书做校验(无认证)

  2. 客户端需要校验服务端的证书(单向认证)

  3. 客户端需要校验服务端的证书,同时服务端也要校验客户端的证书(双向认证)

03-1/

无认证

遇到这种情况,直接按照常规步骤抓包即可。但现在不对证书做校验或者说不使用https进行通信的app已经越来越少了,特别是当Android在7.0之后,系统的安全机制都不再信任用户自己的CA证书了。

0****3-2/

单向认证

这种客户端单向校验服务端证书的情况又叫ssl pinning技术,开发者预先把服务端证书的相关信息预置到App中再打包,这样在https通讯过程中App可以与服务器返回的CA证书可以做合法性校验,如果发现不一致,那么App就可以判断当前环境可能存在代理或者中间人攻击(比如Fiddler/Charles抓包工具),从而终止https链接。因此这种技术可以用来在App端防止一部分"心怀不轨"的人进行通信流量的分析。

有防御就会有对应的绕过方法,目前主要的绕过方法有如下几种:

  1. 信任导入的用户证书

  2. hook证书认证函数

  3. 其他

03-2-1/

信任导入的用户证书

1.将用户证书安装到系统证书列表

将证书安装至系统内部的证书列表中可以解决一部分app不信任用户证书导致对的抓包问题,但是此操作需要将手机root后,才能够访问到系统证书所存放的目录。

安装系统证书有两步:

a. 转换证书格式

`// 转换证书的格式``$ openssl x509 -in cacert.der -inform DER -out cacert.pem -outform PEM``// 提取证书的hash``$ openssl x509 -inform PEM -subject_hash -in cacert.pem``$ mv cacert.pem xxx.0`

b. 使用adb将证书移入/system/etc/security/cacerts/目录下

`$ adb push 7bf17d07.0 /data/local/tmp``$ adb shell` `android:/ $ su``android:/ # mount -o rw,remount / # 挂载/system目录``android:/ # mv /data/local/tmp/xxx.0 /system/etc/security/cacerts/xxx.0 # 移动证书``android:/ # chmod 644 /system/etc/security/cacerts/xxx.0 # 修改权限`

2.使用小于Android 7.0版本的手机

这个方法更具有实用性,而且不需要root手机,只需要将证书安装在用户证书列表即可。若app具有很好的兼容性,那么即使在不同Android版本下运行,其对应的接口也不会有很大的区别。


Android官方文档说明

By default, secure connections (using protocols like TLS and HTTPS) from all apps trust the pre-installed system CAs, and apps targeting Android 6.0 (API level 23) and lower also trust the user-added CA store by default.


03-2-2/    

hook证书认证函数

这类hook方法可以玩出很多花样来,目前也有很多框架和插件支持这样的操作,本文主要介绍以下几种方法:

  1. VirtualXposed + JustTrustMe

    VirtualXposed

    以往来说,若要使用Xposed组件,则需要对手机进行root。但VirtualXposed运用了VirtualApp轻量级沙盒工具和epic hook框架技术,实现了在非root环境下运行Xposed模块(支持Android 5.0~10.0)。

    与 Xposed 相比,目前 VirtualXposed 有两个限制:

    同时,在使用过程中需要注意的一点是:所有的工作(安装Xposed模块,安装APP)必须在 VirtualXposed中进行,否则Xposed模块不会有任何作用。

    JustTrustMe

    JustTrustMe是一个可以绕过证书校验(ssl pinning)的Xposed插件,与其类似的还有SSLUnpinning等插件。其中的原理都类似,主要思路是将目前开发者所常用到的实现https的库(okhttp, apache, jsse)进行hook,替换其中验证证书函数的返回值为真,从而绕过app端的证书认证。

    下面是JustTrustMe中一部分的源码,在这里hook了okhttp3.CertificatePinner.check方法,使其返回值为null,进而跳过验证的步骤。

  2. 不支持修改系统(可以修改普通APP中对系统API的调用),因此重力工具箱,应用控制器等无法使用。

  3. 暂不支持资源hook,因此资源钩子不会起任何作用;使用资源hook的模块,相应的功能不会生效。

`try {`    `classLoader.loadClass("okhttp3.CertificatePinner");`    `findAndHookMethod("okhttp3.CertificatePinner",`        `classLoader,`        `"check",`        `String.class,`        `List.class,`        `new XC_MethodReplacement() {`            `@Override`            `protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {`                `return null;`            `}`        `});``} catch (ClassNotFoundException e) {`    `Log.d(TAG, "OKHTTP 3.x not found in " + currentPackageName + " -- not hooking");`    `// pass``}`

更详细的分析原理见:https://bbs.pediy.com/thread-214012.htm

实践

在VirtualXposed环境下配置SSLUnpinning插件并安装app

绕过某软件的ssl pinning进行抓包

2.Frida

Frida是个轻量级so级别的hook框架,它可以帮助逆向人员对指定的进程的so模块进行分析。它主要提供了功能简单的python接口和功能丰富的js接口,使得hook函数和修改so编程化,值得一提的是接口中包含了主控端与目标进程的交互接口,由此可以即时获取信息并随时进行修改。

利用Frida绕过ssl pinning的步骤参考 -> https://xz.aliyun.com/t/6551#toc-7。最核心的内容在`frida-android-repinning.js`脚本中,其原理是重载了SSLContext中的TrustManager来信任用户导入的证书。

其他

还有很多比较少用的技巧,比如:

1. 修改apk内容

先将apk进行解包,修改AndroidManifest.xml,配置networkSecurityConfig,添加信任用户证书的选项,再重打包apk。

`<base-config cleartextTrafficPermitted="true">`  `<trust-anchors>`    `<certificates src="system" />`    `<certificates src="user" />`  `</trust-anchors>``</base-config>`

2. 证书固定时间

有的app会设置证书固定的到期时间,这样的配置在证书过期后有可能会让“不怀好意”的人绕过证书固定。   

但上述的操作难度都比较高,而且还不一定能够成功,因此不太建议用来抓包。

03-3/

双向认证

在需要更加安全的通信环境中,不仅客户端需要校验服务端的证书,同时服务端也需要校验客户端的证书,这种情况就叫做SSL双向认证。这种双向认证机制可以保证服务端以及客户端的身份,防止任意一方被伪造。

因此在这种情况下,往往客户端内部会内置一套公钥证书 + 私钥。在SSL/TLS三次握手过程中的第二次握手(见下图),服务端会向客户端请求证书,客户端必须将内置的公钥证书发给服务端,以验证公钥证书的真实性。

用于双向认证的公钥证书和私钥代表了客户端的身份,所以一般都是用.p12或者.bks文件+密钥进行存放,并通过密码进行保护。由于是内置在客户端中,密码一般也是写死在客户端的代码中,有些App为了防反编译会将密码写到so库中。

如果客户端既使用证书固定,又使用双向认证,那么它应该内置一套公钥证书 + 一套公钥证书和私钥。第一套与服务端的公钥证书相同,用于客户端系统校验与服务端发来的证书是否相同,即证书固定;第二套SSL/TLS握手时公钥证书发给服务端,服务端进行签名校验,即双向认证。

03-3-1/

获取客户端证书

客户端证书一般会随着其他资源文件一起打包进apk包中,其常见存储目录为/assets/res,常见文件后缀为.p12.bks.jks.pfx。诸如刚刚所说到的证书都有密码的保护,因此需要找到证书密码来安装证书才可以进行后续的抓包分析,否则服务端不会接受客户端的请求。

同时,大多数代理工具仅接受p12格式的证书,因此遇到仅有bks格式的证书时,还需要提取出p12的证书,命令如下:

keytool -importkeystore -srckeystore xxx.bks -srcstoretype BKS -destkeystore xxx.p12 -deststoretype PKCS12 -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-ext-jdk15to18-169.jar

03-3-2/

实践

首先直接使用Http Canary + 代理进行抓包,发现该app做了证书固定。

使用VirtualXposed + SSLUnpinning绕过证书固定。在burp中可以抓到请求包,但返回包中状态码为400,提示400 No required SSL certificate was sent。这意味着服务端需要认证客户端证书,接下来的工作就是获取客户端的证书了。

使用压缩工具解压apk后,在/assert目录下找到了客户端证书mykey.p12

接下来通过GDA反编译dex文件,分析app的源代码。很幸运,当前版本下的app没有做很多限制,直接搜索关键词mykey.p12就能够定位加载证书的位置。

查看文档,keystore.load()函数中第二个参数即为解密证书所用的密码。

在这里,通过反编译apk可以直接拿到明文密码,但在有些安全性较高的app中,密码是通过调用了so库中的函数获取到的。因此,在有必要的情况下,还需要反编译so库进行调试分析,获取解密的密码。

在burp的User options中添加客户端ssl证书,输入对应的域名,证书路径和密码。

重新运行app,双向认证绕过成功,可以愉快的抓包了。

在实战的过程中,从官网上下载的最新版本的app是经过加壳的保护的,而从应用商店上下载的app版本低于最新版本,同时没有进行过加壳的操作。在比对这两个apk解压的文件时发现,其使用的客户端证书md5值是完全相同的,因此这里也给获取客户端证书提供了一个新的思路:在当前版本较难提取出客户端证书时,可以尝试对其较低版本的app进行分析,它们有可能使用的是同一个客户端证书。只要提取出了有效的客户端证书,就可以绕过双向认证。

总结一下,此场景下抓包的基本步骤为:

  1. 绕过ssl pinning,抓包查看服务端返回包

  2. 解压apk,寻找客户端证书文件

  3. 如果客户端证书被加密,反编译apk甚至so文件来寻找解密密码

03-3-3/

hook ssl解密函数

这类方法需要配合frida等hook框架使用,同样也需要root手机,其中的原理主要是hook SSL 对数据解密数据的函数。

下面给出两种思路:

  1. 提取证书

    app在进行https通信时必定需要将证书进行解密并存入内存中,因此如果能够找到 app操作证书的地方, hook 这部分函数,打印必要的参数,比如证书和证书密码,就可以获取客户端证书了。

    大部分情况下app操作证书的类都为java.security.KeyStore,那么就可以通过编写frida脚本,hook  java.security.KeyStore 这个类的load(InputStream stream, char[] password)方法,打印形参(也就是证书和密码)即可。

    详细hook脚本在这里:https://api-caller.com/2019/11/05/capture-note/#%E5%8F%8C%E5%90%91%E8%AE%A4%E8%AF%81

  2. 解密https数据

    这个方法就类似于wireshark解密https流量的方法,只要hook了 SSL 加解密的地方,就可以看到明文传输的数据了。但如果要模拟向服务器发送请求的话,还是只能使用第一种方法,因为客户端必须要提交正确的证书,服务端才会响应。

    谷歌官方提供了这个脚本:https://github.com/google/ssl\_logger

题外话

xposed + 流行插件和root手机已经被一些app列入了检测名单,有的仅仅会弹出一个提示框,有的会直接退出app。下图是某个app反编译后检测root和xposed的源代码。可以看到这里使用的是黑名单的机制,通过检测root路径和app包名来判断app是否运行在root环境或者xposed框架下。

当然了,这样黑名单的检测方法具有一定的局限性,通过修改系统文件,随机包名等技术都可以绕过这样的检测。

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2