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

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

文章总结: 本文档详细分析Frida框架中CPU指令相关模块的JavaScriptAPI与底层C/C++实现之间的五层架构映射关系,涵盖Instruction、X86Writer、Arm64Writer等模块的函数对应表、内存布局和跨平台差异处理。核心发现包括完整的JS-C++函数映射关系、指令集架构抽象机制以及实战应用案例,为开发者提供底层动态代码分析和指令级控制的实用技术参考。 综合评分: 82 文章分类: 逆向分析,二进制安全,漏洞分析,安全工具,WEB安全


cover_image

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

原创

haidragon haidragon

安全狗的自我修养

2026年4月5日 11:40 湖南

  • 官网:http://securitytech.cc

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

    文档概述

    本文档详细分析Frida中CPU指令相关模块(包括Instruction、X86Writer、Arm64Writer等)的JavaScript API与其底层C/C++实现之间的映射关系,涵盖完整的五层架构模型分析。

    五层架构模型分析

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

    CPU模块主要接口:

    Instruction模块主要接口:

    指令写入器模块:

    主要接口包括:

    枚举类型:

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

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

    关键数据结构


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

#### Instruction实现 ( guminstruction.c)

关键函数:

#### 指令写入器实现

关键函数:

#### 指令重定位器实现

关键函数:

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

#### 指令解析器工厂


#### 指令写入器工厂


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


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

CPU和Instruction模块通过frida-core与上层应用集成,为Interceptor、Stalker等高级功能提供底层支持,并与代码生成和动态插桩深度集成。

## 详细函数映射关系表

### Instruction映射表

| JavaScript Function | C Function | File Location | Description | | — | — | — | — | | Instruction.parse() | gum_instruction_parse() | guminstruction.c | 解析指定地址的指令 | | instruction.address | gum_instruction_get_address() | guminstruction.c | 获取指令地址 | | instruction.mnemonic | gum_instruction_get_mnemonic() | guminstruction.c | 获取助记符 | | instruction.opStr | gum_instruction_get_op_str() | guminstruction.c | 获取操作数字符串 |

### X86Writer映射表

| JavaScript Constructor/Method | C Function | File Location | Description | | — | — | — | — | | newX86Writer() | gum_x86_writer_new() | gumx86writer.c | 创建x86指令写入器 | | putCallAddressWithArguments() | gum_x86_writer_put_call_address_with_arguments() | gumx86writer.c | 生成函数调用指令 | | putJmpAddress() | gum_x86_writer_put_jmp_address() | gumx86writer.c | 生成跳转指令 | | flush() | gum_x86_writer_flush() | gumx86writer.c | 刷新写入器缓冲区 |

### Arm64Writer映射表

| JavaScript Constructor/Method | C Function | File Location | Description | | — | — | — | — | | newArm64Writer() | gum_arm64_writer_new() | gumarm64writer.c | 创建ARM64指令写入器 | | putCallAddressWithArguments() | gum_arm64_writer_put_call_address_with_arguments() | gumarm64writer.c | 生成函数调用指令 | | putBImm() | gum_arm64_writer_put_b_imm() | gumarm64writer.c | 生成分支指令 | | flush() | gum_arm64_writer_flush() | gumarm64writer.c | 刷新写入器缓冲区 |

### Relocator映射表

| JavaScript Constructor/Method | C Function | File Location | Description | | — | — | — | — | | newX86Relocator() | gum_x86_relocator_new() | gumx86relocator.c | 创建x86指令重定位器 | | readOne() | gum_x86_relocator_read_one() | gumx86relocator.c | 读取一条指令 | | writeAll() | gum_x86_relocator_write_all() | gumx86relocator.c | 写入所有重定位指令 |

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

### GumInstruction结构体内存布局


### GumX86Writer结构体内存布局


### GumArm64Writer结构体内存布局


### GumX86Relocator结构体内存布局


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

### Instruction.parse()执行流程

### X86Writer.putCallAddressWithArguments()执行流程

### Arm64Writer.putBImm()执行流程

### X86Relocator.readOne()执行流程

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

### 指令集架构差异

#### x86/x86_64架构特点

#### ARM/ARM64架构特点

#### MIPS架构特点

### ABI差异处理

### 抽象层设计


## 调试命令与安全实践

### GDB调试示例


### 性能优化建议

### 安全考虑

## 错误处理与边界情况

### 常见错误场景

### 最佳实践


## 攻击检测场景映射

### 可用于检测的场景

### 防御绕过技术

## 性能分析与优化

### 时间复杂度分析

### 内存使用分析

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

### 自定义指令分析工具


### 自定义代码生成器


### 底层扩展点

## 版本兼容性与演进

### API变更历史

### 向后兼容性保证

## 实战案例分析

### 案例1: 动态代码补丁


### 案例2: ROP链构建


### 案例3: ARM64函数Hook


### 案例4: 指令级别性能剖析


## 总结与最佳实践

CPU和Instruction模块是Frida最底层也是最强大的功能之一,提供了对机器指令级别的精确控制能力。理解其JS与C++的映射关系有助于:

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

  • 核心API保持稳定

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

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

  • Frida早期版本: 基本的x86指令支持

  • Frida 6.x: 添加ARM和ARM64支持

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

  • Frida 10.x: 添加MIPS支持和更多指令特性

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

  • Frida 14.x: 改进指令解析准确性和性能

  • 可以通过修改 guminstruction.c添加新的指令解析特性

  • 通过修改 gumx86writer.c等文件添加新的指令生成原语

  • 扩展指令重定位器支持更复杂的控制流模式

  • 添加新的架构支持(如RISC-V、PowerPC等)

  • Instruction对象: 每个对象占用固定内存(包含字符串和数组)

  • Writer缓冲区: 需要预分配足够的代码缓冲区

  • Relocator缓冲区: 需要存储输入和输出指令信息

  • 优化建议:

  • 重用Instruction对象避免频繁分配

  • 预估代码大小避免缓冲区重新分配

  • 及时释放不再需要的对象

  • Instruction.parse(): O(1),单条指令解析

  • Writer操作: O(1),每条指令生成

  • Relocator操作: O(n),n为重定位的指令数量

  • 批量操作: O(m),m为总指令数量

  • 指令混淆: 使用等价但不同的指令序列

  • 多态代码: 运行时动态生成不同的指令序列

  • 加密指令: 加密存储指令,运行时解密执行

  • 间接跳转: 使用间接跳转隐藏控制流

  • 代码注入检测: 监控可执行内存的分配和修改

  • ROP链检测: 分析可疑的指令序列模式

  • Shellcode检测: 识别常见的shellcode特征

  • 反调试检测: 检测指令级别的反调试技术

  • Instruction错误:

  • 无效地址:无法读取指令字节

  • 无效指令:遇到未定义的操作码

  • 内存保护:无法访问受保护的内存区域

  • Writer错误:

  • 缓冲区溢出:写入超出分配的代码缓冲区

  • 无效地址:跳转目标超出指令范围

  • ABI不匹配:参数类型与ABI要求不符

  • Relocator错误:

  • 指令边界:无法正确识别指令边界

  • 自修改代码:重定位过程中代码被修改

  • 复杂控制流:无法处理复杂的跳转模式

  • 内存保护: 确保代码缓冲区具有可执行权限

  • 地址验证: 验证跳转和调用目标地址的有效性

  • 缓冲区溢出: 避免指令写入超出分配的缓冲区

  • 异常处理: 正确处理无效指令和编码错误

  • 指令缓存: 缓存常用的指令序列避免重复生成

  • 批量写入: 减少flush()调用次数,批量生成指令

  • 内存对齐: 确保代码缓冲区正确对齐以获得最佳性能

  • 架构特定优化: 利用特定架构的优化指令

  • x86_64 System V ABI (Unix/Linux/macOS):

  • 参数传递:整数%rdi, %rsi, %rdx, %rcx, %r8, %r9;浮点%xmm0-%xmm7

  • 返回值:整数%rax,浮点%xmm0

  • 栈对齐:16字节对齐

  • Microsoft x64 ABI (Windows):

  • 参数传递:整数%rcx, %rdx, %r8, %r9;浮点%xmm0-%xmm3

  • 影子空间:调用者为前4个参数预留32字节栈空间

  • 栈对齐:16字节对齐

  • ARM64 AAPCS64 ABI:

  • 参数传递:整数x0-x7,浮点v0-v7

  • 返回值:整数x0,浮点v0

  • 栈对齐:16字节对齐

  • 固定长度指令: 32位固定长度

  • 延迟槽: 分支指令后的延迟槽

  • 加载/存储架构: 类似ARM的内存访问模式

  • 流水线优化: 指令流水线设计考虑

  • 固定长度指令: ARM64为32位固定长度

  • 条件执行: ARM支持条件执行指令

  • 加载/存储架构: 只有加载/存储指令访问内存

  • Thumb模式: ARM支持16/32位混合指令集

  • 变长指令: 1-15字节不等

  • 复杂寻址模式: 支持多种内存寻址方式

  • 寄存器重命名: 现代CPU的寄存器重命名机制

  • 指令前缀: 支持多种指令前缀(LOCK, REP, SEG等)

  • 是否为跳转指令

  • 是否为调用指令

  • 是否有延迟槽(MIPS)

  • System V ABI: 前6个整数参数使用%rdi, %rsi, %rdx, %rcx, %r8, %r9

  • Microsoft x64 ABI: 前4个整数参数使用%rcx, %rdx, %r8, %r9

  • x86/x86_64: 使用Intel XED或Capstone反汇编引擎

  • ARM/ARM64: 使用自定义ARM指令解码器

  • MIPS: 使用自定义MIPS指令解码器

  • gum_x86_relocator_new()

  • gum_x86_relocator_read_one()

  • gum_x86_relocator_write_all()

  • x86/x86_64gumx86relocator.c – x86指令重定位

  • ARM/ARM64gumarmrelocator.cgumarm64relocator.c – ARM指令重定位

  • Thumbgumthumbrelocator.c – Thumb指令重定位

  • MIPSgummipsrelocator.c – MIPS指令重定位

  • gum_x86_writer_new()

  • gum_x86_writer_put_call_address_with_arguments()

  • gum_x86_writer_put_jmp_address()

  • gum_x86_writer_flush()

  • x86/x86_64gumx86writer.c – x86指令生成

  • ARM/ARM64gumarmwriter.cgumarm64writer.c – ARM指令生成

  • Thumbgumthumbwriter.c – Thumb指令生成

  • MIPSgummipswriter.c – MIPS指令生成

  • gum_instruction_parse()

  • gum_instruction_free()

  • gum_instruction_get_address()

  • gum_instruction_get_mnemonic()

  • 通用指令解析guminstruction.c – 跨平台指令解析框架

  • 平台特定后端:

  • x86/x86_64gumx86reader.c – 基于Intel XED或Capstone

  • ARM/ARM64gumarmreader.cgumarm64reader.c – ARM指令解析

  • MIPSgummipsreader.c – MIPS指令解析

  • x86X86RegisterX86OperandTypeX86Group

  • ARMArmRegisterArmOperandTypeArmGroup

  • ARM64Arm64RegisterArm64OperandTypeArm64Group

  • MIPSMipsRegisterMipsOperandTypeMipsGroup

  • newX86Writer(codeAddress[,options])

  • writer.putCallAddressWithArguments(func,argTypes,args)

  • writer.putJmpAddress(address)

  • writer.flush()

  • writer.reset(codeAddress)

  • X86/X86_64X86WriterX86Relocator

  • ARM/ARM64ArmWriterArmRelocatorArm64WriterArm64Relocator

  • ThumbThumbWriterThumbRelocator

  • MIPSMipsWriterMipsRelocator

  • Instruction.parse(target)

  • Instruction.prototype.address

  • Instruction.prototype.mnemonic

  • Instruction.prototype.opStr

  • Instruction.prototype.operands

  • Instruction.prototype.regsRead

  • Instruction.prototype.regsWritten

  • Instruction.prototype.groups

  • Instruction.prototype.next

  • CPU.arch

  • CPU.endian

  • CPU.pointerSize

  1. 精确控制: 对目标进程的机器码进行精确的修改和生成

  2. 性能优化: 利用底层指令特性实现高性能的动态插桩

  3. 安全分析: 进行指令级别的安全检测和漏洞利用分析

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

  5. // 指令级别的性能剖析

  6. function profileInstructions(targetFunc, durationMs =1000){

  7. const instructionCounts =newMap();

  8. const startTime =Date.now();

  9. // Hook函数入口

  10. Interceptor.attach(targetFunc,{

  11. onEnter:function(args){

  12. let currentAddr =this.context.pc;

  13. const endTime =Date.now()+10;// 最多分析10ms

  14. // 动态跟踪执行的指令

  15. while(Date.now()<&nbsp;endTime){

  16. try{

  17. const&nbsp;instr&nbsp;=Instruction.parse(currentAddr);

  18. const&nbsp;key&nbsp;=${instr.mnemonic}:${instr.opStr};

  19. instructionCounts.set(key,(instructionCounts.get(key)||0)+1);

  20. // 模拟执行(仅用于计数,不实际执行)

  21. currentAddr&nbsp;=&nbsp;currentAddr.add(instr.size);

  22. // 简单的控制流处理

  23. if(instr.mnemonic.startsWith('ret')){

  24. break;// 函数返回

  25. }elseif(instr.mnemonic.startsWith('jmp')){

  26. // 简化的跳转处理(实际需要更复杂的分析)

  27. break;

  28. }

  29. }catch(e){

  30. break;// 遇到无效指令停止

  31. }

  32. }

  33. }

  34. });

  35. // 等待指定时间

  36. setTimeout(()=>{

  37. console.log('Instruction profiling results:');

  38. const&nbsp;sorted&nbsp;=Array.from(instructionCounts.entries())

  39. .sort((a,&nbsp;b)=>&nbsp;b[1]-&nbsp;a[1])

  40. .slice(0,20);// 显示前20个

  41. sorted.forEach(([instr,&nbsp;count])=>{

  42. console.log(${count}: ${instr});

  43. });

  44. },&nbsp;durationMs);

  45. }

  46. // ARM64特定的函数Hook实现

  47. function&nbsp;hookArm64Function(targetFunc,&nbsp;hookFunc){

  48. if(Process.arch&nbsp;!=='arm64'){

  49. thrownewError('This function only works on ARM64');

  50. }

  51. // 保存原始指令(ARM64指令为4字节)

  52. const&nbsp;originalInstrs&nbsp;=&nbsp;targetFunc.readByteArray(8);// 保存2条指令

  53. // 分配trampoline内存

  54. const&nbsp;trampolineSize&nbsp;=32;

  55. const&nbsp;trampoline&nbsp;=Memory.alloc(trampolineSize);

  56. Memory.protect(trampoline,&nbsp;trampolineSize,'rwx');

  57. // 生成trampoline代码

  58. const&nbsp;writer&nbsp;=newArm64Writer(trampoline);

  59. // 执行原始指令

  60. writer.putBytes(originalInstrs);

  61. // 跳转回原函数(跳过被替换的指令)

  62. writer.putBImm(targetFunc.add(8));

  63. writer.flush();

  64. // 修改原函数为跳转到hook函数

  65. const&nbsp;hookWriter&nbsp;=newArm64Writer(targetFunc);

  66. hookWriter.putLdrRegAddress('x17',&nbsp;hookFunc);// 加载hook函数地址到x17

  67. hookWriter.putBrReg('x17');// 跳转到x17

  68. hookWriter.flush();

  69. console.log('ARM64 function hooked successfully');

  70. return{&nbsp;originalInstrs,&nbsp;trampoline&nbsp;};

  71. }

  72. // 构建简单的ROP链

  73. function&nbsp;buildROPChain(gadgets,&nbsp;finalTarget){

  74. const&nbsp;chainSize&nbsp;=&nbsp;gadgets.length&nbsp;*Process.pointerSize&nbsp;+Process.pointerSize;

  75. const&nbsp;chain&nbsp;=Memory.alloc(chainSize);

  76. let currentPtr&nbsp;=&nbsp;chain;

  77. // 填充gadgets

  78. gadgets.forEach(gadgetAddr&nbsp;=>{

  79. currentPtr.writePointer(gadgetAddr);

  80. currentPtr&nbsp;=&nbsp;currentPtr.add(Process.pointerSize);

  81. });

  82. // 填充最终目标

  83. currentPtr.writePointer(finalTarget);

  84. return&nbsp;chain;

  85. }

  86. // 查找有用的gadgets

  87. function&nbsp;findGadgets(moduleName,&nbsp;gadgetPattern){

  88. const&nbsp;module&nbsp;=Process.findModuleByName(moduleName);

  89. const&nbsp;results&nbsp;=[];

  90. Memory.scanSync(module.base,&nbsp;module.size,&nbsp;gadgetPattern).forEach(match&nbsp;=>{

  91. try{

  92. const&nbsp;instr&nbsp;=Instruction.parse(match.address);

  93. if(instr.mnemonic&nbsp;==='ret'||&nbsp;instr.mnemonic&nbsp;==='pop'||&nbsp;instr.mnemonic&nbsp;==='add'){

  94. results.push(match.address);

  95. }

  96. }catch(e){

  97. // 忽略无效指令

  98. }

  99. });

  100. return&nbsp;results;

  101. }

  102. // 动态修补函数中的特定指令

  103. function&nbsp;patchFunction(targetFunc,&nbsp;patchCallback){

  104. // 解析函数入口指令

  105. const&nbsp;firstInstr&nbsp;=Instruction.parse(targetFunc);

  106. console.log('Original instruction:',&nbsp;firstInstr.mnemonic,&nbsp;firstInstr.opStr);

  107. // 分配补丁代码内存

  108. const&nbsp;patchSize&nbsp;=32;// 足够大的缓冲区

  109. const&nbsp;patchCode&nbsp;=Memory.alloc(patchSize);

  110. Memory.protect(patchCode,&nbsp;patchSize,'rwx');

  111. // 生成补丁代码

  112. const&nbsp;writer&nbsp;=new&nbsp;X86Writer(patchCode);

  113. // 调用补丁回调函数

  114. writer.putCallAddressWithArguments(patchCallback,['pointer'],[targetFunc]);

  115. // 跳转回原始函数(跳过被替换的指令)

  116. const&nbsp;returnAddr&nbsp;=&nbsp;targetFunc.add(firstInstr.size);

  117. writer.putJmpAddress(returnAddr);

  118. writer.flush();

  119. // 修改原函数入口为跳转到补丁代码

  120. const&nbsp;originalBytes&nbsp;=&nbsp;targetFunc.readByteArray(firstInstr.size);

  121. targetFunc.writeU8(0xE9);// JMP rel32

  122. targetFunc.add(1).writeS32(patchCode.sub(targetFunc.add(5)).toInt32());

  123. console.log('Function patched successfully');

  124. return{&nbsp;originalBytes,&nbsp;patchCode&nbsp;};

  125. }

  126. // 高级代码生成器

  127. classCodeGenerator{

  128. constructor(codeAddress,&nbsp;arch&nbsp;=Process.arch){

  129. this.arch&nbsp;=&nbsp;arch;

  130. this.writer&nbsp;=this.createWriter(codeAddress);

  131. this.labels&nbsp;=newMap();

  132. this.fixups&nbsp;=[];

  133. }

  134. createWriter(codeAddress){

  135. switch(this.arch){

  136. case'x64':

  137. returnnew&nbsp;X86Writer(codeAddress);

  138. case'arm64':

  139. returnnewArm64Writer(codeAddress);

  140. default:

  141. thrownewError(Unsupported architecture: ${this.arch});

  142. }

  143. }

  144. defineLabel(name){

  145. this.labels.set(name,this.writer.pc);

  146. }

  147. callFunction(func,&nbsp;args&nbsp;=[]){

  148. this.writer.putCallAddressWithArguments(func,

  149. args.map(arg&nbsp;=>typeof&nbsp;arg&nbsp;==='number'?'int':'pointer'),

  150. args);

  151. }

  152. jumpToLabel(labelName){

  153. const&nbsp;labelAddr&nbsp;=this.labels.get(labelName);

  154. if(labelAddr){

  155. this.writer.putJmpAddress(labelAddr);

  156. }else{

  157. // 延迟修复

  158. this.fixups.push({&nbsp;type:'jmp',&nbsp;label:&nbsp;labelName,&nbsp;pos:this.writer.code&nbsp;});

  159. this.writer.putJmpNearLabel();// 占位符

  160. }

  161. }

  162. flush(){

  163. // 应用延迟修复

  164. this.fixups.forEach(fixup&nbsp;=>{

  165. if(fixup.type&nbsp;==='jmp'){

  166. const&nbsp;target&nbsp;=this.labels.get(fixup.label);

  167. if(target){

  168. // 重新定位跳转指令

  169. this.relocateJump(fixup.pos,&nbsp;target);

  170. }

  171. }

  172. });

  173. returnthis.writer.flush();

  174. }

  175. relocateJump(jumpPos,&nbsp;target){

  176. // 根据架构重新编码跳转指令

  177. switch(this.arch){

  178. case'x64':

  179. // x86相对跳转重定位

  180. const&nbsp;offset&nbsp;=&nbsp;target.sub(jumpPos.add(5)).toInt32();

  181. jumpPos.add(1).writeS32(offset);

  182. break;

  183. case'arm64':

  184. // ARM64 B指令重定位

  185. const&nbsp;armOffset&nbsp;=&nbsp;target.sub(jumpPos.add(4)).toInt32();

  186. const&nbsp;bInstr&nbsp;=0x14000000|((armOffset&nbsp;>>2)&0x3FFFFFF);

  187. jumpPos.writeU32(bInstr);

  188. break;

  189. }

  190. }

  191. }

  192. // 指令模式匹配

  193. function&nbsp;findInstructionPattern(startAddr,&nbsp;endAddr,&nbsp;pattern){

  194. const&nbsp;matches&nbsp;=[];

  195. let currentAddr&nbsp;=&nbsp;startAddr;

  196. while(currentAddr.compare(endAddr)<0){

  197. try{

  198. const&nbsp;instr&nbsp;=Instruction.parse(currentAddr);

  199. if(instr.mnemonic&nbsp;===&nbsp;pattern.mnemonic&nbsp;&&

  200. instr.opStr&nbsp;===&nbsp;pattern.opStr){

  201. matches.push(instr);

  202. }

  203. currentAddr&nbsp;=&nbsp;currentAddr.add(instr.size);

  204. }catch(e){

  205. // 跳过无效指令

  206. currentAddr&nbsp;=&nbsp;currentAddr.add(1);

  207. }

  208. }

  209. return&nbsp;matches;

  210. }

  211. // 控制流图生成

  212. function&nbsp;generateControlFlowGraph(startAddr,&nbsp;maxInstructions&nbsp;=1000){

  213. const&nbsp;cfg&nbsp;=newMap();

  214. const&nbsp;visited&nbsp;=newSet();

  215. const&nbsp;queue&nbsp;=[startAddr];

  216. while(queue.length&nbsp;>0&&&nbsp;visited.size&nbsp;<&nbsp;maxInstructions){

  217. const&nbsp;addr&nbsp;=&nbsp;queue.shift();

  218. if(visited.has(addr.toString()))continue;

  219. visited.add(addr.toString());

  220. try{

  221. const&nbsp;instr&nbsp;=Instruction.parse(addr);

  222. cfg.set(addr.toString(),{

  223. address:&nbsp;addr,

  224. mnemonic:&nbsp;instr.mnemonic,

  225. opStr:&nbsp;instr.opStr,

  226. successors:[]

  227. });

  228. // 分析控制流指令

  229. if(instr.mnemonic.startsWith('j')||&nbsp;instr.mnemonic&nbsp;==='call'){

  230. // 简化的跳转目标分析

  231. const&nbsp;target&nbsp;=&nbsp;analyzeJumpTarget(instr,&nbsp;addr);

  232. if(target){

  233. cfg.get(addr.toString()).successors.push(target);

  234. queue.push(target);

  235. }

  236. }

  237. // 继续下一条指令(非无条件跳转)

  238. if(!instr.mnemonic.startsWith('jmp')){

  239. queue.push(addr.add(instr.size));

  240. }

  241. }catch(e){

  242. // 跳过无效指令

  243. }

  244. }

  245. return&nbsp;cfg;

  246. }

  247. // 安全的指令解析

  248. function&nbsp;safeParseInstruction(address){

  249. try{

  250. if(!address&nbsp;||&nbsp;address.isNull()){

  251. thrownewError('Invalid address');

  252. }

  253. const&nbsp;instruction&nbsp;=Instruction.parse(address);

  254. return&nbsp;instruction;

  255. }catch(e){

  256. console.error('Failed to parse instruction:',&nbsp;e);

  257. returnnull;

  258. }

  259. }

  260. // 安全的指令写入

  261. function&nbsp;safeWriteInstructions(codeAddress,&nbsp;size,&nbsp;writeFunc){

  262. try{

  263. // 分配可执行内存

  264. const&nbsp;codePtr&nbsp;=Memory.alloc(size);

  265. Memory.protect(codePtr,&nbsp;size,'rwx');

  266. // 创建写入器

  267. const&nbsp;writer&nbsp;=new&nbsp;X86Writer(codePtr);

  268. // 执行写入操作

  269. writeFunc(writer);

  270. // 刷新并返回

  271. writer.flush();

  272. return&nbsp;codePtr;

  273. }catch(e){

  274. console.error('Failed to write instructions:',&nbsp;e);

  275. returnnull;

  276. }

  277. }

  278. // 安全的指令重定位

  279. function&nbsp;safeRelocateInstructions(inputCode,&nbsp;inputSize,&nbsp;outputWriter){

  280. try{

  281. const&nbsp;relocator&nbsp;=new&nbsp;X86Relocator(inputCode,&nbsp;outputWriter);

  282. let instructionCount&nbsp;=0;

  283. while(!relocator.eoi()&&&nbsp;instructionCount&nbsp;<1000){// 防止无限循环

  284. const&nbsp;instruction&nbsp;=&nbsp;relocator.readOne();

  285. if(instruction){

  286. // 处理指令重定位逻辑

  287. relocator.writeAll();

  288. instructionCount++;

  289. }

  290. }

  291. return&nbsp;instructionCount;

  292. }catch(e){

  293. console.error('Failed to relocate instructions:',&nbsp;e);

  294. return0;

  295. }

  296. }

  297. # 在指令解析处设置断点

  298. (gdb)break&nbsp;gum_instruction_parse

  299. # 查看指令解析过程

  300. (gdb)&nbsp;info args

  301. (gdb)&nbsp;x/10i&nbsp;$rdi &nbsp;# 查看目标地址的指令

  302. (gdb)&nbsp;print&nbsp;*(GumInstruction*)$rax

  303. # 在指令写入处设置断点

  304. (gdb)break&nbsp;gum_x86_writer_put_call_address_with_arguments

  305. (gdb)&nbsp;info registers

  306. (gdb)&nbsp;x/20i&nbsp;$rdi &nbsp;# 查看写入器当前代码

  307. // CPU架构抽象

  308. typedefenum{

  309. GUM_CPU_INVALID,

  310. GUM_CPU_IA32,// x86 32-bit

  311. GUM_CPU_X86_64,// x86 64-bit

  312. GUM_CPU_ARM,// ARM 32-bit

  313. GUM_CPU_ARM64,// ARM 64-bit

  314. GUM_CPU_MIPS &nbsp; &nbsp; &nbsp;&nbsp;// MIPS 32/64-bit

  315. }GumCpuType;

  316. // 指令写入器抽象

  317. struct_GumInstructionWriter

  318. {

  319. GObject&nbsp;parent;

  320. GumCpuType&nbsp;cpu_type;

  321. gpointer code;

  322. GumAddress&nbsp;pc;

  323. void(*&nbsp;put_call_address_with_arguments)(GumInstructionWriter*&nbsp;self,GumAddress&nbsp;func,const&nbsp;gchar&nbsp;**&nbsp;arg_types,&nbsp;gsize arg_count,...);

  324. void(*&nbsp;put_jmp_address)(GumInstructionWriter*&nbsp;self,GumAddress&nbsp;address);

  325. gboolean&nbsp;(*&nbsp;flush)(GumInstructionWriter*&nbsp;self);

  326. void(*&nbsp;reset)(GumInstructionWriter*&nbsp;self,&nbsp;gpointer code_address);

  327. };

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

  329. struct_GumRelocator

  330. {

  331. GObject&nbsp;parent;

  332. GumCpuType&nbsp;cpu_type;

  333. gconstpointer input_start;

  334. gconstpointer input_cur;

  335. GumInstructionWriter*&nbsp;output;

  336. guint&nbsp;(*&nbsp;read_one)(GumRelocator*&nbsp;self,GumInstruction**&nbsp;instruction);

  337. gboolean&nbsp;(*&nbsp;eoi)(GumRelocator*&nbsp;self);

  338. void(*&nbsp;write_all)(GumRelocator*&nbsp;self);

  339. };

  340. 将指令信息存储在重定位器的内部缓冲区

  341. 更新输入位置指针

  342. 返回解析的指令对象

  343. JavaScript调用 relocator.readOne() → GumJS绑定层

  344. 调用 gum_x86_relocator_read_one(relocator,&instruction)

  345. 从输入代码当前位置解析一条指令

  346. 分析指令类型和特性:

  347. JavaScript调用 writer.putBImm(target) → GumJS绑定层

  348. 调用 gum_arm64_writer_put_b_imm(writer,target)

  349. 计算相对偏移: offset=target-(current_pc+4)

  350. 验证偏移是否在ARM64 B指令范围内(±128MB)

  351. 编码B指令: 0x14000000|((offset>>2)&0x3FFFFFF)

  352. 将编码后的指令写入代码缓冲区

  353. 更新程序计数器

  354. 生成参数设置指令(mov, push等)

  355. 生成call指令

  356. 如果需要,生成栈清理指令

  357. 更新写入器的程序计数器

  358. JavaScript调用 writer.putCallAddressWithArguments(func,argTypes,args) → GumJS绑定层

  359. 调用 gum_x86_writer_put_call_address_with_arguments(writer,func,argTypes,args)

  360. 根据ABI确定参数传递方式:

  361. 解析指令的各个组成部分(操作码、操作数、寄存器等)

  362. 创建GumInstruction结构体并填充信息

  363. 返回JavaScript Instruction对象

  364. JavaScript调用 Instruction.parse(target) → GumJS绑定层

  365. 调用 gum_instruction_parse(target)

  366. 检测目标CPU架构

  367. 调用对应架构的指令解析器:

  368. +------------------+

  369. |&nbsp;input_start&nbsp;(gconstpointer)|->输入代码起始地址

  370. +------------------+

  371. |&nbsp;input_cur&nbsp;(gconstpointer)|->当前输入位置

  372. +------------------+

  373. |&nbsp;output&nbsp;(GumX86Writer*)|->输出写入器

  374. +------------------+

  375. |&nbsp;inpos&nbsp;(guint)|->输入缓冲区位置

  376. +------------------+

  377. |&nbsp;outpos&nbsp;(guint)|->输出缓冲区位置

  378. +------------------+

  379. |&nbsp;eoi&nbsp;(gboolean)|->是否到达输入末尾

  380. +------------------+

  381. |&nbsp;delay_slot_pending&nbsp;(gboolean)|->延迟槽待处理(MIPS)

  382. +------------------+

  383. +------------------+

  384. |base(GumCodeWriter)|->基础代码写入器

  385. +------------------+

  386. |&nbsp;code&nbsp;(guint32*)|->当前代码指针(32位对齐)

  387. +------------------+

  388. |&nbsp;pc&nbsp;(GumAddress)|->当前程序计数器

  389. +------------------+

  390. |&nbsp;id_to_reg&nbsp;(GumArm64Reg[GUM_ARM64_REG_INVALID])|->寄存器ID映射

  391. +------------------+

  392. +------------------+

  393. |base(GumCodeWriter)|->基础代码写入器

  394. +------------------+

  395. |&nbsp;target_cpu&nbsp;(GumCpuType)|->目标CPU类型

  396. +------------------+

  397. |&nbsp;target_abi&nbsp;(GumAbiType)|->目标ABI类型

  398. +------------------+

  399. |&nbsp;code&nbsp;(guint8*)|->当前代码指针

  400. +------------------+

  401. |&nbsp;pc&nbsp;(GumAddress)|->当前程序计数器

  402. +------------------+

  403. |&nbsp;id_to_reg&nbsp;(GumX86Reg[GUM_X86_REG_NONE])|->寄存器ID映射

  404. +------------------+

  405. +------------------+

  406. |&nbsp;address&nbsp;(GumAddress)|->指令地址

  407. +------------------+

  408. |&nbsp;mnemonic&nbsp;(char*)|->助记符字符串

  409. +------------------+

  410. |&nbsp;op_str&nbsp;(char*)|->操作数字符串

  411. +------------------+

  412. |&nbsp;operands&nbsp;(GArray*)|->操作数数组

  413. +------------------+

  414. |&nbsp;regs_read&nbsp;(GArray*)|->读取的寄存器数组

  415. +------------------+

  416. |&nbsp;regs_written&nbsp;(GArray*)|->写入的寄存器数组

  417. +------------------+

  418. |&nbsp;groups&nbsp;(GArray*)|->指令组数组

  419. +------------------+

  420. |&nbsp;size&nbsp;(guint)|->指令大小(字节)

  421. +------------------+

  422. // GumRelocator工厂

  423. GumRelocator*

  424. gum_relocator_new&nbsp;(gconstpointer input_code,GumInstructionWriter*&nbsp;output);

  425. GumRelocator*

  426. gum_relocator_make_for_cpu&nbsp;(GumCpuType&nbsp;cpu_type,&nbsp;gconstpointer input_code,GumInstructionWriter*&nbsp;output);

  427. // GumInstructionWriter工厂

  428. GumInstructionWriter*

  429. gum_instruction_writer_new&nbsp;(gpointer code_address);

  430. GumInstructionWriter*

  431. gum_instruction_writer_make_for_cpu&nbsp;(GumCpuType&nbsp;cpu_type,&nbsp;gpointer code_address);

  432. // 特定架构写入器

  433. GumX86Writer*

  434. gum_x86_writer_new&nbsp;(gpointer code_address);

  435. GumArm64Writer*

  436. gum_arm64_writer_new&nbsp;(gpointer code_address);

  437. // GumInstruction工厂

  438. GumInstruction*

  439. gum_instruction_parse&nbsp;(gpointer target);

  440. GumInstruction*

  441. gum_instruction_parse_at&nbsp;(gpointer target,GumCpuType&nbsp;cpu_type);

  442. // CPU类型检测

  443. GumCpuType

  444. gum_cpu_detect&nbsp;(void);

  445. // Instruction相关的结构

  446. typedefstruct_GumInstructionApi{

  447. GumInstruction*(*&nbsp;parse)(gpointer target);

  448. void(*&nbsp;free)(GumInstruction*&nbsp;instruction);

  449. GumAddress(*&nbsp;get_address)(GumInstruction*&nbsp;instruction);

  450. const&nbsp;gchar&nbsp;*(*&nbsp;get_mnemonic)(GumInstruction*&nbsp;instruction);

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

  452. }GumInstructionApi;

  453. // 指令写入器相关的结构

  454. typedefstruct_GumInstructionWriterApi{

  455. GumInstructionWriter*(*&nbsp;new_writer)(gpointer code_address);

  456. void(*&nbsp;put_call_address_with_arguments)(GumInstructionWriter*&nbsp;self,GumAddress&nbsp;func,const&nbsp;gchar&nbsp;**&nbsp;arg_types,&nbsp;gsize arg_count,...);

  457. void(*&nbsp;put_jmp_address)(GumInstructionWriter*&nbsp;self,GumAddress&nbsp;address);

  458. gboolean&nbsp;(*&nbsp;flush)(GumInstructionWriter*&nbsp;self);

  459. void(*&nbsp;reset)(GumInstructionWriter*&nbsp;self,&nbsp;gpointer code_address);

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

  461. }GumInstructionWriterApi;

  462. // 指令重定位器相关的结构

  463. typedefstruct_GumRelocatorApi{

  464. GumRelocator*(*&nbsp;new_relocator)(gconstpointer input_code,GumInstructionWriter*&nbsp;output);

  465. guint&nbsp;(*&nbsp;read_one)(GumRelocator*&nbsp;self,GumInstruction**&nbsp;instruction);

  466. gboolean&nbsp;(*&nbsp;eoi)(GumRelocator*&nbsp;self);

  467. void(*&nbsp;write_all)(GumRelocator*&nbsp;self);

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

  469. }GumRelocatorApi;

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

#

#


免责声明:

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

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

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

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

评论:0   参与:  0