文章总结: 本文详细分析了Frida框架中Module和Memory模块的JavaScriptAPI与底层C++实现的五层映射架构,包括接口定义层、绑定层、平台实现层、工厂模式层和应用集成层。文档提供了完整的函数对照表,展示了模块操作和内存管理功能的具体实现机制,并包含跨平台差异分析、性能优化建议和实战案例,为安全研究人员深入理解Frida内部机制和进行二进制分析提供技术参考。 综合评分: 82 文章分类: 二进制安全,逆向分析,安全工具,渗透测试,漏洞分析
frida各模块js与cpp函数分析对照(三)
原创
haidragon haidragon
安全狗的自我修养
2026年4月5日 11:40 湖南
-
官网:http://securitytech.cc
Module和Memory模块 JavaScript与底层C++函数映射关系分析
文档概述
本文档详细分析Frida中Module和Memory模块的JavaScript API与其底层C/C++实现之间的映射关系,涵盖完整的五层架构模型分析。
五层架构模型分析
1. 接口定义层 (JavaScript API Layer)
Module模块主要接口:
Memory模块主要接口:
2. 基础结构层 (GumJS Binding Layer)
在
subprojects/frida-gum/bindings/gumjs目录中,Module和Memory模块的绑定实现在相关文件中。关键数据结构
### 3. 具体实现层 (Platform-specific Implementation)
#### Module实现 ( gummodule-*.c)
关键函数:
#### Memory实现 ( gummemory-*.c)
关键函数:
### 4. 工厂模式层 (Backend Factory)
#### Module工厂
#### Memory工厂
### 5. 应用集成层 (Integration with Frida Core)
Module和Memory模块通过frida-core与上层应用集成,提供统一的API接口。
## 详细函数映射关系表
### Module模块映射表
| JavaScript Function | C++ Function | File Location | Description |
| — | — | — | — |
| Module.findBaseAddress() | gum_module_find_base_address() | gummodule-*.c | 查找模块基地址 |
| Module.findExportByName() | gum_module_find_export_by_name() | gummodule-*.c | 查找导出符号地址 |
| Module.enumerateExports() | gum_module_enumerate_exports() | gummodule-*.c | 枚举模块导出符号 |
| Module.enumerateImports() | gum_module_enumerate_imports() | gummodule-*.c | 枚举模块导入符号 |
| Module.enumerateSymbols() | gum_module_enumerate_symbols() | gummodule-*.c | 枚举模块所有符号 |
| Module.getExports() | gum_module_enumerate_exports() | gummodule-*.c | 获取导出符号列表(同步) |
### Memory模块映射表
| JavaScript Function | C++ Function | File Location | Description |
| — | — | — | — |
| Memory.alloc() | gum_memory_alloc() | gummemory-*.c | 分配内存 |
| Memory.free() | gum_memory_free() | gummemory-*.c | 释放内存 |
| Memory.copy() | gum_memory_copy() | gummemory.c | 内存复制 |
| Memory.protect() | gum_memory_protect() | gummemory-*.c | 修改内存保护属性 |
| Memory.scan() | gum_memory_scan() | gummemory.c | 内存扫描(异步) |
| Memory.scanSync() | gum_memory_scan_sync() | gummemory.c | 内存扫描(同步) |
## 内存布局与数据结构可视化
### ExportDetails结构体内存布局
### ImportDetails结构体内存布局
### MemoryRange结构体内存布局
## 系统调用级执行流程追踪
### Module.findExportByName()执行流程
### Memory.scan()执行流程
## 跨平台差异与抽象机制
### Module实现差异
### Memory实现差异
### 抽象层设计
## 调试命令与安全实践
### GDB调试示例
### 性能优化建议
## 错误处理与边界情况
### 常见错误场景
### 最佳实践
## 攻击检测场景映射
### 可用于检测的场景
### 防御绕过技术
## 性能分析与优化
### 时间复杂度分析
### 内存使用分析
## 扩展功能与自定义实现
### 自定义模块解析
### 自定义内存工具
### 底层扩展点
## 版本兼容性与演进
### API变更历史
### 向后兼容性保证
## 实战案例分析
### 案例1: 动态API解析
### 案例2: 内存特征码扫描
### 案例3: 模块依赖分析
## 总结与最佳实践
Module和Memory模块是Frida中最核心的功能模块,提供了对目标进程二进制结构和内存空间的全面访问能力。理解其JS与C++的映射关系有助于:
通过本文档的五层架构分析,开发者可以全面掌握Module和Memory模块的工作原理和使用技巧,为复杂的动态分析任务提供坚实的基础。
-
核心API保持稳定
-
新功能通过扩展方式添加
-
废弃的API会标记并提供迁移路径
-
Frida早期版本: 基本的模块和内存操作
-
Frida 10.x: 添加完整的符号枚举功能
-
Frida 12.x: 优化内存扫描性能,添加异步API
-
Frida 14.x: 改进跨平台兼容性和错误处理
-
可以通过修改
gummodule-*.c添加新的模块解析功能 -
通过修改
gummemory-*.c添加新的内存操作原语 -
扩展GumModule和GumMemory结构体添加新方法
-
Module操作: 符号枚举会为每个符号分配ExportDetails结构体
-
Memory操作: 扫描会分配临时缓冲区和结果数组
-
优化建议: 使用流式API避免一次性加载大量数据
-
Module操作:
-
findExportByName(): O(n),n为导出符号数量 -
enumerateExports(): O(n),需要遍历所有导出符号 -
getExports(): O(n),同上但返回完整列表 -
Memory操作:
-
alloc()/free(): O(1),系统调用开销 -
scan(): O(size/pattern_length),线性扫描 -
protect(): O(1),系统调用开销 -
直接系统调用: 绕过Module API直接解析二进制
-
内存加密: 隐藏恶意代码和数据
-
动态加载: 运行时加载和解析模块
-
API Hook检测: 监控关键导出函数的地址变化
-
内存扫描检测: 检测可疑的内存扫描行为
-
模块完整性验证: 验证关键模块的导出表完整性
-
Module错误:
-
模块不存在:返回null
-
符号不存在:返回null
-
权限不足:无法读取模块信息
-
Memory错误:
-
无效地址:访问违规
-
内存不足:分配失败
-
保护冲突:无法修改保护属性
-
Module缓存: 缓存常用的模块和符号查找结果
-
Memory批量操作: 避免频繁的小内存分配
-
扫描优化: 使用更精确的模式减少扫描范围
-
Darwin: 使用
mach_vm_allocate()、mach_vm_deallocate()、mach_vm_protect() -
Linux: 使用
mmap()、munmap()、mprotect() -
Windows: 使用
VirtualAlloc()、VirtualFree()、VirtualProtect() -
Darwin (Mach-O):
-
使用
_dyld_get_image_header()获取镜像头 -
解析LCSYMTAB、LCDYSYMTAB等加载命令
-
支持懒绑定和非懒绑定符号
-
Linux (ELF):
-
解析程序头表(PT_DYNAMIC)
-
处理.dynsym、.dynstr段
-
支持PLT/GOT机制
-
Windows (PE):
-
解析IMAGENTHEADERS
-
处理导出目录表
-
支持转发器(forwarder)功能
-
Darwin: 解析Mach-O的LC_SYMTAB加载命令
-
Linux: 解析ELF的.dynamic段和符号表
-
Windows: 解析PE的导出表
-
gum_memory_alloc() -
gum_memory_free() -
gum_memory_copy() -
gum_memory_protect() -
gum_memory_scan() -
通用实现:
gummemory.c– 跨平台内存操作 -
Darwin特定:
gummemory-darwin.c– 使用Mach VM API -
Linux特定:
gummemory-linux.c– 使用mmap/mprotect -
gum_module_find_base_address() -
gum_module_find_export_by_name() -
gum_module_enumerate_exports() -
gum_module_enumerate_imports() -
gum_module_enumerate_symbols() -
Darwin:
gummodule-darwin.c– 使用Mach-O解析 -
Linux:
gummodule-linux.c– 使用ELF解析 -
Windows:
gummodule-windows.c– 使用PE解析 -
Memory.alloc(size) -
Memory.copy(dst,src,n) -
Memory.dup(address,size) -
Memory.protect(address,size,protection) -
Memory.scan(address,size,pattern,callbacks) -
Memory.scanSync(address,size,pattern) -
Memory.allocUtf8String(str) -
Memory.allocAnsiString(str) -
Memory.allocUtf16String(str) -
Module.load(name) -
Module.ensureInitialized(name) -
Module.findBaseAddress(name) -
Module.findExportByName(module,symbol) -
Module.getExports() -
Module.getImports() -
Module.getSymbolByName(module,symbol) -
Module.enumerateExports(module) -
Module.enumerateImports(module) -
Module.enumerateSymbols(module) -
Module.enumerateRanges(module,protection)
-
二进制分析: 深入理解目标应用的模块结构和依赖关系
-
内存操作: 精确控制和监控目标进程的内存使用
-
API Hook: 基于符号信息实现精准的函数Hook
-
安全检测: 利用模块和内存信息进行深度安全分析
-
// 分析模块的导入依赖 -
function analyzeModuleImports(moduleName){ -
console.log(Analyzing imports for ${moduleName}:); -
Module.enumerateImports(moduleName,{ -
onMatch:function(importDetails){ -
console.log(${importDetails.name} from ${importDetails.module}); -
}, -
onComplete:function(){ -
console.log('Import analysis completed'); -
} -
}); -
} -
analyzeModuleImports('libcrypto.so'); -
// 扫描内存中的特定字节序列 -
const pattern ='48 89 ?? ?? ?? 48 8b ?? ?? ?? ?? ??'; -
const base =Module.findBaseAddress('libtarget.so'); -
const size =0x100000;// 1MB扫描范围 -
Memory.scan(base, size, pattern,{ -
onMatch:function(address, size){ -
console.log('Found pattern at:', address); -
// 进一步分析找到的地址 -
}, -
onError:function(reason){ -
console.error('Scan error:', reason); -
}, -
onComplete:function(){ -
console.log('Scan completed'); -
} -
}); -
// 动态解析和调用Windows API -
const kernel32 =Module.findBaseAddress('kernel32.dll'); -
const loadLibraryAddr =Module.findExportByName('kernel32.dll','LoadLibraryA'); -
if(loadLibraryAddr){ -
constLoadLibrary=newNativeFunction(loadLibraryAddr,'pointer',['pointer']); -
const libName =Memory.allocUtf8String('user32.dll'); -
const user32Handle =LoadLibrary(libName); -
console.log('Loaded user32.dll:', user32Handle); -
} -
// 内存区域保护监控 -
Memory.monitorProtectionChanges =function(address, size, callback){ -
const originalProtection =Memory.queryProtection(address); -
// 定期检查保护属性变化 -
const interval = setInterval(()=>{ -
const currentProtection =Memory.queryProtection(address); -
if(currentProtection !== originalProtection){ -
callback(address, originalProtection, currentProtection); -
clearInterval(interval); -
} -
},100); -
return interval; -
}; -
// 扩展Module模块功能 -
Module.findImportByName =function(moduleName, importName){ -
let result =null; -
Module.enumerateImports(moduleName,{ -
onMatch:function(importDetails){ -
if(importDetails.name === importName){ -
result = importDetails; -
return'stop'; -
} -
}, -
onComplete:function(){} -
}); -
return result; -
}; -
// 安全的模块操作 -
function safeFindExport(moduleName, symbolName){ -
try{ -
const base =Module.findBaseAddress(moduleName); -
if(!base){ -
console.warn(Module ${moduleName} not found); -
returnnull; -
} -
const address =Module.findExportByName(moduleName, symbolName); -
if(!address){ -
console.warn(Symbol ${symbolName} not found in ${moduleName}); -
returnnull; -
} -
return address; -
}catch(e){ -
console.error('Module operation failed:', e); -
returnnull; -
} -
} -
// 安全的内存操作 -
function safeMemoryScan(address, size, pattern){ -
try{ -
const results =[]; -
Memory.scanSync(address, size, pattern).forEach(match =>{ -
results.push(match.address); -
}); -
return results; -
}catch(e){ -
console.error('Memory scan failed:', e); -
return[]; -
} -
} -
# 在模块符号查找处设置断点 -
(gdb)break gum_module_find_export_by_name -
# 查看符号查找过程 -
(gdb) info args -
(gdb) x/s $rsi # 查看符号名称 -
(gdb) print/x $rax # 查看返回地址 -
# 在内存分配处设置断点 -
(gdb)break gum_memory_alloc -
(gdb) info registers -
(gdb) x/10gx $rax # 查看分配的内存 -
// Module抽象接口 -
struct_GumModule -
{ -
GObject parent; -
GumAddress(* find_base_address)(GumModule* self,const gchar * name); -
gpointer (* find_export_by_name)(GumModule* self,const gchar * module_name,const gchar * symbol_name); -
gboolean (* enumerate_exports)(GumModule* self,const gchar * module_name,GumFoundExportFunc func, gpointer user_data); -
// ... 其他方法 -
}; -
// Memory抽象接口 -
struct_GumMemory -
{ -
GObject parent; -
gpointer (* alloc)(GumMemory* self, gsize size); -
void(* free)(GumMemory* self, gpointer mem); -
void(* copy)(GumMemory* self, gpointer dst, gconstpointer src, gsize n); -
gboolean (* protect)(GumMemory* self, gpointer address, gsize size,GumPageProtection prot); -
// ... 其他方法 -
}; -
JavaScript调用
Memory.scan(address,size,pattern,callbacks) -
调用
gum_memory_scan(address,size,pattern,callbacks) -
创建扫描上下文和工作线程
-
工作线程逐块扫描内存
-
匹配模式时调用onMatch回调
-
扫描完成后调用onComplete回调
-
在符号表中查找匹配的符号名
-
返回符号的虚拟地址
-
JavaScript调用 → GumJS绑定层
-
调用
gum_module_find_export_by_name(moduleName,symbolName) -
平台特定实现:
-
+------------------+ -
|base(GumAddress)|->内存范围起始地址 -
+------------------+ -
| size (gsize)|->内存范围大小 -
+------------------+ -
+------------------+ -
| type (int)|->导入类型 -
+------------------+ -
| name (char*)|->导入符号名称 -
+------------------+ -
|module(char*)|->导入自哪个模块 -
+------------------+ -
| address (GumAddress)|-> IAT中的地址 -
+------------------+ -
+------------------+ -
| type (int)|->导出类型(函数/变量) -
+------------------+ -
| name (char*)|->符号名称 -
+------------------+ -
| address (GumAddress)|->符号地址 -
+------------------+ -
|module(char*)|->所属模块名称 -
+------------------+ -
// gum_memory_backend_create() -
GumMemoryBackend* -
gum_memory_backend_create (void) -
{ -
#ifdef HAVE_DARWIN -
return gum_darwin_memory_backend_new (); -
#elif defined(HAVE_LINUX) -
return gum_linux_memory_backend_new (); -
// ... 其他平台 -
#endif -
} -
// gum_module_facade_create() -
GumModuleFacade* -
gum_module_facade_create (void) -
{ -
return g_object_new (GUM_TYPE_MODULE_FACADE, NULL); -
} -
// Module相关的API结构 -
typedefstruct_GumModuleApi{ -
GumAddress(* find_base_address)(const gchar * module_name); -
gpointer (* find_export_by_name)(const gchar * module_name,const gchar * symbol_name); -
gboolean (* enumerate_exports)(const gchar * module_name,GumFoundExportFunc func, gpointer user_data); -
// ... 其他函数指针 -
}GumModuleApi; -
// Memory相关的API结构 -
typedefstruct_GumMemoryApi{ -
gpointer (* alloc)(gsize size); -
void(* free)(gpointer mem); -
void(* copy)(gpointer dst, gconstpointer src, gsize n); -
gboolean (* protect)(gpointer address, gsize size,GumPageProtection prot); -
// ... 其他函数指针 -
}GumMemoryApi;
- 公众号:安全狗的自我修养
- vx:2207344074
- http://gitee.com/haidragon
- http://github.com/haidragon
- bilibili:haidragonx
#
#
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:安全狗的自我修养 haidragon haidragon《frida各模块js与cpp函数分析对照(三)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论