frida各模块js与cpp函数分析对照(五)

admin 2026-04-07 01:02:45 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细分析Frida框架中Interceptor和Stalker等Instrumentation模块的JavaScriptAPI与底层C/C++实现的五层架构映射关系,包括接口定义层、基础结构层、具体实现层、工厂模式层和应用集成层。文档提供了完整的函数映射表、内存布局分析、执行流程追踪以及跨平台差异处理,并包含SSL/TLS解密监控、控制流完整性分析等实战案例,为动态二进制分析和安全检测提供技术指导。 综合评分: 85 文章分类: 二进制安全,逆向分析,安全工具,WEB安全,渗透测试


cover_image

frida各模块js与cpp函数分析对照(五)

原创

haidragon haidragon

安全狗的自我修养

2026年4月5日 11:40 湖南

  • 官网:http://securitytech.cc

    Instrumentation模块 JavaScript与底层C++函数映射关系分析

    文档概述

    本文档详细分析Frida中Interceptor、Stalker等仪器模块的JavaScript API与其底层C/C++实现之间的映射关系,涵盖完整的五层架构模型分析。

    五层架构模型分析

    1. 接口定义层 (JavaScript API Layer)

    Interceptor主要接口:

    Stalker主要接口:

    其他仪器相关接口:

    2. 基础结构层 (GumJS Binding Layer)

    在 subprojects/frida-gum/bindings/gumjs目录中,Interceptor和Stalker模块的绑定实现在相关文件中。

    关键数据结构


### 3. 具体实现层 (Platform-specific Implementation)

#### Interceptor实现 ( guminterceptor.c)

关键函数:

#### Stalker实现 ( gumstalker.c)

关键函数:

### 4. 工厂模式层 (Backend Factory)

#### 指令重定位器工厂


#### 拦截器工厂


#### 跟踪器工厂


### 5. 应用集成层 (Integration with Frida Core)

Interceptor和Stalker模块通过frida-core与上层应用集成,提供统一的API接口,并与事件系统和消息通道深度集成。

## 详细函数映射关系表

### Interceptor映射表

| JavaScript Function | C Function | File Location | Description | | — | — | — | — | | Interceptor.attach() | gum_interceptor_attach() | guminterceptor.c | 附加拦截监听器 | | Interceptor.detach() | gum_interceptor_detach() | guminterceptor.c | 分离拦截监听器 | | Interceptor.replace() | gum_interceptor_replace() | guminterceptor.c | 替换目标函数 | | Interceptor.revert() | gum_interceptor_revert() | guminterceptor.c | 恢复被替换的函数 |

### Stalker映射表

| JavaScript Function | C Function | File Location | Description | | — | — | — | — | | Stalker.follow() | gum_stalker_follow() | gumstalker.c | 开始跟踪线程执行 | | Stalker.unfollow() | gum_stalker_unfollow() | gumstalker.c | 停止跟踪线程 | | Stalker.exclude() | gum_stalker_exclude() | gumstalker.c | 排除内存范围不跟踪 | | Stalker.flush() | gum_stalker_flush() | gumstalker.c | 刷新跟踪缓冲区 | | Stalker.garbageCollect() | gum_stalker_garbage_collect() | gumstalker.c | 垃圾回收跟踪代码 |

## 内存布局与数据结构可视化

### GumInterceptor结构体内存布局


### GumStalker结构体内存布局


### GumInvocationListener结构体内存布局


## 系统调用级执行流程追踪

### Interceptor.attach()执行流程

### 函数调用拦截执行流程

### Stalker.follow()执行流程

### 动态二进制插桩执行流程

## 跨平台差异与抽象机制

### 指令集架构差异

### 内存保护机制差异

### 线程控制差异

### 抽象层设计


## 调试命令与安全实践

### GDB调试示例


### 性能优化建议

### 安全考虑

## 错误处理与边界情况

### 常见错误场景

### 最佳实践


## 攻击检测场景映射

### 可用于检测的场景

### 防御绕过技术

## 性能分析与优化

### 时间复杂度分析

### 内存使用分析

## 扩展功能与自定义实现

### 自定义Interceptor变换器


### 自定义Stalker事件处理器


### 底层扩展点

## 版本兼容性与演进

### API变更历史

### 向后兼容性保证

## 实战案例分析

### 案例1: SSL/TLS解密监控


### 案例2: 控制流完整性分析


### 案例3: 函数调用图生成


### 案例4: 性能剖析


## 总结与最佳实践

Interceptor和Stalker模块是Frida最强大的动态分析工具,提供了从函数级别到指令级别的全面监控能力。理解其JS与C++的映射关系有助于:

通过本文档的五层架构分析,开发者可以全面掌握Instrumentation模块的工作原理和使用技巧,为复杂的动态分析任务提供坚实的基础。

  • 核心API保持稳定

  • 新功能通过扩展方式添加

  • 废弃的API会标记并提供迁移路径

  • Frida早期版本: 基本的Interceptor功能

  • Frida 6.x: 添加Stalker支持

  • Frida 8.x: 完善跨平台支持和性能优化

  • Frida 10.x: 添加更多的指令集架构支持

  • Frida 12.x: 优化内存使用和错误处理

  • Frida 14.x: 改进Stalker的可靠性和性能

  • 可以通过修改 guminterceptor.c添加新的拦截策略

  • 通过修改 gumstalker.c添加新的事件类型和处理逻辑

  • 扩展指令重定位器和写入器支持新的指令集特性

  • Interceptor: 每个拦截点需要分配跳板代码和上下文结构体

  • Stalker: 需要分配跟踪缓冲区、代码页和事件队列

  • 优化建议:

  • 限制同时跟踪的线程数量

  • 及时清理不再需要的拦截器和跟踪器

  • 使用exclude排除大块不需要跟踪的内存

  • Interceptor.attach(): O(1),但涉及内存分配和代码修改

  • Interceptor回调: O(n),n为回调函数复杂度

  • Stalker.follow(): O(1),但启动开销较大

  • Stalker事件处理: O(m),m为每条指令的处理开销

  • 直接系统调用: 绕过被拦截的API直接调用系统调用

  • 代码混淆: 使用混淆技术干扰Stalker的分析

  • 反跟踪技术: 检测和规避动态二进制插桩

  • 多线程规避: 在未被跟踪的线程中执行敏感操作

  • API监控: 使用Interceptor监控敏感API调用

  • 控制流分析: 使用Stalker分析程序执行路径

  • 反调试检测: 检测Interceptor和Stalker的存在

  • 行为分析: 基于函数调用序列进行行为分析

  • Interceptor错误:

  • 目标地址无效:无法创建跳板

  • 内存保护冲突:无法修改代码页

  • 多重拦截冲突:同一地址被多次拦截

  • Stalker错误:

  • 线程ID无效:无法跟踪不存在的线程

  • 内存不足:无法分配跟踪缓冲区

  • 性能问题:跟踪开销过大导致应用卡顿

  • 拦截器安全: 避免拦截关键系统函数导致崩溃

  • 跟踪器安全: 注意性能开销,避免影响目标应用正常运行

  • 内存安全: 确保跳板代码和插桩代码的内存安全性

  • Interceptor优化:

  • 避免过度拦截,只拦截必要的函数

  • 使用高效的回调函数,避免复杂计算

  • 考虑使用replace而不是attach/leave组合

  • Stalker优化:

  • 排除不需要跟踪的内存范围

  • 调整队列容量和刷新间隔

  • 使用自定义变换器减少事件数量

  • Darwin: 使用Mach线程API (threadsuspend, threadresume)

  • Linux: 使用ptrace()系统调用

  • Windows: 使用SuspendThread()/ResumeThread()

  • Darwin: 使用VMPROTECTWRITECOPY等Mach VM特性

  • Linux: 使用mprotect()和信号处理

  • Windows: 使用VirtualProtect()和异常处理

  • x86/x86_64:

  • 变长指令,复杂寻址模式

  • 需要精确的指令重定位

  • 支持硬件性能计数器

  • ARM/ARM64:

  • 固定长度指令(ARM64: 32位,ARM: 16/32位混合)

  • 条件执行和分支预测

  • Thumb模式支持

  • MIPS:

  • 固定长度32位指令

  • 延迟槽(branch delay slot)处理

  • 流水线优化考虑

  • 保存原始指令

  • 生成跳转到拦截处理程序的代码

  • 处理指令重定位(跨平台差异)

  • gum_stalker_follow()

  • gum_stalker_unfollow()

  • gum_stalker_exclude()

  • gum_stalker_flush()

  • 通用跟踪器gumstalker.c – 动态二进制插桩引擎

  • 平台特定实现:

  • x86/x86_64: 使用Intel PT或软件跟踪

  • ARM/ARM64: 使用分支跟踪或软件跟踪

  • MIPS: 软件跟踪实现

  • gum_interceptor_attach()

  • gum_interceptor_detach()

  • gum_interceptor_replace()

  • gum_interceptor_revert()

  • 通用拦截器gum_interceptor.c – 跨平台函数拦截框架

  • 平台特定后端:

  • x86/x86_64gumx86relocator.cgumx86writer.c

  • ARM/ARM64gumarmrelocator.cgumarmwriter.cgumarm64relocator.cgumarm64writer.c

  • MIPSgummipsrelocator.cgummipswriter.c

  • Script.bindWeak(callback,target)

  • Script.nextTick(callback)

  • setTimeout(callback,delay)

  • clearTimeout(timerId)

  • Stalker.follow([threadId],options)

  • Stalker.unfollow([threadId])

  • Stalker.garbageCollect()

  • Stalker.exclude(range)

  • Stalker.flush()

  • Stalker.trustThreshold

  • Stalker.queueCapacity

  • Stalker.queueDrainInterval

  • Interceptor.attach(target,callbacks)

  • Interceptor.detach(listener)

  • Interceptor.replace(target,replacement)

  • Interceptor.revert(target)

  • InvocationContext对象(包含 contextreturnAddressdepthregistererrnolastError等属性)

  1. 深度监控: 对应用程序进行全方位的行为监控和分析

  2. 性能优化: 合理使用仪器功能避免过度开销

  3. 安全分析: 利用动态插桩技术进行高级安全检测

  4. 逆向工程: 辅助复杂的逆向工程任务

  5. // 函数级别性能剖析

  6. const profileData =newMap();

  7. Interceptor.attach(Module.findExportByName(null,'some_function'),{

  8. onEnter:function(args){

  9. this.startTime =Date.now();

  10. this.startCpuTime =Process.getCpuTime();

  11. },

  12. onLeave:function(retval){

  13. const duration =Date.now()-this.startTime;

  14. const cpuTime =Process.getCpuTime()-this.startCpuTime;

  15. const funcName ='some_function';

  16. if(!profileData.has(funcName)){

  17. profileData.set(funcName,{ calls:0, totalTime:0, totalCpuTime:0});

  18. }

  19. const data = profileData.get(funcName);

  20. data.calls++;

  21. data.totalTime += duration;

  22. data.totalCpuTime += cpuTime;

  23. }

  24. });

  25. // 定期输出剖析结果

  26. setInterval(()=>{

  27. profileData.forEach((data, funcName)=>{

  28. console.log(${funcName}: ${data.calls} calls, ${data.totalTime}ms total, ${data.totalCpuTime}ms CPU);

  29. });

  30. },5000);

  31. // 生成函数调用图

  32. const callGraph =newMap();

  33. let currentDepth =0;

  34. function trackFunctionCalls(moduleName){

  35. Module.enumerateExports(moduleName,{

  36. onMatch:function(exportDetails){

  37. if(exportDetails.type ==='function'){

  38. Interceptor.attach(exportDetails.address,{

  39. onEnter:function(args){

  40. const caller =this.returnAddress;

  41. const callee = exportDetails.address;

  42. if(!callGraph.has(caller)){

  43. callGraph.set(caller,newSet());

  44. }

  45. callGraph.get(caller).add(callee);

  46. currentDepth++;

  47. },

  48. onLeave:function(retval){

  49. currentDepth--;

  50. }

  51. });

  52. }

  53. },

  54. onComplete:function(){

  55. console.log(Tracked all exports in ${moduleName});

  56. }

  57. });

  58. }

  59. trackFunctionCalls('libtarget.so');

  60. // 使用Stalker分析程序控制流

  61. Stalker.follow(Process.getCurrentThreadId(),{

  62. events:{

  63. call:true,

  64. ret:true,

  65. exec:false

  66. },

  67. onReceive:function(events){

  68. const parsed =Stalker.parse(events);

  69. parsed.forEach(event =>{

  70. if(event.type ==='call'){

  71. console.log('Call to:', event.target);

  72. }elseif(event.type ==='ret'){

  73. console.log('Return from:', event.target);

  74. }

  75. });

  76. }

  77. });

  78. // 排除系统库以减少噪音

  79. const systemLibs =['libc.so','libm.so','libdl.so'];

  80. systemLibs.forEach(libName =>{

  81. const lib =Process.findModuleByName(libName);

  82. if(lib){

  83. Stalker.exclude({

  84. base: lib.base,

  85. size: lib.size

  86. });

  87. }

  88. });

  89. // 监控OpenSSL SSL_write和SSL_read调用

  90. const sslWriteAddr =Module.findExportByName('libssl.so','SSL_write');

  91. const sslReadAddr =Module.findExportByName('libssl.so','SSL_read');

  92. if(sslWriteAddr){

  93. Interceptor.attach(sslWriteAddr,{

  94. onEnter:function(args){

  95. const buf = args[1];

  96. const num = parseInt(args[2]);

  97. const data = buf.readByteArray(num);

  98. console.log('SSL_write data:', hexdump(data));

  99. }

  100. });

  101. }

  102. if(sslReadAddr){

  103. Interceptor.attach(sslReadAddr,{

  104. onLeave:function(retval){

  105. const num = parseInt(retval);

  106. if(num >0){

  107. const buf =this.context.rdi;// 第一个参数是SSL*,第二个是buf

  108. // 注意:实际参数获取需要根据ABI调整

  109. console.log('SSL_read returned:', num,'bytes');

  110. }

  111. }

  112. });

  113. }

  114. // 自定义Stalker事件处理器

  115. const customTransformer =Stalker.parse(function(events){

  116. events.forEach(event =>{

  117. if(event.type ==='call'){

  118. console.log('Function call to:', event.target);

  119. }elseif(event.type ==='ret'){

  120. console.log('Function return from:', event.target);

  121. }

  122. });

  123. });

  124. Stalker.follow(Process.getCurrentThreadId(),{

  125. transform: customTransformer

  126. });

  127. // 创建带日志记录的拦截器

  128. function createLoggingInterceptor(target, functionName){

  129. returnInterceptor.attach(target,{

  130. onEnter:function(args){

  131. console.log(Entering ${functionName}with args:, args);

  132. this.startTime =Date.now();

  133. },

  134. onLeave:function(retval){

  135. const duration =Date.now()-this.startTime;

  136. console.log(Leaving ${functionName}, returned: ${retval}, took: ${duration}ms);

  137. }

  138. });

  139. }

  140. // 安全的Interceptor使用

  141. function safeAttachInterceptor(target, callbacks){

  142. try{

  143. // 验证目标地址

  144. if(!target || target.isNull()){

  145. thrownewError('Invalid target address');

  146. }

  147. // 尝试附加拦截器

  148. const listener =Interceptor.attach(target, callbacks);

  149. console.log('Interceptor attached successfully');

  150. return listener;

  151. }catch(e){

  152. console.error('Failed to attach interceptor:', e);

  153. returnnull;

  154. }

  155. }

  156. // 安全的Stalker使用

  157. function safeFollowThread(threadId, options){

  158. try{

  159. // 验证线程ID

  160. if(threadId ===undefined){

  161. threadId =Process.getCurrentThreadId();

  162. }

  163. // 开始跟踪

  164. Stalker.follow(threadId, options);

  165. console.log(Stalker following thread ${threadId});

  166. // 设置自动清理

  167. setTimeout(()=>{

  168. try{

  169. Stalker.unfollow(threadId);

  170. console.log(Stalker unfollowed thread ${threadId});

  171. }catch(e){

  172. console.error('Failed to unfollow thread:', e);

  173. }

  174. },10000);// 10秒后自动停止

  175. }catch(e){

  176. console.error('Failed to follow thread:', e);

  177. }

  178. }

  179. # 在拦截器附加处设置断点

  180. (gdb)break gum_interceptor_attach

  181. # 查看拦截器状态

  182. (gdb) info args

  183. (gdb) print *(GumInterceptor*)interceptor_instance

  184. (gdb) x/20i $rdi  # 查看目标函数入口

  185. # 在跟踪器跟随处设置断点

  186. (gdb)break gum_stalker_follow

  187. (gdb) info registers

  188. (gdb) thread apply all bt  # 查看所有线程状态

  189. // CPU抽象接口

  190. typedefenum{

  191. GUM_CPU_INVALID,

  192. GUM_CPU_IA32,

  193. GUM_CPU_X86_64,

  194. GUM_CPU_ARM,

  195. GUM_CPU_ARM64,

  196. GUM_CPU_MIPS

  197. }GumCpuType;

  198. // 指令重定位器抽象

  199. struct_GumRelocator

  200. {

  201. GObject parent;

  202. gboolean (* relocate)(GumRelocator* self, guint min_bytes, guint * out_bytes);

  203. void(* write_all)(GumRelocator* self);

  204. // ... 其他方法

  205. };

  206. // 指令写入器抽象

  207. struct_GumInstructionWriter

  208. {

  209. GObject parent;

  210. void(* put_call_address_with_arguments)(GumInstructionWriter* self,GumAddress func, guint n_args,...);

  211. void(* put_jmp_address)(GumInstructionWriter* self,GumAddress address);

  212. // ... 其他方法

  213. };

  214. 线程执行到新代码块

  215. 触发跟踪处理程序

  216. 反汇编原始指令

  217. 应用变换器(transformer)修改指令流

  218. 生成插桩后的代码

  219. 执行插桩代码并记录事件

  220. 继续执行下一个代码块

  221. JavaScript调用 Stalker.follow(threadId,options) → GumJS绑定层

  222. 调用 gum_stalker_follow(threadId,options)

  223. 挂起目标线程

  224. 修改线程上下文指向跟踪入口点

  225. 初始化跟踪状态和缓冲区

  226. 恢复线程执行

  227. 线程开始在跟踪模式下执行

  228. 目标函数被调用 → 执行跳板代码

  229. 跳板保存CPU上下文

  230. 调用 onEnter回调(如果存在)

  231. 执行原始函数逻辑(或替换函数)

  232. 调用 onLeave回调(如果存在)

  233. 恢复CPU上下文并返回

  234. 修改目标函数入口点为跳板地址

  235. 注册监听器到拦截器

  236. 返回监听器对象给JavaScript

  237. JavaScript调用 Interceptor.attach(target,callbacks) → GumJS绑定层

  238. 调用 gum_interceptor_attach(target,callbacks)

  239. 验证目标地址有效性

  240. 创建跳板(trampoline)代码:

  241. +------------------+

  242. | on_enter (GCallback)|->进入回调函数指针

  243. +------------------+

  244. | on_leave (GCallback)|->离开回调函数指针

  245. +------------------+

  246. | user_data (gpointer)|->用户数据指针

  247. +------------------+

  248. |next(GumInvocationListener*)|->下一个监听器(链表)

  249. +------------------+

  250. +------------------+

  251. | transformer (GumStalkerTransformer*)|->指令转换器

  252. +------------------+

  253. | sink (GumEventSink*)|->事件接收器

  254. +------------------+

  255. | excluded_ranges (GArray*)|->排除的内存范围

  256. +------------------+

  257. | pages (GumSlab*)|->代码页分配器

  258. +------------------+

  259. | mutex (GMutex)|->线程同步互斥锁

  260. +------------------+

  261. +------------------+

  262. | trampolines (GHashTable*)|->目标地址到跳板的映射

  263. +------------------+

  264. | exclusions (GArray*)|->排除的内存范围列表

  265. +------------------+

  266. | backend (GumInterceptorBackend*)|->平台特定后端

  267. +------------------+

  268. | mutex (GMutex)|->线程同步互斥锁

  269. +------------------+

  270. // GumStalker工厂

  271. GumStalker*

  272. gum_stalker_new (GumCpuType cpu_type);

  273. GumStalkerTransformer*

  274. gum_stalker_transformer_make_default (void);

  275. // GumInterceptor工厂

  276. GumInterceptor*

  277. gum_interceptor_obtain (void);

  278. GumInterceptorBackend*

  279. gum_interceptor_backend_create (GumCodeAllocator* allocator);

  280. // GumRelocator工厂

  281. GumRelocator*

  282. gum_relocator_new (gconstpointer input_code,GumInstructionWriter* output);

  283. GumRelocator*

  284. gum_relocator_make_for_cpu (GumCpuType cpu_type, gconstpointer input_code);

  285. // 指令写入器工厂

  286. GumInstructionWriter*

  287. gum_instruction_writer_new (gpointer code_address);

  288. GumInstructionWriter*

  289. gum_instruction_writer_make_for_cpu (GumCpuType cpu_type, gpointer code_address);

  290. // Interceptor相关的结构

  291. typedefstruct_GumInterceptorApi{

  292. GumInvocationListener*(* attach)(gpointer target,GumInvocationCallbacks* callbacks);

  293. void(* detach)(GumInvocationListener* listener);

  294. gboolean (* replace)(gpointer target, gpointer replacement, gpointer * original);

  295. void(* revert)(gpointer target);

  296. }GumInterceptorApi;

  297. // Stalker相关的结构

  298. typedefstruct_GumStalkerApi{

  299. void(* follow)(guint thread_id,GumStalkerOptions* options);

  300. void(* unfollow)(guint thread_id);

  301. void(* garbage_collect)(void);

  302. void(* exclude)(constGumMemoryRange* range);

  303. void(* flush)(void);

  304. }GumStalkerApi;

  305. // InvocationContext结构

  306. typedefstruct_GumInvocationContext{

  307. GumCpuContext* cpu_context;

  308. gpointer return_address;

  309. gint depth;

  310. GumThreadId thread_id;

  311. GumPageProtection page_protection;

  312. }GumInvocationContext;

  • 公众号:安全狗的自我修养
  • vx:2207344074
  • http://gitee.com/haidragon
  • http://github.com/haidragon
  • bilibili:haidragonx

#

#


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:安全狗的自我修养 haidragon haidragon《frida各模块js与cpp函数分析对照(五)》

评论:0   参与:  0