这份文档围绕TMF框架的Frida Hook脚本(tmf.js) 展开,是实操过程中对脚本开发、代码逻辑、Frida/Java/OkHttp技术细节的深度解析与问题探讨,核心聚焦tmf.js中Hook TMF框架sendShark方法、自定义回调、协议转发的实现逻辑,同时厘清了Frida操作Java对象、OkHttp发起请求的关键语法和底层原理,整体以实操疑问+逻辑拆解+技术解答的形式推进,核心内容提炼如下:
一、核心开发背景与脚本目标
基于Frida开发tmf.js脚本,实现对TMF框架的请求/响应拦截、篡改与转发,核心是Hook TMF框架的sendShark(请求发送核心方法)和ISharkCallBack2接口的onFinish(响应回调方法),并通过OkHttp将TMF私有协议的请求/响应转换为标准HTTP协议,绕过应用代理检测、实现数据抓包与调试,同时提供RPC接口供外部调用自定义发包。
二、TMF框架核心类与关键结构解析
-
SharkHttpEntity :TMF框架的请求/响应实体类,核心字段包括
params(请求元数据)和data(请求体/响应体原始字节流);其中params字段类型为SashimiHeader。 -
SashimiHeader :TMF框架的请求/响应元数据容器类,封装了
apiName(接口名)、header(请求/响应头,Map类型)、cookies、query等核心参数,同时承载请求和响应元数据 ;实操中发现目标APP存在Protocol.MShark.SashimiHeader和Protocol.MTMFShark.SashimiHeader两个类,前者继承后者且结构/字段完全一致,为开发时的兼容处理提供了基础。 -
ISharkCallBack2 :TMF框架的异步响应回调接口,必须实现
onFinish方法,请求完成后框架会自动回调该方法并传入响应数据(SharkHttpEntity类型)。
三、tmf.js核心实现逻辑拆解
脚本整体遵循**「类初始化→自定义回调注册→Hook请求/响应→协议转换与转发→RPC导出」** 流程,核心模块及实操疑问解答如下:
(一)Java类与工具初始化
通过Java.use(类全限定名)获取TMF框架、Java基础类、OkHttp相关类的引用,为后续Hook和操作做准备,关键包括:
-
TMF相关:SharkClass(sendShark所属类)、SashimiHeader、SharkHttpEntity;
-
基础工具:fastJson(序列化/反序列化)、StringClass(java.lang.String)、MapClass(java.util.Map);
-
OkHttp相关:OkHttpClient、Request、RequestBody、MediaType。
实操中发现预定义的PClass/PPClass(两个SashimiHeader类引用)为冗余代码 ,脚本实际通过Java.use(sharkHttpEnt.params.value.$className)动态获取类名,自动匹配真实的SashimiHeader类,因此错误的包名定义不影响执行。
(二)自定义响应回调类注册:MyHttpEntityCallback
通过Frida的Java.registerClass动态创建实现ISharkCallBack2接口的自定义类,核心作用是接管TMF框架的响应回调,获取响应数据并转发,关键细节:
-
类名规则:自定义全限定名(如com.owl.MyHttpEntityCallback)可随意定义,只需保证进程内唯一,避免与应用原有类冲突;
-
必实现方法 :因实现ISharkCallBack2接口,必须重写
onFinish方法,框架请求完成后会自动触发; -
Frida特殊语法:
-
$init:代表Java构造方法,用于初始化类的成员变量(如保存apiName,为后续区分接口做标记); -
方法需通过
argumentTypes声明参数类型,无参则设为空数组; -
访问Java对象成员变量必须加
.value(Frida封装的取值语法,类似C语言解引用指针,获取堆中实际值)。
-
(三)Hook核心方法:sendShark与onFinish
1. Hook sendShark(请求拦截)
-
拦截APP调用TMF框架的请求发送方法,解析原始请求的apiName、header、body等参数;
-
支持参数篡改:阻塞等待Python控制端(<tmf-killer.py>)的修改指令,替换参数后调用原始sendShark方法完成请求发送。
2. Hook onFinish(响应拦截)
-
接管ISharkCallBack2的响应回调,解析TMF框架返回的响应数据(SharkHttpEntity类型);
-
核心操作:将响应数据转换为标准HTTP格式,通过OkHttp转发,实现私有协议到HTTP的转换。
关键技术:Java.cast(对象, 目标类)------解决Frida跨语言(JS调用Java)的类型丢失问题,将Object类型的参数强制转换为目标类,才能正常访问其成员变量和方法。
(四)私有协议转标准HTTP:OkHttp转发实现
将解析到的TMF请求/响应数据,通过OkHttp重新构造标准HTTP请求发送,绕过应用代理检测,核心步骤与语法:
-
OkHttp核心三要素:OkHttpClient(请求执行者)、Request$Builder(请求构造器)、RequestBody(请求体封装);
-
建造者模式 :OkHttpClient和Request均通过内部类
$Builder构建,链式配置参数后调用build()生成实例,解决复杂对象的创建问题; -
关键配置:
-
MediaType:指定请求体MIME类型(如application/json),等效于HTTP的Content-Type头,告诉服务端数据格式; -
RequestBody.create:将TMF的data字节流封装为OkHttp可识别的请求体;
-
-
转发逻辑 :在自定义回调的
onFinish方法中,解析响应的apiName、header、body,拼接为JSON格式,通过OkHttp发送到指定地址,实现响应数据的转发。
(五)RPC接口导出
封装自定义的sendShark方法,通过rpc.exports导出为RPC接口,供Python控制端(<tmf-killer.py>)调用,实现PC端控制移动端发送自定义TMF请求,形成完整的请求/响应闭环。
四、Frida操作Java的核心语法与底层原理
-
Java.use :入参为类的全限定名(包名+类名),获取Java类的引用,支持类、接口、静态内部类;
-
Java.registerClass :Frida动态创建Java类,必填
name(类名)和methods(方法定义),可选implements(实现的接口)和fields(成员变量); -
Java.cast:强制类型转换,解决JS调用Java的类型丢失问题,仅当需要访问对象的成员/方法时使用;
-
.value:Frida访问Java对象成员变量的专属语法,获取堆中实际值,否则仅拿到对象引用;
-
$new() :Frida中创建Java对象的方法,等效于Java的
new关键字; -
$className:Frida中获取Java对象所属类的全限定名的属性;
-
静态内部类访问 :通过
外部类$内部类的形式获取,如OkHttpClient$Builder。
五、OkHttp核心使用原理
-
核心角色:OkHttpClient是请求"引擎",负责底层网络连接、超时、重试;Request是请求"蓝图",定义URL、方法、头、体;
-
建造者模式 :通过Builder类链式配置参数,避免多构造器的冗余,最终通过
build()生成可执行实例; -
POST请求关键:必须封装RequestBody并指定MediaType,否则服务端无法解析请求体;
-
请求执行 :通过
OkHttpClient.newCall(Request).execute()发送同步请求,获取响应数据。
六、实操关键问题与解决方案
-
两个SashimiHeader类的兼容:目标APP同时存在两个包下的SashimiHeader,且结构一致,脚本通过动态获取类名实现自动匹配,无需手动区分;
-
代理检测绕过:不依赖系统代理设置,通过OkHttp直接构造HTTP请求发送到指定地址,在代码层面绕过应用的代理检测逻辑;
-
冗余代码清理:删除未被引用的PClass/PPClass,简化代码结构,提升可读性;
-
代码可读性优化:规范变量命名(见名知意)、统一日志格式、按功能分层、抽离公共代码(如解析SharkHttpEntity的方法)。
七、整体联动逻辑
tmf.js并非独立运行,而是与Python控制端(<tmf-killer.py>)、Burp形成**「移动端拦截→PC端转发→Burp修改→PC端返回→移动端篡改」** 的闭环:
-
tmf.js拦截TMF请求/响应,通过Frida的
send()将数据发送到Python端; -
Python端将数据转发到Burp,供用户可视化修改参数;
-
Python端将Burp修改后的参数通过
script.post()返回给tmf.js; -
tmf.js接收修改指令,篡改请求/响应后执行原始方法,完成全链路控制;
-
同时支持外部调用Python端的HTTP服务,触发tmf.js的RPC接口,实现自定义TMF发包。
(注:文档部分内容可能由 AI 生成)