Burpsuite插件-Brida
本文作者:杉木@涂鸦智能安全实验室
通过一道CTF题目来认识一下Frida
objection
前面两篇通过对Frida的了解,以及利用objection来分析,这篇来了解一下分析后实际利用,以及通过实现插件自动化的方式来利用。
Brida介绍
https://github.com/federicodotta/Brida
官方使用文档翻译
时间记录,20230725;
测试版本:0.5
虽然说官方文档是最新的,但是使用文档的截图依旧跟新版本的插件不一致,然后能够查到的资料也是比较久的内容,不过大体功能是差不多,但是还是自己操作一遍后记录一下相关问题;
这里只记录自己测试的环境,其他环境参考官方文档;
Android
- 安装frida和其server,并启动具体可以参考通过一道CTF题目来认识一下Frida
- 配置brida
在配置之前先简单了解一下brida的UI及其功能;
1 主面板
这里包含所有brida工具和配置
- Configurations
- JS Editor
- Hooks and functions
- Graphical analysis
- Graphical hooks
- Custom plugins
- Generate stubs
- Debug export
2 brida按钮面板
Brida按钮面板由三个不同的部分组成:
- 顶部(前两行)是 Pyro4 服务器的状态(启动/停止)和应用程序的状态(hook状态)
- (在两条黄线上方的按钮)在中间有一组固定在Brida所有选项卡上的按钮。这些按钮用于执行常规任务,如启动/停止 Pyro4 服务器、生成/附加/停止/分离应用程序(使用 frida-compile 编译)、重新加载 JS 文件、编译重新加载JS、分离所有hook、清除log等。
- (黄线下)底部有一组按钮,取决于特定的Brida子选项卡
3 brida控制台
log输出
brida工具介绍
Configurations
配置界面
从上往下依次是
- Pyro服务状态
- 应用状态
- 是否使用虚拟的python环境
- python可以执行文件的路径
- Pyro服务地址(默认)
- Pyro端口(默认)
- frida-complile可以执行文件的路径
- 是否使用旧版本的frida-complile,尽量使用10以下的版本,一开始用默认版本会出现问题,hook上了,但是总有奇怪的报错
- 包含所有Brida JS文件的文件夹,第一次需要先生成一下默认的JS文件
- 需要hook的应用名/PID,如果为应用名,则在连接的时候是点按钮面板的Spawn application,如果为PID,则Attach;
- Frida连接方式
- 如果配置是远程连接frida,需要配置对应的地址和端口;
JS Editor
集成到Burp Suite中的JS编辑器,以便能够编辑Brida JS文件并直接从Burp Suite添加自定义hook和导出函数。编辑器具有JS语法突出显示。
Hooks and functions
此选项卡包括许多默认hooks和方法,可以通过按钮启用/执行。这些Frida脚本包括最新的Android和iOS平台的hook能力,以绕过和检查安全功能。
Graphical analysis
这里功能类似于objection的能力集成进来,
load tree = android hooking list classes //展示所有class
搜索 = android hooking search methods [search_name] //在内存中所有已加载的方法中搜索包含特定关键词的方法
//但是这里Android的用起来会导致应用闪退,官方提了这个,只有iOS支持;
双击对应的class = android hooking watch class com.xxx.xxx //hook指定类, 会打印该类下的所以调用
右键Inspect = android hooking watch class_method com.xxx.xxx.methodName --dump-args --dump-backtrace --dump-return //hook指定类, 会打印该类下的所以调用
右键change return vule = android hooking set return_value com.xxx.xxx.methodName false //设置返回值
实际使用
对函数进行打印,然后替换返回值,但是这里官方提供的返回值没有byte
Graphical hooks
管理之前hook的所有内容;
Custom plugins
强大的功能;
可以理解成自定义生成burpsuite插件,有四种可自定义插件类型;
- IHttpListener:能让所有请求,通过正则匹配去替换/修改指定的内容,并让这个匹配到的内容通过frida构造的hook脚本处理(加解密、重新生成sign等)
- IMessageEditorTab:将自定义选项卡添加到Burp Suite请求/响应窗格,以便能够使用Frida导出的函数解密/解码/处理请求/响应(或其中的一部分)(然后加密/编码/处理修改并替换原始请求/响应,如果有)
- IContextMenu:将自定义上下文菜单选项添加到Burp Suite的右键菜单中,用于在请求和响应(或其中的一部分)上调用Frida导出的函数
- JButton:添加调用/启用 Frida 导出函数的按钮
Generate stubs
如果内部自定义插件引擎无法解决复杂情况,则可以从外部Burp Suite插件使用Brida引擎。此选项卡生成 Java 和 Python 存根,可以复制并粘贴到外部插件中,以便允许 Burp Suite 和 Frida 使用 Brida 进行通信。
Debug export
此选项卡可用于在 Brida 插件中使用 Frida 导出的函数之前对其进行调试。为了使用 Brida 自定义插件(或使用 Brida 的外部插件),有必要将 Frida 代码放入一些由插件调用的 Frida 导出函数中。在此选项卡中,可以直接调用 Frida 导出,以便轻松调试。
使用问题记录
Windows环境
Spawn/Attach application时报错:entrypoint must be inside the project root
【移动安全】Frida + Burp -> Brida | APP加解密 | CN-SEC 中文网
把Frida的js文件放到burpsuite应用的目录下;
在Debug export中Run export是报错[frida.core.RPCException] unable to find method 'test’
排查了很久,只找到了frida-compile版本过高这种情况,只能测试一下低版本是否会有问题,用npm在burpsuite应用的目录下执行npm install frida-compile@9.5.2,然后将安装的目录配置到frida-compile path中就能解决;
使用了低版本的frida-compile后报错java.io.IOException: Cannot run program
"C:\AAAA\agent\BurpSuiteCommunity\node_modules\.bin\frida-compile":
CreateProcess error=193, %1 不是有效的 Win32 应用程序。
一开始配置没有带.cmd,
**UnicodeEncodeError: ‘gbk’ codec can’t encode
character '\u03f1' in position 49: illegal multibyte sequence**
刚好遇到一个反编译后用中文混淆的,这里用objection和python执行相关处理的时候就会报编码错误,在对应路径相关代码输出处加上utf-8编码输出就能解决;然后objection需要修改后重新编译;
源码解析
java调用python脚本
# -*- coding: utf-8 -*-
import frida
import codecs
import Pyro4
import sys
#reload(sys)
#sys.setdefaultencoding('utf-8')
class Unbuffered(object):
def __init__(self, stream):
self.stream = stream
def write(self, data):
self.stream.write(data)
self.stream.flush()
def writelines(self, datas):
self.stream.writelines(datas)
self.stream.flush()
def __getattr__(self, attr):
return getattr(self.stream, attr)
@Pyro4.expose
class BridaServicePyro:
def __init__(self, daemon):
self.daemon = daemon
def attach_application(self,pid,frida_script,device,host_port_device_id):
self.frida_script = frida_script
if pid.isnumeric():
self.pid = int(pid)
else:
self.pid = pid
if device == 'remote':
self.device = frida.get_remote_device()
elif device == 'usb':
self.device = frida.get_usb_device()
elif device == 'local':
self.device = frida.get_local_device()
elif device == 'device':
self.device = frida.get_device(host_port_device_id)
else:
self.device = frida.get_device_manager().add_remote_device(host_port_device_id)
self.session = self.device.attach(self.pid)
with codecs.open(self.frida_script, 'r', 'utf-8') as f:
source = f.read()
self.script = self.session.create_script(source)
self.script.load()
return
def spawn_application(self,application_id,frida_script,device,host_port_device_id):
self.application_id = application_id
self.frida_script = frida_script
if device == 'remote':
self.device = frida.get_remote_device()
elif device == 'usb':
self.device = frida.get_usb_device()
elif device == 'local':
self.device = frida.get_local_device()
elif device == 'device':
self.device = frida.get_device(host_port_device_id)
else:
self.device = frida.get_device_manager().add_remote_device(host_port_device_id)
self.pid = self.device.spawn([self.application_id])
self.session = self.device.attach(self.pid)
with codecs.open(self.frida_script, 'r', 'utf-8') as f:
source = f.read()
self.script = self.session.create_script(source)
self.script.load()
return
def resume_application(self):
self.device.resume(self.pid)
return
def reload_script(self):
with codecs.open(self.frida_script, 'r', 'utf-8') as f:
source = f.read()
self.script = self.session.create_script(source)
self.script.load()
return
def disconnect_application(self):
self.device.kill(self.pid)
return
def detach_application(self):
self.session.detach()
return
def callexportfunction(self, methodName, args):
method_to_call = getattr(self.script.exports, methodName)
# Take the Java list passed as argument and create a new variable list of argument
# (necessary for bridge Python - Java, I think)
s = []
for i in args:
s.append(i)
return_value = method_to_call(*s)
return return_value
@Pyro4.oneway
def shutdown(self):
print('shutting down...')
self.daemon.shutdown()
# Disable python buffering (cause issues when communicating with Java...)
sys.stdout = Unbuffered(sys.stdout)
sys.stderr = Unbuffered(sys.stderr)
host = sys.argv[1]
port = int(sys.argv[2])
daemon = Pyro4.Daemon(host=host,port=port)
#daemon = Pyro4.Daemon(host='127.0.0.1',port=9999)
bs = BridaServicePyro(daemon)
uri = daemon.register(bs,objectId='BridaServicePyro')
print("Ready.")
daemon.requestLoop()
漏洞悬赏计划:涂鸦智能安全响应中心(https://src.tuya.com)欢迎白帽子来探索。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!