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();
}

五、数据分析

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

六、总结

蛮有意思的~

相关推荐
码上一元3 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
枫叶_v5 小时前
【SpringBoot】22 Txt、Csv文件的读取和写入
java·spring boot·后端
杜杜的man5 小时前
【go从零单排】Closing Channels通道关闭、Range over Channels
开发语言·后端·golang
java小吕布6 小时前
Java中Properties的使用详解
java·开发语言·后端
2401_857610037 小时前
Spring Boot框架:电商系统的技术优势
java·spring boot·后端
杨哥带你写代码8 小时前
网上商城系统:Spring Boot框架的实现
java·spring boot·后端
camellias_8 小时前
SpringBoot(二十一)SpringBoot自定义CURL请求类
java·spring boot·后端
背水9 小时前
初识Spring
java·后端·spring
晴天飛 雪9 小时前
Spring Boot MySQL 分库分表
spring boot·后端·mysql
weixin_537590459 小时前
《Spring boot从入门到实战》第七章习题答案
数据库·spring boot·后端