[App逆向]环境搭建下篇 — — 逆向源码+hook实战

[App逆向]环境搭建下篇------逆向源码+hook

上篇:[App逆向]环境搭建上篇------抓取apk https包

免责声明:本教程仅供技术学习和安全研究使用,禁止用于任何非法用途。逆向他人 App 前请获得授权。

环境搭建

1. 安装jadx------逆向代码

1.安装jadx

方式一:mac用户可直接通过brew安装

bash 复制代码
brew install jadx

# jadx --version
1.5.1


方式二:如果不想通过brew安装的也可以直接下载zip包

访问Github:https://github.com/skylot/jadx/releases/tag/v1.5.5下载jadx zip包

  1. 解析apk源文件
bash 复制代码
# 1. 启动jadx可视化页面
## mac/linux用户
jadx-gui 

## Windows用户,双击即可启动
jadx-gui.bat

# 2. 将需要反编译的apk拖入jadx可视化页面即可

2. 安装Frida------Hook

Hook 是一种在程序运行时动态修改或拦截函数调用、参数或返回值的技术。在 Android 安全研究、逆向分析以及自动化测试中,Hook 技术扮演着至关重要的角色。

目前 Android 生态中主流的 Hook 框架主要有两种,而本文将重点介绍逆向中最常用的 Frida 框架。

Frida 采用 C/S 架构(客户端/服务端),安装分为 PC 端(客户端)和手机端(服务端)两部分。

1.安装 PC 端(客户端)

bash 复制代码
#  确保已安装 Python 环境,使用 pip 安装:
# 推荐指定版本安装(PC 端和手机端版本保持一致,以保证稳定性):
pip install frida==17.6.2 frida-tools

# 安装最新版
# pip install frida frida-tools
  1. 安装手机端(服务端)
    第一步:确认设备 CPU 架构
bash 复制代码
adb shell getprop ro.product.cpu.abi


第二步 :下载对应版本的 frida-server

前往 Frida Releases 下载。

📌 下载原则:版本号与 PC 端一致,架构与手机匹配。 例如:手机为 arm64-v8a,PC 端 Frida 版本为 17.6.2,则下载 frida-server-17.6.2-android-arm64.xz。下载后直接双击解压即可。

第三步:部署到手机

bash 复制代码
# 1. 推送到手机临时目录
adb push frida-server-17.6.2-android-arm64 /data/local/tmp/

# 2. 进入手机 Shell 并提权
adb shell
su

# 3. 赋予执行权限并后台运行
chmod +x /data/local/tmp/frida-server-17.6.2-android-arm64
/data/local/tmp/frida-server-17.6.2-android-arm64 &

## 如果要退出Frida hook,执行exit命令即可

💡 建议重命名 frida-server 文件(如 fs),既方便输入,也能规避部分 App 对 "frida-server" 文件名的字符串检测。


第四步:检查是否能hook

bash 复制代码
# 本地mac执行下面命令,列出已连接的设备
frida-ls-devices

# 查看当前手机上活跃的进程
frida-ps -U

比如我就hook下我的设置应用,首先打开设置应用,然后编写js代码

main.js:

javascript 复制代码
Java.perform(function () {
    console.log("[*] Hook script loaded successfully!");

    // Hook android.util.Log 的 d() 方法(调试日志输出函数)
    var Log = Java.use("android.util.Log");
    Log.d.overload("java.lang.String", "java.lang.String").implementation = function (tag, msg) {
        console.log("[+] Log.d called");
        console.log("    Tag: " + tag);
        console.log("    Message: " + msg);
        // 调用原始方法,保持原有日志输出
        return this.d(tag, msg);
    };
});
bash 复制代码
# 终端执行下面命令,进行hook。然后点击任意子模块,比如【通知模块】等
frida -U -n "设置" -l main.js

出现有日志打印,表示hook没问题。

拓展:Frida Hook 有两种方式,分别是 附加模式(Attach) 和 孵化模式(Spawn)

bash 复制代码
# 1. 附加模式 (Attach) -- 进程已运行时
#Frida 连接到已经在运行的进程,适合对已经打开的应用进行 Hook,或者需要动态注入脚本的场景。例如:
frida -U -n "设置" -l main.js

# 2. 孵化模式 (Spawn) -- 应用未启动时
#Frida 先启动应用(孵化进程),然后立即注入脚本,适合需要 Hook 应用启动过程中的初始化代码或 onCreate 等早期方法。
#-f 后跟包名,表示启动该应用。
#--no-pause 让应用自动继续运行(否则需要手动调用 resume())。
frida -U -f com.android.settings -l main.js --no-pause
特性 Attach (附加) Spawn (孵化)
目标状态 进程已存在 进程未启动
能否 Hook 启动过程 ❌ 可能错过早期方法 ✅ 可 Hook 从 onCreate 开始的所有代码
命令标志 -n 或 -p -f
常见用途 动态注入、调试已运行应用 分析应用启动流程、绕过反调试

实战案例

App逆向常规思路:从抓包找到可疑参数 → 静态分析定位代码 → 动态 Hook 验证猜想 → 编写脚本模拟请求。

术语 核心任务 典型应用场景 工具示例
抓包反编译 静态分析:通过抓包获取接口参数,再反编译APK找到对应的加密/签名代码逻辑 分析通信协议、查找硬编码密钥、理解功能实现 Charles + Jadx
抓包逆向 动态分析:在抓包基础上,通过Hook技术动态监控或修改加密算法、签名参数 破解加密参数、绕过签名校验、模拟请求、自动化脚本 Charles + Frida

下面我们将以"尿大夫"App登录接口为例,我们先用抓包反编译定位到 sign 字段的生成算法(静态分析),再用抓包逆向编写Frida脚本动态Hook该算法,验证其输入输出,甚至篡改签名(动态分析)。

1. 抓包反编译

尿大夫.apk,反编译破解登录接口

APK下载地址:https://apkpure.com/niao-da-fu/com.uulife.medical.activity/download

  1. 配置好Charles抓包,然后手机打开apk
  2. 输入用户名密码,点击登录,抓取对应接口
  3. 观察请求体,我们会发现主要是sign和devisetoken字段比较特殊,那么我们就需要挨个尝试,看哪些是需要我们逆向的
  4. 尝试Charles compose,移除部分字段,观察哪些字段是必须的
  • 首先移除devisetoken字段
  • 我们会发现移除devisetoken字段后,请求依然没问题
  1. 按照上面流程我们尝试移除sign字段,会发现移除之后状态码不一样了,出现了报错,那么说明sign字段是需要我们逆向的。

其他字段都是除了时间戳都是固定的,大家可以多请求几次观察

  1. 打开jadx,将apk包拖入jad中。进行逆向分析
  • 主要是这个sign字段,所以我们全局搜索这个sign,这个sign字符是固定的,我们推测目标是一个map,且通过put方式设置到请求参数中
  • 双击进入该代码文件
  • 我们发现sign是通过SafeUtils.getSign方法获取到的,那么我们选中getSign方法,鼠标右键,点击跳转到方法声明处,查看底层实现逻辑
  • 于是我们就找到了底层加密逻辑,接着直接复制给AI,让它给我们一个python版本

  1. 最后完善我们的python代码,实现登录逻辑
python 复制代码
import requests
import time
import hashlib
from urllib.parse import parse_qsl

channel = "android"

def getSign(j):
    try:
        str1 = "niaodaifu" + str(j)
        md5_1 = hashlib.md5(str1.encode('utf-8')).hexdigest()
        part1 = md5_1[12:30]

        str2 = channel + str(j)
        md5_2 = hashlib.md5(str2.encode('utf-8')).hexdigest()
        part2 = md5_2[12:26]

        return part1 + part2
    except Exception:
        return ""
    
 
def query_to_dict(query_string):
    return dict(parse_qsl(query_string))

phone = input('请输入手机号/邮箱:')
password = input('请输入密码:')
sign = getSign(int(time.time()))
print('----',sign)
q = 'password=%s&mobile=%s&channel=android&sign=%s&time=%s&mechanism=0&platform=1' % (
    password, phone, sign,int(time.time()))
# 实现query转字典

data = query_to_dict(q)
 
res = requests.post('https://api.niaodaifu.cn/v4/site/loginnew', json=data, verify=False)
print(res.json())
  1. 运行代码,观察效果,成功逆向

2. 抓包逆向(动态Hook)

目标:使用 Frida 动态 Hook getSign 方法,验证其输入输出,甚至篡改签名。

  1. 基于上面的反编译,我们知道加密是通过SafeUtils.getSign方法实现的。于是可编写 Frida Hook 脚本 hook_sign.js
js 复制代码
Java.perform(function () {
    // 定位 SafeUtils 类
    var SafeUtils = Java.use("com.uulife.medical.utils.SafeUtils");
    
    // Hook getSign 方法(注意参数类型为 long)
    SafeUtils.getSign.implementation = function (timestamp) {
        console.log("[*] getSign 被调用");
        console.log("    参数 timestamp (long): " + timestamp);
        
        // 调用原始方法,获取原始签名
        var originalSign = this.getSign(timestamp);
        console.log("    原始签名: " + originalSign);
        
        // 可选:篡改签名(例如在后面加 "hacked")
        var fakeSign = originalSign + "hacked";
        console.log("    篡改签名: " + fakeSign);
        
        // 返回篡改后的签名(演示修改返回值)
        return fakeSign;
        // 若想保持原逻辑,则返回 originalSign
    };
    
    console.log("[*] Hook 安装成功,等待登录操作...");
});
  1. 检查Frida-server是否运行,若没运行,则启动运行
bash 复制代码
# 检查是否Android是否运行
adb shell
su
ps | grep frida

# 若未运行则运行Frida-server
/data/local/tmp/frida-server-17.6.2-android-arm64 &

检测到Android未运行Frida-server,则执行命令运行。

  1. 在手机上打开尿大夫 App,然后运行Hook
bash 复制代码
# 通过应用名定位
frida -U -n "尿大夫" -l hook_sign.js

# 或者通过包名进行hook
frida -U -n com.uulife.medical.activity -l hook_sign.js
  1. 输入尿大夫App账号密码,点击登录,观察 Frida 控制台输出
bash 复制代码
[*] getSign 被调用
    参数 timestamp (long): 1775641135
    原始签名: d9828d465a091f9bba31f28710172db3
    篡改签名: d9828d465a091f9bba31f28710172db3hacked

由于我们篡改了签名,服务器会返回签名错误(如 401),证明 Hook 生效且成功修改了参数。基于此,我们可以确认apk登录后台确实调用了com.uulife.medical.utils.SafeUtils.getSign方法。

当然,验证猜想只是Hook最基础的功能。Hook 的真正威力在于动态篡改------可以让 App 做任何你想让它做的事,比如:

  • 绕过支付校验
  • 修改游戏金币
  • 禁用广告
  • 自动回复聊天消息
  • 抓取加密数据

当然,这些行为都需要遵循相关法律法规。

相关推荐
洒满阳光的庄园2 小时前
Electron 桌面端打包流程说明
前端·javascript·electron
财经资讯数据_灵砚智能2 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(夜间-次晨)2026年4月7日
人工智能·python·信息可视化·自然语言处理·ai编程
deephub2 小时前
向量数据库对比:Pinecone、Chroma、Weaviate 的架构与适用场景
人工智能·python·大语言模型·embedding·向量检索
星马梦缘2 小时前
强化学习实战5——BaseLine3使用自定义环境训练【输入状态向量】
pytorch·python·jupyter·强化学习·baseline3·gymnasium
子琦啊2 小时前
【算法复习】数组与双指针篇
javascript·算法
SuperEugene2 小时前
前端通用基础组件设计:按钮/输入框/弹窗,统一设计标准|组件化设计基础篇
前端·javascript·vue.js·架构
范什么特西2 小时前
web练习
java·前端·javascript
吃西瓜的年年2 小时前
react(三)action 表单
前端·javascript·react.js
我命由我123452 小时前
在 React 项目中,可以执行 npm start 命令,但是,无法执行 npm build 命令
前端·javascript·vue.js·react.js·前端框架·json·ecmascript