https://github.com/frida
Frida 常用模块API:
1. 安装python3.7以上版本,并安装frida和frida-tools。
pip install frida
pip install frida-tools
2. 在手机上下载frida-sever端,官方下载地址:https://github.com/frida/frida/releases,下载时要选择对应的版本下载,例如我的机器为arm64位架构,就选择frida-server-15.1.11-android-arm64.xz
下载
# 查看手机架构
adb shell
su
getprop ro.product.cpu.abi
3. 将第四步下载好的文件解压,名字修改为frida-server
,然后通过命令adb push 电脑存放位置 /data/local/tmp
将文件传输到手机中,然后通过adb shell
进入手机端,给文件赋权777,并于root权限启动。
# 然后进入手机
adb shell
su
cd /data/local/tmp
chmod 777 frida-server
4. 启动frida,执行未输出任何东西,表示执行成功
./fridaserver1280_32
./fridaserver1280_32& (以后台模式运行)
5. 启动frida-server之后, 再打开一个cmd窗口,通过命令转发tcp端口 (端口转发, 将设备信息端口转发至PC端)
adb forward tcp:27043 tcp:27043
adb forward tcp:27042 tcp:27042
功能:不改变代码功能的前提下,捕获要用的代码,获取要用的信息。hook一般hook两层:
# -*- coding: utf-8 -*-
import sys
import frida
def on_message(message, data):
if message["type"] == "send": # 当通过send函数发送时,会打印至控制台
print(u"[*] {0}".format(message["payload"]))
else:
print(message)
jsCode = """
Java.perform(
function(){
java.use("com.me.world").check.implentation = function (v1,v2){
return False;
}
}
)
"""
process = frida.get_remote_device().attach("com.taobao.taobao") # 标准端口 使用包名 该包名通过frida-ps -U 获取
script = process.create_script(jsCode) # 识别JS字符串
script.on("message", on_message) # 输出 打印
script.load() # 加载 注入
sys.stdin.read() # 程序等待, 防止程序结束
# -------------------------------------------------------------------------------
# 如果我们想要在app启动的时候就想hook到某个函数,将上述的代码改成如下
# 前提也需要将APP启动,只不过后面有函数会让app重启
device = frida.get_remote_device()
pid = device.spawn("com.yaotong.crackme") # 获取进程id
process = device.attach(pid)
script = process.create_script(jsCode)
script.on("message", on_message)
script.load()
device.resume(pid) 表示app重启
sys.stdin.read()
其中jsCode中的函数有一些是固定写法,分别代表
Java.perform(匿名函数)
var MainActivity=Java.use(app类名)
MainActivity.方法名.implementation = function(){} hook这个类中的函数
由于在JAVA中有函数重载,即函数名相同,传入参数类型不同或者数量不同,执行的函数也不同,因此在面对这种情况,hook的时候需要找到自己究竟要hook哪个函数
例如Overloading.java 有两个test函数
public class Overloading {
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a){
System.out.println("test2");
}
}
这种情况hook就需要指定是哪一个函数,在overload里传参数代表hook哪一个
jsCode = """
Java.perfom(
function(){
// 无参数的test
java.use("Overloading").test.overload().implentation = function (){};
// 有参数的test
java.use("Overloading").test.overload(a).implentation = function (a){};
}
)
"""
正常分析app加密值的逻辑
反向分析app加密值的逻辑
无论加密值怎么变化,通常是调用常见的加密算法(md5,rsa,base64等等)
那么我们直接hook底层加密算法,并在hook的时候进行堆栈打印,这样就可以知道哪个方法调用了加密操作,然后找到该方法
// 打印调用栈
function print_stack(){
send(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Excepetion").$new()));
}
进行hook操作需要注意
尽量不要改写原来的方法流程逻辑,执行完自己的操作以后,别忘了调用本身
this.function()
安装该app到手机:http://www.downcc.com/soft/276877.html
安装app后进入app,会提示输入手机号,然后输入一个手机号,点击下一步,进行抓包
{"phone":"15811223344","sign":"BE1B05B2ED7689457F9DCE74E4F8C743","currTime":"20220818161311","type":"1"}
看到里边生成了一个sign,然后我们用jadx反编译一下该app,该app是无壳的,然后我们搜一下getSmscode
HttpUtils.getStringMD5toUpperCase(yyyyMMddHHmmss + i + str + str2);
而四个值分别是: 日期格式化 + type + str + 手机号
看样子是进行拼接后,然后好像进行md5
str是传入的值,因此我们需要知道str是什么,这里使用frida抓一下
打开cmd窗口开启frida-server
再卡开另一个cmd,进行转发
然后构造python代码
# -*- coding: utf-8 -*-
import sys
import frida
def on_message(message, data):
if message["type"] == "send": # 当通过send函数发送时,会打印至控制台
print(u"[*] {0}".format(message["payload"]))
else:
print(message)
jsCode = """
Java.perform(
function () {
var MainActivity = Java.use('com.jx885.library.http.CommAction');
MainActivity.getSmscode.implementation = function (arg1,arg2,arg3) {
console.log(arg1,arg2,arg3);
return this.getSmscode(arg1,arg2,arg3);
}
});
"""
process = frida.get_remote_device().attach("驾培创业教练") # 标准端口 使用包名 该包名通过frida-ps -U 获取
script = process.create_script(jsCode) # 识别JS字符串
script.on("message", on_message) # 输出 打印
script.load() # 加载 注入
sys.stdin.read() # 程序等待, 防止程序结束
重启app,运行代码,输入手机号,点击下一步,我们看到刚才的str串结果是wocaonima
,然后我们将刚才的值拼接一下
日期格式化 + type + str + 手机号
202208181613111wocaonima15811223344
找个网站md5一下,发现和刚开始的值吻合
这里我们有两种方式得出结果
我们不通过app触发得到结果,我们主动调用的方式一般就是frida-rpc解决。
然后修改代码,变为主动调用app里的md5方法
# -*- coding: utf-8 -*-
import sys
import frida
def on_message(message, data):
if message["type"] == "send": # 当通过send函数发送时,会打印至控制台
print(u"[*] {0}".format(message["payload"]))
else:
print(message)
jsCode = """
var sign = function (s) {
var result = '';
Java.perform(function () {
result = Java.use('com.jx885.library.http.network.HttpUtils').getStringMD5toUpperCase(s);
});
return result;
};
rpc.exports = {
getsign: sign
};
"""
process = frida.get_remote_device().attach("驾培创业教练") # 标准端口 使用包名 该包名通过frida-ps -U 获取
script = process.create_script(jsCode) # 识别JS字符串
script.on("message", on_message) # 输出 打印
script.load() # 加载 注入
yyyyMMddHHmmss = '20220818161311'
i = '1'
str_1 = 'wocaonima'
str_2 = '15811223344'
s = yyyyMMddHHmmss + i + str_1 + str_2
sign = script.exports.getsign(s)
print(sign)