Android端应用逆向分析:关键接口与数据提取实操指南(机票APP场景)

一、逆向分析前置准备(工具与环境)

在开始 Android 端逆向前,需搭建适配的工具链,覆盖 “抓包 - 反编译 - 动态调试” 全流程,尤其针对机票 APP 常见的加密加固场景(如 360 加固、爱加密),需额外准备脱壳工具。

1. 核心工具清单
工具类别工具名称用途说明机票 APP 适配点
抓包工具Fiddler/Charles捕获 APP 网络请求,获取接口 URL、参数、响应数据分析机票查询、预订接口的请求格式(如是否含 sign 签名、timestamp 时间戳)
脱壳工具Frida-dexdump/BlackDex对加固 APP 脱壳,提取真实 DEX 文件(核心代码载体)多数航司 APP 会加固,需脱壳后才能反编译查看接口加密逻辑
反编译工具Apktool/Jadx-Gui反编译 APK 为 Smali/Java 代码,查看源码逻辑定位接口调用处(如机票价格请求的方法名、参数组装逻辑)
动态调试工具Frida/IDA Pro动态 Hook APP 方法,打印参数与返回值,破解加密算法Hook 机票接口的加密函数(如 sign 生成方法),获取明文参数
模拟器 / 真机夜神模拟器 / ROOT 安卓机运行待逆向 APP,提供逆向环境(需 ROOT 或开启 USB 调试)模拟器可规避部分 APP 的真机检测,适合初期测试
代码编辑器VS Code(Smali 插件)编辑 Smali 代码(如需修改 APP 逻辑绕过检测)若 APP 检测 Root 环境,可修改 Smali 代码禁用检测逻辑
2. 环境配置关键步骤
  • ROOT 环境搭建

    真机选择已 ROOT 的 Android 设备(如小米 / 一加,解锁 Bootloader 后刷入 Magisk);模拟器需开启 “ROOT 权限”(夜神模拟器:设置→开启 ROOT 权限→重启),确保 Frida 等工具能正常注入。

  • 证书配置(抓包必备)

    因机票 APP 多采用 HTTPS 协议,需将 Fiddler/Charles 根证书安装到 Android 设备(系统证书目录:/system/etc/security/cacerts/),避免抓包时出现 “证书无效” 导致请求失败。

    注意:Android 7.0 + 默认不信任用户证书,需将证书转为系统证书格式(.0 格式)并通过 ROOT 权限复制到系统目录。

二、逆向核心流程:从抓包到接口提取(机票 APP 案例)

以 “某航司 Android APP” 为例,完整拆解从网络请求分析到关键接口提取的全流程,重点解决 “接口加密”“参数未知” 两大核心问题。

1. 第一步:初步抓包分析(定位目标接口)

目标:通过抓包确定机票相关接口的基本信息(URL、请求方式、参数特征),为后续逆向提供方向。

操作步骤:
  1. 配置 Fiddler 代理

    手机 / 模拟器与电脑处于同一局域网,设置代理 IP 为电脑 IP,端口为 Fiddler 默认端口(8888),开启 Fiddler 的 “Capture Traffic”。

  2. 触发目标行为

    打开航司 APP,操作 “查询北京 - 上海 2025 年 1 月 10 日机票”,Fiddler 捕获到请求(如https://api.airline.com/flights/query)。

  3. 分析请求特征

  • 查看 “Inspectors→Headers”:确认请求方法为 POST,Content-Type 为application/json,请求头含Device-ID(设备唯一标识)、Token(用户登录态)。

  • 查看 “Inspectors→Request Body”:发现参数加密(如{"data":"U2FsdGVkX1+...","sign":"a3f2d1e4..."}),无法直接获取明文参数(如出发地、日期)。

结论:该机票查询接口参数已加密,需通过反编译与动态调试破解加密逻辑。

2. 第二步:APP 脱壳(提取可反编译的 DEX 文件)

若航司 APP 已加固(如启动页显示 “360 加固保护”),直接用 Apktool 反编译会得到加密的 DEX 文件(如classes.dex.encrypted),需先脱壳。

实操(以 Frida-dexdump 为例):
  1. 安装 Frida 环境

    电脑端:pip install frida-tools;手机端:根据 CPU 架构(arm64/arm)推送对应版本的frida-server/data/local/tmp/,并赋予执行权限(chmod 755 frida-server),启动服务(./frida-server)。

  2. 执行脱壳命令

\# 查看APP包名(如com.airline.app)

adb shell dumpsys window | grep mCurrentFocus

\# 脱壳并输出DEX文件到当前目录

frida-dexdump -U -f com.airline.app -o ./dex\_output
  1. 验证脱壳结果

    进入dex_output目录,若存在classes.dex“classes2.dex” 等文件,且文件大小正常(通常几 MB),说明脱壳成功。

3. 第三步:反编译(定位加密与接口调用逻辑)

用 Jadx-Gui 打开脱壳后的 DEX 文件,可视化查看 Java 代码,定位机票接口的加密方法与调用处。

关键操作:
  1. 搜索关键词定位

    在 Jadx-Gui 中搜索抓包得到的接口 URL 片段(如/flights/query),找到对应的请求方法:

// 示例:找到机票查询接口的调用方法

public class FlightApi {

    public static void queryFlight(String departCity, String destCity, String date, Callback callback) {

        // 1. 组装明文参数

        HashMap\<String, String> params = new HashMap<>();

        params.put("departCity", departCity);

        params.put("destCity", destCity);

        params.put("date", date);

        params.put("timestamp", String.valueOf(System.currentTimeMillis()));

        

        // 2. 加密参数(关键:调用EncryptUtil加密)

        String encryptedData = EncryptUtil.encrypt(params.toString());

        String sign = EncryptUtil.generateSign(params);

        

        // 3. 发起POST请求

        OkHttpClient client = new OkHttpClient();

        RequestBody body = RequestBody.create(MediaType.parse("application/json"), 

            "{\\"data\\":\\"" + encryptedData + "\\",\\"sign\\":\\"" + sign + "\\"}");

        Request request = new Request.Builder()

            .url("https://api.airline.com/flights/query")

            .post(body)

            .build();

        client.newCall(request).enqueue(callback);

    }

}
  1. 分析加密逻辑

    定位EncryptUtil类,查看encryptgenerateSign方法:

  • encrypt方法:使用 AES 算法,密钥从Build.MANUFACTURER(设备厂商)与固定字符串拼接生成(如key = "airline_" + Build.MANUFACTURER)。

  • generateSign方法:将参数按 key 排序后拼接,再用 MD5 哈希生成 sign(如sign = MD5(paramsSortedStr + "secretKey123"))。

关键发现:已明确接口参数的加密算法(AES)、密钥生成规则、sign 签名逻辑,下一步通过动态调试验证并提取明文参数。

4. 第四步:动态调试(Hook 加密方法,提取明文与接口)

用 Frida 编写 Hook 脚本,动态拦截EncryptUtil.encryptFlightApi.queryFlight方法,打印明文参数、加密结果、接口 URL,最终获取可直接调用的接口信息。

Frida Hook 脚本示例(hook_flight_api.js):
// 1. Hook EncryptUtil.encrypt方法,打印明文与加密结果

Java.use("com.airline.util.EncryptUtil").encrypt.implementation = function(plainText) {

    console.log("\[+] EncryptUtil.encrypt 明文参数: " + plainText);

    // 调用原方法获取加密结果

    var encrypted = this.encrypt(plainText);

    console.log("\[+] EncryptUtil.encrypt 加密结果: " + encrypted);

    return encrypted;

};

// 2. Hook FlightApi.queryFlight方法,打印完整参数与接口URL

Java.use("com.airline.api.FlightApi").queryFlight.implementation = function(departCity, destCity, date, callback) {

    console.log("\[+] 机票查询接口参数: ");

    console.log("    出发地: " + departCity);

    console.log("    目的地: " + destCity);

    console.log("    日期: " + date);

    console.log("    接口URL: https://api.airline.com/flights/query");

    // 调用原方法,不影响APP正常运行

    this.queryFlight(departCity, destCity, date, callback);

};
执行 Hook 并查看结果:
  1. 运行 Hook 脚本
frida -U -f com.airline.app -l hook\_flight\_api.js --no-pause
  1. 触发查询行为

    在 APP 中再次查询 “北京 - 上海 2025 年 1 月 10 日机票”,电脑端控制台输出:

\[+] 机票查询接口参数: 

    出发地: PEK(北京首都机场三字码)

    目的地: SHA(上海虹桥机场三字码)

    日期: 2025-01-10

    接口URL: https://api.airline.com/flights/query

\[+] EncryptUtil.encrypt 明文参数: {"departCity":"PEK","destCity":"SHA","date":"2025-01-10","timestamp":1736486400000}

\[+] EncryptUtil.encrypt 加密结果: U2FsdGVkX1+...(与抓包结果一致)

成果:已提取到机票查询接口的明文参数规则(出发地用三字码、含 timestamp)、完整 URL加密算法细节,可基于此编写 Python 脚本模拟请求。

三、关键数据提取与接口调用(落地实现)

基于逆向得到的接口信息,编写 Python 脚本模拟 APP 请求,提取机票价格、舱位等关键数据,解决 “手动抓包无法自动化” 的问题。

1. 还原加密逻辑(Python 实现)

根据逆向得到的 AES 加密与 sign 生成规则,编写加密工具函数:

import json

import time

import hashlib

from Crypto.Cipher import AES

from Crypto.Util.Padding import pad

from base64 import b64encode

\# 1. AES加密(对应APP中的EncryptUtil.encrypt)

def aes\_encrypt(plain\_text, device\_manufacturer="Xiaomi"):

    \# 密钥生成规则:airline\_ + 设备厂商(APP中获取Build.MANUFACTURER)

    key = ("airline\_" + device\_manufacturer).encode("utf-8")

    \# AES模式:CBC,IV为固定16位(逆向从代码中找到:"airline\_iv\_123456")

    iv = "airline\_iv\_123456".encode("utf-8")

    \# 明文编码并补位

    plain\_bytes = plain\_text.encode("utf-8")

    padded\_bytes = pad(plain\_bytes, AES.block\_size)

    \# 加密

    cipher = AES.new(key, AES.MODE\_CBC, iv)

    encrypted\_bytes = cipher.encrypt(padded\_bytes)

    \# Base64编码返回(与APP加密结果格式一致)

    return b64encode(encrypted\_bytes).decode("utf-8")

\# 2. 生成sign(对应APP中的EncryptUtil.generateSign)

def generate\_sign(params, secret\_key="secretKey123"):

    \# 参数按key升序排序

    sorted\_params = sorted(params.items(), key=lambda x: x\[0])

    \# 拼接为字符串(如departCity=PEK\&date=2025-01-10...)

    params\_str = "&".join(\[f"{k}={v}" for k, v in sorted\_params])

    \# 拼接secretKey后MD5哈希

    sign\_str = params\_str + secret\_key

    return hashlib.md5(sign\_str.encode("utf-8")).hexdigest()

\# 3. 组装请求参数

def build\_request\_params(depart\_city, dest\_city, date):

    \# 明文参数(与APP中一致)

    params = {

        "departCity": depart\_city,

        "destCity": dest\_city,

        "date": date,

        "timestamp": str(int(time.time() \* 1000))  # 毫秒级时间戳

    }

    \# 加密data与生成sign

    encrypted\_data = aes\_encrypt(json.dumps(params))

    sign = generate\_sign(params)

    \# 返回最终请求体

    return {

        "data": encrypted\_data,

        "sign": sign

    }
2. 调用接口提取机票数据

使用requests库发送 POST 请求,解析响应数据(需先逆向响应解密逻辑,此处假设响应为明文 JSON):

import requests

def get\_flight\_data(depart\_city, dest\_city, date):

    \# 1. 组装请求参数

    request\_body = build\_request\_params(depart\_city, dest\_city, date)

    \# 2. 设置请求头(与APP抓包结果一致,含Device-ID、Token)

    headers = {

        "User-Agent": "AirlineApp/7.2.0 (Android; 13; Xiaomi M2102K1C)",

        "Device-ID": "861234567890123",  # 从APP中Hook获取真实Device-ID

        "Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",  # 登录后获取的Token

        "Content-Type": "application/json"

    }

    \# 3. 发送请求

    url = "https://api.airline.com/flights/query"

    response = requests.post(url, json=request\_body, headers=headers, verify=False)

    \# 4. 解析响应(示例:响应为机票列表JSON)

    if response.status\_code == 200:

        flight\_list = response.json()\["data"]\["flights"]

        \# 提取关键数据(航班号、价格、舱位)

        result = \[]

        for flight in flight\_list:

            result.append({

                "flight\_no": flight\["flightNo"],

                "depart\_time": flight\["departTime"],

                "arrive\_time": flight\["arriveTime"],

                "cabin": flight\["cabin"],

                "price": flight\["price"],

                "remaining\_seats": flight\["remainingSeats"]  # 剩余座位数

            })

        return result

    else:

        raise Exception(f"接口请求失败:{response.status\_code},响应:{response.text}")

\# 调用示例:查询北京(PEK)-上海(SHA)2025-01-10机票

if \_\_name\_\_ == "\_\_main\_\_":

    flights = get\_flight\_data("PEK", "SHA", "2025-01-10")

    print("提取的机票数据:")

    for idx, flight in enumerate(flights, 1):

        print(f"\n航班{idx}:")

        print(f"  航班号:{flight\['flight\_no']}")

        print(f"  时间:{flight\['depart\_time']} - {flight\['arrive\_time']}")

        print(f"  舱位/价格:{flight\['cabin']} / ¥{flight\['price']}")

        print(f"  剩余座位:{flight\['remaining\_seats']}")

四、常见问题与解决方案(QA)

Q1:逆向时 APP 检测到 Root / 模拟器,直接闪退怎么办?

A:两种应对方案:

  1. 修改 Smali 代码绕过检测:用 Apktool 反编译 APP,搜索 “Root”“emulator” 相关关键词,找到检测方法(如isRooted()),将返回值改为false(Smali 中const/4 v0, 0x0),重新打包签名。
  • 示例:若找到 Smali 代码method public static isRooted()Z,原代码为:
.method public static isRooted()Z

    .locals 1

    \# 原逻辑:检测到 Root 则返回 0x1(true)

    const/4 v0, 0x1

    return v0

.end method
  • 修改后:
.method public static isRooted()Z

    .locals 1

    \# 强制返回 0x0(false),绕过 Root 检测

    const/4 v0, 0x0

    return v0

.end method
  • 重新打包:apktool b 反编译目录 -o modified.apk,再用 jarsigner 签名(需提前生成签名文件:keytool -genkey -v -keystore my.keystore -alias myalias -keyalg RSA -validity 3650)。
  1. 使用 Frida Hook 禁用检测:编写 Hook 脚本拦截检测方法,强制返回 “非 Root / 非模拟器”:
// Hook Root 检测方法

Java.use("com.airline.util.DeviceCheck").isRooted.implementation = function() {

    console.log("\[+] 绕过 Root 检测");

    return false; // 强制返回非 Root

};

// Hook 模拟器检测方法(如 isEmulator())

Java.use("com.airline.util.DeviceCheck").isEmulator.implementation = function() {

    console.log("\[+] 绕过模拟器检测");

    return false; // 强制返回非模拟器

};

// 若检测通过 Build.PROP 识别模拟器,Hook Build 类修改属性

Java.use("android.os.Build").MANUFACTURER.implementation = function() {

    return "Xiaomi"; // 伪装为小米真机

};

Java.use("android.os.Build").MODEL.implementation = function() {

    return "M2102K1C"; // 伪装为小米11机型

};
  • 执行脚本:frida -U -f com.airline.app -l hook_bypass_detection.js --no-pause,APP 即可正常启动。
Q2:接口参数中出现动态变化的 “nonce”“sign”,逆向时无法固定生成规则怎么办?

A:这类动态参数通常由 APP 本地算法生成(如结合时间戳、设备信息、随机字符串),可通过以下两种方式解决:

  1. Hook 动态参数生成方法:直接拦截生成参数的函数,获取最终生成的参数值,无需还原算法。
  • 示例:若 signSignUtil.generateSign(params, nonce, timestamp) 生成,Hook 该方法:
// 找到 SignUtil 类的 generateSign 方法(需根据实际包名调整)

const SignUtil = Java.use("com.airline.util.SignUtil");

// 重载方法(需匹配参数个数与类型,此处假设为 3 个参数:params(Map)、nonce(String)、timestamp(String))

SignUtil.generateSign.overload("java.util.Map", "java.lang.String", "java.lang.String").implementation = function(params, nonce, timestamp) {

    // 打印输入参数

    console.log("\[+] generateSign 参数:");

    console.log("    params: " + JSON.stringify(params));

    console.log("    nonce: " + nonce);

    console.log("    timestamp: " + timestamp);

    // 调用原方法获取 sign

    const sign = this.generateSign(params, nonce, timestamp);

    console.log("\[+] 生成的 sign: " + sign);

    return sign;

};
  • 执行脚本后,触发接口请求,控制台会输出 nonce“timestamp”“sign” 的真实值,直接用于 Python 模拟请求即可。
  1. 直接调用 APP 本地算法生成参数:若参数生成逻辑复杂(如涉及 Native 层 C++ 代码),可通过 frida-injectXposed 模块,在 APP 运行时调用其算法生成参数,再传递给爬虫脚本。
  • 示例:用 Frida 调用 generateSign 方法生成参数:
// 在脚本中主动调用 APP 方法生成 sign

function generateSignForCrawl(params) {

    const SignUtil = Java.use("com.airline.util.SignUtil");

    const nonce = Java.use("java.util.UUID").randomUUID().toString().replace(/-/g, ""); // 生成随机 nonce(模仿 APP 逻辑)

    const timestamp = String(Date.now());

    const sign = SignUtil.generateSign(params, nonce, timestamp);

    return { nonce, timestamp, sign };

}

// 暴露方法给外部(如通过 frida-rpc 供 Python 调用)

rpc.exports = {

    getsign: generateSignForCrawl

};
  • Python 端调用:
import frida

import json

\# 连接设备

device = frida.get\_usb\_device()

\# 附加到 APP 进程

session = device.attach("com.airline.app")

\# 加载脚本

with open("hook\_call\_sign\_method.js", "r", encoding="utf-8") as f:

    script = session.create\_script(f.read())

script.load()

\# 调用脚本中的 getsign 方法生成参数

params = {"departCity": "PEK", "destCity": "SHA", "date": "2025-01-10"}

sign\_data = script.exports.getsign(params)

print("动态参数:", sign\_data)

\# 输出:{"nonce": "a1b2c3d4e5f6...", "timestamp": "1736486400000", "sign": "f8e7d6c5b4a3..."}
Q3:接口响应是加密数据(如乱码字符串),无法直接解析怎么办?

A:需先逆向响应解密逻辑,步骤如下:

  1. 定位解密方法:在 Jadx-Gui 中搜索 “decrypt”“decode” 等关键词,或跟踪接口回调逻辑(如 FlightApi.queryFlightCallback 实现类),找到响应处理代码。
  • 示例:回调中解密响应的代码:
public class FlightCallback implements Callback {

    @Override

    public void onSuccess(String response) {

        // 响应解密(调用 EncryptUtil.decrypt)

        String decryptedResponse = EncryptUtil.decrypt(response);

        // 解析明文 JSON

        JSONObject json = new JSONObject(decryptedResponse);

        List\<Flight> flightList = parseFlightList(json);

    }

}
  1. 分析解密算法:查看 EncryptUtil.decrypt 方法,确认算法类型(如 AES、RSA)、密钥、IV 等信息。
  • 示例:AES 解密逻辑:
public static String decrypt(String encryptedData) {

    // 密钥与加密时一致(airline\_ + 设备厂商)

    String key = "airline\_" + Build.MANUFACTURER;

    String iv = "airline\_iv\_123456"; // 与加密 IV 相同

    //  Base64 解码 → AES 解密 → 去除补位

    byte\[] encryptedBytes = Base64.decode(encryptedData, Base64.DEFAULT);

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

    cipher.init(Cipher.DECRYPT\_MODE, new SecretKeySpec(key.getBytes(), "AES"), new IvParameterSpec(iv.getBytes()));

    byte\[] decryptedBytes = cipher.doFinal(encryptedBytes);

    return new String(decryptedBytes, StandardCharsets.UTF\_8);

}
  1. Python 实现解密:根据逆向结果编写解密函数,解析响应数据:
from Crypto.Cipher import AES

from Crypto.Util.Padding import unpad

from base64 import b64decode

def aes\_decrypt(encrypted\_data, device\_manufacturer="Xiaomi"):

    \# 与 APP 解密逻辑一致

    key = ("airline\_" + device\_manufacturer).encode("utf-8")

    iv = "airline\_iv\_123456".encode("utf-8")

    \# Base64 解码

    encrypted\_bytes = b64decode(encrypted\_data)

    \# AES 解密

    cipher = AES.new(key, AES.MODE\_CBC, iv)

    decrypted\_bytes = cipher.decrypt(encrypted\_bytes)

    \# 去除补位(PKCS5Padding)

    plain\_bytes = unpad(decrypted\_bytes, AES.block\_size)

    return plain\_bytes.decode("utf-8")

\# 调用示例:解密接口响应

encrypted\_response = response.json()\["data"]  # 加密的响应数据

plain\_response = aes\_decrypt(encrypted\_response)

flight\_json = json.loads(plain\_response)

print("解密后的机票数据:", flight\_json)
Q4:APP 采用 Native 层(C/C++)加密,Jadx-Gui 无法查看代码怎么办?

A:Native 层加密需通过逆向 SO 文件(libxxx.so)解决,核心步骤如下:

  1. 提取 SO 文件:从 APK 解压目录的 lib/arm64-v8a/(或 lib/armeabi-v7a/)文件夹中找到加密相关的 SO 文件(如 libencrypt.so)。

  2. 分析 SO 文件:使用 IDA Pro 或 Ghidra 反编译 SO 文件,定位加密函数(如 Java_com_airline_util_EncryptUtil_nativeEncrypt,对应 Java 层的 native encrypt 方法)。

  • 关键技巧:在 IDA 中搜索 “AES”“MD5” 等关键词,或跟踪函数调用栈,找到加密算法的核心逻辑(如 AES 密钥扩展、轮函数)。
  1. Hook Native 函数:若无法还原算法,直接用 Frida Hook Native 方法获取输入输出:
// Hook Native 加密函数(需根据实际函数签名调整)

// 函数签名格式:Java\_包名\_类名\_方法名(包名中的 . 替换为 \_,内部类用 \$ 连接)

Interceptor.attach(Module.findExportByName("libencrypt.so", "Java\_com\_airline\_util\_EncryptUtil\_nativeEncrypt"), {

    onEnter: function(args) {

        // args\[0] = JNIEnv\*, args\[1] = jobject(this), args\[2] = jstring(明文参数)

        const plainText = Java.vm.getEnv().getStringUtfChars(args\[2], null).readCString();

        console.log("\[+] Native 加密明文:", plainText);

        // 保存明文参数,供 onLeave 时使用

        this.plainText = plainText;

    },

    onLeave: function(retval) {

        // retval = jstring(加密结果)

        const encryptedText = Java.vm.getEnv().getStringUtfChars(retval, null).readCString();

        console.log("\[+] Native 加密结果:", encryptedText);

    }

});
  • 执行脚本后,即可获取 Native 层加密的明文与结果,直接用于模拟请求。

五、逆向合规性与风险提示

  1. 法律合规
  • 逆向前需确认 APP 的《用户协议》《隐私政策》,禁止逆向未经授权的商业 APP(如航司 APP 若明确禁止 “抓取、逆向”,需提前获得授权);

  • 禁止利用逆向获取的数据从事违法活动(如倒卖机票价格、侵犯用户隐私),仅可用于合法的技术研究或企业内部数据分析。

  1. 技术风险
  • 部分 APP 采用 “加固 + 反调试 + 行为检测” 三重防护(如梆梆加固、爱加密高级版),逆向难度极高,可能导致工具崩溃、设备被封禁;

  • 动态调试时需避免频繁操作,防止 APP 触发风控系统(如临时封禁设备 ID、账号),建议使用测试账号而非真实用户账号。

  1. 维护成本
  • APP 版本更新可能导致加密算法、接口参数变化(如 sign 生成规则修改),需定期重新逆向,确保爬虫脚本兼容性;

  • 建议监控接口返回码(如 401 未授权、403 禁止访问),及时发现逆向逻辑失效问题。

六、工具链推荐与进阶学习

1. 进阶工具推荐
工具名称用途说明适用场景
ObjectionFrida 可视化交互工具,支持一键绕过 Root 检测、查看内存中的类与方法快速调试,无需编写复杂 Hook 脚本
Xposed + JustTrustMe禁用 APP 的 SSL 证书校验,解决抓包时 “证书无效” 问题无需安装系统证书,适合 Android 7.0+ 设备
GDA (Ghidra)免费开源的逆向工具,支持反编译 SO 文件、分析 Native 代码替代 IDA Pro(收费),适合个人学习
Packet CaptureAndroid 端抓包工具,无需电脑,直接在手机上捕获 APP 网络请求临时分析,无需配置代理
2. 学习资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝麻开门-新起点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值