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

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

文章总结: 本文档详细分析Frida框架中ObjC和Java模块的JavaScriptAPI与底层C/C++实现的五层映射架构,涵盖接口定义、GumJS绑定、平台实现、工厂模式和核心集成层。关键发现包括两类模块的函数映射表、内存布局、执行流程和跨平台差异,提供移动应用动态分析、安全测试和逆向工程的实际应用场景。文档强调通过理解JS-C++映射关系可提升移动平台Hook、SSLPinning绕过等实战能力,并给出性能优化与错误处理的最佳实践。 综合评分: 85 文章分类: 移动安全,逆向分析,WEB安全,红队,渗透测试


cover_image

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

原创

haidragon haidragon

安全狗的自我修养

2026年4月5日 11:40 湖南

  • 官网:http://securitytech.cc

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

    文档概述

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

    五层架构模型分析

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

    ObjC模块主要接口:

    Java模块主要接口:

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

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

    关键数据结构


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

#### ObjC实现 ( gumobjc*.c)

关键函数:

#### Java实现 ( gumjava*.c)

关键函数:

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

#### ObjC工厂


#### Java工厂


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

ObjC和Java模块通过frida-core与上层应用集成,提供统一的API接口,并与JNI(Java)和Objective-C Runtime深度集成。

## 详细函数映射关系表

### ObjC模块映射表

| JavaScript Function | C Function | File Location | Description | | — | — | — | — | | ObjC.classes.ClassName | gum_objc_api_resolver_get_class() | gumobjcapiresolver.c | 获取Objective-C类 | | ObjC.Object.choose() | gum_objc_object_choose() | gumobjcobject.c | 枚举指定类的所有实例 | | ObjC.selectorAsString() | gum_objc_selector_to_string() | gumobjcmessage.c | 将选择器转换为字符串 | | ObjC.schedule() | gum_objc_schedule_on_queue() | gumobjcdispatch.c | 在指定队列上调度任务 |

### Java模块映射表

| JavaScript Function | C Function | File Location | Description | | — | — | — | — | | Java.use() | gum_java_use() | gumjavaapiresolver.c | 获取Java类包装器 | | Java.choose() | gum_java_choose() | gumjavaobject.c | 枚举指定类的所有实例 | | Java.cast() | gum_java_cast() | gumjavaobject.c | 转换Java对象类型 | | Java.perform() | gum_java_perform() | gumjavavm.c | 在Java VM线程上执行代码 | | Java.enumerateLoadedClasses() | gum_java_enumerate_loaded_classes() | gumjavavm.c | 枚举已加载的Java类 |

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

### GumObjCObject结构体内存布局


### GumJavaObject结构体内存布局


### GumJavaClassWrapper结构体内存布局


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

### ObjC.classes.ClassName执行流程

### Java.use()执行流程

### Java.perform()执行流程

### ObjC.Object.choose()执行流程

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

### 平台特定实现

### 内存管理差异

### 线程模型差异

### 抽象层设计


## 调试命令与安全实践

### GDB调试示例


### 性能优化建议

### 安全考虑

## 错误处理与边界情况

### 常见错误场景

### 最佳实践


## 攻击检测场景映射

### 可用于检测的场景

### 防御绕过技术

## 性能分析与优化

### 时间复杂度分析

### 内存使用分析

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

### 自定义ObjC工具


### 自定义Java工具


### 底层扩展点

## 版本兼容性与演进

### API变更历史

### 向后兼容性保证

## 实战案例分析

### 案例1: iOS应用Hook


### 案例2: Android SSL Pinning Bypass


### 案例3: 动态类分析


### 案例4: ObjC内存分析


## 总结与最佳实践

ObjC和Java模块是Frida在移动平台上的核心功能,提供了对高级语言运行时的深度访问能力。理解其JS与C++的映射关系有助于:

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

  • 核心API保持稳定

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

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

  • Frida早期版本: 基本的ObjC支持

  • Frida 6.x: 添加Java支持

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

  • Frida 10.x: 添加更多的高级语言特性支持

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

  • Frida 14.x: 改进Android版本兼容性和稳定性

  • 可以通过修改 gumobjcapiresolver.c添加新的Objective-C特性支持

  • 通过修改 gumjavaapiresolver.c添加新的Java API支持

  • 扩展对象包装器支持更多的属性和方法访问模式

  • ObjC包装器: 每个对象和类包装器占用固定内存

  • Java包装器: 需要维护JNI引用和JavaScript包装器

  • 优化建议:

  • 及时释放不再使用的对象引用

  • 重用类包装器避免重复查找

  • 使用weak引用避免内存泄漏

  • ObjC类查找: O(1)(缓存后),O(n)(首次查找,n为类数量)

  • Java类查找: O(m)(m为类路径搜索时间)

  • 对象创建: O(1)(简单包装),O(k)(k为构造函数复杂度)

  • 方法调用: O(1)(直接调用),O(p)(p为参数转换开销)

  • 直接调用: 绕过高级语言API直接调用底层函数

  • 动态加载: 运行时动态加载和解析类

  • 混淆技术: 使用混淆技术隐藏类和方法名

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

  • ObjC Hook检测: 监控关键Objective-C方法的调用

  • Java Hook检测: 监控敏感Java API的使用

  • 反调试检测: 检测ObjC和Java运行时的存在

  • 行为分析: 基于高级语言API调用进行行为分析

  • ObjC错误:

  • 类不存在:返回undefined

  • 方法不存在:调用时抛出异常

  • 内存不足:对象创建失败

  • Java错误:

  • Java VM不可用:Java.available为false

  • 类未找到:Java.use()抛出异常

  • JNI异常:需要正确处理和清除

  • 线程错误:在非Java线程上执行JNI调用

  • ObjC安全:

  • 避免调用可能导致崩溃的私有方法

  • 注意内存管理避免循环引用

  • 处理nil对象和异常情况

  • Java安全:

  • 正确处理JNI异常

  • 避免在错误的线程上下文中操作

  • 注意Android版本兼容性

  • ObjC优化:

  • 缓存常用的类和方法引用

  • 避免频繁的对象创建和销毁

  • 使用批处理减少消息发送开销

  • Java优化:

  • 重用Java.use()返回的类对象

  • 减少Java.perform()调用次数

  • 使用局部变量避免重复字段访问

  • ObjC:

  • 可以在任何线程上调用Objective-C方法

  • Grand Central Dispatch(GCD)支持

  • 主队列和自定义队列调度

  • Java:

  • 必须在附加到Java VM的线程上执行JNI调用

  • 主线程通常已经附加,其他线程需要显式附加

  • Android主线程有特殊限制

  • ObjC内存管理:

  • 自动引用计数(ARC)或手动引用计数(MRC)

  • 使用 retainrelease管理对象生命周期

  • JavaScript包装器持有强引用

  • Java内存管理:

  • Java垃圾回收自动管理

  • JNI局部引用和全局引用管理

  • 需要显式释放全局引用避免内存泄漏

  • ObjC: 仅在Apple平台(macOS、iOS)可用

  • 依赖Objective-C Runtime API

  • 使用 objc_msgSend()进行消息发送

  • 支持ARC和MRC内存管理

  • Java: 主要在Android平台可用

  • 依赖JNI(Java Native Interface)

  • 需要处理Java VM线程附加/分离

  • 支持不同的Android版本和Java VM实现

  • 分离线程 ( DetachCurrentThread())

  • 附加线程到Java VM ( AttachCurrentThread())

  • 调用 FindClass() JNI函数

  • 处理类加载器上下文

  • gum_java_api_resolver_new()

  • gum_java_perform()

  • gum_java_use()

  • gum_java_choose()

  • gum_java_cast()

  • 核心实现gumjavaapiresolver.c – Java API解析器

  • VM交互gumjavavm.c – Java VM交互层

  • 对象管理gumjavaobject.c – Java对象包装

  • 类加载gumjavaclassloader.c – 类加载器管理

  • gum_objc_api_resolver_new()

  • gum_objc_api_resolver_query_method()

  • gum_objc_object_new()

  • gum_objc_send_message()

  • 核心实现gumobjcapiresolver.c – Objective-C API解析器

  • 对象管理gumobjcobject.c – Objective-C对象包装

  • 消息发送gumobjcmessage.c – 消息发送机制

  • 类枚举gumobjcmodule.c – 类和方法枚举

  • Java.available

  • Java.androidVersion

  • Java.enumerateLoadedClasses(callbacks)

  • Java.enumerateClassLoaders(callbacks)

  • Java.use(className)

  • Java.choose(className,callbacks)

  • Java.cast(handle,klass)

  • Java.array(className,elements)

  • Java.registerClass(spec)

  • Java.scheduleOnMainThread(fn)

  • Java.perform(fn)

  • Java.performNow(fn)

  • Java.vm

  • Java.classFactory

  • ObjC.available

  • ObjC.classes

  • ObjC.Object

  • ObjC.Object.choose()

  • ObjC.selectorAsString(sel)

  • ObjC.schedule(queue,work)

  • ObjC.mainQueue

  • ObjC.deepUnwrap(obj)

  • ObjC.deepWrap(value)

  1. 移动应用分析: 对iOS和Android应用进行深入的动态分析

  2. 安全测试: 绕过各种安全机制进行渗透测试

  3. 逆向工程: 辅助复杂的移动应用逆向工程任务

  4. 自动化测试: 构建基于高级语言API的自动化测试框架

  5. // 分析iOS应用内存中的对象

  6. if(ObjC.available){

  7. // 枚举特定类的所有实例

  8. constNSString=ObjC.classes.NSString;

  9. ObjC.Object.choose(NSString,{

  10. onMatch:function(instance){

  11. try{

  12. const stringContent = instance.UTF8String().readUtf8String();

  13. if(stringContent && stringContent.includes('password')){

  14. console.log('Password-related string found:', stringContent);

  15. }

  16. }catch(e){

  17. // 忽略无效对象

  18. }

  19. },

  20. onComplete:function(){

  21. console.log('NSString enumeration completed');

  22. }

  23. });

  24. // 监控对象创建

  25. constNSObject=ObjC.classes.NSObject;

  26. Interceptor.attach(NSObject['- init'].implementation,{

  27. onLeave:function(retval){

  28. const obj =newObjC.Object(retval);

  29. console.log('New object created:', obj.$className);

  30. }

  31. });

  32. }

  33. // 动态分析Android应用类

  34. if(Java.available){

  35. Java.perform(function(){

  36. // 枚举所有加载的类

  37. Java.enumerateLoadedClasses({

  38. onMatch:function(className){

  39. if(className.startsWith('com.targetapp.')){

  40. console.log('Target class found:', className);

  41. try{

  42. const klass =Java.use(className);

  43. // 分析类的方法

  44. const methods = klass.class.getDeclaredMethods();

  45. methods.forEach(method =>{

  46. const methodName = method.getName();

  47. if(methodName.includes('encrypt')|| methodName.includes('decrypt')){

  48. console.log(Sensitive method found: ${className}.${methodName});

  49. // Hook敏感方法

  50. klass[methodName].implementation =function(){

  51. console.log(Called sensitive method: ${className}.${methodName});

  52. returnthis[methodName].apply(this, arguments);

  53. };

  54. }

  55. });

  56. }catch(e){

  57. console.error(Failed to analyze class ${className}:, e);

  58. }

  59. }

  60. },

  61. onComplete:function(){

  62. console.log('Class enumeration completed');

  63. }

  64. });

  65. });

  66. }

  67. // 绕过Android SSL证书锁定

  68. if(Java.available){

  69. Java.perform(function(){

  70. constCertificateFactory=Java.use('java.security.cert.CertificateFactory');

  71. constFileInputStream=Java.use('java.io.FileInputStream');

  72. constBufferedInputStream=Java.use('java.io.BufferedInputStream');

  73. const X509Certificate =Java.use('java.security.cert.X509Certificate');

  74. constKeyStore=Java.use('java.security.KeyStore');

  75. constTrustManagerFactory=Java.use('javax.net.ssl.TrustManagerFactory');

  76. // Hook X509TrustManager的checkServerTrusted方法

  77. const X509TrustManager =Java.use('javax.net.ssl.X509TrustManager');

  78. X509TrustManager.checkServerTrusted.implementation =function(chain, authType){

  79. console.log('Bypassing SSL certificate check');

  80. // 不执行任何验证,直接通过

  81. };

  82. // Hook OkHttp的CertificatePinner

  83. constCertificatePinner=Java.use('okhttp3.CertificatePinner');

  84. CertificatePinner.check.overload('java.lang.String','java.util.List').implementation =function(hostname, certificates){

  85. console.log('Bypassing OkHttp certificate pinning for:', hostname);

  86. // 不执行任何检查,直接通过

  87. };

  88. });

  89. }

  90. // Hook iOS UIApplication delegate

  91. if(ObjC.available){

  92. constUIApplication=ObjC.classes.UIApplication;

  93. const appDelegate =UIApplication.sharedApplication().delegate();

  94. console.log('App delegate:', appDelegate.$className);

  95. // Hook特定方法

  96. constViewController=ObjC.classes.ViewController;

  97. if(ViewController!==undefined){

  98. Interceptor.attach(ViewController['- viewDidLoad'].implementation,{

  99. onEnter:function(args){

  100. console.log('View controller loaded');

  101. const self =newObjC.Object(args[0]);

  102. console.log('Self:', self.$className);

  103. }

  104. });

  105. }

  106. }

  107. // 扩展Java模块功能

  108. Java.dumpClass =function(className){

  109. const klass =Java.use(className);

  110. console.log(Class: ${className});

  111. console.log('Methods:');

  112. // 获取所有方法

  113. const methods = klass.class.getDeclaredMethods();

  114. methods.forEach(method =>{

  115. console.log(  ${method.toString()});

  116. });

  117. console.log('Fields:');

  118. const fields = klass.class.getDeclaredFields();

  119. fields.forEach(field =>{

  120. console.log(  ${field.toString()});

  121. });

  122. };

  123. // Java对象属性访问简化

  124. Java.getObjectProperty =function(obj, propertyName){

  125. try{

  126. const getterName ='get'+ propertyName.charAt(0).toUpperCase()+ propertyName.slice(1);

  127. if(obj[getterName]){

  128. return obj[getterName]();

  129. }

  130. const fieldName = propertyName.charAt(0).toLowerCase()+ propertyName.slice(1);

  131. if(obj[fieldName]){

  132. return obj[fieldName].value;

  133. }

  134. }catch(e){

  135. console.error('Failed to get property:', e);

  136. }

  137. returnnull;

  138. };

  139. // 扩展ObjC模块功能

  140. ObjC.dumpClass =function(className){

  141. const klass =ObjC.classes[className];

  142. if(!klass){

  143. console.log(Class ${className} not found);

  144. return;

  145. }

  146. console.log(Class: ${className});

  147. console.log('Methods:');

  148. // 获取所有实例方法

  149. const methods = klass.$ownMethods;

  150. methods.forEach(method =>{

  151. console.log(-${method});

  152. });

  153. // 获取所有类方法

  154. const classMethods = klass.$ownClassMethods;

  155. classMethods.forEach(method =>{

  156. console.log(+${method});

  157. });

  158. };

  159. // 安全的ObjC使用

  160. function safeUseObjCClass(className){

  161. if(!ObjC.available){

  162. console.warn('Objective-C runtime not available');

  163. returnnull;

  164. }

  165. try{

  166. const klass =ObjC.classes[className];

  167. if(klass ===undefined){

  168. console.warn(Class ${className} not found);

  169. returnnull;

  170. }

  171. return klass;

  172. }catch(e){

  173. console.error(Failed to use ObjCclass ${className}:, e);

  174. returnnull;

  175. }

  176. }

  177. // 安全的Java使用

  178. function safeUseJavaClass(className){

  179. if(!Java.available){

  180. console.warn('Java runtime not available');

  181. returnnull;

  182. }

  183. try{

  184. returnJava.use(className);

  185. }catch(e){

  186. console.error(Failed to use Javaclass ${className}:, e);

  187. returnnull;

  188. }

  189. }

  190. // 安全的Java执行

  191. function safeJavaPerform(fn){

  192. if(!Java.available){

  193. console.warn('Java runtime not available');

  194. returnnull;

  195. }

  196. try{

  197. returnJava.perform(fn);

  198. }catch(e){

  199. console.error('Java perform failed:', e);

  200. returnnull;

  201. }

  202. }

  203. # 在ObjC类查找处设置断点

  204. (gdb)break gum_objc_api_resolver_get_class

  205. # 查看类查找过程

  206. (gdb) info args

  207. (gdb) print (char*)$rsi  # 查看类名

  208. (gdb) print/x $rax  # 查看返回的类指针

  209. # 在Java类使用处设置断点

  210. (gdb)break gum_java_use

  211. (gdb) info registers

  212. (gdb) x/s $rdi  # 查看类名字符串

  213. // 语言API解析器抽象

  214. struct_GumLanguageApiResolver

  215. {

  216. GObject parent;

  217. gpointer (* get_class)(GumLanguageApiResolver* self,const gchar * name);

  218. gpointer (* create_instance)(GumLanguageApiResolver* self, gpointer klass,...);

  219. gpointer (* invoke_method)(GumLanguageApiResolver* self, gpointer object,const gchar * method_name,...);

  220. // ... 其他方法

  221. };

  222. // 对象包装器抽象

  223. struct_GumScriptObjectWrapper

  224. {

  225. JSObjectRef wrapper;

  226. gpointer handle;

  227. GumScriptClassWrapper* klass;

  228. GumScript* script;

  229. void(* dispose)(GumScriptObjectWrapper* self);

  230. gpointer (* get_property)(GumScriptObjectWrapper* self,const gchar * name);

  231. void(* set_property)(GumScriptObjectWrapper* self,const gchar * name,JSValueRef value);

  232. };

  233. JavaScript调用 ObjC.Object.choose(klass,callbacks) → GumJS绑定层

  234. 调用 gum_objc_object_choose(klass,callbacks)

  235. 使用Objective-C Runtime的 objc_getClassList()获取所有类

  236. 对每个类实例进行内存扫描

  237. 验证实例类型匹配

  238. 对每个匹配实例调用onMatch回调

  239. 完成后调用onComplete回调

  240. 返回执行结果

  241. 执行传入的JavaScript函数

  242. 如果线程是临时附加的:

  243. JavaScript调用 Java.perform(fn) → GumJS绑定层

  244. 调用 gum_java_perform(fn)

  245. 获取当前线程的JNIEnv

  246. 如果当前线程不是Java线程:

  247. 创建GumJavaClassWrapper包装器

  248. 缓存方法和字段信息

  249. 返回JavaScript类对象

  250. JavaScript调用 Java.use("com.example.ClassName") → GumJS绑定层

  251. 调用 gum_java_use("com.example.ClassName")

  252. 验证Java VM可用性

  253. 在Java VM线程上执行类查找:

  254. JavaScript访问 ObjC.classes.ClassName → GumJS绑定层

  255. 调用 gum_objc_api_resolver_get_class("ClassName")

  256. 查询Objective-C Runtime的类注册表

  257. 如果类存在,创建GumScriptClassWrapper包装器

  258. 缓存类包装器以供后续使用

  259. 返回JavaScript类对象

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

  261. | wrapper (JSObjectRef)|->JavaScript类包装器

  262. +------------------+

  263. | handle (jclass)|-> JNI类引用

  264. +------------------+

  265. | name (char*)|->类名字符串

  266. +------------------+

  267. | methods (GHashTable*)|->方法缓存表

  268. +------------------+

  269. | fields (GHashTable*)|->字段缓存表

  270. +------------------+

  271. +------------------+

  272. | wrapper (JSObjectRef)|->JavaScript对象包装器

  273. +------------------+

  274. | handle (jobject)|-> JNI局部/全局引用

  275. +------------------+

  276. | klass (GumScriptClassWrapper*)|->类包装器引用

  277. +------------------+

  278. | script (GumScript*)|->脚本上下文引用

  279. +------------------+

  280. | is_global_ref (gboolean)|->是否为全局引用

  281. +------------------+

  282. +------------------+

  283. | wrapper (JSObjectRef)|->JavaScript对象包装器

  284. +------------------+

  285. | handle (gpointer)|->Objective-C对象指针

  286. +------------------+

  287. | klass (GumScriptClassWrapper*)|->类包装器引用

  288. +------------------+

  289. | script (GumScript*)|->脚本上下文引用

  290. +------------------+

  291. | ref_count (gint)|->引用计数

  292. +------------------+

  293. // GumJavaApiResolver工厂

  294. GumJavaApiResolver*

  295. gum_java_api_resolver_new (void);

  296. // GumJavaObject工厂

  297. GumJavaObject*

  298. gum_java_object_new (jobject handle,GumScript* script);

  299. // 类工厂

  300. GumJavaClassFactory*

  301. gum_java_class_factory_new (void);

  302. // GumObjCApiResolver工厂

  303. GumObjCApiResolver*

  304. gum_objc_api_resolver_new (void);

  305. // GumObjCObject工厂

  306. GumObjCObject*

  307. gum_objc_object_new (gpointer handle,GumScript* script);

  308. // ObjC相关的结构

  309. typedefstruct_GumObjCApi{

  310. gboolean (* is_available)(void);

  311. gpointer (* get_class)(const gchar * name);

  312. gpointer (* alloc_object)(gpointer klass);

  313. gpointer (* send_message)(gpointer object,const gchar * selector,...);

  314. // ... 其他函数指针

  315. }GumObjCApi;

  316. // Java相关的结构

  317. typedefstruct_GumJavaApi{

  318. gboolean (* is_available)(void);

  319. void(* perform)(GumScriptCallback callback, gpointer data);

  320. gboolean (* use)(const gchar * class_name,GError** error);

  321. gboolean (* choose)(const gchar * class_name,GumScriptCallback on_match,GumScriptCallback on_complete, gpointer user_data);

  322. // ... 其他函数指针

  323. }GumJavaApi;

  324. // 类包装器结构

  325. typedefstruct_GumScriptClassWrapper{

  326. JSObjectRef wrapper;

  327. gpointer handle;

  328. gchar * name;

  329. GumScript* script;

  330. }GumScriptClassWrapper;

  331. // 对象包装器结构

  332. typedefstruct_GumScriptObjectWrapper{

  333. JSObjectRef wrapper;

  334. gpointer handle;

  335. GumScriptClassWrapper* klass;

  336. GumScript* script;

  337. }GumScriptObjectWrapper;

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

#

#


免责声明:

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

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

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

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

评论:0   参与:  0