#pragma once #include "frida-gum.h" #include #include #include #include // HookFunc struct _ExampleListener { GObject parent; guint num_calls; std::vector ArgumentCount; std::string RetType; HSQOBJECT CallBackOnEnter; HSQOBJECT CallBackOnLeave; }; enum _ExampleHookId { EXAMPLE_HOOK_OPEN, EXAMPLE_HOOK_CLOSE }; typedef struct _ExampleListener ExampleListener; typedef enum _ExampleHookId ExampleHookId; static void example_listener_iface_init(gpointer g_iface, gpointer iface_data); static GumInterceptor* interceptor; #define EXAMPLE_TYPE_LISTENER (example_listener_get_type()) G_DECLARE_FINAL_TYPE(ExampleListener, example_listener, EXAMPLE, LISTENER, GObject) G_DEFINE_TYPE_EXTENDED(ExampleListener, example_listener, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE(GUM_TYPE_INVOCATION_LISTENER, example_listener_iface_init)) static SQInteger L_HookFunc(HSQUIRRELVM v) { static bool InitFlag = false; if (!InitFlag) { InitFlag = true; gum_init_embedded(); interceptor = gum_interceptor_obtain(); } GumInvocationListener* listener = (GumInvocationListener*)g_object_new(EXAMPLE_TYPE_LISTENER, NULL); // 得到函数地址 SQInteger FuncAddressbuf; Sq_getinteger(v, 2, &FuncAddressbuf); void* FuncAddress = (void*)FuncAddressbuf; // 遍历参数类型数组 std::vector ParameterType; sq_pushnull(v); // null iterator while (SQ_SUCCEEDED(sq_next(v, 3))) { const SQChar* path; Sq_getstring(v, -1, &path); char* OutPutText2 = DNFTOOL::SquirrelU2W(path); std::string Realpath(OutPutText2); delete[]OutPutText2; ParameterType.push_back(Realpath); Sq_pop(v, 2); } Sq_pop(v, 1); // 得到入口回调函数 HSQOBJECT CallBackOnEnter; sq_getstackobj(v, 4, &CallBackOnEnter); // 必须增加一次引用一会记得删除 不然这个函数会被释放 sq_addref(v, &CallBackOnEnter); // 得到出口回调函数 HSQOBJECT CallBackOnLeave; sq_getstackobj(v, 5, &CallBackOnLeave); // 必须增加一次引用一会记得删除 不然这个函数会被释放 sq_addref(v, &CallBackOnLeave); EXAMPLE_LISTENER(listener)->ArgumentCount = ParameterType; // EXAMPLE_LISTENER(listener)->RetType = std::string(RetBuf); EXAMPLE_LISTENER(listener)->CallBackOnEnter = CallBackOnEnter; EXAMPLE_LISTENER(listener)->CallBackOnLeave = CallBackOnLeave; gum_interceptor_begin_transaction(interceptor); gum_interceptor_attach(interceptor, GSIZE_TO_POINTER(FuncAddress), listener, GSIZE_TO_POINTER(FuncAddress)); gum_interceptor_end_transaction(interceptor); Sq_pushuserpointer(v, listener); return 1; } static SQInteger L_DeHookFunc(HSQUIRRELVM v) { // 得到函数地址 SQUserPointer FuncAddress; Sq_getuserpointer(v, 2, &FuncAddress); GumInvocationListener* listener = (GumInvocationListener*)FuncAddress; gum_interceptor_detach(interceptor, listener); return 0; } static void example_listener_on_enter(GumInvocationListener* listener, GumInvocationContext* ic) { ExampleListener* self = EXAMPLE_LISTENER(listener); HSQUIRRELVM v = *(HSQUIRRELVM*)0x1AF3544; // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushobject(v, self->CallBackOnEnter); Sq_pushroottable(v); sq_newarray(v, 0); for (size_t i = 0; i < self->ArgumentCount.size() - 1; i++) { void* Abuf = gum_invocation_context_get_nth_argument(ic, i); if (CONTAINS_STRING(self->ArgumentCount[i], "int")) Sq_pushinteger(v, (int)Abuf); else if (CONTAINS_STRING(self->ArgumentCount[i], "float")) { SQFloat* a = reinterpret_cast(&Abuf); Sq_pushfloat(v, *(SQFloat*)a); } else if (CONTAINS_STRING(self->ArgumentCount[i], "bool")) Sq_pushbool(v, (bool)Abuf); else if (CONTAINS_STRING(self->ArgumentCount[i], "string")) { std::wstring ss = DNFTOOL::charTowchar_t((char*)Abuf); Sq_pushstring(v, ss.c_str(), -1); } else if (CONTAINS_STRING(self->ArgumentCount[i], "pointer")) Sq_pushuserpointer(v, (void*)Abuf); else if (CONTAINS_STRING(self->ArgumentCount[i], "short")) Sq_pushinteger(v, (int)Abuf); else if (CONTAINS_STRING(self->ArgumentCount[i], "char")) Sq_pushinteger(v, (int)Abuf); else Sq_pushuserpointer(v, (void*)Abuf); sq_arrayappend(v, -2); } Sq_call(v, 2, SQTrue, SQTrue); // calls the function if (sq_gettype(v, -1) == OT_ARRAY) { sq_pushnull(v); // null iterator int Idx = 0; while (SQ_SUCCEEDED(sq_next(v, -2))) { if (CONTAINS_STRING(self->ArgumentCount[Idx], "int")) { SQInteger Abuf; Sq_getinteger(v, -1, &Abuf); gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount[Idx], "float")) { SQFloat Abuf; Sq_getfloat(v, -1, &Abuf); gum_invocation_context_replace_nth_argument(ic, Idx, &Abuf); } else if (CONTAINS_STRING(self->ArgumentCount[Idx], "bool")) { SQBool Abuf; Sq_getbool(v, -1, &Abuf); gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount[Idx], "string")) { const SQChar* Abuf; Sq_getstring(v, -1, &Abuf); gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount[Idx], "pointer")) { SQUserPointer Abuf; Sq_getuserpointer(v, -1, &Abuf); gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount[Idx], "short")) { SQInteger Abuf; Sq_getinteger(v, -1, &Abuf); gum_invocation_context_replace_nth_argument(ic, Idx, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount[Idx], "char")) { SQInteger Abuf; Sq_getinteger(v, -1, &Abuf); char CBUF = Abuf; gum_invocation_context_replace_nth_argument(ic, Idx, (void*)CBUF); } Idx++; Sq_pop(v, 2); } Sq_pop(v, 1); } Sq_settop(v, top); // restores the original stack size } static void example_listener_on_leave(GumInvocationListener* listener, GumInvocationContext* ic) { ExampleListener* self = EXAMPLE_LISTENER(listener); HSQUIRRELVM v = *(HSQUIRRELVM*)0x1AF3544; // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushobject(v, self->CallBackOnLeave); Sq_pushroottable(v); sq_newarray(v, 0); for (size_t i = 0; i < self->ArgumentCount.size(); i++) { void* Abuf; if (i == (self->ArgumentCount.size() - 1)) Abuf = gum_invocation_context_get_return_value(ic); else Abuf = gum_invocation_context_get_nth_argument(ic, i); if (CONTAINS_STRING(self->ArgumentCount[i], "int")) Sq_pushinteger(v, (int)Abuf); else if (CONTAINS_STRING(self->ArgumentCount[i], "float")) { SQFloat* a = reinterpret_cast(&Abuf); Sq_pushfloat(v, *(SQFloat*)a); } else if (CONTAINS_STRING(self->ArgumentCount[i], "bool")) Sq_pushbool(v, (bool)Abuf); else if (CONTAINS_STRING(self->ArgumentCount[i], "string")) { std::wstring ss = DNFTOOL::charTowchar_t((char*)Abuf); Sq_pushstring(v, ss.c_str(), -1); } else if (CONTAINS_STRING(self->ArgumentCount[i], "pointer")) Sq_pushuserpointer(v, (void*)Abuf); else if (CONTAINS_STRING(self->ArgumentCount[i], "short")) Sq_pushinteger(v, (int)Abuf); else if (CONTAINS_STRING(self->ArgumentCount[i], "char")) Sq_pushinteger(v, (int)Abuf); else Sq_pushuserpointer(v, (void*)Abuf); sq_arrayappend(v, -2); } Sq_call(v, 2, SQTrue, SQTrue); // calls the function if (sq_gettype(v, -1) != OT_NULL) { if (CONTAINS_STRING(self->ArgumentCount.back(), "int")) { SQInteger Abuf; Sq_getinteger(v, -1, &Abuf); gum_invocation_context_replace_return_value(ic, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount.back(), "float")) { SQFloat Abuf; Sq_getfloat(v, -1, &Abuf); gum_invocation_context_replace_return_value(ic, &Abuf); } else if (CONTAINS_STRING(self->ArgumentCount.back(), "bool")) { SQBool Abuf; Sq_getbool(v, -1, &Abuf); gum_invocation_context_replace_return_value(ic, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount.back(), "string")) { const SQChar* Abuf; Sq_getstring(v, -1, &Abuf); gum_invocation_context_replace_return_value(ic, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount.back(), "pointer")) { SQUserPointer Abuf; Sq_getuserpointer(v, -1, &Abuf); gum_invocation_context_replace_return_value(ic, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount.back(), "short")) { SQInteger Abuf; Sq_getinteger(v, -1, &Abuf); gum_invocation_context_replace_return_value(ic, (void*)Abuf); } else if (CONTAINS_STRING(self->ArgumentCount.back(), "char")) { SQInteger Abuf; Sq_getinteger(v, -1, &Abuf); char CBUF = Abuf; gum_invocation_context_replace_return_value(ic, (void*)Abuf); } } } static void example_listener_class_init(ExampleListenerClass* klass) { (void)EXAMPLE_IS_LISTENER; #ifndef _MSC_VER (void) glib_autoptr_cleanup_ExampleListener; #endif } static void example_listener_iface_init(gpointer g_iface, gpointer iface_data) { GumInvocationListenerInterface* iface = (GumInvocationListenerInterface*)g_iface; iface->on_enter = example_listener_on_enter; iface->on_leave = example_listener_on_leave; } static void example_listener_init(ExampleListener* self) { }