吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1523|回复: 30
上一主题 下一主题
收起左侧

[Android 原创] Android app三种常见抓包场景及案例分析

  [复制链接]
跳转到指定楼层
楼主
scllqk 发表于 2024-9-15 22:45 回帖奖励
本帖最后由 scllqk 于 2024-9-15 22:48 编辑

一、未校验:配置证书就能抓

1.这种情况是最简单的情况,Android 7.0之前的设备,直接配置用户证书,就能进行抓包,Android 7.0之后的设备,需要获取root权限1后,把用户证书移到系统证书目录下,或者配置系统强制信任用户证书。
对于移动用户证书到系统证书目录下的情况,推荐使用这个插件:https://github.com/ys1231/MoveCertificate
对于强制信任用户证书的这种情况,推荐使用这个插件:https://github.com/NVISOsecurity/MagiskTrustUserCerts
2.对于这种情况,我们安装完证书后,直接使用代理/vpn的方式进行抓包就可以了,这里我们以某浏览器为例,进行抓包演示,因为我用的设备是Android 7.0以上的,所以我们首先是配置系统强制信任用户证书的插件。

3.配置完成后,我们在抓包软件上导出证书,然后在设备上进行安装。

4.接下来,我们就可以进行抓包了,抓包成功。

二、单向证书认证:客户端校验服务器证书--SSL Pinning

1.这是第二种情况,也就是我们常说的sslpinning,想具体了解sslpining技术,可以去看这2篇文章:
https://shunix.com/ssl-pinning/
https://yu-jack.github.io/2020/03/02/ssl-pinning/

2.针对这种情况,我们以x答x单app为例,进行抓包,上面我们已经试过了,用我们的测试设备是可以正常抓到https的数据包的,然后我们再去抓一下x答x单这个app的包,点击发送验证码按钮后会提示发送失败,请重试 ,说明我们抓包失败了。

3.这里报错:Client closed the connection before a request was made. Possibly the SSL certificate was rejected,表明在 SSL/TLS 握手阶段,客户端在没有发送 HTTP 请求之前就关闭了连接,客户端拒绝了服务器的证书,也就是上面我们所说的sslpinning技术,还有另外一种报错得情况:SSL handshake with client failed: An unknown issue occurred processing the certificate (certificate_unknown),也是用到了sslpinning技术。那遇到上述这2种情况,我们应该怎么处理呢?使用frida进行hook,我们这里直接用大佬们写好的脚本进行hook,地址:https://github.com/WooyunDota/DroidSSLUnpinning/blob/master/ObjectionUnpinningPlus/hooks.js

4.用了大佬的脚本后,发现还是不行,还是失败了,只能换一个再试试了,又尝试了justtrustme,结果还是不行。地址:https://github.com/Fuzion24/JustTrustMe

5.在辗转反侧之时,我想起之前用算法助手时,里面带着一个justtruatme的升级版,于是就拿来试了试,结果成功拿下。可以正常进行抓包了。

6.经过上述尝试,我们针对sslpinning这种,可以先用市面上已有的sslunpinning工具进行尝试,如果遇到都无法进行成功的情况,那就需要我们去手工进行hook了,大致有两种思路,一是对所有HTTP字符串相关类进行Hook,二是考虑到App在验证证书时会打开证书文件判断是否是App自身所信任的,因此一定会使用File类的构造函数打开证书文件获得文件的句柄,所以我们在测试时可以Hook上所有File类的构造函数,即对File.$init函数进行hook。这里我用了objection进行hook的:`objection -N -h 127.0.0.1 -p 26666  -g cn.ticktick.task explore -P ~/.objection/plugins -s "android hooking watch class_method java.io.File.\$init --dump-args --dump-backtrace --dump-return"`,这里因为$在命令行中有特殊含义,所以用\对它进行转义,避免被当成命令行变量。hook之后,我们在得到的数据里面搜索/system/etc/security/cacerts

7.我们在搜到的数据里面,找到了一个关于证书的堆栈信息,我们用jadx反编译后,找到这个方法

8.复制一下,丢给chatgpt分析一下,得出结论,这段代码是关于处理 SSL 证书验证的逻辑,是基于域名和证书的哈希值进行匹配,检查传入的证书是否符合某些预期的标准,那我们尝试hook它,并让它返回空,这样不就能绕过证书校验了嘛。

function main(){
    Java.perform(function(){
        console.log("启动");
       let f = Java.use("ll.f");
        f["a"].implementation=function(str, list){
            console.log(`f.a is called: str=${str}, list=${list}`);
           return;
       };
   });
}
setTimeout(main,500)

9.非常幸运,经过hook后,我们成功抓到了这个数据包,至此完成。

三、双向证书认证:服务器校验客户端证书。

1.这是第三种情况,我们以x利蜂app为例,进行抓包尝试,经过尝试,还是和之前一样报错:SSL handshake with client failed: An unknown issue occurred processing the certificate (certificate_unknown)

2.我们先使用objection的android sslpinning disable把这个sslpinning过掉,过掉之后,我们再抓包,发现请求正常发出,响应返回报错:400 No required SSL certificate was sent。判断为服务器校验客户端证书。

3.当我们遇到这种情况,需要我们从app中找到内置的客户端证书,导入到抓包工具中,才能正常进行抓包,那怎么才能找到客户端的证书呢?通常是有二种方法,第一种是用r0ysue大佬写的r0capture进行hook导出,第二种是去hook Keystore,找到加载证书的地方,手动分析源码去找到证书和密码。我们先用一下第一种方案:直接上r0capture,有枣没枣打一杆子试试。

4.运气不错,证书找到了,我们直接在dowload目录下把证书拿出来,安装到Charles里

5.然后,再次进行抓包,可以看到,我们成功绕过了双向证书认证。

6.我们去看一下r0ysue大佬的脚本,简单来解释一下原理,在安卓开发中,系统包是无法混淆的,例如java.security.KeyStore不会被混淆,所以可以去hook这个类,并且在 Java 中,KeyStore$PrivateKeyEntry 是存储在 KeyStore 中,包含私鑰和相關的證書,即getPrivateKey() 和 getCertificateChain() 這兩個方法,也就是说当應用程序調用 getPrivateKey() 或 getCertificateChain() 方法來獲取私鑰和證書時,会被脚本拦截并提取返回的私钥和证书数据,然后storeP12() 函數,將提取的私鑰和證書組合起來,存儲為一個 .p12 文件,并使用密码r0ysue進行加密並寫入到指定的文件路徑。

Java.perform(function(){
   functionuuid(len, radix){
       var chars ='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
       var uuid =[], i;
        radix = radix || chars.length;
       if(len){
           // Compact form
           for(i =0; i < len; i++) uuid[i]= chars[0| Math.random()* radix];
       }else{
           // rfc4122, version 4 form
           var r;
           // rfc4122 requires these characters
            uuid[8]= uuid[13]= uuid[18]= uuid[23]='-';
            uuid[14]='4';
           // Fill in random data. At i==19 set the high bits of clock sequence as
           // per rfc4122, sec. 4.1.5
           for(i =0; i <36; i++){
               if(!uuid[i]){
                    r =0| Math.random()*16;
                    uuid[i]= chars[(i ==19)?(r &0x3)|0x8: r];
               }
           }
       }
       return uuid.join('');
   }
   functionstoreP12(pri, p7, p12Path, p12Password){
       var X509Certificate = Java.use("java.security.cert.X509Certificate")
       var p7X509 = Java.cast(p7, X509Certificate);
       var chain = Java.array("java.security.cert.X509Certificate",[p7X509])
       var ks = Java.use("java.security.KeyStore").getInstance("PKCS12","BC");
        ks.load(null,null);
        ks.setKeyEntry("client", pri, Java.use('java.lang.String').$new(p12Password).toCharArray(), chain);
       try{
           var out = Java.use("java.io.FileOutputStream").$new(p12Path);
            ks.store(out, Java.use('java.lang.String').$new(p12Password).toCharArray())
       }catch(exp){
            console.log(exp)
       }
   }
     // 在服务器校验客户端的情形下,帮助dump客户端证书,并保存为p12的格式,证书密码为r0ysue
    Java.use("java.security.KeyStore$PrivateKeyEntry").getPrivateKey.implementation=function(){
       var result =this.getPrivateKey()
       var packageName = Java.use("android.app.ActivityThread").currentApplication().getApplicationContext().getPackageName();
       storeP12(this.getPrivateKey(),this.getCertificate(),'/sdcard/Download/'+ packageName +uuid(10,16)+'.p12','r0ysue');
       return result;
   }
    Java.use("java.security.KeyStore$PrivateKeyEntry").getCertificateChain.implementation=function(){
       var result =this.getCertificateChain()
       var packageName = Java.use("android.app.ActivityThread").currentApplication().getApplicationContext().getPackageName();
       storeP12(this.getPrivateKey(),this.getCertificate(),'/sdcard/Download/'+ packageName +uuid(10,16)+'.p12','r0ysue');
       return result;
   }
});

7.这个x利蜂的例子到此为止,我们再拿出某Location,它也是双向证书认证,这次我们自己去找一下证书,还是一样启动charles进行抓包。

8.可以看到,报错和之前是一样的,我们之前说过了,这种是sslpinning的情况,我们用objection的android sslpinning disable把它过掉,过掉之后,再重新抓包,发现报错变了,请求包正常,响应包400的情况。

9.这种情况就是双向证书校验了,我们需要去解包找证书搜索.p12,.bks,.pem,还是一样没找到,我们只能去脱壳反编译代码,这次脱壳我用的是大佬给分享的一个脱壳网站:https://nop.gs/

10.然后我们去代码里找找看,这里我们直接搜索keystore,发现就这几个,而且就这俩货带着BKS的关键字样。

11.点进去看看,终于知道为啥我解包后,搜索常见证书后缀搜不着的原因了,原来是用了图片做证书。md

12.证书找到了,接下来就是找密码了,怎么找呢?当然是hook了,上脚本。之前也说过了,因为java.security.KeyStore是系统的类是不会被混淆的,所以我们hook它就行了。

function hook_KeyStore_load(){
    Java.perform(function(){
       var StringClass = Java.use("java.lang.String");
       var KeyStore = Java.use("java.security.KeyStore");
        KeyStore.load.overload('java.security.KeyStore$LoadStoreParameter').implementation=function(arg0){
           // printStack("KeyStore.load1");
           // 输出调用栈
            console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
            console.log("KeyStore.load1:", arg0);
           this.load(arg0);
       };
        KeyStore.load.overload('java.io.InputStream','[C').implementation=function(arg0, arg1){
           // printStack("KeyStore.load2");
            console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
            console.log("KeyStore.load2:", arg0, arg1 ? StringClass.$new(arg1):null);
           this.load(arg0, arg1);
       };
        console.log("hook_KeyStore_load...");
   });
}
hook_KeyStore_load()

13.来,让我们来看看hook的效果如何?hook出来了,密码是lerist.key.2021

14.然后我们把证书拿出来

15.这里我用了keystore explorer对证书进行格式的转换

16.我们得把证书转成p12格式,才能在charles里安装,安装完成后,虽然是加密得,但是可以正常抓包了。

四、总结

在Android应用的抓包过程中,处理不同类型的证书验证机制的方法有所不同:

无证书校验:如果应用没有进行证书验证,我们只需配置抓包工具的证书即可进行抓包。

单向证书认证(SSL Pinning):对于SSL Pinning的应用,我们通常需要使用Frida等工具进行hook,以绕过SSL Pinning机制。在某些情况下,可能需要尝试多种方法,如使用JustTrustMe脚本,才能成功进行抓包。

双向证书认证:对于双向证书认证,我们可以使用r0capture直接dump证书。此外,也可以通过代码中找到证书和密码,然后将其转换为.p12证书,并导入到抓包工具中进行抓包。

免费评分

参与人数 15威望 +1 吾爱币 +33 热心值 +14 收起 理由
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
宝明软件作者 + 1 + 1 谢谢@Thanks!
decor + 1 可以!
zhangsan173 + 1 + 1 我很赞同!
NonsenseMe + 1 + 1 鼓励转贴优秀软件安全工具和文档!
ioyr5995 + 1 + 1 我很赞同!
allspark + 1 + 1 用心讨论,共获提升!
twl288 + 1 谢谢@Thanks!
Roshan + 1 + 1 用心讨论,共获提升!
whichway + 1 谢谢@Thanks!
wangofjian + 1 + 1 整理的很全面,学习了!
debug_cat + 1 + 1 谢谢@Thanks!
正己 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
helian147 + 1 + 1 热心回复!
无问且问 + 1 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
正己 发表于 2024-9-18 07:42
哦豁,撞车了,跟我下一期要讲的部分一致

点评

走你的路,让你无路可走  发表于 2024-9-18 14:37
沙发
reinmj 发表于 2024-9-17 22:22
3#
9812263 发表于 2024-9-17 22:32
5#
WeiZhiDeR8 发表于 2024-9-18 08:15
很有用,学习学习
6#
yxnwh 发表于 2024-9-18 09:11
很详细,适合新手小白入门,感谢!
7#
debug_cat 发表于 2024-9-18 09:27
很详细,如果可以提供样本的下载就更好了
8#
laustar 发表于 2024-9-18 10:24
学习了。很详细
9#
gto250 发表于 2024-9-18 10:31
Android 7.0之后的设备有没有免root的方法
10#
yunteng9527 发表于 2024-9-18 10:36
感谢分享,学习学习
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-9-20 15:09

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表