frida-gum 虽然功能强大,但由于使用了 C 语言的接口,扩展开发不方便,因此frida 使用 JavaScript 作为编写 hook 的语言,底层使用quickjs和v8封装。
image.png
相关文件
- frida-gum/bindings/gumjs/runtime/core.js
- frida-gum/bindings/gumjs/gumv8process.cpp
代码
void
_gum_v8_process_init (GumV8Process * self,
GumV8Module * module,
GumV8Core * core,
Local<ObjectTemplate> scope)
{
auto isolate = core->isolate;
self->module = module;
self->core = core;
auto process = _gum_v8_create_module ("Process", scope, isolate);
process->Set (_gum_v8_string_new_ascii (isolate, "id"),
Number::New (isolate, gum_process_get_id ()), ReadOnly);
process->Set (_gum_v8_string_new_ascii (isolate, "arch"),
String::NewFromUtf8Literal (isolate, GUM_SCRIPT_ARCH), ReadOnly);
process->Set (_gum_v8_string_new_ascii (isolate, "platform"),
String::NewFromUtf8Literal (isolate, GUM_SCRIPT_PLATFORM), ReadOnly);
process->Set (_gum_v8_string_new_ascii (isolate, "pageSize"),
Number::New (isolate, gum_query_page_size ()), ReadOnly);
process->Set (_gum_v8_string_new_ascii (isolate, "pointerSize"),
Number::New (isolate, GLIB_SIZEOF_VOID_P), ReadOnly);
process->Set (_gum_v8_string_new_ascii (isolate, "codeSigningPolicy"),
String::NewFromUtf8 (isolate, gum_code_signing_policy_to_string (
gum_process_get_code_signing_policy ())).ToLocalChecked (), ReadOnly);
_gum_v8_module_add (External::New (isolate, self), process,
gumjs_process_functions, isolate);
}
static const GumV8Function gumjs_process_functions[] =
{
{ "getCurrentDir", gumjs_process_get_current_dir },
{ "getHomeDir", gumjs_process_get_home_dir },
{ "getTmpDir", gumjs_process_get_tmp_dir },
{ "isDebuggerAttached", gumjs_process_is_debugger_attached },
{ "getCurrentThreadId", gumjs_process_get_current_thread_id },
{ "_enumerateThreads", gumjs_process_enumerate_threads },
{ "findModuleByName", gumjs_process_find_module_by_name },
{ "_enumerateModules", gumjs_process_enumerate_modules },
{ "_enumerateRanges", gumjs_process_enumerate_ranges },
{ "enumerateSystemRanges", gumjs_process_enumerate_system_ranges },
{ "_enumerateMallocRanges", gumjs_process_enumerate_malloc_ranges },
{ "setExceptionHandler", gumjs_process_set_exception_handler },
{ NULL, NULL }
};
makeEnumerateApi(Process, 'enumerateThreads', 0);
makeEnumerateApi(Process, 'enumerateModules', 0);
makeEnumerateRanges(Process);
makeEnumerateApi(Process, 'enumerateMallocRanges', 0);
Object.defineProperties(Process, {
findModuleByAddress: {
enumerable: true,
value: function (address) {
let module = null;
Process._enumerateModules({
onMatch(m) {
const base = m.base;
if (base.compare(address) <= 0 && base.add(m.size).compare(address) > 0) {
module = m;
return 'stop';
}
},
onComplete() {
}
});
return module;
}
},
getModuleByAddress: {
enumerable: true,
value: function (address) {
const module = Process.findModuleByAddress(address);
if (module === null)
throw new Error('unable to find module containing ' + address);
return module;
}
},
getModuleByName: {
enumerable: true,
value: function (name) {
const module = Process.findModuleByName(name);
if (module === null)
throw new Error("unable to find module '" + name + "'");
return module;
}
},
getRangeByAddress: {
enumerable: true,
value: function (address) {
const range = Process.findRangeByAddress(address);
if (range === null)
throw new Error('unable to find range containing ' + address);
return range;
}
},
});
if (Process.findRangeByAddress === undefined) {
Object.defineProperty(Process, 'findRangeByAddress', {
enumerable: true,
value: function (address) {
let range = null;
Process._enumerateRanges('---', {
onMatch(r) {
const base = r.base;
if (base.compare(address) <= 0 && base.add(r.size).compare(address) > 0) {
range = r;
return 'stop';
}
},
onComplete() {
}
});
return range;
}
});
}