跳转到正文

App 数据爬取与协议分析 ​

Web 端的数据在 HTML 或 Ajax 接口里,App 端的数据则全部走接口——没有页面源码可看,唯一的入口是网络流量。因此 App 爬取的第一步永远是抓包,而不是写代码。

⚖️ 合规边界(务必先读)

App 逆向的法律与合规风险显著高于 Web 爬取。以下行为超出正常技术研究范畴:

  • 破解加固、脱壳、绕过 SSL Pinning 用于第三方商业 App —— 可能违反《著作权法》对技术保护措施的规定,以及 App 的用户协议
  • 批量获取 App 内的用户信息 —— App 内数据多为登录后可见,抓取几乎必然触及《个人信息保护法》
  • 规避付费或权限限制

正当场景:分析自己开发或所属组织的 App、有明确书面授权的安全测试、以学习协议机制为目的的原理研究。本篇按技术原理组织,不针对任何特定 App。

一、三条技术路线 ​

路线做法效率难度稳定性
接口抓包抓 HTTP(S) 流量,还原接口后用代码直接请求最高中受签名/加固影响
UI 自动化驱动真机或模拟器操作界面,抓取屏幕内容最低低最高,几乎不会被反制
协议逆向反编译 App,还原签名/加密算法高最高算法更新即失效

决策顺序:先抓包看接口是否可直接复用 → 参数有签名则评估逆向成本 → 逆向成本过高或数据量小则退回 UI 自动化。


二、HTTPS 抓包的原理 ​

2.1 中间人代理的工作方式 ​

抓 HTTP 明文很简单,难点全在 HTTPS。抓包工具的本质是受信任的中间人(MITM):

text
App  ──TLS 握手──>  代理(用自签证书冒充服务端)
                      │  代理作为客户端与真实服务端建立第二条 TLS 连接
                      └──TLS 握手──>  真实服务端

代理持有两条独立的加密连接,因此能看到明文。成立的前提是 App 信任代理的自签 CA 证书——整个抓包体系的所有障碍都源于此。

2.2 证书信任的三道门槛 ​

门槛表现处理
未安装 CA 证书所有 HTTPS 请求失败安装代理工具的 CA 证书到设备
Android 7+ 用户证书不受信证书装了但仍失败需将证书装入系统证书目录(需 root),或 App 声明了 networkSecurityConfig 才信任用户证书
SSL Pinning(证书固定)单个 App 失败,其他 App 正常见 2.4

💡 Android 7 是关键分水岭

Android 7.0 起,App 默认只信任系统证书,用户手动安装的证书不再自动生效。这是「证书明明装了却抓不到包」最常见的原因。

可行方案:使用 root 设备将证书写入系统证书区、使用 Android 7 以下的模拟器、或在自有 App 中通过 network_security_config.xml 显式信任用户证书。

2.3 工具对比 ​

工具特点适用
Charles图形界面友好,断点改包方便交互式探索、手动分析
mitmproxy命令行 + Python 脚本化,可编程自动化采集,本篇重点
FiddlerWindows 生态成熟Windows 用户
Wireshark抓的是链路层原始包,能看非 HTTP 协议私有 TCP 协议分析

mitmproxy 的三种运行形态:mitmproxy(终端交互界面)、mitmweb(浏览器界面)、mitmdump(无界面 + 脚本,用于自动化)。

python
# addon.py:mitmdump 的脚本接口,可直接把流量落库
import json

def response(flow):
    """每个响应都会回调,在这里筛选并处理目标接口。"""
    if "/api/list" not in flow.request.pretty_url:
        return

    data = json.loads(flow.response.get_text())
    for item in data.get("items", []):
        save_to_db(item)          # 边抓边入库,无需还原签名算法

def request(flow):
    """也可以改写请求,例如统一注入调试参数。"""
    flow.request.headers["X-Debug"] = "1"
sh
mitmdump -s addon.py -p 8080

💡 mitmdump 的战术价值

当接口签名逆向成本过高时,mitmdump + UI 自动化 是一个被低估的组合:让自动化脚本驱动 App 正常翻页(签名由 App 自己算),mitmdump 在旁边静默截获所有响应并入库。

完全不需要理解加密算法,代价是速度受限于 App 的真实操作节奏。

2.4 SSL Pinning ​

App 在代码里内置了服务端证书或公钥的指纹,握手时主动校验对方证书是否与内置值一致,代理的自签证书因此被拒绝。

实现层次说明
Java 层OkHttp 的 CertificatePinner、TrustManager 自定义校验
Native 层在 .so 里用 OpenSSL/BoringSSL 校验,隐蔽性更高
双向认证服务端还要校验客户端证书,需从 App 中提取客户端证书

技术上的处理方式是用 Frida 在运行时 Hook 校验函数使其恒返回通过,或用 objection 的自动化脚本。这属于绕过 App 的安全机制,仅应在自有 App 或授权测试中使用。

若无授权,遇到 Pinning 的正确响应是改走 UI 自动化路线——它不触碰任何安全机制。


三、UI 自动化 ​

不解析协议,直接驱动界面操作并读取屏幕上的内容。最笨但最稳:不受签名、加密、Pinning 影响,因为你走的就是真实用户路径。

3.1 方案对比 ​

方案原理特点
Appium基于 WebDriver 协议,驱动 UIAutomator2(Android)/XCUITest(iOS)跨平台、生态成熟、需元素定位
Airtest + Poco图像识别 + UI 层级树对无法定位的元素(游戏、Canvas)有优势
uiautomator2直接对接 Android UIAutomator轻量,纯 Android,API 简洁
adb 命令input tap / shell最底层,适合简单固定操作

⚠️ Appium 的 driver 需单独安装

Appium 2.x 起,driver 与 plugin 从主程序中拆分,安装 Appium Server 后必须再单独装驱动(如 appium driver install uiautomator2),否则连接设备时会直接报找不到 driver。网上大量旧教程沿用 1.x 的一体化写法,不能直接照搬。

3.2 核心操作模式 ​

python
# 以 uiautomator2 为例,展示 UI 自动化的通用范式
import uiautomator2 as u2

d = u2.connect()                       # 连接设备(adb 已识别)

d(text="搜索").click()                  # 按文本定位
d(resourceId="com.example:id/input").set_text("关键词")
d.press("enter")

d.xpath('//*[@resource-id="list"]').wait(timeout=10)    # 显式等待

# 滚动加载:UI 自动化的数据获取核心是"边滚动边采集"
seen = set()
for _ in range(50):
    for el in d.xpath('//*[@resource-id="item_title"]').all():
        if el.text not in seen:
            seen.add(el.text)
    d.swipe_ext("up", scale=0.8)       # 上滑加载更多

三个必须处理的工程问题:

  1. 去重:滚动过程中同一元素会被反复读取,必须用业务主键去重。
  2. 终止判断:连续 N 次滚动都没有新增数据即视为到底,不能靠固定次数。
  3. 异常恢复:弹窗、广告、网络错误页会打断流程,需要在每轮循环前检查并处理当前界面状态。

3.3 与抓包组合使用 ​

UI 自动化最强的用法不是读屏幕,而是只负责触发请求,数据由抓包层截获:

text
Airtest/Appium 驱动滚动  →  App 自己发起带签名的请求  →  mitmdump 截获 JSON  →  入库

这样既避开了签名逆向,又拿到了结构化的接口数据(而非从屏幕文本还原),是很多场景下性价比最高的方案。


四、协议逆向的技术路线 ​

数据量大到 UI 自动化撑不住、且有正当授权时,才进入这一步。

4.1 工具链 ​

阶段工具作用
查看资源与结构apktool解包 APK,得到资源和 smali
反编译 Javajadx(开源,首选)、JEB(商业)把 dex 还原成近似 Java 源码
分析 native 层IDA Pro、Ghidra(开源)反汇编 .so 文件
动态分析Frida、objection运行时 Hook 函数、打印参数与返回值
网络层mitmproxy、Wireshark确认逆向结果与真实流量一致

4.2 静态分析的定位方法 ​

与 JS 逆向 的思路完全一致——先定位,再理解:

  1. 抓包确定目标参数名(如 sign);
  2. jadx 打开 APK,全局搜索该参数名的字符串;
  3. 找到拼装请求的位置,回溯签名函数;
  4. 若签名函数是 native 方法(声明带 native 关键字),说明实现在 .so 里,需转入 native 分析。

💡 加固会让静态分析直接失效

主流商业 App 普遍使用加固(壳)。表现为 jadx 打开后看不到业务代码,只有壳的加载器。

此时静态分析基本无效,只能转向动态分析——因为代码运行时必然要在内存中还原。这也是 Frida 成为主流工具的原因。

4.3 动态分析:Frida 的核心价值 ​

Frida 在进程运行时注入 JS 引擎,可以 Hook 任意函数,打印其入参、返回值和调用栈。它跳过了「读懂代码」这一步,直接观察实际行为。

javascript
// Frida 脚本的通用范式:Hook Java 层方法,观察输入输出
Java.perform(function () {
  const Target = Java.use("com.example.security.SignUtil");

  Target.sign.overload("java.lang.String").implementation = function (input) {
    const result = this.sign(input);          // 调用原方法
    console.log("[sign] 入参:", input);
    console.log("[sign] 返回:", result);
    return result;
  };
});

关键认知:Hook 的目标不一定是「破解」,更多时候是观察——搞清楚签名函数到底接收了什么格式的输入,往往比读懂算法本身更重要。多数逆向失败不是算法错了,而是入参拼接顺序错了。

4.4 RPC 模拟执行:不还原算法也能调用 ​

算法在 native 层且复杂度极高时,还有一条捷径:不还原它,而是让 App 自己算。

text
Python 爬虫  ──HTTP──>  运行在设备上的 RPC 服务  ──调用──>  App 内的签名函数
                                                              │
             <────────────  返回签名结果  ────────────────────┘

实现方式有两种:Frida-RPC(用 Frida 把 App 内的函数暴露成可远程调用的接口)或 AndServer 类方案(在设备上跑一个 HTTP 服务,内部调用 App 的类方法)。

这与 JS 逆向 里的「Node RPC 服务」是完全相同的思想:脱离环境的成本过高时,就把环境本身变成一台可调用的服务器。

代价:需要设备常驻运行、并发能力受限于设备性能、设备故障即服务中断。


五、路线选择速查 ​

场景建议路线
接口无签名,抓包即可复现直接用 httpx 请求接口
接口有签名,数据量大且有授权协议逆向 → Python 复现或 RPC
有 SSL Pinning,无授权UI 自动化
App 已加固动态分析(Frida),或直接 UI 自动化
数据量小(几千条以内)UI 自动化,不值得逆向
需要结构化数据但不想逆向UI 自动化驱动 + mitmdump 截获(推荐组合)

六、与 Web 爬取的技术对应关系 ​

App 逆向的多数概念在 Web 端都有同构物,理解一边就能迁移另一边:

App 端Web 端共同本质
抓包分析接口Ajax 接口分析找到真实数据源
签名参数逆向JS 加密参数逆向还原参数生成算法
Frida HookJS Hook(重写原生函数)运行时拦截观察
Frida-RPC / AndServerNode RPC 服务让原环境当计算服务
SSL PinningTLS 指纹校验客户端身份验证
UI 自动化(Appium)浏览器自动化(Playwright)走真实用户路径
App 加固JS 混淆 / WASM提高静态分析成本

📚 模块与官方文档 ​

抓包工具 ​

工具安装官方文档
mitmproxypip install mitmproxydocs.mitmproxy.org
mitmproxy Addon API—Addon 概览 · 事件钩子 · HTTP 对象
Charles官网下载charlesproxy.com
Fiddler官网下载docs.telerik.com/fiddler
Wireshark系统包wireshark.org/docs

UI 自动化 ​

模块安装官方文档
Appium-Python-Clientpip install Appium-Python-ClientGitHub
Appium Servernpm i -g appiumappium.io/docs
UiAutomator2 Driverappium driver install uiautomator2GitHub
uiautomator2pip install uiautomator2GitHub
airtestpip install airtestairtest.doc.io.netease.com
pocouipip install pocouipoco.readthedocs.io
facebook-wda(iOS)pip install facebook-wdaGitHub
adbAndroid SDKdeveloper.android.com

逆向分析 ​

工具类型官方文档
frida / frida-toolspip install frida-toolsfrida.re/docs · JavaScript API
objectionpip install objectionGitHub
jadx反编译 dexGitHub
apktool解包 APKapktool.org
Ghidra反汇编 soghidra-sre.org
JEB商业反编译pnfsoftware.com

Android 平台文档 ​

资源说明
网络安全配置证书信任规则,抓包受阻时必读
Android 7 CA 证书变更用户证书不再默认受信的官方说明
UI AutomatorUI 自动化的系统级基础

相关笔记 ​

JavaScript 逆向(同构的算法还原与 RPC 思路)· 反爬对抗(代理与登录态)· 请求库详解(拿到接口后的高并发实现)


← 返回 Python 深度研究