APP逆向必备(反编译hook算法)
day03 逆向必备
目标:了解app逆向的流程和必要的环境准备。
课堂随笔
day03 逆向必备
今日概要:
- 安装运行
- 抓包分析
- **反编译apk**
- **在Java代码中定位 + Hook校验**
- **基于Python还原算法**
1.反编译apk
- 简单APP,抓包 + 模拟发送(臧航+爱安丘)
- 复杂APP,抓包动态(车智赢) APK -> Java代码
1.1 反编译工具
jadx(推荐)、JEB、GDA、MT管理
1.2 依赖jre(推荐jdk【jre+其他】)
- jre,普通用户想要运行java程序写的工具
- jdk,开发人员,写代码时类库+编译->工具,运行jre
注意:必须1.8版本
windows系统:
- 下载exe文件
- 安装在你知道的目录(不要有中文、不要用有空格)
D:\soft\jdk
- bin
- java.exe 类似Python.exe
...
- 系统环境变量 D:\soft\jdk\bin\
>>>java --version
mac系统:
- 自带java
1.3 下载jadx & 解压
- github:https://github.com/skylot/jadx/releases
- 网盘
- 版本:v1.2.0(推荐)
- D:\coding\jadx\bin\
- jadx-gui mac
- jadx-gui.bat win
- 打开
1.4 反编译apk
- 成功
- 失败(有壳)
2.Java代码中定位
根据抓包抓到的数据,找到一些关键字,去java代码寻找蛛丝马迹。
- URL定位:/api/axxxx/xxx
- 直接搜索:pwd "pwd" &pwd pwd= &pwd=
- 间接搜索:其他好找
- Hook搜索:找内存TreeMap,put换成我的put方法 + 调用栈(了解)
TreeMap obj = new TreeMap(); obj = {}
obj.put("_appid","123") obj["_appid"] = "123"
obj.put("pwd","99")
obj.put("name","xxxx")
循环obj,获取键值对
_appid=123&age=99&pwd=xxxx
分析:pwd大概率是md5加密(猜测)
- 数据证明:明文 -> md5算法 -> 密文比对
- Hook证明+获取相关数据
3.基于frida的Hook
3.1 电脑安装frida模块
- Python3.7系统解释器
- 创建项目 + 基于Python3.7系统创建虚拟环境
- 安装模块
pip install frida==16.0.1
pip install frida-tools==12.0.1
- 报错
- 下载egg文件
- 放在指定目录
- 再安装
3.2 手机端
- adb查看CPU架构
>>>adb shell getprop ro.product.cpu.abi
- 下载frida-server
- 版本:16.0.1
- 解压并找到解压后的文件,不是文件夹
- 文件 frida-server-16.0.1-android-arm64
- 文件夹/文件 frida-server-16.0.1-android-arm64
注意:可以文件重命名 fd-16.0.1
- 上传到手机
>>>adb push .... /data/local/tmp/
- 查看 & 赋予可执行权限
>>>adb shell
>>>su ->shell获取ROOT权限
>>>cd /data/local/tmp/
>>>ls
>>>chmod 755 frida-server-16.0.1-android-arm64
3.3 启动+编写Hook脚本+运行
- 启动手机上的frida-server
>>>adb shell
>>>su
>>>cd /data/local/tmp/
>>>./frida-server-16.0.1-android-arm64
- 端口转发
>>>adb forward tcp:27042 tcp:27042
>>>adb forward tcp:27043 tcp:27043
- 固定脚本,python代码执行上述两条命令
- 编写Hook脚本+运行(项目+虚拟环境+frida+frida-tools)
- 固定脚本,查看手机中的进程
- 固定模板,修改内部Hook脚本
- 例如:车智赢登录
问题:
1.frida-server 和 端口转发 注意次数
2.端口固定
3.frida框架:JS方式写Hook -> 找固定的java替换
3.4 Hook脚本形式(编写+运行)
- 基于Python+JavaScript
- attach,手动app启动 + 运行Hook脚本
- spawn, 运行Hook脚本:重启APP+HOOK
- JavaScript + 终端命令(环境frida)
- attach
- spawn
4.Python进行算法的还原
- 固定算法:AES、MD5、DES..
- 自定义算法:看懂java代码 + 还原
5.实现业务功能
- 自动登录
- 自动注册....
## 感受
1.不懂Java不行呀 【看懂&分析】
2.算法的还原
1.逆向基本流程
常见app的逆向的基本流程:
- 安装运行
- 抓包分析
- 反编译apk
- 在Java代码中定位 + Hook校验
- 基于Python还原算法
2.反编译APK
如果抓包发现一些参数是动态,明显看不出来是什么意思?那就需要反编译得到Java代码,然后再java代码中寻找算法。
例如:车智赢登录
常见的反编译工具:jadx(推荐)、jeb、GDA
- 反编译工具均依赖
JRE(Java运行环境)
,安装JDK(包含jre) - 下载jadx并解压至任意目录
2.1 jdk
需要在你的电脑上安装Java开发工具包JDK,JDK中包含JRE。
https://www.oracle.com/java/technologies/downloads/
# 请务必安装 JDK8==JDK1.8(后期工具需要)
https://www.oracle.com/java/technologies/downloads/#java8
安装好之后需要配置下环境变量。
关于mac系统,自带JDK:
/Library/Java/JavaVirtualMachines
2.2 jadx
版本推荐:jadx-1.2.0
-
直接去官网
https://github.com/skylot/jadx/releases
-
去课件的网盘
注意:代码、文件尽量不要让他存在中文路径。
3.定位
在反编译得到的java中,根据抓包得到的关键字,去java代码中寻找指定算法的生成位置。
注意:这个过程需要掌握Java和安卓开发。
常见的可以搜索URL网址 或 参数关键字pwd
或 "pwd"
等,也可以搜索其他的关键字。
搜索网址: /tradercloud/sealed/login/login.ashx
4.hook验证
基于frida对代码进行验证,是否当前请求会执行此方法。
4.1 Python系解释器
请在系统解释器中安装Python3.7.9
https://www.python.org/downloads/release/python-379/
如果你现在电脑上只安装了python3.9,也可以再安装一个python3.8,Python支持多版本共存。
然后再用Python3.7.9 创建一个虚拟环境 + 项目,后续逆向课程都在此项目中进行。
4.2 frida==16.0.1【电脑端】
pip install frida==16.0.1
pip install frida-tools==12.0.1
正常情况下,就可以安装成功:
如果你在安装过程中,遇到以下错误,就需要:
- 下载egg文件并放在指定目录
- 再次安装 frida和frida-tools
1.下载egg
https://pypi.doubanio.com/simple/frida/
根据:frida版本 + Python版本 + 操作系统 来选择下载响应的egg文件。
2.放入指定目录
在错误提示中有指定egg放置的目录。
3.再次安装
pip install frida==16.0.1
pip install frida-tools==12.0.1
4.3 frida-server【手机端】
1.手机CPU架构
用ADB与手机连接,然后再电脑中终端运行如下命令:
adb shell getprop ro.product.cpu.abi
2.下载frida-server
https://github.com/frida/frida/releases
3.解压&上传到手机
将下载来的压缩包解压得到的 文件 上传到手机的 /data/local/tmp/
目录。
注意:一定是解压后的文件,不是文件夹。
-
上传
>>>adb push C:\soft\frida-server-16.0.1-arm64 /data/local/tmp/
-
赋予可执行权限
>>>adb shell >>>su >>>cd /data/local/tmp/ >>>chmod 755 frida-server-16.0.1-android-arm64
4.4 启动和Hook
1.【手机端】frida-server
在手机上运行 /data/local/tmp
目录下的 frida-server-16.0.1-android-arm64
>>>adb shell
>>>su
>>>cd /data/local/tmp
>>>./frida-server-16.0.1-android-arm64
2.【电脑端】Hook
第一步:端口转发
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
import subprocess
subprocess.getoutput("adb forward tcp:27042 tcp:27042")
subprocess.getoutput("adb forward tcp:27043 tcp:27043")
第二步:手机运行进程
# 枚举手机上的所有进程 & 前台进程
import frida
# 获取设备信息
rdev = frida.get_remote_device()
# 枚举所有的进程
processes = rdev.enumerate_processes()
for process in processes:
print(process)
# 获取在前台运行的APP
front_app = rdev.get_frontmost_application()
print(front_app)
第三步:Hook脚本
import frida
import sys
# 连接手机设备
rdev = frida.get_remote_device()
session = rdev.attach("车智赢+")
scr = """
Java.perform(function () {
// 包.类
var UserModel = Java.use("com.che168.autotradercloud.user.model.UserModel");
var SecurityUtil = Java.use("com.autohome.ahkit.utils.SecurityUtil");
UserModel.loginByPassword.implementation = function(str,str2,str3,responseCallback){
console.log(str2,str3);
var res = this.loginByPassword(str,str2,str3,responseCallback);
return res;
};
SecurityUtil.encodeMD5.implementation = function(str){
console.log("明文:",str);
var res = this.encodeMD5(str);
console.log("md5加密结果=",res);
return "305eb636-eb15-4e24-a29d-9fd60fbc91bf";
}
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
sys.stdin.read()
4.5 Hook方式
1.Python脚本
-
attach:手动运行app,打开APP后,再运行Hook脚本。
import frida import sys # 连接手机设备 rdev = frida.get_remote_device() session = rdev.attach("车智赢+") scr = """ Java.perform(function () { // 包.类 var SecurityUtil = Java.use("com.autohome.ahkit.utils.SecurityUtil"); SecurityUtil.encodeMD5.implementation = function(str){ console.log("明文:",str); var res = this.encodeMD5(str); console.log("md5加密结果=",res); return "305eb636-eb15-4e24-a29d-9fd60fbc91bf"; } }); """ script = session.create_script(scr) def on_message(message, data): print(message, data) script.on("message", on_message) script.load() sys.stdin.read()
-
spawn,脚本自动重启APP并进行Hook
import frida import sys rdev = frida.get_remote_device() pid = rdev.spawn(["com.che168.autotradercloud"]) session = rdev.attach(pid) scr = """ Java.perform(function () { // 包.类 var SecurityUtil = Java.use("com.autohome.ahkit.utils.SecurityUtil"); SecurityUtil.encodeMD5.implementation = function(str){ console.log("明文:",str); var res = this.encodeMD5(str); console.log("md5加密结果=",res); return "305eb636-eb15-4e24-a29d-9fd60fbc91bf"; } }); """ script = session.create_script(scr) def on_message(message, data): print(message, data) script.on("message", on_message) script.load() rdev.resume(pid) sys.stdin.read()
2.JavaScript + 命令行
创建一个js文件,例如:demo.js
Java.perform(function () {
// 包.类
var SecurityUtil = Java.use("com.autohome.ahkit.utils.SecurityUtil");
SecurityUtil.encodeMD5.implementation = function(str){
console.log("明文:",str);
var res = this.encodeMD5(str);
console.log("md5加密结果=",res);
return "305eb636-eb15-4e24-a29d-9fd60fbc91bf";
}
});
-
attach,先启动app,然后再在终端执行:
>>>frida -UF -l demo.js
-
spwan,脚本自动重启APP并进行Hook
>>>frida -U -f com.che168.autotradercloud -l demo.js 注意:输入q + 再点击回车则退出
5.算法还原
将算法逆向出来之后,就要根据Java中的实现,用Python代码实现。
5.1 固定算法
import hashlib
obj = hashlib.md5()
obj.update('密码'.encode('utf-8'))
hex_string = obj.hexdigest()
print(hex_string)
5.2 自定义算法
import random
import string
import base64
def base64_encrypt(data_string):
data_bytes = bytearray(data_string.encode('utf-8'))
data_bytes[0] = data_bytes[0] ^ (len(data_bytes) & 0xFF)
for i in range(1, len(data_bytes)):
data_bytes[i] = (data_bytes[i - 1] ^ data_bytes[i]) & 0xFF
res = base64.encodebytes(bytes(data_bytes))
return res.strip().strip(b"==").decode('utf-8')