[1091]Frida的环境搭建及入门实战

2023-10-28 10:40

本文主要是介绍[1091]Frida的环境搭建及入门实战,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 简介
      • 插桩技术
    • 配置环境需求
    • 环境配置
      • windows安装frida客户端:
      • Android 安装frida服务端
      • 问题1:模拟器与真机
      • 问题2:版本一致
    • 反编译nice app,找到hook点
      • 分析源码
      • 编写脚本
      • 运行脚本
    • 扩展
    • frida相关用法
      • js脚本用法示例
      • Python脚本运行通用样例
      • 基本使用
    • 可能遇到的错误
    • 参考:

简介

Frida是一款基于python + javascript 的hook框架,可运行在android ios linux windows osx等各平台,主要使用动态二进制插桩技术;由于是基于脚本(javascript)的交互,因此相比xposed和substrace cydia更加便捷

官网址址:https://frida.re/
github地址:https://github.com/frida/frida
https://github.com/frida/frida-python

插桩技术

插桩技术是指将额外的代码注入程序中以收集运行时的信息,可分为两种:

  • 源代码插桩[Source Code Instrumentation(SCI)]:额外代码注入到程序源代码中。

  • 二进制插桩(Binary Instrumentation):额外代码注入到二进制可执行文件中。

  • 静态二进制插桩[Static Binary Instrumentation(SBI)]:在程序执行前插入额外的代码和数据,生成一个永久改变的可执行文件。

  • 动态二进制插桩[Dynamic Binary Instrumentation(DBI)]:在程序运行时实时地插入额外代码和数据,对可执行文件没有任何永久改变。

配置环境需求

  • python使用版本python3.7:https://www.python.org/
  • mumu android模拟器:http://mumu.163.com/baidu/
  • adb驱动:https://adb.clockworkmod.com/
  • jadx-gui(apk反编译):http://www.pc6.com/softview/SoftView_579787.html
  • apkhelper v3.0(应用包名等查看):http://www.pc6.com/softview/SoftView_472196.html
  • vscode编辑器(主要用于源码分析):https://code.visualstudio.com/
  • windows10 64位
  • nice app(实战使用的app):https://www.wandoujia.com/apps/2604261

环境配置

Frida的安装很简单,需要在windows安装frida客户端和在安卓安装frida服务端。

windows安装frida客户端:

pip install frida-tools
pip install frida   

Android 安装frida服务端

下载 : https://github.com/frida/frida/releases相应的版本
我用的是mumu模拟器所以下载的是frida-server-12.8.6-android-x86.xz

image.png

下载后解压(注意下载是压缩包,要解压一下)

使用adb连接mumu模拟器(注意打开root权限及usb调试模式)
image.png

adb connect 127.0.0.1:7555

关闭指令为

adb disconnect 127.0.0.1:7555

将上面的解压得到的文件传送至模拟器上到/data/local/tmp 目录,并命名为frida-server

adb push frida-server-12.8.6-android-x86 /data/local/tmp/frida-server

进入adb shell并设置frida-server的权限

image.png

使用./frida-server启动服务

之后另外开启一个命令窗口运行命令:frida-ps -U(查看运行的进程)
image.png

出现上图说明服务起成功

最后将手机端的端口转发到PC端进行通信

adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043

指定手机端口转发,97dc2d9为手机driver名称

os.system("adb -s 97dc2d9 forward tcp:27042 tcp:27042")
os.system("adb -s 97dc2d9 forward tcp:27043 tcp:27043")

frida-trace追踪指定的函数的调用:
image.png

问题1:模拟器与真机

如果目标设备是真机,那么请提前把设备root。如果是模拟器,先把root权限打开。

打开终端,使用命令 adb devices 查看设备是否被adb检查到了

如果没找到,先执行这条命令 adb kill-server,再去查找一般都能找到。

一个小坑,真机的arm架构和模拟器的x86差异,如果是真机需要下载-arm64.xz文件,模拟器则是-x86.xz,下载解压后,使用adb连接机器,使用push将frida-server放到手机目录/data/local/tmp,然后修改属性为可执行,以root权限启动。

image.png

可以看到如果模拟器使用的是arm类型文件,则会报错:

Not executable: 64-bit ELF file

换成-x86 server成功运行:

image.png

问题2:版本一致

frida-server版本要和frida版本一致,否则调用js脚本会报错,pip安装客户端一般是最新版本,在GitHub上下载server版本也要选择最新版本。

image.png

反编译nice app,找到hook点

使用jdax-gui工具打开nice-main-5.4.29-release.apk(反编译时间过长,耐心等待…),反编译完点击jdax-gui的File—> Save as gradle project将源码保存在本地,并使用vscode打开
本次实战hook点是使用已有账登录,输入账号密码后,点登录获取账号密码信息
image.png

image.png

Fiddler代理设置请自行百度

通过Fiddlert查看,每获次登录的请求响应如下
image.png

由上图片得出请求路径:/account/login

分析源码

vscode中全文搜索/account/login
在bil.java中a方法中找到
image.png
image.png

由此得见,我们从a方法就是我们的hook点,a方法的参数jsonObject str即是我们要获取的内容

编写脚本

import frida
import sys# hook逻辑脚本
jscode = """
Java.perform(function () {
//获取bli类型,使用js将其包状成代理对象var bil = Java.use('bil');var function_a = bil.a;//重写方法afunction_a.overload("org.json.JSONObject","java.lang.String").implementation = function (obj,str) {// Show a message to know that the function got calledsend('function_a');send('obj'+obj);send('str'+str);// Call the original onClick handler//调用实际的a方法(即包装之前的a方法,类似于装饰器工能)return    this.a( obj,str);};
});
"""
# 通过usb连接方法
# process = frida.get_usb_device(timeout=60).attach('美团')
# 通过usb连接,指定手机
# process = frida.get_device(id='97dc2d9').attach('美团')# 注入进程,attach传入进程名称(字符串)或者进程号(整数)
rdev = frida.get_remote_device()
session = rdev.attach("com.nice.main")
script = session.create_script(jscode)
#int()函数把字符串表示的16进制数转换成整数
#上面的jscode % int(sys.argv[1], 16)是python格式化字符串的语法# 接收脚本信息的回调函数
# message是一个对象,type属性为send则表示send函数发送的信息,其内容在payload里
# 下面这个on_message函数可以做固定用法,一般无需改动,当然也可直接打印message看看里边的内容
def on_message(message, data):if message['type'] == 'send':print(message['payload'])elif message['type'] == 'error':print(message['stack'])
# 应该是设置message事件的回调函数
script.on('message', on_message)
# 加载hook脚本
script.load()
# 保持主线程不结束(也可以使用time.sleep循环)
sys.stdin.read()

在反编译的文件中有些类没有包名如:
image.png

package defpackage;说明没有包名,在使用Java.use();方法时
直接使用类名就可以了如Java.use(‘bil’);

参考:https://blog.csdn.net/chifu5720/article/details/102861359

运行脚本

运行脚本前一定要先在模拟器中将nice app运行起来
然后在cmd中运行

python my_script.py

image.png

然后输入账号密码即可获取到账号与密码(此处密码是加密后的)等相关内容
image.png
成功hook!!!

相关资料:
https://blog.csdn.net/qq_44906504/article/details/89672518
https://blog.csdn.net/u014476720/article/details/83537843
https://blog.csdn.net/qq_44906504/article/details/89672518

https://blog.csdn.net/jinangl_vsnake/article/details/72919329
https://www.cnblogs.com/tjp40922/p/11353808.html

https://www.52pojie.cn/forum.php?mod=viewthread&tid=931872

扩展

在使用frida过程中发现有些app会对27042 /27043端口或frida-server服务名称进行检测,导制一运行frida注入app就闪退,解决方法如下:
1.重命名服务frida-server为不fs64或其他名字
2.frida服务默认启动端口为27042可指定端口端启动如:

chmod 777 fs64
fs64 -l 0.0.0.0:1234

然后转发

adb forward tcp:1234 tcp:1234

客户端使用方式:
frida-cli的使用自定端口的方式:

frida -H 127.0.0.1:1234 package_name -l hook.js 

python脚本使用自定义端口的方式:

host = '127.0.0.1:1234'
manager = frida.get_device_manager()
device= manager.add_remote_device(host)

备注:get_remote_device()方法,后来发现这个函数默认连接的是127.0.0.1:27042,使用上面代码代替即可

相关资料:
https://bbs.pediy.com/thread-254974.htm
https://wrlu.cn/cyber-security/mobile-security/android-frida/

frida相关用法

js脚本用法示例

// javascript
// 将线程附加到Java虚拟机,成功会回调function()
Java.perform(function() {});
// 由于js代码注入存在超时,通常在外面再包装一层
setImmediate(function() {...
});// 动态获取一个js包装的Java类
var clazz = Java.use(className);
// $new()调用类构造方法,$dispose()调用析构清空js对象
// 获取到Java类之后,直接通过<wrapper>.<method>获取方法
// 有些重载的方法需要通过.overload()传入参数类型指定方法
// 通过方法的.call(args)来调用函数,通过方法的.implementations = function(){}来实现hook
clazz.method.implementation = function(args) {......
}
clazz.method.overload(argumentsType[]).call(args);
// 将js包装的类实例转换成另一种js包装类
Java.cast(clazz1, Clazz2)

Python脚本运行通用样例

# -*- coding: utf-8 -*-
import frida
import sysdef on_message(message, data):if message['type'] == 'send':print("*****[frida hook]***** : {0}".format(message['payload']))else:print("*****[frida hook]***** : " + str(message))def get_javascript(filepath):code = ''with open(filepath, 'r') as file:code = code + file.read()return code# 连接远端设备
device = frida.get_remote_device()
# 附加到进程
session = device.attach(package_name)
# 1、直接写入 javascript 代码
javascript = """
<javascript code>
"""
# 2、从文件中加载 javascript 脚本代码
javascript = get_javascript(javascript_file)
# 基于脚本内容创建运行脚本对象
script = session.create_script(javascript)
script.on('message', on_message)
# 加载脚本并执行
script.load()
sys.stdin.read()

基本使用

Frida提供了一些工具直接操作
比如查看连接的设备

# bash
$ frida-ls-devices
Id                Type    Name        
----------------  ------  ------------
local             local   Local System
0105a575959b9fa9  usb     LGE Nexus 5X
tcp               remote  Local TCP 

使用python脚本获取的也是这样

# python
import frida
print(frida.get_local_device())
print(frida.get_usb_device())
print(frida.get_remote_device())
-------------------------------------------------------------------------
Device(id="local", name="Local System", type='local')
Device(id="0105a575959b9fa9", name="LGE Nexus 5X", type='usb')
Device(id="tcp", name="Local TCP", type='remote')

其中,local device对应的就是PC本机,usb device对应连接的Android设备,remote device也是经过端口转发的Android设备

附加指定进程

$ frida-trace -i open -U <package_name/pid>

也封装了许多常用功能和函数,可以直接调用接口

查看所有进程

# python
processes = device.enumerate_processes()
for process in processes:print(process)

查看所有安装的应用

# python
applications = device.enumerate_applications()
for application in applications:print(application)

获取顶层应用进程

# python
front_app = remote_device.get_frontmost_application()
print(front_app)
-------------------------------------------------------------------------
Application(identifier="com.android.settings", name="设置", pid=6683)

获取加载的类

// javascript
Java.enumerateLoadedClasses({onMatch:function(_className){log("found instance of '" + _className + "'");},onComplete: function(){log("enumerating completed !!!");}
});

获取类声明的函数

// javascript
var clazz = Java.use(className);
var methods = clazz.class.getDeclaredMethods();
if(methods.length > 0){log("getDeclaredMethods of class '" + className + "':");methods.forEach(function(method){log(method);});
}

获取调用堆栈

// javascript
var stack = Java.use("java.lang.Thread").$new().currentThread().getStackTrace();
for(var i = 2; i < stack.length; i++){log("getStackTrace[" + (i-2) + "] : " + stack[i].toString());
}

获取加载的所有模块

// javascript
Process.enumerateModules({onMatch: function(module) {log(module.name + " : " +  module.base + "\t" + module.size + "\t" + module.path);},onComplete: function() {log("enumerating completed !!!");}
});

获取所有的导出符号

// javascript
var symbols = Module.enumerateExportsSync(moduleName);
symbols.forEach(function(symbol){log(symbol.name + " address = " + symbol.address);
});
return symbols;

获取JNI注册的函数信息

// javascript
var RegisterNativesAddr = getSymbolAddr("libart.so", "_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi");
if(RegisterNativesAddr != null){log("find symbol 'RegisterNatives' in libart.so, address = " + RegisterNativesAddr);Interceptor.attach(RegisterNativesAddr, {onEnter: function(args) {var class_name = Java.vm.getEnv().getClassName(args[1]);var methods_ptr = ptr(args[2]);var module = Process.findModuleByAddress(Memory.readPointer(methods_ptr));log("RegisterNativeMethod class = " + class_name + ", module = " + module.name + ", base = " + module.base);var method_count = parseInt(args[3]);log("registered methods count = " + method_count);// get registered native method infovar offset = Process.pointerSize;for (var i = 0; i < method_count; i++) {var name = Memory.readCString(Memory.readPointer(methods_ptr.add(offset*3*i)));var sig = Memory.readCString(Memory.readPointer(methods_ptr.add(offset*3*i+offset)));var address = Memory.readPointer(methods_ptr.add(offset*(3*i+2)));log("methods name = " + name + ", sig = " + sig + ", address = " + ptr(address) + ", offset = " + ptr(address).sub(module.base));}},onLeave: function() {}});
}

导出远程方法,注意不支持大写字母和下划线

// javascript
rpc.exports = {<exportfuncname1>: function(args) {......},<exportfuncname2>: function(args) {......}
};

远程调用

# python
script.exports.exportfuncname1(args)

可能遇到的错误

1、 提示:frida.ServerNotRunningError: unable to connect to remote frida-server
解决1:没有打开 frida-server,按照上面的教程打开 server
解决2:端口没有转发,执行一下这个命令:adb forward tcp:27042 tcp:27042

2、 提示:frida.ProcessNotFoundError: unable to find process with name ‘xxx’
解决:这是因为app的包名填错了,先用:frida-ps -U 找到想操作的包名,然后再填入到这里:frida.get_remote_device().attach(‘京东’)

3、如果出现以下错误:

image.png

可以通过以下方式关闭SELinux,在adb shell中执行:

echo 0 > /sys/fs/selinux/enforce
或者
setenforce 0

确认是否设置成功

参考:

Android逆向之hook框架Frida:Frida的环境搭建及入门实战:https://blog.csdn.net/m0_37696990/article/details/103916289
Hook框架Frida之安装踩坑日记:https://cloud.tencent.com/developer/article/1662286
Frida用法详解【附用例】:https://blog.csdn.net/weixin_35016347/article/details/104002411
Frieda 的简单使用:http://www.kidcaoblog.com/articles/2021/09/27/1632708995856.html
Android hook神器frida:https://www.cnblogs.com/goodhacker/p/10016028.html
frida运行出错超时问题解决:https://blog.csdn.net/helloexp/article/details/90200447

其他:
https://www.jianshu.com/p/aa466d198a20
https://www.cnblogs.com/tjp40922/p/11353808.html

https://github.com/WooyunDota/DroidSSLUnpinning
https://github.com/WooyunDota/DroidDrops/blob/master/2018/Frida.Android.Practice.md

这篇关于[1091]Frida的环境搭建及入门实战的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/292667

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

搭建Kafka+zookeeper集群调度

前言 硬件环境 172.18.0.5        kafkazk1        Kafka+zookeeper                Kafka Broker集群 172.18.0.6        kafkazk2        Kafka+zookeeper                Kafka Broker集群 172.18.0.7        kafkazk3

安装nodejs环境

本文介绍了如何通过nvm(NodeVersionManager)安装和管理Node.js及npm的不同版本,包括下载安装脚本、检查版本并安装特定版本的方法。 1、安装nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash 2、查看nvm版本 nvm --version 3、安装

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联