当前位置: 首页 > news >正文

Android 14/15抓包实战:从系统证书注入到应用进程级捕获

1. Android 14/15抓包的核心挑战

最近在给公司做安全测试时,遇到了一个头疼的问题:新采购的一批Android 14/15设备死活抓不到HTTPS包。折腾了整整两天才发现,原来是系统证书存储机制发生了重大变化。传统方法把证书放到/system/etc/security/cacerts完全失效了,这让我这个老手也栽了跟头。

Android 14开始,Google引入了APEX模块化机制,证书存储路径改到了/apex/com.android.conscrypt/cacerts。这个目录受到SELinux严格保护,就算有root权限也很难直接修改。更麻烦的是,很多厂商设备现在默认都锁了bootloader,根本没法持久化修改系统分区。

我测试过市面上主流的抓包方案:

  • 直接导入用户证书(Android 7以下有效)
  • 修改系统证书目录(Android 13以下有效)
  • 各种抓包工具的VPN模式(部分应用会检测)

结果发现,在Android 14/15上这些方法全军覆没。特别是金融类App,基本都启用了证书固定(Certificate Pinning),连Frida hook都变得异常困难。经过反复实验,终于摸索出一套可行的组合拳方案。

2. 临时注入系统证书的实战方案

2.1 动态挂载证书目录的黑科技

传统方案是直接修改系统分区,但在新设备上这招已经行不通了。我的解决方案是利用tmpfs内存文件系统动态挂载:

#!/system/bin/sh # 创建临时证书目录 mkdir -p -m 700 /data/local/tmp/tmp-ca-copy # 复制原有证书 cp /apex/com.android.conscrypt/cacerts/* /data/local/tmp/tmp-ca-copy/ # 挂载tmpfs到系统证书目录 mount -t tmpfs tmpfs /system/etc/security/cacerts # 迁移证书并添加自定义CA mv /data/local/tmp/tmp-ca-copy/* /system/etc/security/cacerts/ cp /data/local/tmp/your_ca.0 /system/etc/security/cacerts/ # 设置权限和SELinux上下文 chmod 644 /system/etc/security/cacerts/* chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*

这个脚本的精妙之处在于:

  1. 完全在内存中操作,不修改物理分区
  2. 保持原有证书不丢失
  3. 通过SELinux权限检查

2.2 进程级证书注入技巧

光挂载还不够,必须让所有进程看到新证书。这里需要用到Linux的namespace技术:

# 获取zygote进程ID ZYGOTE_PID=$(pidof zygote || true) ZYGOTE64_PID=$(pidof zygote64 || true) # 注入到zygote的mount namespace for Z_PID in "$ZYGOTE_PID" "$ZYGOTE64_PID"; do if [ -n "$Z_PID" ]; then nsenter --mount=/proc/$Z_PID/ns/mnt -- \ /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts fi done # 处理已启动的应用进程 APP_PIDS=$(ps -o PID -P $ZYGOTE_PID $ZYGOTE64_PID | grep -v PID) for PID in $APP_PIDS; do nsenter --mount=/proc/$PID/ns/mnt -- \ /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts & done

实测发现,有些应用会自己重新挂载namespace,所以最好每隔10秒重新执行一次注入。可以用while循环配合sleep实现自动化。

3. 应用级流量精准捕获

3.1 基于tcpdump的进程过滤

证书问题解决后,接下来就是精准抓包。我最推荐tcpdump+wireshark组合:

# 查找目标应用进程 ps -Ao PID,NAME,ARGS | grep com.target.app # 获取该进程使用的端口 netstat -anp | grep <PID> # 抓取特定端口流量 tcpdump -i wlan0 -s0 -w /sdcard/capture.pcap 'port 443 or port 8080'

这里有几个实用技巧:

  • -s0参数确保抓完整数据包
  • WiFi和移动网络要分别抓(wlan0 vs rmnet_data0)
  • 复杂过滤条件可以保存到文件用-F参数加载

3.2 高级过滤技巧

遇到这些特殊情况可以这样处理:

  1. IPv6流量:添加ip6过滤条件
  2. QUIC协议:抓取UDP 443端口
  3. WebSocket:过滤tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420

推荐保存常用过滤规则:

# HTTP请求头捕获 tcpdump -i any -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420' # 抓取DNS查询 tcpdump -i any -s0 -A 'udp port 53'

4. 疑难问题解决方案

4.1 证书仍然不生效?

遇到过几次脚本执行成功但证书就是不生效的情况,通常是因为:

  1. 应用使用了自定义TrustManager
  2. 系统启用了hardened_malloc
  3. SELinux策略阻止了mount操作

解决方案分三步走:

  1. 检查SELinux审计日志:
dmesg | grep avc
  1. 临时放宽SELinux:
setenforce 0
  1. 用strace跟踪SSL握手过程:
strace -f -e trace=openat -p <APP_PID>

4.2 应对证书固定(Pinning)

对于使用证书固定的应用,可以尝试:

  1. Xposed模块:TrustMeAlready
  2. Frida脚本
Java.perform(function() { var Certificate = Java.use('java.security.cert.Certificate'); Certificate.verify.implementation = function() { console.log("Bypassing certificate verification"); }; });
  1. 内核模块:手动修改内核中的证书校验函数

5. 自动化脚本集

我把常用操作封装成了几个实用脚本:

cert_inject.sh(证书注入)

#!/system/bin/sh # 自动识别Android版本 if [ -d "/apex/com.android.conscrypt" ]; then # Android 14+方案 ./inject_apex.sh else # 传统方案 mount -o rw,remount /system cp *.0 /system/etc/security/cacerts/ chmod 644 /system/etc/security/cacerts/* mount -o ro,remount /system fi

capture.sh(智能抓包)

#!/system/bin/sh # 自动选择网卡 INTERFACE=$(ip route | awk '/default/ {print $5}') # 智能识别HTTP/HTTPS端口 PORTS=$(netstat -tuln | awk '/LISTEN/ {print $4}' | awk -F: '{print $NF}' | sort -u) # 开始抓包 tcpdump -i $INTERFACE -s0 -w "/sdcard/$(date +%s).pcap" "port ($(echo $PORTS | tr ' ' '|'))"

这些脚本我都放在Gist上持续更新,建议保存到设备的/data/local/tmp目录下使用。

http://www.jsqmd.com/news/651356/

相关文章:

  • 量子计算开发者入局时机分析:软件测试从业者的专业视角
  • 从单线到四线:手把手教你用Vivado Tcl脚本一键优化FPGA配置速度,告别龟速启动
  • 从Multisim转战Cadence Pspice:一个硬件工程师的仿真工具迁移实战(附RC滤波电路保姆级教程)
  • 5分钟掌握B站视频解析工具:从入门到实战的完整指南
  • 高效获取国家中小学智慧教育平台电子课本:一键批量下载完整指南
  • carsim与simulink联合仿真(3)——‘两轮独立驱动电动汽车的差动驱动与控制策略
  • 别再死记硬背课文了!用‘技术思维’拆解《大学英语综合教程四》Unit 2,手把手教你构建知识图谱
  • 西门子840D HMI Advanced for PC及其相关功能特性“由于我仅需要根据给...
  • 别再只啃教材了!我是如何用B站、知乎和一本英文书搞定电机控制入门的(资源清单+学习路径)
  • Modbus功能码选错了?一个真实PLC与SCADA通信故障的排查复盘(附报文分析)
  • DNF装备搭配避坑指南:详解‘额外伤害’与‘最终伤害’到底怎么算
  • DataX与dataX-web集群部署实战:从单机到分布式的高效数据同步
  • 利用SpringSecurity的@PreAuthorize与SpEL打造动态RBAC权限校验体系
  • 如何彻底解决电脑风扇噪音?FanControl风扇控制软件深度体验
  • Python桌面应用自动化升级:从原理到实践的全方位指南
  • 6DD1606-0AD0阀门定位器模块
  • 质数 gcd 同余总结
  • 飞利浦HX9352电动牙刷摔坏自救指南:从拆机到更换锂电池与MP9361芯片的完整流程
  • Solutions - 板刷 UOJ 小记
  • GLM模型这么火,咱们用vllm也咧一个呗!
  • Steam成就管理终极指南:如何免费掌控你的游戏成就
  • 手把手教你用STM32F103C8T6和ZH03B传感器DIY一个PM2.5检测仪(附完整代码)
  • 中小企业福音:5分钟搞定StarWind Virtual SAN双节点安装(附详细截图)
  • 国产崛起之路:本土在线粘度计品牌技术实力与市场表现评析 - 品牌推荐大师1
  • 百度网盘秒传脚本:三步实现永久文件分享的革命性方案
  • 2026年正规外汇平台有哪些 盘点新手必读 - 速递信息
  • CSS复合属性:交互提效与实战技巧
  • 用MATLAB手把手复现OFDM通信:从子载波到循环前缀,一个完整帧的诞生记
  • PvZWidescreen:为经典游戏注入现代显示适配能力
  • Android Studio中文语言包:打破语言壁垒,提升中文开发者效率的终极解决方案