Fiddler + 安卓模拟器 + java 数据抓包分析

一、背景

描述

复制代码
接近年底,工作不是很忙,刚好朋友找我问下,能不能抓取安卓apk的的一些接口数据,进行一些数据分析,(这里仅对公开数据抓取,并不涉及篡改接口数据等操作)。寻思着,早些年做过安卓开发,以前玩游戏的时候也一直想自己做个脚本自己玩,遂花了几天时间研究了下,目前世面上的一些主流抓包工具以及方法,一番尝试操作下来,虽然从技术层面来看不难,但真的做完还是挺有意思的。

二、前期资料准备

1、抓包工具:

复制代码
fiddler + 雷电模拟器(一款安卓模拟器)

2、后端数据分析:

复制代码
springboot + Mybatis + mysql

3、抓包对象

复制代码
xxk软件(一款语音社交软件)

三、抓包工具以及相关配置

📎fiddler adb.zip(fiddler以及adb工具)

写在前面:fiddler这块的操作,参考了csdn 上 青凯平 大佬的博客

原文链接如下: blog.csdn.net/weixin_4339...

整个流程大概是这样:

1、Fiddler设置

1.1、HTTPS:解密https流量、忽略不安全证书

1.2、连接设置:允许远程计算机连接

点击允许远程计算机连接,点确定保存


在桌面点击导出的证书进行下一步安装即可,全部默认一直点,点到导入成功为止。


Fiddler配置完成将其关闭重启

2、模拟器设置

2.1、网络设置:桥接驱动安装,及开启桥接

安装网桥驱动,出现安装成功即可。

安装完成后点保存设置自动重启。

2.2、WLAN设置:设置fiddler代理

打开模拟器设置-打开WiFi菜单-修改wifi配置(有些模拟器有小笔头修改键,有些模拟器是鼠标长按会出现"修改网络"大同小异,可自行参照,核心就是修改连接wifi的手动代理,ip写本机,端口写8888 对饮fiddler软件里面的,如果端口占用在fiddler里面修改此处改成一致即可)最后点击保存!

2.3、证书安装:物理机ip:8888

打开模拟器浏览器,地址栏输入本物理机ip跟上8888端口,就是输入代理ip和端口。会跳转证书安装页面。

为什么要这样安装证书1.简单便捷2.可以变相去检测与物理机的连接是否正常

图片有点长,耐心按步骤点击

2.4、设置信任证书:使用adb命令,将安装好的证书挪到系统目录中。

使用雷电模拟器的直接看

bash 复制代码
原-用户证书目录:/data/misc/user/0/cacerts-added/
新-系统证书目录:/system/etc/security/cacerts/

如果不移动安装好的证书,此处会出现不信任的证书,频繁弹出(可以看到组织单位是我们安装fiddler)。

此处需要提前开启,模拟器的root权限,否则无法su 切换用户(具体因模拟器而异:有些root权限要在模拟器里面开启,有些不需要,遇到无法su的问题,找找模拟器原因)

2.5、报错分析

随即我们继续操作,将/data/misc/user/0/cacerts-added/的证书文件,移动到/system/etc/security/cacerts/,使其变为信任证书。

bash 复制代码
    # 进入adb shell 工具
    adb shell

    # 切换root用户
    gracelte:/ $ su

    # 查看用户证书安装的名称
    127|gracelte:/ # ls /data/misc/user/0/cacerts-added/
    e5c3944b.0

    # 将用户证书挪至系统证书目录 /system/etc/security/cacerts/
    gracelte:/ # mv /data/misc/user/0/cacerts-added/e5c3944b.0 /system/etc/security/cacerts/
    mv: /system/etc/security/cacerts//e5c3944b.0: Read-only file system
报错1:

在移动证书到/system/etc/security/cacerts/ 会报出问题

bash 复制代码
    报错:mv: /system/etc/security/cacerts//e5c3944b.0: Read-only file system

报错原因:/system 是以只读的形式挂载上来的,所以无论你怎么chmod都无法修改其权限。

解决办法:重新挂载,挂载读写执行权限

ruby 复制代码
    gracelte:/ $ su

    # 重新挂载/system 文件夹
    :/ #  mount -o rw,remount /system
    mount: '/system' not in /proc/mounts
报错2:
bash 复制代码
    报错:mount: '/system' not in /proc/mounts

报错原因:在Android8.0以上通过以上mount命令,找不到/system代表的节点和拥有的权限信息,这是因为Android8.0之后谷歌加入了A/B system的特性,system分区跟ramdisk分区打包在一起,因此系统起来之后也就不存在system分区了,而是直接把system镜像挂载到/根目录上。所以/proc/mounts文件中没有包含/system的权限信息。

查看模拟器安卓版本:

ruby 复制代码
    # 进入adb shell 工具
    adb shell

    # 切换root用户
    gracelte:/ $ su

    # 查看安卓版本
    gracelte:/ # getprop ro.build.version.release
    9

解决办法:解锁磁盘,重新挂载

bash 复制代码
    # 在windows窗口运行以下命令,不要进到adb shell 里面运行
    D:\platform-tools> adb root

    # 解锁分区(需要升级到最新版本adb,才有disable-verity工具)
    D:\platform-tools> adb disable-verity

    # 重新挂载,没加权限 表示rwx全部挂上
    D:\platform-tools> adb remount
报错3:

报错:如果是旧版本adb会显示如下信息

sql 复制代码
    networking:
      adb ppp <tty> [parameters]   - Run PPP over USB.
     Note: you should not automatically start a PPP connection.
     <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1
     [parameters] - Eg. defaultroute debug dump local notty usepeerdns

    adb sync notes: adb sync [ <directory> ]
      <localdir> can be interpreted in several ways:

      - If <directory> is not specified, both /system and /data partitions will be updated.

      - If it is "system" or "data", only the corresponding partition
        is updated.

    environmental variables:
      ADB_TRACE                    - Print debug information. A comma separated list of the following values
                                     1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp
      ANDROID_SERIAL               - The serial number to connect to. -s takes priority over this if given.
      ANDROID_LOG_TAGS             - When used with the logcat option, only these debug tags are printed.

原因:旧版本adb不含disable-verity 工具包

解决办法:安装最新adb工具

报错4:

报错:Failed to read fstab Maybe run adb root?

arduino 复制代码
    Failed to read fstab Maybe run adb root?

原因:雷电模拟器9把,这块直接界面化了,不需要通过disable-verity 解锁磁盘,但是其他种类模拟器会用到这个功能,大同小异,自己拿捏吧

解决办法:在模拟器设置,磁盘管理开启 system.vmdk可写入

解决雷电模拟器问题直接从这开始看,以上是报错处理,供其他模拟器参考分析。

perl 复制代码
    # 在windows窗口运行以下命令,不要进到adb shell 里面运行
    D:\platform-tools> adb root

    # 雷电模拟器,直接在设置打开磁盘写入功能

    # 重新挂载,没加权限 表示rwx全部挂上
    D:\platform-tools> adb remount

    # 进入adb shell
    D:platform-tools>adb shell

    # 查看用户证书位置
    gracelte:/ # ls /data/misc/user/0/cacerts-added/
    e5c3944b.0

    # 拷贝证书到目标文件夹
    gracelte:/ # mv /data/misc/user/0/cacerts-added/e5c3944b.0 /system/etc/security/cacerts/

雷电模拟器,直接在设置打开磁盘写入功能

将以上配置完重启模拟器和fiddler就可以抓包了

四、后端服务搭建

基于第三步,apk的数据已经可以通过fiddler拦截并抓取到了,那么对于这一条一条请求数据我们该怎么进行提取并进行分析呢。

方案一:

这里博主一开始是通过自定义规则,对特定的url 进行拦截,然后将请求内容和响应内容写入到本地txt文件,

然后通过程序去读取txt 文件并解析,运行了一段时间后,发现fiddler 写入到本地的文件编码格式为 utf16El ,每次去转码另存为太麻烦,遂采用了第二种方案。

方案二:

在这里,主要也是通过fiddler的自定义规则,在 OnBeforeResponse 方法中,对于获取到的请求和响应,直接再次发送到我们自己的服务上,在我们自己的服务上对 json 数据进行解析,直接存入数据库(这里可以结合自己的需求对数据进行解析去重),说做就做!

1、fiddler 自定义规则

见上图,找到fiddler中的自定义规则,这边自定义规则,在我看来主要是一个c#的语法,与c#不同的是,在导包的时候,c#这边使用的是using, 自定义规则里面使用的是 import,至于这个脚本语言的编写,大家可以自定研究,博主这里主要针对我自己的需求提供下相关代码。

因为需要用到网络请求,所以这里我引用了c#的一些原生包,大家用到的话,可以在规则的头部加上这些

ini 复制代码
    import System;
    import System.Windows.Forms;
    import Fiddler;
    import System.IO;
    import System.Net;
    import System.Text;
    import System.Threading.Tasks;
    import Newtonsoft.Json;
    import System.Net.Http;

2、对fiddler的response 转发到自己的服务

博主这里主要是对response 数据进行二次请求到我们自己的服务,那么可以在 OnBeforeResponse中添加以下方法:

javascript 复制代码
	static function OnBeforeResponse(oSession: Session) {
		if (m_Hide304s && oSession.responseCode == 304) {
			oSession["ui-hide"] = "true";
		}

		if (oSession.fullUrl.Contains("api.chenlongtech.cn/v1/gift")){
			try{
				// 获取响应内容
				var responseContent = oSession.GetResponseBodyAsString().replace(/"/g,"'");
				// 地址替换成自己的服务地址
            	var newServiceUrl = "http://127.0.0.1:8080/uki/msg";
				var webClient = new WebClient();
				webClient.Headers["Content-Type"] = "application/json";
                // 防止后端服务中文乱码
				webClient.Headers["charset"] = "utf-8";
                // 这行是自定义需求,博主需要拿到request的请求里面的时间,你们用不到可不加
				webClient.Headers["x-timestamp"] = oSession.oRequest.headers["x-timestamp"];
                // 防止后端服务中文乱码
				webClient.Encoding = Encoding.UTF8;
				var newServiceResponse = webClient.UploadString(newServiceUrl, "POST", responseContent);
			}catch(e){
			}
		}

	}

2.1、后端服务controller接收解析数据

这里的后端语言是java,在controller里面对上面转发的response 数据进行接收,这部分代码就简单贴一下,如果如要,后面博主可以传到gitee 上

kotlin 复制代码
package com.see.you.controller;
import com.see.you.pojo.Result;
import com.see.you.service.UkiService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/uki")
public class UkiController {

    @Resource
    private UkiService ukiService;

    /**
     * 接收fiddler的response的数据
     * @param json 原始json
     * @param request req
     * @return
     */
    @PostMapping(value = "/msg", produces = "application/json;charset=UTF-8")
    public Result<String> test(@RequestBody String json, HttpServletRequest request) {
        String timestamp = request.getHeader("x-timestamp");
        ukiService.handleJson(json, timestamp);
        return Result.success("");
    }

    /**
     * 先保存数据
     * 再保存百分比
     * 再清洗数据去重
     */
    @GetMapping("/list")
    public Result<String> parseGift() {
        ukiService.listGift();
        return Result.success("");
    }
}

这边如果取到的json数据有问题,可能需要替换一下。

ini 复制代码
json = json.replace('\'', '\"');

3、对fiddler的response 保存到本地

另外在规则里面,找到 OnBeforeResponse 该方法,如果你需要写入本地 txt 文件,可以添加以下代码

ini 复制代码
// api.chenlongtech.cn/v1/gift 这里的地址可以替换你们需要拦截的地址
if (oSession.fullUrl.Contains("api.chenlongtech.cn/v1/gift")){
    //消除保存的请求可能存在乱码的情况
    oSession.utilDecodeResponse();
    var fso;
    var file;
    fso = new ActiveXObject("Scripting.FileSystemObject");
    //文件保存路径,可自定义
    file = fso.OpenTextFile("D:\\logs\\gift.txt",8 ,true, true);
    file.writeLine(oSession.GetResponseBodyAsString());
    file.writeLine("\n");
    file.close();
}

五、数据分析

数据通过后端服务已经落库,后面想怎么分析就怎么分析啦~

六、总结

蛮有意思的~

相关推荐
小羊失眠啦.2 分钟前
深入解析Rust的所有权系统:告别空指针和数据竞争
开发语言·后端·rust
q***718539 分钟前
Spring Boot 集成 MyBatis 全面讲解
spring boot·后端·mybatis
大象席地抽烟1 小时前
使用 Ollama 本地模型与 Spring AI Alibaba
后端
程序员小假1 小时前
SQL 语句左连接右连接内连接如何使用,区别是什么?
java·后端
小坏讲微服务1 小时前
Spring Cloud Alibaba Gateway 集成 Redis 限流的完整配置
数据库·redis·分布式·后端·spring cloud·架构·gateway
方圆想当图灵1 小时前
Nacos 源码深度畅游:Nacos 配置同步详解(下)
分布式·后端·github
方圆想当图灵2 小时前
Nacos 源码深度畅游:Nacos 配置同步详解(上)
分布式·后端·github
小羊失眠啦.2 小时前
用 Rust 实现高性能并发下载器:从原理到实战
开发语言·后端·rust
Filotimo_3 小时前
SpringBoot3入门
java·spring boot·后端
一 乐3 小时前
校园墙|校园社区|基于Java+vue的校园墙小程序系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端·小程序