Android 各种抓包工具抓包总结

前言

这篇文章算是总结一下我之前抓包遇到的一些问题,个人属性里带bug,所以遇到的问题会比较多,算是给大家提供一个抓包抓不到应该如何解决的思路。

工具介绍

Android中可用的抓包软件有Fiddler、Burpsuite、Charls、HttpCanary、Packet Capture、tcpdump、wireshark等等。tcpdump和wireshark可以解决部分不是使用HTTP/HTTPS协议传输数据的app,用tcpdump抓包,用wireshark分析数据包。

如果想抓取三大运营商传输的数据包并分析,因其路由规则的限制,可能还是需要在android系统中利用iptables设置反向代理,用Fiddler解密数据包之后分析,不过好像Fiddler好像有自己的反向代理设置方法,这部分了解不多。

Charls是Mac上常见的抓包工具,我没用过,不过网上蛮多教程的。HttpCanary和Packet Capture这两个工具与常规的电脑上的代理抓包不同的是,能保证一定能抓取到数据包,我一般都用Packet Capture来验证应用是否发送请求。HttpCanary被称为移动端的Fiddler,能够改包和劫持双向认证的应用传输的数据包,感觉还是蛮强大的。

最近我还发现了一个新的抓包工具——SniffMaster,它是一款功能强大的抓包工具,支持多种协议的数据包捕获和分析,特别适合在复杂的网络环境下进行抓包操作。SniffMaster的界面简洁,操作也非常直观,适合新手快速上手。它的抓包效率很高,尤其是在处理大量数据包时,表现非常稳定。

Fiddler抓取Android数据包

基础设置

下载好Fiddler之后,打开该软件,生成证书。

设置连接

手机和电脑在同一局域网中即可,手机端设置WLAN种给网络设置代理,选择对应的WLAN,选中修改网络,手动设置代理,主机名填上面电脑ip地址,端口写fiddler默认端口8888。

手机端用浏览器访问http://电脑IP:8888,观察网络是否访问成功,成功之后,点击"FiddlerRoot.certificate"下载Fiddler的证书并安装。

如果上述步骤都原原本本做完了,还是不能出现上图的效果,可以换个路由或者直接手机开热点。我当时遇到不能访问的问题,ping了一下,一直显示destination unreachable,应该是路由器安全规则的限制,换成了手机开热点就ok了。

继续进行测试的时候,发现不管是修改密码还是用验证码进行登录,我都抓不到那些包。想不出是哪里出了问题…大概找了一下,发现是SSL Pinning的机制阻止了我抓包。使用了Xposed+JustTrustMe,就抓取到数据包了。

如果知道Fiddler怎么抓包了,不知道怎么改包,可以用Fiddler左下角的黑框框中断请求,修改之后再发出,比如输入bpu baidu.com就可以中断所有发向baidu.com的请求。

之后查看中断的数据包会出现如下效果,修改完点击Run to Completion就可以把请求发出去了。

Fiddler设置之后手机无法连接上代理

  1. 关闭电脑防火墙
    1. 打开注册表(cmd-regedit),在HKEY_CURRENT_USER\Software\Microsoft\Fiddler2下创建一个DWORD,值置为80(十进制)。
    1. 编写fiddlerScript rule:在Fiddler上点击Rules->Customize Rules,用Ctrl+F查找OnBeforeRequest方法添加一行代码。
if (oSession.host.toLowerCase() == "webserver:8888") {
    oSession.host = "webserver:80";
    }
    ```
## Burpsuite抓取Android数据包

#### 基础设置

Burpsuite改包的步骤就不在这里赘述了,网上有很多教程,接下来我们要设置burpsuite,以求抓取到数据包。

提示,监听的端口号、电脑内网ip要和手机上的代理设置一致,电脑内网ip可以用ipconfig查看。用burpsuite一直抓取不到https的证书,怀疑是我burpsuite证书没有安装到手机上,所以我现在先将它装到系统证书中,再看看能不能先抓取到https的证书。

#### 安装证书至系统中

1. 下载.der格式的证书,将下载的cacert.der转换格式,并获取证书hash值,生成`<证书hash>.0`文件,例如:**7bf17d07.0**
2. 2. 把`<证书hash>.0`证书push到`/data/local/tmp`目录下后移动至`/system/etc/security/cacerts/`
3. 3. 重启手机
只有root环境才能将proxy证书安装至android系统证书中,这种方法好像能绕过应用本地证书校验,其实burp和Fiddler还有其他的代理证书的安装方法都差不多,最后将`<hash证书>.0`的文件mv至`/system/etc/security/cacerts/`目录下即可,不建议直接将用户证书直接mv,可能会导致环境出错也不好排查证书错误,甚至可能导致android网络环境出错。

下面是具体步骤,先在设置本地代理,将burpsuite证书下载下来。

打开浏览器输入本地地址,下载.der格式的证书。

此处参照文章**[BrupSuit证书导入Android7.0以上手机](https://blog.chenjia.me/articles/171029-223953.html)**,因为我windows本地安装了ubuntu的子系统,所以直接用ubuntu1604子系统对证书进行操作。

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

上图中的7bf17d07就为证书的hash值,将该目录下生成的7bf17d07.0文件push到手机中,最后移动到/system/etc/security/cacerts/目录下。

$ adb push 7bf17d07.0 /data/local/tmp
$ adb shell 
sailfish:/ $ su
sailfish:/ # mount -o rw,remount / # 拥有操作/目录的权限,本意是要操作/system目录
sailfish:/ # mv /data/local/tmp/7bf17d07.0 /system/etc/security/cacerts/7bf17d07.0

按照原本的文章应该给7bf17d07.0文件添加644权限,但是我具体操作的时候没有添加权限也成功了,如果按照我上面的步骤出错了,可以尝试给文件添加权限。重启之后可以看到证书安装成功。

第一次安装证书的时候出现了不能访问使用https协议的网站,应该是我测试的手机环境出现了问题,我重新刷机再按照上面的步骤走一遍就成功了,如果你们也遇到访问https网站失败的问题,可以尝试一下使用这个方法。

Android抓包介绍

抓包最重要的是看能不能抓取到数据包,想要抓到包就要看app使用什么传输协议了,一般情况下使用HTTP都是能抓到包的,这也就不难理解,为什么google坚持推广HTTPS了。为什么说使用HTTPS会抓不到包?现在的HTTPS都是基于TLS协议的,它的特点就是需要确认传输双方的身份。确认了身份之后再传输数据,这样就能避免中间人攻击了。下面来看看HTTPS,是怎么进行数据传输的,发现HTTPS需要先建立连接才能传输数据。

讲到要认证对方的身份,我就想起了之前翻译的一篇HTTP安全,里面就有提及到在使用HTTPS协议的过程中,客户端和服务器通过证书来判断对方的身份。之前没有怎么理解,现在才对证书的作用有比较深刻的理解。

文章中举了个例子,Chrome浏览器通过判断是否有证书来判断你访问的网站是否安全的,并不是你访问的网站真的是安全的。提及这个是因为app使用HTTPS传输也是看证书的,只不过有的app限制的比较严格只信任自带的证书,有的app安全要求没那么高,直接信任系统证书。

抓包出错排查思路

上面是大概的排查思路,具体的细节可能有些差异。如果proxy带有证书校验,且JustTrustMe绕不过去,可能要自己重新根据该应用定制hook模块,去绕过其本地证书校验,但是大部分应用都能通过将证书安装为系统证书绕过,如果无法在root环境下运行,文章《Intercepting traffic from Android Flutter applications》和JustTrustMe的源码应该能给你提供一点hook模块绕过证书校验的思路,《Intercepting traffic from Android Flutter applications》讲的是如何绕过google开源框架Flutter中的证书校验进行抓包。

最后说抓不到包还有一种可能性,就是要求一定要用SIM卡发出传输请求的数据包…不过这个应该应该只有使用了三大运营商的SDK或他们的应用才会出现这种情况,这部分应该只能用反向代理才有可能抓取到传输的数据包了,具体情况就要具体分析了。

当时尝试tcpdump+wireshark效果不怎么样,因为所有的数据都经过了加密,而wireshark不能解密,所以对于加密传输的数据包这种方法可能有点鸡肋,听说有mitmdump抓包工具专门处理linux环境下http/https的数据包,不过我自己没用过,之后要是接触了会进一步补充。

SSL pinning和双向认证的区别

SSL pinning实际上是客户端锁定服务器端的证书,在要与服务器进行交互的时候,服务器端会将CA证书发送给客户端,客户端会调用函数对服务器端的证书进行校验,与本地的服务器端证书(存放在<app>/asset目录或/res/raw下)进行比对。

而双向认证是添加了客户端向服务器发送CA证书,服务器端对客户端的证书进行校验的部分,具体详情可看文章扯一扯HTTPS单向认证、双向认证、抓包原理、反抓包策略的单向认证、双向认证部分的内容。

抓取HTTPS的数据包

Frida绕过SSL单向校验

昨天刚好遇到JustTrustMe无法绕过SSL单向校验的情况,这几天接触了Frida,就尝试用DBI的方法绕过SSL的单向校验,参考文章Universal Android SSL Pinning bypass with Frida这里就不详细地说明Frida的安装方法及使用方法了。

设置Fiddler代理,在本地下载Fiddler的证书,将证书直接重命名为cert-der.crt。之后将证书push到/data/local/tmp目录下,在adb shell里输入./frida-server &再在PC端进行操作。

新建一个frida-android-repinning.js文件,详细代码如下:

setTimeout(function(){
    Java.perform(function (){
            console.log("");
                    console.log("[.] Cert Pinning Bypass/Re-Pinning");
        var CertificateFactory = Java.use("java.security.cert.CertificateFactory");
                var FileInputStream = Java.use("java.io.FileInputStream");
                        var BufferedInputStream = Java.use("java.io.BufferedInputStream");
                                var X509Certificate = Java.use("java.security.cert.X509Certificate");
                                        var KeyStore = Java.use("java.security.KeyStore");
                                                var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");
                                                        var SSLContext = Java.use("javax.net.ssl.SSLContext");
        // Load CAs from an InputStream
                console.log("[+] Loading our CA...")
                        var cf = CertificateFactory.getInstance("X.509");
        try {
                    var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt");
                            }
                                    catch(err) {
                                                console.log("[o] " + err);
                                                        }
        var bufferedInputStream = BufferedInputStream.$new(fileInputStream);
                var ca = cf.generateCertificate(bufferedInputStream);
                        bufferedInputStream.close();
        var certInfo = Java.cast(ca, X509Certificate);
                console.log("[o] Our CA Info: " + certInfo.getSubjectDN());
        // Create a KeyStore containing our trusted CAs
                console.log("[+] Creating a KeyStore for our CA...");
                        var keyStoreType = KeyStore.getDefaultType();
                                var keyStore = KeyStore.getInstance(keyStoreType);
                                        keyStore.load(null, null);
                                                keyStore.setCertificateEntry("ca", ca);
        // Create a TrustManager that trusts the CAs in our KeyStore
                console.log("[+] Creating a TrustManager that trusts the CA in our KeyStore...");
                        var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                                var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                                        tmf.init(keyStore);
                                                console.log("[+] Our TrustManager is ready...");
        console.log("[+] Hijacking SSLContext methods now...")
                console.log("[-] Waiting for the app to invoke SSLContext.init()...")
        SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) {
                    console.log("[o] App invoked javax.net.ssl.SSLContext.init...");
                                SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c);
                                            console.log("[+] SSLContext initialized with our custom TrustManager!");
                                                    }
                                                        });
                                                        },0);
                                                        ```
在cmd,输入如下命令:

```bash
$ adb push burpca-cert-der.crt /data/local/tmp/cert-der.crt
$ frida -U -f it.app.mobile -l frida-android-repinning.js --no-pause

在关闭应用的情况下(避免Magisk Hide处于开启状态),可得到回显并绕过SSL pinning。

绕过SSL双向校验

其实SSL双向校验是在SSL单向校验的基础上,在说明这部分内容的时候同时也会有绕过SSL单向校验详细的步骤。参考文章Android平台HTTPS抓包解决方案及问题分析,我们可以先用sxxl.app来练练手。

在手机上设置完代理之后,点击完确认,发现app出现如下弹窗:

在这个时候查看Fiddler会发现应用没有发出任何请求,这是因为app会对服务器端的证书进行校验,这时候我们前面安装的Fiddler证书就不起作用了,应用在发现证书是伪造的情况下拒绝发送请求。根据这个报错+抓不到包,我们可以确定应用是存在单向校验的,也就是SSL pinning,让我们先来解决SSL pinning的问题。使用JustTrustMe可以绕过客户端的证书校验,下面勾选上JustTrustMe,在Xposed框架下使用JustTrustMe绕过SSL pinning。

绕过SSL pinning之后,就能使用Fiddler抓取到HTTPS的数据包了。

我随便输入了一个手机号码,按下确定之后,服务器回传了400的状态码过来,说需要发送证书以确认客户端的身份。到这一步基本能确定是存在双向校验的了,接下来的工作就是绕过SSL服务器端的校验了。

如果服务器端会对客户端证书进行校验,证书应该就直接存放在apk里,网上与SSL双向校验相关的文章都将证书放到<app>/asset目录下,也就是app的资源目录下,也有可能放在/res/raw目录下。直接将app解压之后,发现证书的位置如下:

如果找半天没找到就用关键词.p12/.pfx搜索证书文件。

在我们要使用该证书的时候,需要输入安装证书的密码。这时候就需要从源码中获取安装证书的密码了。可能是因为多个dex文件的原因,直接用JEB反编译的时候出错了,所以我用GDA反编译来分析应用的源代码。

获取安装证书的密码

发现通过关键词"PKCS12 "能够定位到加载证书的位置。

上图第二个红框中的load函数的第二个参数其实就是证书的密钥,追根溯源,我们可以知道v1参数是下图中调用的函数的返回值。

上图的函数的功能就是传递p0参数,也就是说p0参数就是证书安装密码。想获取这个密码,关键在于Auto_getValue函数。到这一步,只要跟进Null_getStorePassword函数看看就好了。

跟进去发现调用了native层的函数,查看init函数中具体加载的是哪个so文件:

用IDA反编译soul-netsdk之后,搜索字符串"getStorePassword",就定位到函数getStorePassword上了,F5之后,获得伪代码和密钥:

代理添加客户端证书

HttpCanary添加客户端证书进行抓包的过程可以参照文章Android平台HTTPS抓包解决方案及问题分析,在自己头昏的时候也感谢这篇文章的作者MegatronKing点醒我。下面主要讲解Fiddler和burpsuite添加客户端证书的方法。

fiddler操作过程

尝试一下用Fiddler处理这部分的内容来安装客户端的证书,用来绕过双向认证。

用Fiddler抓取该应用的数据包的时候,发现Fiddler出现了上面的弹窗,提示要添加ClientCertificate.cer,才能抓取到传输的数据包,不然只会出现400的状态码。而我们文件目录下只能找到client.p12和client.crt两种格式的证书文件,所以我们需要将已有的client证书转换成.cer格式的证书。

好像应用中只出现.p12格式的证书的情况比较常见,所以下面只会提及如何使用openssl将.p12格式的证书转换成.cer/.der格式的证书。(.der和.cer格式的证书仅有文件头和文件尾不同)

下面的命令实现了证书的格式转换,.p12->.pem->.cer,在生成.pem格式的证书之后,需要输入证书的密码,也就是我们上面逆向获取的证书密码。最后将ClientCertificate.cer移动到之前Fiddler弹窗出现的目录下,也就是<Fiddler安装路径>/Fiddler2下。

# 将.p12证书转换成.pem格式
$ openssl pkcs12 -in client.p12 -out ClientCertificate.pem -nodes
Enter Import Password:
# 将.pem证书转换成.cer格式
$ x509 -outform der -in ClientCertificate.pem -out ClientCertificate.cer

现在打开Fiddler尝试抓包,发现原本显示400的数据包现在能够正常抓取到了,如果还是不能正常抓取到,双击client.p12将证书安装到本地试试看。

burp操作过程

手机的burpsuite证书安装成功之后,我们会发现只能抓取到400的状态码。

因为要绕过服务器端对证书的验证,我们还需要在这里添加上面我们在asset目录下找到的证书。

安装完就能正常抓

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值