文章总结: 本文详细分析Frida框架中Interceptor和Stalker等Instrumentation模块的JavaScriptAPI与底层C/C++实现的五层架构映射关系,包括接口定义层、基础结构层、具体实现层、工厂模式层和应用集成层。文档提供了完整的函数映射表、内存布局分析、执行流程追踪以及跨平台差异处理,并包含SSL/TLS解密监控、控制流完整性分析等实战案例,为动态二进制分析和安全检测提供技术指导。 综合评分: 85 文章分类: 二进制安全,逆向分析,安全工具,WEB安全,渗透测试
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_64:
gumx86relocator.c,gumx86writer.c -
ARM/ARM64:
gumarmrelocator.c,gumarmwriter.c,gumarm64relocator.c,gumarm64writer.c -
MIPS:
gummipsrelocator.c,gummipswriter.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对象(包含context,returnAddress,depth,register,errno,lastError等属性)
-
深度监控: 对应用程序进行全方位的行为监控和分析
-
性能优化: 合理使用仪器功能避免过度开销
-
安全分析: 利用动态插桩技术进行高级安全检测
-
逆向工程: 辅助复杂的逆向工程任务
-
// 函数级别性能剖析 -
const profileData =newMap(); -
Interceptor.attach(Module.findExportByName(null,'some_function'),{ -
onEnter:function(args){ -
this.startTime =Date.now(); -
this.startCpuTime =Process.getCpuTime(); -
}, -
onLeave:function(retval){ -
const duration =Date.now()-this.startTime; -
const cpuTime =Process.getCpuTime()-this.startCpuTime; -
const funcName ='some_function'; -
if(!profileData.has(funcName)){ -
profileData.set(funcName,{ calls:0, totalTime:0, totalCpuTime:0}); -
} -
const data = profileData.get(funcName); -
data.calls++; -
data.totalTime += duration; -
data.totalCpuTime += cpuTime; -
} -
}); -
// 定期输出剖析结果 -
setInterval(()=>{ -
profileData.forEach((data, funcName)=>{ -
console.log(${funcName}: ${data.calls} calls, ${data.totalTime}ms total, ${data.totalCpuTime}ms CPU); -
}); -
},5000); -
// 生成函数调用图 -
const callGraph =newMap(); -
let currentDepth =0; -
function trackFunctionCalls(moduleName){ -
Module.enumerateExports(moduleName,{ -
onMatch:function(exportDetails){ -
if(exportDetails.type ==='function'){ -
Interceptor.attach(exportDetails.address,{ -
onEnter:function(args){ -
const caller =this.returnAddress; -
const callee = exportDetails.address; -
if(!callGraph.has(caller)){ -
callGraph.set(caller,newSet()); -
} -
callGraph.get(caller).add(callee); -
currentDepth++; -
}, -
onLeave:function(retval){ -
currentDepth--; -
} -
}); -
} -
}, -
onComplete:function(){ -
console.log(Tracked all exports in ${moduleName}); -
} -
}); -
} -
trackFunctionCalls('libtarget.so'); -
// 使用Stalker分析程序控制流 -
Stalker.follow(Process.getCurrentThreadId(),{ -
events:{ -
call:true, -
ret:true, -
exec:false -
}, -
onReceive:function(events){ -
const parsed =Stalker.parse(events); -
parsed.forEach(event =>{ -
if(event.type ==='call'){ -
console.log('Call to:', event.target); -
}elseif(event.type ==='ret'){ -
console.log('Return from:', event.target); -
} -
}); -
} -
}); -
// 排除系统库以减少噪音 -
const systemLibs =['libc.so','libm.so','libdl.so']; -
systemLibs.forEach(libName =>{ -
const lib =Process.findModuleByName(libName); -
if(lib){ -
Stalker.exclude({ -
base: lib.base, -
size: lib.size -
}); -
} -
}); -
// 监控OpenSSL SSL_write和SSL_read调用 -
const sslWriteAddr =Module.findExportByName('libssl.so','SSL_write'); -
const sslReadAddr =Module.findExportByName('libssl.so','SSL_read'); -
if(sslWriteAddr){ -
Interceptor.attach(sslWriteAddr,{ -
onEnter:function(args){ -
const buf = args[1]; -
const num = parseInt(args[2]); -
const data = buf.readByteArray(num); -
console.log('SSL_write data:', hexdump(data)); -
} -
}); -
} -
if(sslReadAddr){ -
Interceptor.attach(sslReadAddr,{ -
onLeave:function(retval){ -
const num = parseInt(retval); -
if(num >0){ -
const buf =this.context.rdi;// 第一个参数是SSL*,第二个是buf -
// 注意:实际参数获取需要根据ABI调整 -
console.log('SSL_read returned:', num,'bytes'); -
} -
} -
}); -
} -
// 自定义Stalker事件处理器 -
const customTransformer =Stalker.parse(function(events){ -
events.forEach(event =>{ -
if(event.type ==='call'){ -
console.log('Function call to:', event.target); -
}elseif(event.type ==='ret'){ -
console.log('Function return from:', event.target); -
} -
}); -
}); -
Stalker.follow(Process.getCurrentThreadId(),{ -
transform: customTransformer -
}); -
// 创建带日志记录的拦截器 -
function createLoggingInterceptor(target, functionName){ -
returnInterceptor.attach(target,{ -
onEnter:function(args){ -
console.log(Entering ${functionName}with args:, args); -
this.startTime =Date.now(); -
}, -
onLeave:function(retval){ -
const duration =Date.now()-this.startTime; -
console.log(Leaving ${functionName}, returned: ${retval}, took: ${duration}ms); -
} -
}); -
} -
// 安全的Interceptor使用 -
function safeAttachInterceptor(target, callbacks){ -
try{ -
// 验证目标地址 -
if(!target || target.isNull()){ -
thrownewError('Invalid target address'); -
} -
// 尝试附加拦截器 -
const listener =Interceptor.attach(target, callbacks); -
console.log('Interceptor attached successfully'); -
return listener; -
}catch(e){ -
console.error('Failed to attach interceptor:', e); -
returnnull; -
} -
} -
// 安全的Stalker使用 -
function safeFollowThread(threadId, options){ -
try{ -
// 验证线程ID -
if(threadId ===undefined){ -
threadId =Process.getCurrentThreadId(); -
} -
// 开始跟踪 -
Stalker.follow(threadId, options); -
console.log(Stalker following thread ${threadId}); -
// 设置自动清理 -
setTimeout(()=>{ -
try{ -
Stalker.unfollow(threadId); -
console.log(Stalker unfollowed thread ${threadId}); -
}catch(e){ -
console.error('Failed to unfollow thread:', e); -
} -
},10000);// 10秒后自动停止 -
}catch(e){ -
console.error('Failed to follow thread:', e); -
} -
} -
# 在拦截器附加处设置断点 -
(gdb)break gum_interceptor_attach -
# 查看拦截器状态 -
(gdb) info args -
(gdb) print *(GumInterceptor*)interceptor_instance -
(gdb) x/20i $rdi # 查看目标函数入口 -
# 在跟踪器跟随处设置断点 -
(gdb)break gum_stalker_follow -
(gdb) info registers -
(gdb) thread apply all bt # 查看所有线程状态 -
// CPU抽象接口 -
typedefenum{ -
GUM_CPU_INVALID, -
GUM_CPU_IA32, -
GUM_CPU_X86_64, -
GUM_CPU_ARM, -
GUM_CPU_ARM64, -
GUM_CPU_MIPS -
}GumCpuType; -
// 指令重定位器抽象 -
struct_GumRelocator -
{ -
GObject parent; -
gboolean (* relocate)(GumRelocator* self, guint min_bytes, guint * out_bytes); -
void(* write_all)(GumRelocator* self); -
// ... 其他方法 -
}; -
// 指令写入器抽象 -
struct_GumInstructionWriter -
{ -
GObject parent; -
void(* put_call_address_with_arguments)(GumInstructionWriter* self,GumAddress func, guint n_args,...); -
void(* put_jmp_address)(GumInstructionWriter* self,GumAddress address); -
// ... 其他方法 -
}; -
线程执行到新代码块
-
触发跟踪处理程序
-
反汇编原始指令
-
应用变换器(transformer)修改指令流
-
生成插桩后的代码
-
执行插桩代码并记录事件
-
继续执行下一个代码块
-
JavaScript调用
Stalker.follow(threadId,options)→ GumJS绑定层 -
调用
gum_stalker_follow(threadId,options) -
挂起目标线程
-
修改线程上下文指向跟踪入口点
-
初始化跟踪状态和缓冲区
-
恢复线程执行
-
线程开始在跟踪模式下执行
-
目标函数被调用 → 执行跳板代码
-
跳板保存CPU上下文
-
调用
onEnter回调(如果存在) -
执行原始函数逻辑(或替换函数)
-
调用
onLeave回调(如果存在) -
恢复CPU上下文并返回
-
修改目标函数入口点为跳板地址
-
注册监听器到拦截器
-
返回监听器对象给JavaScript
-
JavaScript调用
Interceptor.attach(target,callbacks)→ GumJS绑定层 -
调用
gum_interceptor_attach(target,callbacks) -
验证目标地址有效性
-
创建跳板(trampoline)代码:
-
+------------------+ -
| on_enter (GCallback)|->进入回调函数指针 -
+------------------+ -
| on_leave (GCallback)|->离开回调函数指针 -
+------------------+ -
| user_data (gpointer)|->用户数据指针 -
+------------------+ -
|next(GumInvocationListener*)|->下一个监听器(链表) -
+------------------+ -
+------------------+ -
| transformer (GumStalkerTransformer*)|->指令转换器 -
+------------------+ -
| sink (GumEventSink*)|->事件接收器 -
+------------------+ -
| excluded_ranges (GArray*)|->排除的内存范围 -
+------------------+ -
| pages (GumSlab*)|->代码页分配器 -
+------------------+ -
| mutex (GMutex)|->线程同步互斥锁 -
+------------------+ -
+------------------+ -
| trampolines (GHashTable*)|->目标地址到跳板的映射 -
+------------------+ -
| exclusions (GArray*)|->排除的内存范围列表 -
+------------------+ -
| backend (GumInterceptorBackend*)|->平台特定后端 -
+------------------+ -
| mutex (GMutex)|->线程同步互斥锁 -
+------------------+ -
// GumStalker工厂 -
GumStalker* -
gum_stalker_new (GumCpuType cpu_type); -
GumStalkerTransformer* -
gum_stalker_transformer_make_default (void); -
// GumInterceptor工厂 -
GumInterceptor* -
gum_interceptor_obtain (void); -
GumInterceptorBackend* -
gum_interceptor_backend_create (GumCodeAllocator* allocator); -
// GumRelocator工厂 -
GumRelocator* -
gum_relocator_new (gconstpointer input_code,GumInstructionWriter* output); -
GumRelocator* -
gum_relocator_make_for_cpu (GumCpuType cpu_type, gconstpointer input_code); -
// 指令写入器工厂 -
GumInstructionWriter* -
gum_instruction_writer_new (gpointer code_address); -
GumInstructionWriter* -
gum_instruction_writer_make_for_cpu (GumCpuType cpu_type, gpointer code_address); -
// Interceptor相关的结构 -
typedefstruct_GumInterceptorApi{ -
GumInvocationListener*(* attach)(gpointer target,GumInvocationCallbacks* callbacks); -
void(* detach)(GumInvocationListener* listener); -
gboolean (* replace)(gpointer target, gpointer replacement, gpointer * original); -
void(* revert)(gpointer target); -
}GumInterceptorApi; -
// Stalker相关的结构 -
typedefstruct_GumStalkerApi{ -
void(* follow)(guint thread_id,GumStalkerOptions* options); -
void(* unfollow)(guint thread_id); -
void(* garbage_collect)(void); -
void(* exclude)(constGumMemoryRange* range); -
void(* flush)(void); -
}GumStalkerApi; -
// InvocationContext结构 -
typedefstruct_GumInvocationContext{ -
GumCpuContext* cpu_context; -
gpointer return_address; -
gint depth; -
GumThreadId thread_id; -
GumPageProtection page_protection; -
}GumInvocationContext;
- 公众号:安全狗的自我修养
- vx:2207344074
- http://gitee.com/haidragon
- http://github.com/haidragon
- bilibili:haidragonx
#
#
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:安全狗的自我修养 haidragon haidragon《frida各模块js与cpp函数分析对照(五)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论