#pragma once #include "frida-gum.h" #include #include #include "squirrel.h" #include "sqstdaux.h" #include "sqstdblob.h" #include "sqstdio.h" #include "sqstdmath.h" #include "sqstdstring.h" #include "sqstdsystem.h" #include #include extern HSQUIRRELVM v; extern std::recursive_mutex SqMtx; #define CONTAINS_STRING(str, substr) (str == substr) // 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); // 得到函数地址 SQUserPointer FuncAddress; sq_getuserpointer(v, 2, &FuncAddress); // 遍历参数类型数组 std::vector ParameterType; sq_pushnull(v); // null iterator while (SQ_SUCCEEDED(sq_next(v, 3))) { const SQChar *path; sq_getstring(v, -1, &path); ParameterType.push_back(path); 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) { gpointer ReturnAddress = gum_invocation_context_get_return_address(ic); ExampleListener *self = EXAMPLE_LISTENER(listener); std::lock_guard lock(SqMtx); // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); sq_pushstring(v, _SC("_Haker_SetNextReturnAddress"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { sq_pushroottable(v); sq_pushuserpointer(v, ReturnAddress); sq_call(v, 2, SQFalse, SQTrue); } sq_settop(v, top); 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")) sq_pushstring(v, (char *)Abuf, -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); std::lock_guard lock(SqMtx); // 执行虚拟机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")) sq_pushstring(v, (char *)Abuf, -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; (void)glib_autoptr_cleanup_ExampleListener; } 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) { } static void RegisterActiveHook(HSQUIRRELVM v) { register_World_func(v, L_HookFunc, _SC("Sq_HookFunc")); register_World_func(v, L_DeHookFunc, _SC("Sq_DeHookFunc")); }