原文链接: https://frida.re/docs/javascript-api/#memory
欢迎加入 Frida 交流群: 1049977261
Memory
-
Memory.scan(address, size, pattern, callbacks)
:
根据NativePointer
类型的address
和size
扫描内存, 并在满足pattern
时触发回调.-
pattern
必须满足 "13 37 ?? ff" 格式才能匹配 0x13 后面跟着 0x37 后面跟着任意字节后面跟着 0xff.
您可以指定 r2 风格的掩码用于实现更高级的匹配模式.
The mask is bitwise AND-ed against both the needle and the haystack. To specify the mask append a:
character after the needle, followed by the mask using the same syntax. For example: "13 37 13 37 : 1f ff ff f1". For convenience it is also possible to specify nibble-level wildcards, like "?3 37 13 ?7", which gets translated into masks behind the scenes. -
callbacks
是一个包含以下方法的对象:-
onMatch: function (address, size)
:address
包含回调触发时的
NativePointer
类型的地址,size
指明了以 byte 为单位的尺寸.这个方法可以通过返回
stop
字符串来提前终止内存扫描. -
onError: function (reason)
: 当内存扫描出现错误时伴随reason
被调用. -
onComplete: function ()
: 当指定的内存范围被完整的扫描过时被调用.
-
-
-
Memory.scanSync(address, size, pattern)
:scan()
的同步执行版本, 返回一个包含以下属性的数组:-
address
包含NativePointer
类型的绝对地址. -
size
以byte
为单位的尺寸.
-
var m = Process.enumerateModules()[0];// enumerate loaded modules and take the first one
// var m = Module.load('win32u.dll'); // or load module by name
console.log(JSON.stringify(m));// print its properties
console.log(hexdump(m.base));// dump it form its base address
var pattern = '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00';// the pattern that you are interested in
Memory.scan(/*NativePointer*/ m.base, /*number*/ m.size, /*string*/ pattern, {
onMatch: function (address, size) {// called when pattern matches
console.log("Memory.scan() found at " + address + " with size " + size);
return 'stop';// optional, stop scanning early
},
onComplete: function () {
console.log("Memory.scan() complete");
}
});
var results = Memory.scanSync(m.base, m.size, pattern);
console.log("Memory.scanSync() result = \n" + JSON.stringify(results));
-
Memory.alloc(size)
: 在堆上分配size
个字节的内存, 或者, 如果size
是Process.pageSize
的倍数, 一个或多个被操作系统管理的原始内存页. 返回的值是一个NativePointer
对象并且底层的内存将在所有的 JavaScript 脚本
不再对其持有引用时被释放. 这意味着您需要在这个指针正在被 JavaScript 运行时外的代码使用时维持一个对它的引用. -
Memory.copy(dst, src, n)
: 类似于memcpy
. -
Memory.dup(address, size)
: 顺序调用Memory.alloc()
,Memory.copy()
的简写. -
Memory.protect(address, size, protection)
:
更新指定范围内存的读写权限,projection
格式与Process.enumerateRanges()
相同.例如:
Memory.protect(ptr('0x1234'), 4096, 'rw-');
-
Memory.patchCode(address, size, apply)
:
安全的在NativePointer
类型的address
处修改size
个字节.
您所提供的 JavaScript 方法apply
将伴随一个可写的指针被调用, 您必须在该方法返回之前写入预期的修改. 请不要假设这个指针与address
处于相同的位置, 因为一些系统要求内存改动需要在映射到原内存页的顶部之前先写入到临时位置 (比如在 iOS 上直接修改内存中的代码有可能造成进程丢失 CS_VALID 状态).例如:
var getLivesLeft = Module.getExportByName('game-engine.so', 'get_lives_left');
var maxPatchSize = 64; // Do not write out of bounds, may be a temporary buffer!
Memory.patchCode(getLivesLeft, maxPatchSize, function (code) {
var cw = new X86Writer(code, { pc: getLivesLeft });
cw.putMovRegU32('eax', 9000);
cw.putRet();
cw.flush();
});
-
Memory.allocUtf8String(str)
,
Memory.allocUtf16String(str)
,
Memory.allocAnsiString(str)
:
分配, 编码并且将str
在堆上写出为一个 UTF-8/UTF-16/ANSI 字符串.
返回一个NativePointer
对象. 与其生命周期相关的详情请参考Memory#alloc
.
MemoryAccessMonitor
-
MemoryAccessMonitor.enable(ranges, callbacks)
:
监控一个或多个内存范围的访问情况, 并且在每个内存页第一次访问时触发回调.
ranges
可以是一个范围对象, 也可以是一个由范围对象构成的数组.
这个对象包含以下属性:-
base
:NativePointer
类型的基础地址 -
size
: 以 byte 为单位的尺寸
callbacks
对象包含以下方法:-
onAccess: function (details)
:
伴随着包含以下属性的details
对象被同步调用:-
operation
: 触发这次访问的操作类型, 仅限于read
,write
, 或execute
. -
from
:NativePointer
类型的触发这次访问的指令的地址 -
address
:NativePointer
类型的被访问的地址 -
rangeIndex
: 被访问的范围在MemoryAccessMonitor.enable()
方法的ranges
参数中的索引 -
pageIndex
: 被访问的内存页在指定范围中的索引 -
pagesCompleted
: 到目前为止已访问(并且不再受监控)的内存页总数 -
pagesTotal
: 已被监控的内存页总数
-
-
-
MemoryAccessMonitor.disable()
:
停止对传递给MemoryAccessMonitor.enable()
的剩余的内存页的监控
网友评论