序章:当抓包工具遇上"铜墙铁壁"

序章:当抓包工具遇上"铜墙铁壁"

本章字数:约5500字 阅读时间:约18分钟 难度等级:★★☆☆☆

声明:本文中的公司名称、包名、API地址、密钥等均已脱敏处理,使用虚构名称替代。"梦想世界"、"dreamworld"等均为虚构名称,与任何真实公司无关。


引言

2026年1月5日,深夜23:15。

实验室里只有显示器的微光和咖啡机偶尔发出的咕噜声。我坐在工位前,手指在键盘上轻轻敲击,屏幕上的Charles Proxy正在等待连接。作为一名有十年经验的安全研究员,我已经习惯了深夜的工作节奏,也习惯了各种APP的安全防护措施。

但今晚,我即将遇到一个让我整整困扰三周的对手。

这款APP来自国内某知名新能源车企,内部代号为"dw_mall_shop",对外显示为"梦想世界",当前版本v8.x.x。我之所以选择这款APP进行安全测试,是因为近年来车企APP的数据安全问题日益突出。

用户的车辆数据、行驶轨迹、个人信息都通过这类APP进行传输,其安全防护水平直接关系到用户的隐私和财产安全。作为安全研究员,评估这类APP的安全性是我们的职责所在。


1.1 第一次尝试:常规抓包

按照常规流程,我的第一步是进行抓包分析,了解APP与服务器之间的通信协议和数据格式。这是逆向工程的基础------只有了解了数据是如何传输的,才能进一步分析数据是如何生成的。

我熟练地完成了抓包环境的配置:

1.1.1 环境准备

测试设备

  • 手机:Pixel 6 Pro,Android 13
  • 电脑:MacBook Pro M2,macOS Ventura
  • 抓包工具:Charles Proxy 4.6.4

配置步骤

bash 复制代码
# 1. 启动Charles Proxy
# 默认监听端口:8888

# 2. 在手机上配置WiFi代理
# 设置 -> WiFi -> 当前网络 -> 代理 -> 手动
# 服务器:电脑IP地址
# 端口:8888

# 3. 安装Charles根证书
# 在手机浏览器访问 chls.pro/ssl
# 下载并安装证书
# 设置 -> 安全 -> 加密与凭据 -> 安装证书

验证配置

为了确认代理配置正确,我先用手机浏览器访问了几个网站:

arduino 复制代码
✓ https://www.baidu.com - Charles成功捕获
✓ https://www.google.com - Charles成功捕获
✓ https://api.github.com - Charles成功捕获

一切正常。代理配置没有问题。

1.1.2 启动目标APP

深吸一口气,我点击了"梦想世界"的图标。

APP正常启动了。启动画面、加载动画、主界面------一切看起来都很正常。我开始在APP中进行各种操作:

  • 浏览商城首页
  • 查看商品详情
  • 搜索商品
  • 查看个人中心

APP响应流畅,数据加载正常,图片显示清晰。从用户体验的角度来看,这是一款非常优秀的APP。

然而,当我切换到Charles窗口时,我愣住了。

Charles的请求列表------空空如也

没有任何HTTP请求。没有任何HTTPS请求。什么都没有。

我以为是自己眼花了,揉了揉眼睛,仔细看了看屏幕。确实是空的。

1.1.3 排查问题

"不可能啊,"我自言自语道,"APP明明在正常加载数据,怎么可能没有网络请求?"

我开始排查可能的问题:

检查1:代理配置

bash 复制代码
# 在手机上确认代理设置
设置 -> WiFi -> 当前网络 -> 代理
# 显示:手动,服务器:192.168.1.100,端口:8888
# 配置正确 ✓

检查2:Charles监听状态

bash 复制代码
Charles -> Proxy -> Proxy Settings
# 端口:8888
# 启用透明代理:是
# 状态正常 ✓

检查3:证书安装

bash 复制代码
# 在手机上确认证书
设置 -> 安全 -> 加密与凭据 -> 用户凭据
# 显示:Charles Proxy CA
# 证书已安装 ✓

检查4:其他APP测试

我打开了手机上的其他几个APP进行测试:

复制代码
✓ 微信 - Charles成功捕获请求
✓ 淘宝 - Charles成功捕获请求
✓ 抖音 - Charles成功捕获请求

其他APP都能正常抓包,只有"梦想世界"抓不到。

这说明问题出在APP本身,而不是我的抓包环境。


1.2 深入分析:为什么抓不到?

1.2.1 排除SSL Pinning

我的第一反应是:这可能是SSL Pinning导致的。

SSL Pinning(证书锁定)是一种常见的安全措施,APP会验证服务器证书是否与预期的证书匹配。如果不匹配(比如使用了Charles的代理证书),就会拒绝连接。

但是,SSL Pinning通常会导致以下现象:

  • APP显示网络错误
  • APP提示"无法连接到服务器"
  • Charles中显示SSL握手失败

而我观察到的现象是:

  • APP正常运行
  • 数据正常加载
  • Charles中什么都没有

这不像是SSL Pinning的表现。

1.2.2 一个关键发现

就在我百思不得其解的时候,我想起了一件事。

前几天,我在这台手机上安装了一款科学上网工具(类似VPN的代理软件),用于访问一些国外的技术文档。这款工具使用的是SOCKS5代理协议。

我突然好奇:如果开启这个科学上网工具,"梦想世界"APP还能正常使用吗?

我打开了科学上网工具,然后启动"梦想世界"APP。

APP完全正常!

数据加载正常,功能使用正常,没有任何异常提示。

这个发现让我陷入了沉思。

1.2.3 代理类型的差异

让我们来分析一下不同代理类型的工作原理:

HTTP代理(Charles使用)

markdown 复制代码
┌─────────┐    HTTP请求    ┌─────────┐    HTTP请求    ┌─────────┐
│   APP   │ ────────────> │  Charles │ ────────────> │  服务器  │
└─────────┘               └─────────┘               └─────────┘
                               │
                          解析HTTP协议
                          记录请求内容

SOCKS5代理(科学上网工具使用)

markdown 复制代码
┌─────────┐    TCP连接     ┌─────────┐    TCP连接     ┌─────────┐
│   APP   │ ────────────> │  SOCKS5  │ ────────────> │  服务器  │
└─────────┘               └─────────┘               └─────────┘
                               │
                          只转发TCP数据
                          不解析应用层协议

关键区别

  • HTTP代理工作在应用层(第7层),需要解析HTTP协议
  • SOCKS5代理工作在会话层(第5层),只负责转发TCP数据

这意味着什么?

APP可能实现了这样的逻辑:

  1. 检测系统是否设置了HTTP代理
  2. 如果检测到HTTP代理,就绕过系统网络栈,使用自定义的网络通信方式
  3. 如果没有检测到HTTP代理(或者是SOCKS代理),就正常通信

这是一种精准打击的策略:

  • 针对安全研究员的抓包工具(HTTP代理):完全失效
  • 针对普通用户的科学上网需求(SOCKS代理):正常使用

太精妙了!


1.3 验证假设:代理检测机制

1.3.1 系统代理检测

在Android系统中,HTTP代理设置可以通过以下方式获取:

java 复制代码
// 方法1:通过System.getProperty获取
String proxyHost = System.getProperty("http.proxyHost");
String proxyPort = System.getProperty("http.proxyPort");

// 方法2:通过ProxySelector获取
ProxySelector selector = ProxySelector.getDefault();
List<Proxy> proxies = selector.select(new URI("https://api.example.com"));

// 方法3:通过ConnectivityManager获取(Android特有)
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
ProxyInfo proxyInfo = cm.getDefaultProxy();

如果APP在发起网络请求之前检测这些值,就能知道系统是否设置了HTTP代理。

1.3.2 WiFi代理检测

除了系统级别的代理设置,Android还支持针对特定WiFi网络设置代理:

java 复制代码
// 获取当前WiFi配置
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
WifiConfiguration config = getWifiConfiguration(wifiInfo.getNetworkId());

// 检查代理设置
if (config.getProxySettings() == ProxySettings.STATIC) {
    ProxyInfo proxyInfo = config.getHttpProxy();
    String host = proxyInfo.getHost();
    int port = proxyInfo.getPort();
    // 检测到代理!
}

1.3.3 绕过代理的方法

一旦检测到代理,APP可以使用以下方法绕过:

方法1:使用NO_PROXY

java 复制代码
// 创建不使用代理的OkHttpClient
OkHttpClient client = new OkHttpClient.Builder()
    .proxy(Proxy.NO_PROXY)  // 明确指定不使用代理
    .build();

方法2:自定义SocketFactory

java 复制代码
// 创建直连的Socket,绕过系统代理
public class DirectSocketFactory extends SocketFactory {
    @Override
    public Socket createSocket() throws IOException {
        Socket socket = new Socket();
        // 直接连接,不经过代理
        return socket;
    }
    
    @Override
    public Socket createSocket(String host, int port) throws IOException {
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress(host, port));
        return socket;
    }
}

方法3:使用自定义DNS

java 复制代码
// 绕过系统DNS,直接使用IP地址
public class DirectDns implements Dns {
    @Override
    public List<InetAddress> lookup(String hostname) throws UnknownHostException {
        // 使用硬编码的IP地址,或者自定义DNS服务器
        if (hostname.equals("api.dreamworld.com")) {
            return Arrays.asList(InetAddress.getByName("1.2.3.4"));
        }
        return Dns.SYSTEM.lookup(hostname);
    }
}

1.4 更多尝试:寻找突破口

1.4.1 VPN抓包

既然HTTP代理不行,我尝试使用VPN方式抓包。

工具:HttpCanary

HttpCanary是一款Android平台的抓包工具,它通过创建本地VPN来捕获所有网络流量。

markdown 复制代码
┌─────────┐    所有流量    ┌─────────────┐    转发    ┌─────────┐
│   APP   │ ────────────> │ HttpCanary  │ ────────> │  服务器  │
└─────────┘               │   (VPN)     │           └─────────┘
                          └─────────────┘
                                │
                           捕获所有流量

测试结果

安装HttpCanary,启动VPN,然后打开"梦想世界"APP。

依然抓不到任何数据。

APP正常运行,但HttpCanary中没有任何来自"梦想世界"的请求记录。

1.4.2 iptables流量转发

在Root设备上,我尝试使用iptables强制转发所有流量:

bash 复制代码
# 将所有443端口的流量转发到本地代理
iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-port 8888

# 将所有80端口的流量转发到本地代理
iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 8888

测试结果

还是抓不到。

APP似乎使用了非标准端口,或者有其他方式绑过iptables规则。

1.4.3 Wireshark抓包

作为最后的尝试,我使用Wireshark在路由器层面抓包:

bash 复制代码
# 在路由器上运行tcpdump
tcpdump -i eth0 host 手机IP -w capture.pcap

测试结果

终于抓到了一些数据!但是:

  • 所有数据都是加密的(TLS 1.3)
  • 无法看到HTTP请求的具体内容
  • 只能看到连接的目标IP和端口

这证实了APP确实在进行网络通信,只是我们无法通过常规手段看到通信内容。


1.5 阶段性总结

经过一个晚上的尝试,我对这款APP的网络防护有了初步了解:

1.5.1 防护特点

特点 说明
精准检测 只检测HTTP代理,不影响SOCKS代理
静默处理 检测到代理后不崩溃,而是切换通信方式
用户友好 普通用户完全感知不到异常
多层防护 HTTP代理、VPN、iptables都无法突破

1.5.2 技术推测

基于观察到的现象,我推测APP可能使用了以下技术:

  1. 代理检测:在应用启动时检测系统代理设置
  2. 通信切换:检测到代理后,切换到直连模式
  3. 自定义网络栈:使用自定义的Socket实现,绕过系统网络层
  4. 非标准端口:可能使用非80/443的端口进行通信

1.5.3 下一步计划

既然网络层的抓包行不通,我需要换一个思路:

  1. 静态分析:反编译APK,分析代码逻辑
  2. 动态调试:使用Frida等工具Hook网络请求
  3. 模拟执行:如果动态调试也被阻止,考虑使用Unidbg

1.6 意外发现:Frida的命运

在结束这个晚上的工作之前,我决定快速尝试一下Frida。

Frida是一款强大的动态插桩工具,可以在运行时注入代码到目标进程中。如果能用Frida Hook住网络请求相关的函数,就能看到APP发送的数据。

1.6.1 准备Frida环境

bash 复制代码
# 安装Frida
pip install frida-tools

# 在手机上启动frida-server
adb push frida-server /data/local/tmp/
adb shell chmod +x /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &

1.6.2 编写Hook脚本

javascript 复制代码
// hook_network.js
Java.perform(function() {
    console.log("[*] Starting network hook...");
    
    // Hook OkHttp的请求方法
    var OkHttpClient = Java.use('okhttp3.OkHttpClient');
    var Request = Java.use('okhttp3.Request');
    
    OkHttpClient.newCall.implementation = function(request) {
        console.log("[*] ========== New Request ==========");
        console.log("[*] URL: " + request.url().toString());
        console.log("[*] Method: " + request.method());
        console.log("[*] Headers: " + request.headers().toString());
        return this.newCall(request);
    };
    
    console.log("[*] Hook installed!");
});

1.6.3 运行Frida

bash 复制代码
frida -U -f com.dreamworld.app -l hook_network.js --no-pause

结果

bash 复制代码
     ____
    / _  |   Frida 16.1.4 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Pixel 6 Pro (id=192.168.1.101:5555)
Spawning `com.dreamworld.app`...
Process crashed: Segmentation fault

APP直接崩溃了!

Frida注入后,APP立即发生段错误(Segmentation fault)并退出。

这说明APP实现了反Frida检测机制。一旦检测到Frida的存在,就会触发崩溃,阻止任何动态调试。

1.6.4 这意味着什么?

这款APP的安全防护不仅仅是网络层的:

防护层 防护措施 效果
网络层 代理检测 + 通信切换 抓包工具失效
运行时 Frida检测 动态调试失败
??? ??? 待发现

看来,这将是一场持久战。


1.7 本章小结

1.7.1 关键发现

  1. 抓包完全失效:Charles、HttpCanary、iptables都无法捕获APP的网络请求
  2. 精准代理检测:APP只检测HTTP代理,SOCKS代理可以正常使用
  3. 静默通信切换:检测到代理后不崩溃,而是切换到直连模式
  4. Frida被检测:动态调试工具注入后APP直接崩溃

1.7.2 技术启示

这款APP展示了现代移动应用安全防护的一个重要趋势:精准打击 + 用户友好

  • 精准打击:只针对安全研究员的工具(HTTP代理、Frida),不影响普通用户
  • 用户友好:检测到威胁后不是简单崩溃,而是静默处理,保证用户体验

这种设计思路值得所有移动开发者学习。

1.7.3 下一步

既然网络抓包和动态调试都行不通,我需要:

  1. 静态分析:反编译APK,从代码层面理解APP的工作原理
  2. 寻找突破口:分析代理检测和Frida检测的具体实现
  3. 探索新工具:考虑使用Unidbg等离线模拟执行工具

本章思考题

  1. 为什么APP选择"静默切换通信方式"而不是"直接崩溃"?这种设计有什么优缺点?

  2. 如果你是这款APP的安全工程师,你会如何改进现有的代理检测机制?

  3. 除了HTTP代理检测,还有哪些方法可以阻止抓包分析?


下一章:第一章 - 静态分析的艺术


章节附录

A. 本章涉及的工具

工具 用途 官网
Charles Proxy HTTP/HTTPS抓包 www.charlesproxy.com/
HttpCanary Android VPN抓包 httpcanary.com/
Frida 动态插桩 frida.re/
Wireshark 网络协议分析 www.wireshark.org/

B. 本章关键代码

代理检测示例

java 复制代码
public static boolean isProxySet() {
    String proxyHost = System.getProperty("http.proxyHost");
    return proxyHost != null && !proxyHost.isEmpty();
}

绕过代理示例

java 复制代码
OkHttpClient client = new OkHttpClient.Builder()
    .proxy(Proxy.NO_PROXY)
    .build();

C. 参考资料

  1. Android Proxy Settings: developer.android.com/reference/a...
  2. OkHttp Proxy Configuration: square.github.io/okhttp/
  3. Frida Documentation: frida.re/docs/

本章完

相关推荐
尼古拉斯·纯情暖男·天真·阿玮16 小时前
实验一 安全威胁与攻击实验
网络·安全·智能路由器
上海云盾-高防顾问17 小时前
AI原生防御,筑牢智能时代安全屏障
安全·ai-native
小五传输17 小时前
认准好用的跨网文件安全交换系统:安全传输与高效协作两全其美
大数据·运维·安全
前端不太难17 小时前
Flutter 列表性能的一套“长期安全写法”
安全·flutter·状态模式
Ryuuuuko17 小时前
认知驱动的AI黑客:鸾鸟Agent如何让渗透测试拥有“人类专家”思维?
安全
档案宝档案管理17 小时前
权限分级+加密存储+操作追溯,筑牢会计档案安全防线
大数据·网络·人工智能·安全·档案·档案管理
数据光子17 小时前
【YOLO数据集】国内交通信号检测
人工智能·python·安全·yolo·目标检测·目标跟踪
携欢17 小时前
portswigger靶场之修改序列化数据类型通关秘籍
android·前端·网络·安全
资生算法程序员_畅想家_剑魔17 小时前
Kotlin常见技术分享-01-相对于Java 的核心优势-空安全
java·安全·kotlin