1.0
This commit is contained in:
385
include/SqrReg_ActiveHook.hpp
Normal file
385
include/SqrReg_ActiveHook.hpp
Normal file
@@ -0,0 +1,385 @@
|
||||
#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)
|
||||
|
||||
typedef struct {
|
||||
const SQChar* name;
|
||||
size_t offset;
|
||||
} CpuContextMember;
|
||||
|
||||
// HookFunc
|
||||
struct _ExampleListener
|
||||
{
|
||||
GObject parent;
|
||||
guint num_calls;
|
||||
std::vector<std::string> ArgumentCount;
|
||||
std::string RetType;
|
||||
HSQOBJECT CallBackOnEnter;
|
||||
HSQOBJECT CallBackOnLeave;
|
||||
SQUserPointer FuncAddress;
|
||||
};
|
||||
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;
|
||||
|
||||
static std::thread::id Zhuxianc = std::this_thread::get_id();
|
||||
|
||||
#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 void replacement_function(GumInvocationContext* context)
|
||||
{
|
||||
// 在这里执行你的逻辑
|
||||
// gum_print("自定义逻辑已执行!\n");
|
||||
// 跳过原函数,直接返回
|
||||
// 如果需要修改返回值,可以通过 context->cpu_context 修改寄存器
|
||||
}
|
||||
|
||||
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;
|
||||
EXAMPLE_LISTENER(listener)->FuncAddress = FuncAddress;
|
||||
|
||||
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::cout << "调用点: " << self->FuncAddress << std::endl;
|
||||
|
||||
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);
|
||||
|
||||
//传入CPU上下文
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, _SC("_Haker_SetCpuContext"), -1);
|
||||
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_newtable(v);
|
||||
struct TableEntry
|
||||
{
|
||||
const SQChar* key;
|
||||
SQUserPointer value;
|
||||
} entries[] = {
|
||||
{_SC("eip"), (SQUserPointer)ic->cpu_context->eip},
|
||||
{_SC("edi"), (SQUserPointer)ic->cpu_context->edi},
|
||||
{_SC("esi"), (SQUserPointer)ic->cpu_context->esi},
|
||||
{_SC("ebp"), (SQUserPointer)ic->cpu_context->ebp},
|
||||
{_SC("esp"), (SQUserPointer)ic->cpu_context->esp},
|
||||
{_SC("ebx"), (SQUserPointer)ic->cpu_context->ebx},
|
||||
{_SC("edx"), (SQUserPointer)ic->cpu_context->edx},
|
||||
{_SC("ecx"), (SQUserPointer)ic->cpu_context->ecx},
|
||||
{_SC("eax"), (SQUserPointer)ic->cpu_context->eax},
|
||||
};
|
||||
|
||||
for (const auto& entry : entries)
|
||||
{
|
||||
sq_pushstring(v, entry.key, -1);
|
||||
sq_pushuserpointer(v, entry.value);
|
||||
sq_newslot(v, -3, SQFalse);
|
||||
}
|
||||
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
|
||||
return;
|
||||
}
|
||||
sq_settop(v, top); // restores the original stack size
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
sq_settop(v, top);
|
||||
}
|
||||
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"));
|
||||
}
|
||||
Reference in New Issue
Block a user