DP_S/include/SqrReg_ActiveHook.hpp

324 lines
11 KiB
C++

#pragma once
#include "frida-gum.h"
#include <fcntl.h>
#include <unistd.h>
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <mutex>
#include <iostream>
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<std::string> 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<std::string> 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<std::recursive_mutex> 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<float *>(&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<std::recursive_mutex> 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<float *>(&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"));
}