原文链接: https://frida.re/docs/javascript-api/#cmodule
欢迎加入 Frida 交流群: 1049977261
CModule
-
new CModule(source[, symbols])
: 将 Csource
代码字符串编译为机器码放入内存中.可用于实现调用非常频繁的回调, 例如: Interceptor 和 Stalker.
但在需要启动新线程以在紧密循环中调用函数时也很有用, 例如, 用于模糊测试.全局方法被自动导出为以 C 源码中相同名称的 NativePointer 类型的属性.
这意味着您可以将它们传递给 Interceptor 和 Stalker, 或者通过 NativeFunction 调用它们.例如:
var source =
"#include <stdio.h>" +
"void functionFromCModule(){" +
" printf(\"Print from CModule\n\");" +
"}";
var cModule = new CModule(source);
console.log(JSON.stringify(cModule));
var ptrFunctionFromCModule = cModule['functionFromCModule'];
var functionFromCModule = new NativeFunction(ptrFunctionFromCModule, 'void', []);
functionFromCModule();
第二个可选参数 `symbols` 是一个指明了符号名称与它的 *NativePointer* 值的对象, 它们将在对象创建时被插入进来. 例如, 一个或多个通过 *Memory.alloc()* 分配的内存块, 以及/或者用于从 C 模块接收回调的 *NativeCallback*.
为了执行初始化与清理, 您可以定义以下签名的方法:
- `void init (void)`
- `void finalize (void)`
请注意, 所有的数据都是只读的, 所以可写的全局属性应当被声明为 *extern*, 通过 *Memory.alloc()* 进行内存分配, 并通过构造器的第二个参数以符号的形式传入.
-
dispose()
:
提前从内存中取消模块映射. 可用于不想等待垃圾回收的短期模块.
Instruction
-
Instruction.parse(target)
:
解析在NativePointer
类型的target
内存地址的指令.
请注意, 在 32 位 ARM 上, 对于 ARM 函数, 此地址的最低有效位必须设置为 0, 对于 Thumb 函数, 此地址必须设置为 1.
如果您通过 Frida 的 API 来获得一个地址, 例如Module.getExportByName()
, 那么 Frida 就会替您处理这个细节.返回的对象包含以下属性:
-
address
: 该指令的NativePointer
类型的地址 (EIP) -
next
: 指向下一条指令, 你可以对它进行parse()
-
size
: 当前指令的大小 -
mnemonic
: 指令助记符的字符串表示形式 -
opStr
: 指令操作数的字符串表示形式 -
operands
: 一个描述各个操作数的数组, 数组中的每个对象至少包含type
与value
属性, 但根据 CPU 架构, 也可能包含一些附加属性. -
regsRead
: 该指令隐式读取的寄存器名称数组 -
regsWritten
: 该指令隐式写入的寄存器名称数组 -
groups
: 该指令所属的组名称数组array of group names that this instruction belongs to -
toString()
: 转换为人类可读的字符串
关于
operands
和groups
的详细信息, 请参考您 CPU 架构对应文档的 Capstone -
Kernel
Kernel.available
:
一个指明了核心 API 是否可用的布尔值.
当这个值为 false 时请不要调用其他任何的Kernel
属性或方法.Kernel.base
: UInt64 类型的核心的基础地址.Kernel.pageSize
: 以字节为单位的核心页的大小数字.-
Kernel.enumerateModules()
:
列举当前已加载的核心模块, 返回一个包含以下属性的数组:-
name
: 规范的模块名称字符串. -
base
:NativePointer
类型的基础地址. -
size
: 以字节为单位的大小.
-
-
Kernel.enumerateRanges(protection|specifier)
:
列举满足rwx
格式的字符串参数protection
的核心内存范围, 其中rw-
意为 "必须至少是可读可写".
Alternatively you may provide aspecifier
object with aprotection
key whose value is as
aforementioned, and acoalesce
key set totrue
if you'd like neighboring
ranges with the same protection to be coalesced (the default isfalse
;
i.e. keeping the ranges separate).返回一个包含以下属性的数组:
-
base
:NativePointer
类型的基础地址. -
size
: 以字节为单位的大小. -
protection
: 读写权限 (如上所述)
-
Kernel.enumerateModuleRanges(name, protection)
:
类似于Kernel.enumerateRanges
, 但它仅限于指定模块name
内, 当name
为null
时意为核心模块自身. 每一个范围都包含一个作为唯一标识的name
字段.Kernel.alloc(size)
: 分配size
字节的核心内存, 舍入为内核页面大小的倍数. 返回的值是一个以UInt64
指明的已分配内存的基础地址.-
Kernel.protect(address, size, protection)
:
更新一个区域的核心内存的读写权限,protection
的格式与Kernel.enumerateRanges()
一致.例如:
Kernel.protect(UInt64('0x1234'), 4096, 'rw-');
Kernel.readByteArray(address, length)
:
类似于NativePointer#readByteArray
, 但是从核心内存中进行读取的.Kernel.writeByteArray(address, bytes)
:
类似于NativePointer#writeByteArray
, 但是从核心内存中进行写入的.Kernel.scan(address, size, pattern, callbacks)
:
类似于Memory.scan
, 但是在核心内存中进行扫描的.
-
Kernel.scanSync(address, size, pattern)
:
scan()
的同步版, 返回匹配的对象数组.