mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2025-01-13 23:53:54 +08:00
.
This commit is contained in:
parent
91bbdde9b2
commit
cb44b53259
@ -1,7 +1,7 @@
|
||||
include_directories(. util engines)
|
||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
||||
set(enginessrc
|
||||
BGI MKXPZ Ryujinx livecaptions Kincaid vita3k rpcs3 yuzu TYPEMOON UnrealEngine AGES7 mono
|
||||
BGI MKXPZ Ryujinx livecaptions Kincaid vita3k rpcs3 yuzu TYPEMOON UnrealEngine AGES7
|
||||
Godot 5pb lucasystem LightVN V8 Artemis KiriKiri YOX CMVS Suika2)
|
||||
set(enginepath "engine64")
|
||||
set(collector "enginecollection64.cpp")
|
||||
@ -14,7 +14,7 @@ else()
|
||||
BKEngine Overflow SRPGStudio Suika2 FVP LCScript Ohgetsu RPGMakerRGSS3 ONScripterru OVERDRIVE
|
||||
HXP Palette Purple Ruf RUNE Tarte Tomato Sakuradog Troy VitaminSoft UnknownEngine TSSystem
|
||||
Xbangbang Anisetta Nijyuei Interheart LovaGame Giga Jisatu101 EntisGLS Ciel ACTGS TerraLunar
|
||||
jukujojidai VanillawareGC cef V8 mono PONScripter Bishop sakanagl Lightvn KiriKiri SideB BGI
|
||||
jukujojidai VanillawareGC cef V8 PONScripter Bishop sakanagl Lightvn KiriKiri SideB BGI
|
||||
Bootup morning shyakunage Regista NNNConfig Eushully Majiro littlecheese Elf Silkys CMVS Wolf
|
||||
Circus1 Circus2 Cotopha Artemis CatSystem Atelier Tenco QLIE Pal AIL NeXAS LunaSoft Unicorn
|
||||
Rejet Interlude AdobeAir Retouch Malie Live Nexton Lucifen Waffle TinkerBell SystemAoi Yuris
|
||||
|
@ -10,7 +10,7 @@ class ENGINE
|
||||
public:
|
||||
const char *enginename;
|
||||
bool is_engine_certain; // stop when match a engine ,even if not attached
|
||||
|
||||
JITTYPE jittype;
|
||||
enum class CHECK_BY
|
||||
{
|
||||
ALL_TRUE,
|
||||
@ -36,7 +36,7 @@ public:
|
||||
return enginename;
|
||||
return typeid(*this).name() + 6;
|
||||
}
|
||||
ENGINE() : enginename(nullptr), is_engine_certain(true), check_by(CHECK_BY::ALL_TRUE){};
|
||||
ENGINE() : enginename(nullptr), is_engine_certain(true), check_by(CHECK_BY::ALL_TRUE), jittype(JITTYPE::PC) {};
|
||||
bool check_function();
|
||||
};
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
#include "mono.h"
|
||||
#include "mono/monocommon.hpp"
|
||||
|
||||
bool monobdwgc()
|
||||
{
|
||||
|
||||
HMODULE module = GetModuleHandleW(L"mono-2.0-bdwgc.dll");
|
||||
if (module == 0)
|
||||
return false;
|
||||
auto [minAddress, maxAddress] = Util::QueryModuleLimits(module);
|
||||
BYTE bytes[] = {
|
||||
0x3D, 0x00, 0x00, 0x01, 0x00,
|
||||
0x73, XX,
|
||||
0xb8, 0x03, 0x00, 0x00, 0x00,
|
||||
0xEB, XX};
|
||||
auto addrs = Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, minAddress, maxAddress);
|
||||
auto succ = false;
|
||||
for (auto addr : addrs)
|
||||
{
|
||||
ConsoleOutput("monobdwgcdll %p", addr);
|
||||
HookParam hp;
|
||||
hp.address = (DWORD)addr;
|
||||
hp.offset = regoffset(eax);
|
||||
hp.type = CODEC_UTF16 | NO_CONTEXT;
|
||||
succ |= NewHook(hp, "monobdwgcdll");
|
||||
}
|
||||
return succ;
|
||||
}
|
||||
bool monodll()
|
||||
{
|
||||
|
||||
HMODULE module = GetModuleHandleW(L"mono.dll");
|
||||
if (module == 0)
|
||||
return false;
|
||||
auto [minAddress, maxAddress] = Util::QueryModuleLimits(module);
|
||||
BYTE bytes[] = {
|
||||
0x81, 0xFB, XX4,
|
||||
0x73};
|
||||
auto addrs = Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, minAddress, maxAddress);
|
||||
auto succ = false;
|
||||
for (auto addr : addrs)
|
||||
{
|
||||
ConsoleOutput("monodll %p", addr);
|
||||
HookParam hp;
|
||||
hp.address = (DWORD)addr;
|
||||
hp.offset = regoffset(ebx);
|
||||
hp.type = CODEC_UTF16 | NO_CONTEXT;
|
||||
succ |= NewHook(hp, "monodll");
|
||||
}
|
||||
return succ;
|
||||
}
|
||||
|
||||
bool mono::attach_function_()
|
||||
{
|
||||
|
||||
bool common = monocommon::hook_mono_il2cpp();
|
||||
return common;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
|
||||
|
||||
class mono : public ENGINE
|
||||
{
|
||||
public:
|
||||
mono()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::CUSTOM;
|
||||
check_by_target = [this]()
|
||||
{ return attach_function_(); };
|
||||
};
|
||||
bool attach_function_();
|
||||
bool attach_function() { return true; }
|
||||
};
|
@ -241,9 +241,6 @@ bool rpcs3::attach_function()
|
||||
if (DoJitPtr == 0)
|
||||
return false;
|
||||
unsafeinithooks();
|
||||
spDefault.isjithook = true;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1;
|
||||
HookParam hp;
|
||||
hp.address = DoJitPtr;
|
||||
hp.text_fun = [](hook_context *context, HookParam *hp, TextBuffer *buffer, uintptr_t *split)
|
||||
|
@ -5,7 +5,7 @@ class rpcs3 : public ENGINE
|
||||
public:
|
||||
rpcs3()
|
||||
{
|
||||
|
||||
jittype = JITTYPE::RPCS3;
|
||||
check_by = CHECK_BY::FILE;
|
||||
is_engine_certain = false;
|
||||
check_by_target = L"rpcs3.exe";
|
||||
|
@ -91,9 +91,6 @@ bool vita3k::attach_function()
|
||||
if (DoJitPtr == 0)
|
||||
return false;
|
||||
trygetgameinwindowtitle();
|
||||
spDefault.isjithook = true;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1;
|
||||
HookParam hp;
|
||||
hp.address = DoJitPtr;
|
||||
hp.text_fun = [](hook_context *context, HookParam *hp, TextBuffer *buffer, uintptr_t *split)
|
||||
|
@ -5,7 +5,7 @@ class vita3k : public ENGINE
|
||||
public:
|
||||
vita3k()
|
||||
{
|
||||
|
||||
jittype = JITTYPE::VITA3K;
|
||||
check_by = CHECK_BY::FILE;
|
||||
is_engine_certain = false;
|
||||
check_by_target = L"Vita3K.exe";
|
||||
|
@ -175,9 +175,6 @@ bool yuzu::attach_function()
|
||||
return false;
|
||||
trygetgameinwindowtitle();
|
||||
Hook_Network_RoomMember_SendGameInfo();
|
||||
spDefault.isjithook = true;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1;
|
||||
HookParam hp;
|
||||
hp.address = DoJitPtr;
|
||||
hp.text_fun = [](hook_context *context, HookParam *hp, TextBuffer *buffer, uintptr_t *split)
|
||||
|
@ -5,7 +5,7 @@ class yuzu : public ENGINE
|
||||
public:
|
||||
yuzu()
|
||||
{
|
||||
|
||||
jittype = JITTYPE::YUZU;
|
||||
is_engine_certain = false;
|
||||
check_by = CHECK_BY::CUSTOM;
|
||||
check_by_target = []()
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "engine32/V8.h"
|
||||
#include "engine32/cef.h"
|
||||
#include "engine32/KISS.h"
|
||||
#include "engine32/mono.h"
|
||||
#include "engine32/Tarte.h"
|
||||
#include "engine32/sakanagl.h"
|
||||
#include "engine32/H_do_C.h"
|
||||
@ -187,6 +186,7 @@
|
||||
#include "engine32/e_Erekiteru.h"
|
||||
#include "engine32/GuruGuruSMF4.h"
|
||||
#include "NoEngine.h"
|
||||
#include "engines/mono/mono.h"
|
||||
#include "engines/lua/lua51.h"
|
||||
#include "engines/python/Renpy.h"
|
||||
#include "engines/ppsspp/ppsspp.h"
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "engine64/Godot.h"
|
||||
#include "engine64/V8.h"
|
||||
#include "engine64/mono.h"
|
||||
#include "engine64/AGES7.h"
|
||||
#include "engine64/Artemis.h"
|
||||
#include "engine64/KiriKiri.h"
|
||||
@ -20,6 +19,7 @@
|
||||
#include "engine64/vita3k.h"
|
||||
#include "engine64/rpcs3.h"
|
||||
#include "engine64/MKXPZ.h"
|
||||
#include "engines/mono/mono.h"
|
||||
#include "engines/lua/lua51.h"
|
||||
#include "engines/python/Renpy.h"
|
||||
#include "engines/ppsspp/ppsspp.h"
|
||||
|
@ -86,14 +86,18 @@ bool checkengine()
|
||||
bool matched = safematch(m);
|
||||
bool attached = matched && safeattach(m);
|
||||
|
||||
//ConsoleOutput("Progress %d/%d, checked engine %s, %s",current,engines.size(),m->getenginename(),infomations[matched+attached]);
|
||||
//ConsoleOutput("Progress %d/%d, %s",current,engines.size(),infomations[matched+attached]);
|
||||
// ConsoleOutput("Progress %d/%d, checked engine %s, %s",current,engines.size(),m->getenginename(),infomations[matched+attached]);
|
||||
// ConsoleOutput("Progress %d/%d, %s",current,engines.size(),infomations[matched+attached]);
|
||||
if (matched == false)
|
||||
continue;
|
||||
ConsoleOutput(TR[MatchedEngine], m->getenginename());
|
||||
if (m->is_engine_certain)
|
||||
{
|
||||
ConsoleOutput(TR[ConfirmStop], m->getenginename());
|
||||
jittypedefault = m->jittype;
|
||||
spDefault.isjithook = true;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1;
|
||||
return attached;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
add_library(commonengine mono/impl_mono.cpp mono/monoil2cpp.cpp mono/impl_il2cpp.cpp ppsspp/ppsspp.cpp mages/mages.cpp v8/v8.cpp v8/httpserver.cpp python/python2.cpp python/python3.cpp python/python.cpp pchooks/pchooks.cpp lua/lua51.cpp)
|
||||
add_library(commonengine mono/impl_mono.cpp mono/monoil2cpp.cpp mono/mono.cpp mono/impl_il2cpp.cpp ppsspp/ppsspp.cpp mages/mages.cpp v8/v8.cpp v8/httpserver.cpp python/python2.cpp python/python3.cpp python/python.cpp pchooks/pchooks.cpp lua/lua51.cpp)
|
||||
target_precompile_headers(commonengine REUSE_FROM pchhook)
|
||||
|
||||
|
@ -369,7 +369,9 @@ struct Il2CppObject
|
||||
};
|
||||
void *monitor;
|
||||
};
|
||||
|
||||
struct Il2CppDomain;
|
||||
struct Il2CppAssembly;
|
||||
struct Il2CppImage;
|
||||
// not real Il2CppString class
|
||||
struct Il2CppString
|
||||
{
|
||||
@ -519,12 +521,13 @@ struct Il2CppReflectionType
|
||||
const Il2CppType *type;
|
||||
};
|
||||
|
||||
inline void **(*il2cpp_domain_get_assemblies)(void *domain, std::size_t *size);
|
||||
inline Il2CppClass *(*il2cpp_class_from_name)(void *image, const char *namespaze, const char *name);
|
||||
inline MethodInfo *(*il2cpp_class_get_methods)(Il2CppClass *klass, void **iter);
|
||||
inline MethodInfo *(*il2cpp_class_get_method_from_name)(Il2CppClass *klass, const char *name, int argsCount);
|
||||
inline Il2CppAssembly **(*il2cpp_domain_get_assemblies)(const Il2CppDomain *domain, std::size_t *size);
|
||||
inline const Il2CppClass *(*il2cpp_class_from_name)(const Il2CppImage *image, const char *namespaze, const char *name);
|
||||
inline MethodInfo *(*il2cpp_class_get_methods)(const Il2CppClass *klass, void **iter);
|
||||
inline const MethodInfo *(*il2cpp_class_get_method_from_name)(const Il2CppClass *klass, const char *name, int argsCount);
|
||||
inline MethodInfo *(*il2cpp_method_get_from_reflection)(Il2CppObject *ref);
|
||||
inline const Il2CppType *(*il2cpp_method_get_param)(const MethodInfo *method, uint32_t index);
|
||||
inline char* (*il2cpp_type_get_name)(const Il2CppType *type);
|
||||
inline Il2CppObject *(*il2cpp_object_new)(Il2CppClass *klass);
|
||||
inline void (*il2cpp_add_internal_call)(const char *name, uintptr_t pointer);
|
||||
inline Il2CppArraySize *(*il2cpp_array_new)(Il2CppClass *klass, uintptr_t count);
|
||||
@ -537,14 +540,12 @@ inline void (*il2cpp_field_static_get_value)(FieldInfo *field, void *value);
|
||||
inline void (*il2cpp_field_static_set_value)(FieldInfo *field, void *value);
|
||||
inline const Il2CppType *(*il2cpp_field_get_type)(FieldInfo *field);
|
||||
inline Il2CppObject *(*il2cpp_type_get_object)(const Il2CppType *type);
|
||||
inline const char *(*il2cpp_image_get_name)(void *image);
|
||||
inline size_t (*il2cpp_image_get_class_count)(void *image);
|
||||
inline const Il2CppClass *(*il2cpp_image_get_class)(void *image, size_t index);
|
||||
inline const char *(*il2cpp_image_get_name)(const Il2CppImage *image);
|
||||
inline bool (*il2cpp_type_is_byref)(const Il2CppType *type);
|
||||
inline uint32_t (*il2cpp_method_get_flags)(const MethodInfo *mehod, uint32_t *iflags);
|
||||
inline const Il2CppType *(*il2cpp_method_get_return_type)(const MethodInfo *method);
|
||||
inline Il2CppClass *(*il2cpp_class_from_type)(const Il2CppType *type);
|
||||
inline const char *(*il2cpp_class_get_name)(Il2CppClass *klass);
|
||||
inline const char *(*il2cpp_class_get_name)(const Il2CppClass *klass);
|
||||
inline const PropertyInfo *(*il2cpp_class_get_properties)(Il2CppClass *klass, void **iter);
|
||||
inline bool (*il2cpp_class_is_enum)(const Il2CppClass *klass);
|
||||
inline FieldInfo *(*il2cpp_class_get_fields)(Il2CppClass *klass, void **iter);
|
||||
@ -553,8 +554,8 @@ inline uint32_t (*il2cpp_method_get_param_count)(const MethodInfo *method);
|
||||
inline const char *(*il2cpp_method_get_param_name)(const MethodInfo *method, uint32_t index);
|
||||
inline Il2CppClass *(*il2cpp_class_get_parent)(Il2CppClass *klass);
|
||||
inline Il2CppClass *(*il2cpp_class_get_interfaces)(Il2CppClass *klass, void **iter);
|
||||
inline const char *(*il2cpp_class_get_namespace)(Il2CppClass *klass);
|
||||
inline void *(*il2cpp_class_get_image)(Il2CppClass *klass);
|
||||
inline const char *(*il2cpp_class_get_namespace)(const Il2CppClass *klass);
|
||||
inline const Il2CppImage *(*il2cpp_class_get_image)(const Il2CppClass *klass);
|
||||
inline int (*il2cpp_class_get_flags)(const Il2CppClass *klass);
|
||||
inline bool (*il2cpp_class_is_valuetype)(const Il2CppClass *klass);
|
||||
inline uint32_t (*il2cpp_property_get_flags)(PropertyInfo *prop);
|
||||
@ -572,9 +573,9 @@ inline Il2CppObject *(*il2cpp_value_box)(Il2CppClass *klass, void *data);
|
||||
inline void *(*il2cpp_object_unbox)(Il2CppObject *obj);
|
||||
inline Il2CppString *(*il2cpp_string_new_utf16)(const wchar_t *str, unsigned int len);
|
||||
inline Il2CppString *(*il2cpp_string_new)(const char *str);
|
||||
inline void *(*il2cpp_domain_get)();
|
||||
inline void *(*il2cpp_domain_assembly_open)(void *domain, const char *name);
|
||||
inline void *(*il2cpp_assembly_get_image)(void *assembly);
|
||||
inline Il2CppDomain *(*il2cpp_domain_get)();
|
||||
inline Il2CppAssembly *(*il2cpp_domain_assembly_open)(Il2CppDomain *domain, const char *name);
|
||||
inline const Il2CppImage *(*il2cpp_assembly_get_image)(const Il2CppAssembly *assembly);
|
||||
inline void *(*il2cpp_resolve_icall)(const char *name);
|
||||
inline void *(*il2cpp_thread_attach)(void *domain);
|
||||
inline void (*il2cpp_thread_detach)(void *thread);
|
||||
@ -588,12 +589,15 @@ inline void (*il2cpp_runtime_class_init)(void *klass);
|
||||
inline void *(*il2cpp_runtime_invoke)(MethodInfo *method, void *obj, void **params, Il2CppObject **exc);
|
||||
inline Il2CppChar *(*il2cpp_string_chars)(Il2CppString *str);
|
||||
inline int (*il2cpp_string_length)(Il2CppString *str);
|
||||
|
||||
inline const Il2CppClass *(*il2cpp_image_get_class)(const Il2CppImage *image, size_t index);
|
||||
inline size_t (*il2cpp_image_get_class_count)(const Il2CppImage *image);
|
||||
namespace il2cppfunctions
|
||||
{
|
||||
inline HMODULE game_dll;
|
||||
void init(HMODULE dll);
|
||||
uintptr_t get_method_pointer(const char *assemblyName, const char *namespaze,
|
||||
const char *klassName, const char *name, int argsCount, bool strict);
|
||||
std::optional<std::wstring_view> get_string(void *);
|
||||
void *create_string(std::wstring_view ws);
|
||||
il2cpploopinfo loop_all_methods(bool show);
|
||||
}
|
@ -415,7 +415,6 @@ inline MonoTableInfo *(*mono_image_get_table_info)(MonoImage *, int);
|
||||
inline int (*mono_table_info_get_rows)(MonoTableInfo *);
|
||||
inline gunichar2 *(*mono_string_chars)(MonoString *str);
|
||||
inline int (*mono_string_length)(MonoString *str);
|
||||
|
||||
namespace monofunctions
|
||||
{
|
||||
void init(HMODULE dll);
|
||||
@ -424,4 +423,5 @@ namespace monofunctions
|
||||
|
||||
std::optional<std::wstring_view> get_string(void *);
|
||||
void *create_string(std::wstring_view ws);
|
||||
monoloopinfo loop_all_methods(bool show);
|
||||
}
|
@ -2,16 +2,15 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
Il2CppClass *get_il2cppclass1(const char *assemblyName, const char *namespaze,
|
||||
const char *klassName, bool strict)
|
||||
const Il2CppClass *get_il2cppclass1(const char *assemblyName, const char *namespaze,
|
||||
const char *klassName, bool strict)
|
||||
{
|
||||
auto il2cpp_domain = (SafeFptr(il2cpp_domain_get))();
|
||||
if (!il2cpp_domain)
|
||||
return NULL;
|
||||
void *assembly = 0;
|
||||
do
|
||||
{
|
||||
assembly = (SafeFptr(il2cpp_domain_assembly_open))(il2cpp_domain, assemblyName);
|
||||
auto assembly = (SafeFptr(il2cpp_domain_assembly_open))(il2cpp_domain, assemblyName);
|
||||
if (!assembly)
|
||||
break;
|
||||
auto image = (SafeFptr(il2cpp_assembly_get_image))(assembly);
|
||||
@ -44,13 +43,39 @@ namespace
|
||||
auto st = (std::vector<Il2CppClass *> *)userData;
|
||||
st->push_back(klass);
|
||||
}
|
||||
std::vector<Il2CppClass *> get_il2cppclass2(const char *namespaze,
|
||||
const char *klassName)
|
||||
std::vector<const Il2CppClass *> loopclass()
|
||||
{
|
||||
std::vector<Il2CppClass *> maybes;
|
||||
std::vector<Il2CppClass *> klasses;
|
||||
std::vector<const Il2CppClass *> klasses;
|
||||
(SafeFptr(il2cpp_class_for_each))(foreach_func, &klasses);
|
||||
if (klasses.size())
|
||||
return klasses;
|
||||
|
||||
auto domain = (SafeFptr(il2cpp_domain_get))();
|
||||
if (!domain)
|
||||
return klasses;
|
||||
size_t assemblyCount = 0;
|
||||
Il2CppAssembly **assemblies = SafeFptr(il2cpp_domain_get_assemblies)(domain, &assemblyCount);
|
||||
for (size_t i = 0; i < assemblyCount; i++)
|
||||
{
|
||||
Il2CppAssembly *assembly = assemblies[i];
|
||||
auto image = SafeFptr(il2cpp_assembly_get_image)(assembly);
|
||||
if (!image)
|
||||
continue;
|
||||
auto classcount = SafeFptr(il2cpp_image_get_class_count)(image);
|
||||
for (auto ci = 0; ci < classcount; ci++)
|
||||
{
|
||||
auto klass = SafeFptr(il2cpp_image_get_class)(image, ci);
|
||||
if (!klass)
|
||||
continue;
|
||||
klasses.push_back(klass);
|
||||
}
|
||||
}
|
||||
return klasses;
|
||||
}
|
||||
std::vector<const Il2CppClass *> get_il2cppclass2(const char *namespaze, const char *klassName)
|
||||
{
|
||||
std::vector<const Il2CppClass *> maybes;
|
||||
auto klasses = loopclass();
|
||||
for (auto klass : klasses)
|
||||
{
|
||||
auto classname = (SafeFptr(il2cpp_class_get_name))(klass);
|
||||
@ -86,29 +111,116 @@ namespace
|
||||
(SafeFptr(il2cpp_thread_detach))(thread);
|
||||
}
|
||||
};
|
||||
void tryprintimage(Il2CppClass *klass)
|
||||
std::optional<std::string> getclassinfo(const Il2CppClass *klass)
|
||||
{
|
||||
auto image = (SafeFptr(il2cpp_class_get_image))(klass);
|
||||
if (!image)
|
||||
return;
|
||||
return {};
|
||||
auto imagen = (SafeFptr(il2cpp_image_get_name))(image);
|
||||
auto names = (SafeFptr(il2cpp_class_get_namespace))(klass);
|
||||
if (imagen && names)
|
||||
ConsoleOutput("%s:%s", imagen, names);
|
||||
auto classname = (SafeFptr(il2cpp_class_get_name))(klass);
|
||||
if (imagen && names && classname)
|
||||
{
|
||||
std::string _ = imagen;
|
||||
_ += ":";
|
||||
_ += names;
|
||||
_ += ":";
|
||||
_ += classname;
|
||||
return _;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
uintptr_t getmethodofklass(Il2CppClass *klass, const char *name, int argsCount)
|
||||
std::string getmethodinfo(const MethodInfo *method)
|
||||
{
|
||||
const char *methodName = SafeFptr(il2cpp_method_get_name)(method);
|
||||
std::stringstream info;
|
||||
if (method->methodPointer)
|
||||
info << std::hex << (method->methodPointer - (uintptr_t)il2cppfunctions::game_dll);
|
||||
else
|
||||
info << "??";
|
||||
|
||||
if (methodName) // il2cpp似乎没办法从method查询name
|
||||
info << " " << methodName;
|
||||
info << " (";
|
||||
for (uint32_t i = 0; i < SafeFptr(il2cpp_method_get_param_count)(method); i++)
|
||||
{
|
||||
if (i != 0)
|
||||
info << ", ";
|
||||
if (auto rt = SafeFptr(il2cpp_method_get_param)(method, i))
|
||||
if (auto tp = SafeFptr(il2cpp_type_get_name)(rt))
|
||||
info << tp;
|
||||
}
|
||||
info << ")";
|
||||
if (auto rt = SafeFptr(il2cpp_method_get_return_type)(method))
|
||||
if (auto returntype = SafeFptr(il2cpp_type_get_name)(rt))
|
||||
{
|
||||
info << " -> " << returntype;
|
||||
}
|
||||
return info.str();
|
||||
}
|
||||
uintptr_t getmethodofklass(const Il2CppClass *klass, const char *name, int argsCount)
|
||||
{
|
||||
if (!klass)
|
||||
return NULL;
|
||||
auto ret = (SafeFptr(il2cpp_class_get_method_from_name))(klass, name, argsCount);
|
||||
|
||||
if (!ret)
|
||||
return NULL;
|
||||
tryprintimage(klass);
|
||||
if (auto s = getclassinfo(klass))
|
||||
{
|
||||
ConsoleOutput(s.value().c_str());
|
||||
ConsoleOutput(getmethodinfo(ret).c_str());
|
||||
}
|
||||
return ret->methodPointer;
|
||||
}
|
||||
}
|
||||
il2cpploopinfo il2cppfunctions::loop_all_methods(bool show)
|
||||
{
|
||||
auto thread = AutoThread();
|
||||
if (!thread.thread)
|
||||
return {};
|
||||
auto klasses = loopclass();
|
||||
il2cpploopinfo hps;
|
||||
for (auto klass : klasses)
|
||||
{
|
||||
auto s = getclassinfo(klass);
|
||||
if (!s)
|
||||
continue;
|
||||
if (show)
|
||||
ConsoleOutput(s.value().c_str());
|
||||
|
||||
void *iter = nullptr;
|
||||
while (auto method = SafeFptr(il2cpp_class_get_methods)(klass, &iter))
|
||||
{
|
||||
if (show)
|
||||
ConsoleOutput(getmethodinfo(method).c_str());
|
||||
else
|
||||
{
|
||||
if (method->methodPointer)
|
||||
{
|
||||
for (uint32_t i = 0; i < SafeFptr(il2cpp_method_get_param_count)(method); i++)
|
||||
{
|
||||
if (auto rt = SafeFptr(il2cpp_method_get_param)(method, i))
|
||||
if (auto tp = SafeFptr(il2cpp_type_get_name)(rt))
|
||||
if (strcmp(tp, "System.String") == 0)
|
||||
{
|
||||
hps.push_back({i + 1, method->methodPointer});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (show && klasses.size())
|
||||
return {{0, 0}};
|
||||
return hps;
|
||||
}
|
||||
void il2cppfunctions::init(HMODULE game_module)
|
||||
{
|
||||
game_dll = game_module;
|
||||
RESOLVE_IMPORT(il2cpp_type_get_name);
|
||||
RESOLVE_IMPORT(il2cpp_method_get_param_count);
|
||||
RESOLVE_IMPORT(il2cpp_string_new_utf16);
|
||||
RESOLVE_IMPORT(il2cpp_string_chars);
|
||||
RESOLVE_IMPORT(il2cpp_string_length);
|
||||
@ -119,6 +231,8 @@ void il2cppfunctions::init(HMODULE game_module)
|
||||
RESOLVE_IMPORT(il2cpp_domain_get);
|
||||
RESOLVE_IMPORT(il2cpp_domain_assembly_open);
|
||||
RESOLVE_IMPORT(il2cpp_assembly_get_image);
|
||||
RESOLVE_IMPORT(il2cpp_image_get_class);
|
||||
RESOLVE_IMPORT(il2cpp_image_get_class_count);
|
||||
RESOLVE_IMPORT(il2cpp_class_from_name);
|
||||
RESOLVE_IMPORT(il2cpp_class_get_methods);
|
||||
RESOLVE_IMPORT(il2cpp_class_get_method_from_name);
|
||||
@ -142,6 +256,7 @@ void il2cppfunctions::init(HMODULE game_module)
|
||||
RESOLVE_IMPORT(il2cpp_runtime_invoke);
|
||||
RESOLVE_IMPORT(il2cpp_class_get_name);
|
||||
RESOLVE_IMPORT(il2cpp_class_get_namespace);
|
||||
RESOLVE_IMPORT(il2cpp_method_get_return_type);
|
||||
RESOLVE_IMPORT(il2cpp_domain_get_assemblies);
|
||||
}
|
||||
uintptr_t il2cppfunctions::get_method_pointer(const char *assemblyName, const char *namespaze,
|
||||
|
@ -37,9 +37,8 @@ namespace
|
||||
return NULL;
|
||||
return maybe;
|
||||
}
|
||||
std::vector<MonoClass *> mono_findklassby_class(std::vector<MonoImage *> &images, const char *_namespace, const char *_class)
|
||||
std::vector<MonoClass *> loopclass(std::vector<MonoImage *> &images)
|
||||
{
|
||||
|
||||
std::vector<MonoClass *> maybes;
|
||||
for (auto image : images)
|
||||
{
|
||||
@ -54,32 +53,59 @@ namespace
|
||||
auto klass = (MonoClass *)(SafeFptr(mono_class_get))(image, MONO_TOKEN_TYPE_DEF | i + 1);
|
||||
if (!klass)
|
||||
continue;
|
||||
auto name = (SafeFptr(mono_class_get_name))(klass);
|
||||
if (!name)
|
||||
continue;
|
||||
if (strcmp(name, _class) != 0)
|
||||
continue;
|
||||
maybes.push_back(klass);
|
||||
auto namespacename = (SafeFptr(mono_class_get_namespace))(klass);
|
||||
if (!namespacename)
|
||||
continue;
|
||||
if (strlen(_namespace) && (strcmp(namespacename, _namespace) == 0))
|
||||
{
|
||||
return {klass};
|
||||
}
|
||||
}
|
||||
}
|
||||
return maybes;
|
||||
}
|
||||
void tryprintimage(MonoClass *klass)
|
||||
std::vector<MonoClass *> mono_findklassby_class(std::vector<MonoImage *> &images, const char *_namespace, const char *_class)
|
||||
{
|
||||
std::vector<MonoClass *> maybes;
|
||||
for (auto klass : loopclass(images))
|
||||
{
|
||||
auto name = (SafeFptr(mono_class_get_name))(klass);
|
||||
if (!name)
|
||||
continue;
|
||||
if (strcmp(name, _class) != 0)
|
||||
continue;
|
||||
maybes.push_back(klass);
|
||||
auto namespacename = (SafeFptr(mono_class_get_namespace))(klass);
|
||||
if (!namespacename)
|
||||
continue;
|
||||
if (strlen(_namespace) && (strcmp(namespacename, _namespace) == 0))
|
||||
{
|
||||
return {klass};
|
||||
}
|
||||
}
|
||||
return maybes;
|
||||
}
|
||||
std::optional<std::string> getclassinfo(MonoClass *klass)
|
||||
{
|
||||
auto image = (SafeFptr(mono_class_get_image))(klass);
|
||||
if (!image)
|
||||
return;
|
||||
return {};
|
||||
auto imagen = (SafeFptr(mono_image_get_name))(image);
|
||||
auto names = (SafeFptr(mono_class_get_namespace))(klass);
|
||||
if (imagen && names)
|
||||
ConsoleOutput("%s:%s", imagen, names);
|
||||
auto classname = (SafeFptr(mono_class_get_name))(klass);
|
||||
if (imagen && names && classname)
|
||||
{
|
||||
std::string _ = imagen;
|
||||
_ += ":";
|
||||
_ += names;
|
||||
_ += ":";
|
||||
_ += classname;
|
||||
return _;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
std::string getmethodinfo(MonoMethod *method)
|
||||
{
|
||||
const char *methodName = SafeFptr(mono_method_get_name)(method); // 谜之没有输出
|
||||
if (!methodName)
|
||||
methodName = SafeFptr(mono_method_full_name)(method, true);
|
||||
if (methodName)
|
||||
return methodName;
|
||||
return "";
|
||||
}
|
||||
uintptr_t getmethodofklass(MonoClass *klass, const char *name, int argsCount)
|
||||
{
|
||||
@ -88,7 +114,11 @@ namespace
|
||||
auto MonoClassMethod = (SafeFptr(mono_class_get_method_from_name))(klass, name, argsCount);
|
||||
if (!MonoClassMethod)
|
||||
return NULL;
|
||||
tryprintimage(klass);
|
||||
if (auto s = getclassinfo(klass))
|
||||
{
|
||||
ConsoleOutput(s.value().c_str());
|
||||
ConsoleOutput(getmethodinfo(MonoClassMethod).c_str());
|
||||
}
|
||||
return (uintptr_t)(SafeFptr(mono_compile_method))(MonoClassMethod);
|
||||
}
|
||||
struct AutoThread
|
||||
@ -108,9 +138,102 @@ namespace
|
||||
(SafeFptr(mono_thread_detach))(thread);
|
||||
}
|
||||
};
|
||||
void __safe_getxx(monoloopinfo *hps, MonoMethod *method, MonoClass *klass)
|
||||
{
|
||||
if (auto methodName = SafeFptr(mono_method_full_name)(method, true))
|
||||
{
|
||||
if (auto sig = SafeFptr(mono_method_signature)(method))
|
||||
{
|
||||
if (auto cnt = SafeFptr(mono_signature_get_param_count)(sig))
|
||||
{
|
||||
gpointer itertype = nullptr;
|
||||
while (auto type = SafeFptr(mono_signature_get_params)(sig, &itertype))
|
||||
{
|
||||
if (auto tp = SafeFptr(mono_type_get_name)(type))
|
||||
{
|
||||
if (strcmp(tp, "System.String") == 0)
|
||||
{
|
||||
if (auto ptr = (uintptr_t)(SafeFptr(mono_compile_method))(method))
|
||||
{
|
||||
std::string meth = methodName;
|
||||
if (meth.find(" (") != meth.npos)
|
||||
{
|
||||
meth = meth.substr(0, meth.find(" ("));
|
||||
auto _ = strSplit(meth, ":");
|
||||
if (_.size() >= 2)
|
||||
{
|
||||
auto m = _[_.size() - 1];
|
||||
|
||||
auto image = (SafeFptr(mono_class_get_image))(klass);
|
||||
auto imagen = (SafeFptr(mono_image_get_name))(image);
|
||||
auto names = (SafeFptr(mono_class_get_namespace))(klass);
|
||||
auto classname = (SafeFptr(mono_class_get_name))(klass);
|
||||
std::string s;
|
||||
s = imagen;
|
||||
s += ":";
|
||||
s += names;
|
||||
s += ":";
|
||||
s += classname;
|
||||
s += ":";
|
||||
s += m;
|
||||
s += ":";
|
||||
s += std::to_string(cnt);
|
||||
hps->push_back({ptr, s});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void safe_getxx(monoloopinfo *hps, MonoMethod *method, MonoClass *klass)
|
||||
{
|
||||
__try
|
||||
{
|
||||
__safe_getxx(hps, method, klass);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
monoloopinfo monofunctions::loop_all_methods(bool show)
|
||||
{
|
||||
auto thread = AutoThread();
|
||||
if (!thread.thread)
|
||||
return {};
|
||||
monoloopinfo hps;
|
||||
auto klasses = loopclass(mono_loop_images());
|
||||
for (auto klass : klasses)
|
||||
{
|
||||
auto s = getclassinfo(klass);
|
||||
if (!s)
|
||||
continue;
|
||||
if (show)
|
||||
ConsoleOutput(s.value().c_str());
|
||||
gpointer iter = nullptr;
|
||||
while (auto method = SafeFptr(mono_class_get_methods)(klass, &iter))
|
||||
{
|
||||
if (show)
|
||||
ConsoleOutput(getmethodinfo(method).c_str());
|
||||
else
|
||||
{
|
||||
safe_getxx(&hps, method, klass);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (show && klasses.size())
|
||||
return {{0, ""}};
|
||||
return hps;
|
||||
}
|
||||
void monofunctions::init(HMODULE game_module)
|
||||
{
|
||||
RESOLVE_IMPORT(mono_class_get_methods);
|
||||
RESOLVE_IMPORT(mono_string_chars);
|
||||
RESOLVE_IMPORT(mono_string_length);
|
||||
RESOLVE_IMPORT(mono_table_info_get_rows);
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "mono.h"
|
||||
#include "mono/monocommon.hpp"
|
||||
|
||||
#if 0
|
||||
namespace
|
||||
{
|
||||
bool monobdwgc()
|
||||
@ -81,8 +81,59 @@ namespace
|
||||
return suc;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
bool monobdwgc()
|
||||
{
|
||||
|
||||
HMODULE module = GetModuleHandleW(L"mono-2.0-bdwgc.dll");
|
||||
if (module == 0)
|
||||
return false;
|
||||
auto [minAddress, maxAddress] = Util::QueryModuleLimits(module);
|
||||
BYTE bytes[] = {
|
||||
0x3D, 0x00, 0x00, 0x01, 0x00,
|
||||
0x73, XX,
|
||||
0xb8, 0x03, 0x00, 0x00, 0x00,
|
||||
0xEB, XX};
|
||||
auto addrs = Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, minAddress, maxAddress);
|
||||
auto succ = false;
|
||||
for (auto addr : addrs)
|
||||
{
|
||||
ConsoleOutput("monobdwgcdll %p", addr);
|
||||
HookParam hp;
|
||||
hp.address = (DWORD)addr;
|
||||
hp.offset = regoffset(eax);
|
||||
hp.type = CODEC_UTF16 | NO_CONTEXT;
|
||||
succ |= NewHook(hp, "monobdwgcdll");
|
||||
}
|
||||
return succ;
|
||||
}
|
||||
bool monodll()
|
||||
{
|
||||
|
||||
HMODULE module = GetModuleHandleW(L"mono.dll");
|
||||
if (module == 0)
|
||||
return false;
|
||||
auto [minAddress, maxAddress] = Util::QueryModuleLimits(module);
|
||||
BYTE bytes[] = {
|
||||
0x81, 0xFB, XX4,
|
||||
0x73};
|
||||
auto addrs = Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, minAddress, maxAddress);
|
||||
auto succ = false;
|
||||
for (auto addr : addrs)
|
||||
{
|
||||
ConsoleOutput("monodll %p", addr);
|
||||
HookParam hp;
|
||||
hp.address = (DWORD)addr;
|
||||
hp.offset = regoffset(ebx);
|
||||
hp.type = CODEC_UTF16 | NO_CONTEXT;
|
||||
succ |= NewHook(hp, "monodll");
|
||||
}
|
||||
return succ;
|
||||
}
|
||||
|
||||
#endif
|
||||
bool mono::attach_function_()
|
||||
{
|
||||
bool common = monocommon::hook_mono_il2cpp();
|
||||
return common;
|
||||
return monocommon::hook_mono_il2cpp();
|
||||
}
|
@ -5,7 +5,7 @@ class mono : public ENGINE
|
||||
public:
|
||||
mono()
|
||||
{
|
||||
|
||||
jittype = JITTYPE::UNITY;
|
||||
check_by = CHECK_BY::CUSTOM;
|
||||
check_by_target = [this]()
|
||||
{ return attach_function_(); };
|
@ -24,7 +24,8 @@ namespace
|
||||
*/
|
||||
void SpecialHookMonoString(hook_context *context, HookParam *hp, TextBuffer *buffer, uintptr_t *split)
|
||||
{
|
||||
commonsolvemonostring(context->argof(1), buffer);
|
||||
if (auto sw = commonsolvemonostring(context->argof(1)))
|
||||
buffer->from(sw.value());
|
||||
|
||||
#ifndef _WIN64
|
||||
auto s = context->ecx;
|
||||
@ -99,7 +100,7 @@ namespace monocommon
|
||||
{
|
||||
hp.type = USING_STRING | CODEC_UTF16 | FULL_STRING;
|
||||
if (!hp.text_fun)
|
||||
hp.type |= SPECIAL_JIT_STRING;
|
||||
hp.type |= CSHARP_STRING;
|
||||
if (hook.Embed)
|
||||
hp.type |= EMBED_ABLE;
|
||||
}
|
||||
@ -171,7 +172,9 @@ namespace monocommon
|
||||
succ |= NewHook_check(addr, hook);
|
||||
}
|
||||
if (succ)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ namespace
|
||||
return newstring;
|
||||
}
|
||||
}
|
||||
void commonsolvemonostring(uintptr_t arg, TextBuffer *buffer)
|
||||
std::optional<std::wstring_view> commonsolvemonostring(uintptr_t arg)
|
||||
{
|
||||
auto sw = il2cppfunctions::get_string((void *)arg);
|
||||
if (!sw)
|
||||
@ -32,10 +32,10 @@ void commonsolvemonostring(uintptr_t arg, TextBuffer *buffer)
|
||||
if (!sw)
|
||||
sw = readmonostring((void *)arg);
|
||||
if (!sw)
|
||||
return;
|
||||
return {};
|
||||
if (sw.value().size() > TEXT_BUFFER_SIZE)
|
||||
return;
|
||||
buffer->from(sw.value());
|
||||
return {};
|
||||
return sw;
|
||||
}
|
||||
|
||||
void unity_ui_string_embed_fun(uintptr_t &arg, TextBuffer buff)
|
||||
@ -55,4 +55,11 @@ uintptr_t tryfindmonoil2cpp(const char *_dll, const char *_namespace, const char
|
||||
if (addr)
|
||||
return addr;
|
||||
return monofunctions::get_method_pointer(_dll, _namespace, _class, _method, paramCoun, strict);
|
||||
}
|
||||
std::variant<monoloopinfo, il2cpploopinfo> loop_all_methods(bool show)
|
||||
{
|
||||
auto ms = il2cppfunctions::loop_all_methods(show);
|
||||
if (ms.size())
|
||||
return ms;
|
||||
return monofunctions::loop_all_methods(show);
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
#define RESOLVE_IMPORT(name) name = (decltype(name))(GetProcAddress(game_module, #name))
|
||||
#pragma once
|
||||
void commonsolvemonostring(uintptr_t arg, TextBuffer *buffer);
|
||||
std::optional<std::wstring_view> commonsolvemonostring(uintptr_t arg);
|
||||
void unity_ui_string_embed_fun(uintptr_t &arg, TextBuffer buff);
|
||||
|
||||
typedef std::vector<std::pair<int, uintptr_t>> il2cpploopinfo;
|
||||
typedef std::vector<std::pair<uintptr_t, std::string>> monoloopinfo;
|
||||
std::variant<monoloopinfo, il2cpploopinfo> loop_all_methods(bool show);
|
||||
uintptr_t tryfindmonoil2cpp(const char *_dll, const char *_namespace, const char *_class, const char *_method, int paramCoun, bool strict = false);
|
@ -549,9 +549,6 @@ namespace ppsspp
|
||||
return false;
|
||||
trygetgameinwindowtitle();
|
||||
Load_PSP_ISO_StringFromFormat();
|
||||
spDefault.isjithook = true;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1;
|
||||
HookParam hp;
|
||||
hp.address = DoJitPtr; // Jit::DoJit
|
||||
hp.user_value = (uintptr_t) new uintptr_t;
|
||||
|
@ -7,6 +7,7 @@ public:
|
||||
check_by = CHECK_BY::FILE;
|
||||
is_engine_certain = false;
|
||||
check_by_target = L"PPSSPP*.exe";
|
||||
jittype = JITTYPE::PPSSPP;
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
@ -14,13 +14,14 @@ namespace
|
||||
int offset = 0;
|
||||
JITTYPE jittype;
|
||||
char text[MAX_STRING_SIZE] = {};
|
||||
bool csstring;
|
||||
};
|
||||
std::unique_ptr<HookRecord[]> records;
|
||||
long recordsAvailable;
|
||||
uint64_t signatureCache[CACHE_SIZE] = {};
|
||||
long sumCache[CACHE_SIZE] = {};
|
||||
uintptr_t pageCache[CACHE_SIZE] = {};
|
||||
|
||||
std::unordered_map<uintptr_t, std::string> remapunityjit;
|
||||
#ifndef _WIN64
|
||||
BYTE trampoline[] =
|
||||
{
|
||||
@ -123,7 +124,7 @@ bool IsBadReadPtr(void *data)
|
||||
}
|
||||
return cacheEntry == BAD_PAGE;
|
||||
}
|
||||
void DoSend(int i, uintptr_t address, char *str, intptr_t padding, JITTYPE jittype = JITTYPE::PC, uint64_t em_addr = 0)
|
||||
void DoSend(int i, uintptr_t address, char *str, intptr_t padding, JITTYPE jittype = JITTYPE::PC, uint64_t em_addr = 0, bool csstring = false)
|
||||
{
|
||||
str += padding;
|
||||
if (IsBadReadPtr(str) || IsBadReadPtr(str + MAX_STRING_SIZE))
|
||||
@ -156,7 +157,13 @@ void DoSend(int i, uintptr_t address, char *str, intptr_t padding, JITTYPE jitty
|
||||
{
|
||||
records[n].jittype = jittype;
|
||||
records[n].padding = padding;
|
||||
if (jittype == JITTYPE::PC)
|
||||
records[n].csstring = csstring;
|
||||
if (csstring)
|
||||
{
|
||||
records[n].address = address;
|
||||
records[n].offset = i;
|
||||
}
|
||||
else if (jittype == JITTYPE::PC)
|
||||
{
|
||||
records[n].address = address;
|
||||
records[n].offset = i * sizeof(char *);
|
||||
@ -195,6 +202,24 @@ void Send(char **strs, uintptr_t address)
|
||||
DoSend(i, address, strs[i], sp.padding);
|
||||
}
|
||||
}
|
||||
template <JITTYPE t>
|
||||
void SendCSharpString(char **strs, uintptr_t address)
|
||||
{
|
||||
// it is unsafe to call ANY external functions from this, as they may have been hooked (if called the hook would call this function making an infinite loop)
|
||||
// the exceptions are compiler intrinsics like _InterlockedDecrement
|
||||
if (recordsAvailable <= 0)
|
||||
return;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
__try
|
||||
{
|
||||
DoSend(i, address, (char *)commonsolvemonostring(hook_context::fromBase((uintptr_t)strs)->argof(i)).value().data(), 0, t, 0, true);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
void SafeSendJitVeh(hook_context *context, uintptr_t address, uint64_t em_addr, JITTYPE jittype, intptr_t padding)
|
||||
{
|
||||
__try
|
||||
@ -289,8 +314,18 @@ void SearchForHooks_Return()
|
||||
hp.jittype = records[i].jittype;
|
||||
hp.padding = records[i].padding;
|
||||
hp.offset = records[i].offset;
|
||||
|
||||
if (records[i].jittype == JITTYPE::PC)
|
||||
if (records[i].csstring)
|
||||
{
|
||||
if (!records[i].address)
|
||||
continue;
|
||||
hp.type = CODEC_UTF16 | USING_STRING | CSHARP_STRING;
|
||||
hp.address = records[i].address;
|
||||
if (hp.jittype == JITTYPE::UNITY)
|
||||
{
|
||||
strncpy(hp.function, remapunityjit[hp.address].c_str(), sizeof(hp.function));
|
||||
}
|
||||
}
|
||||
else if (records[i].jittype == JITTYPE::PC)
|
||||
{
|
||||
if (!records[i].address)
|
||||
continue;
|
||||
@ -325,182 +360,235 @@ void initrecords()
|
||||
}
|
||||
while (!records && sp.maxRecords);
|
||||
}
|
||||
void inlinehookpipeline(std::vector<uintptr_t> &addresses)
|
||||
{
|
||||
auto trampolines = (decltype(trampoline) *)VirtualAlloc(NULL, sizeof(trampoline) * addresses.size(), MEM_COMMIT, PAGE_READWRITE);
|
||||
VirtualProtect(trampolines, addresses.size() * sizeof(trampoline), PAGE_EXECUTE_READWRITE, DUMMY);
|
||||
std::vector<uintptr_t> mherroridx;
|
||||
for (int i = 0; i < addresses.size(); ++i)
|
||||
{
|
||||
void *original;
|
||||
// 避免MH_RemoveHook时移除原本已有hook
|
||||
if (MH_CreateHook((void *)addresses[i], trampolines[i], &original) != MH_OK)
|
||||
{
|
||||
mherroridx.push_back(i);
|
||||
}
|
||||
MH_QueueEnableHook((void *)addresses[i]);
|
||||
memcpy(trampolines[i], trampoline, sizeof(trampoline));
|
||||
*(uintptr_t *)(trampolines[i] + addr_offset) = addresses[i];
|
||||
*(void **)(trampolines[i] + original_offset) = original;
|
||||
if (i % 2500 == 0)
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZING], 1 + 98. * i / addresses.size());
|
||||
}
|
||||
// 避免MH_RemoveHook时移除原本已有hook
|
||||
for (int i = 0; i < mherroridx.size(); i++)
|
||||
{
|
||||
auto reverseidx = mherroridx[mherroridx.size() - 1 - i];
|
||||
addresses.erase(addresses.begin() + reverseidx);
|
||||
}
|
||||
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZED], addresses.size());
|
||||
MH_ApplyQueued();
|
||||
ConsoleOutput(TR[HOOK_SEARCH_STARTING]);
|
||||
ConsoleOutput(TR[MAKE_GAME_PROCESS_TEXT], sp.searchTime / 1000);
|
||||
Sleep(sp.searchTime);
|
||||
for (auto addr : addresses)
|
||||
MH_QueueDisableHook((void *)addr);
|
||||
MH_ApplyQueued();
|
||||
Sleep(1000);
|
||||
for (auto addr : addresses)
|
||||
MH_RemoveHook((void *)addr);
|
||||
VirtualFree(trampolines, 0, MEM_RELEASE);
|
||||
}
|
||||
void _SearchForHooks(SearchParam spUser)
|
||||
{
|
||||
static std::mutex m;
|
||||
std::scoped_lock lock(m);
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZING], 0.);
|
||||
|
||||
sp = spUser.length == 0 ? spDefault : spUser;
|
||||
sp.codepage = spUser.codepage;
|
||||
initrecords();
|
||||
if ((!sp.isjithook) || (jittypedefault == JITTYPE::PC))
|
||||
{
|
||||
*(void **)(trampoline + send_offset) = Send;
|
||||
std::vector<uintptr_t> addresses;
|
||||
if (*sp.boundaryModule)
|
||||
{
|
||||
auto [minaddr, maxaddr] = Util::QueryModuleLimits(GetModuleHandleW(sp.boundaryModule));
|
||||
if (sp.address_method == 0)
|
||||
{
|
||||
sp.minAddress = min(max(minaddr, sp.minAddress), maxaddr);
|
||||
sp.maxAddress = max(min(maxaddr, sp.maxAddress), minaddr);
|
||||
}
|
||||
else if (sp.address_method == 1)
|
||||
{
|
||||
auto maxoff = maxaddr - minaddr;
|
||||
sp.minAddress = minaddr + min(sp.minAddress, maxoff);
|
||||
sp.maxAddress = minaddr + min(sp.maxAddress, maxoff);
|
||||
}
|
||||
// std::tie(sp.minAddress, sp.maxAddress) = Util::QueryModuleLimits(GetModuleHandleW(sp.boundaryModule));
|
||||
}
|
||||
if (*sp.exportModule)
|
||||
addresses = GetFunctions((uintptr_t)GetModuleHandleW(sp.exportModule));
|
||||
if (*sp.boundaryModule)
|
||||
{
|
||||
auto _addresses = GetFunctions((uintptr_t)GetModuleHandleW(sp.boundaryModule));
|
||||
mergevector(addresses, _addresses);
|
||||
}
|
||||
std::vector<uintptr_t> addresses1;
|
||||
if (sp.search_method == 0)
|
||||
{
|
||||
for (auto &addr : addresses1 = Util::SearchMemory(sp.pattern, sp.length, PAGE_EXECUTE, sp.minAddress, sp.maxAddress))
|
||||
addr += sp.offset;
|
||||
}
|
||||
else if (sp.search_method == 1)
|
||||
{
|
||||
auto checklength = 3;
|
||||
auto checker = [checklength](DWORD k)
|
||||
{
|
||||
if (k == 0xcccccccc || k == 0x90909090 || k == 0xccccccc3 || k == 0x909090c3)
|
||||
return true;
|
||||
DWORD t = k & 0xff0000ff;
|
||||
if (t == 0xcc0000c2 || t == 0x900000c2)
|
||||
return true;
|
||||
if (checklength == 4)
|
||||
return false;
|
||||
k >>= 8;
|
||||
if (k == 0xccccc3 || k == 0x9090c3)
|
||||
return true;
|
||||
if (checklength == 3)
|
||||
return false;
|
||||
// t = k & 0xff;
|
||||
// if (t == 0xc2)
|
||||
// return true;
|
||||
k >>= 8;
|
||||
if (k == 0xccc3 || k == 0x90c3)
|
||||
return true;
|
||||
if (checklength == 2)
|
||||
return false;
|
||||
k >>= 8;
|
||||
if (k == 0xc3)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
for (uintptr_t addr = sp.minAddress & ~0xf; addr < sp.maxAddress; addr += 0x10)
|
||||
{
|
||||
if (IsBadReadPtr((void *)(addr - 0x10), 0x110))
|
||||
{
|
||||
addr += 0x100 - 0x10;
|
||||
continue;
|
||||
}
|
||||
auto need = checker(*(DWORD *)(addr - 4));
|
||||
if (need)
|
||||
addresses1.push_back(addr);
|
||||
}
|
||||
}
|
||||
else if (sp.search_method == 2)
|
||||
{
|
||||
for (uintptr_t addr = sp.minAddress; addr < sp.maxAddress; addr++)
|
||||
{
|
||||
if (IsBadReadPtr((void *)addr, 0x100))
|
||||
{
|
||||
addr += 0x100 - 1;
|
||||
continue;
|
||||
}
|
||||
if (((*(BYTE *)addr) == 0xe8))
|
||||
{
|
||||
auto off = *(DWORD *)(addr + 1);
|
||||
auto funcaddr = addr + 5 + off;
|
||||
if (sp.minAddress < funcaddr && sp.maxAddress > funcaddr)
|
||||
{
|
||||
auto it = std::find(addresses1.begin(), addresses1.end(), funcaddr);
|
||||
addresses1.push_back(funcaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mergevector(addresses, addresses1);
|
||||
|
||||
auto limits = Util::QueryModuleLimits(GetModuleHandleW(LUNA_HOOK_DLL));
|
||||
addresses.erase(std::remove_if(addresses.begin(), addresses.end(), [&](auto addr)
|
||||
{ return addr > limits.first && addr < limits.second; }),
|
||||
addresses.end());
|
||||
|
||||
inlinehookpipeline(addresses);
|
||||
}
|
||||
else if (jittypedefault == JITTYPE::UNITY)
|
||||
{
|
||||
auto methods = loop_all_methods(false);
|
||||
try
|
||||
{
|
||||
*(void **)(trampoline + send_offset) = SendCSharpString<JITTYPE::PC>;
|
||||
std::vector<uintptr_t> addrs;
|
||||
for (auto [_, addr] : std::get<il2cpploopinfo>(methods))
|
||||
addrs.push_back(addr);
|
||||
inlinehookpipeline(addrs);
|
||||
}
|
||||
catch (std::bad_variant_access const &ex)
|
||||
{
|
||||
|
||||
*(void **)(trampoline + send_offset) = SendCSharpString<JITTYPE::UNITY>;
|
||||
auto functions = std::get<monoloopinfo>(methods);
|
||||
std::vector<uintptr_t> addrs;
|
||||
for (auto [addr, func] : functions)
|
||||
{
|
||||
addrs.push_back(addr);
|
||||
remapunityjit[addr] = func;
|
||||
}
|
||||
inlinehookpipeline(addrs);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
safeautoleaveveh = false;
|
||||
|
||||
std::vector<uint64_t> successaddr;
|
||||
uintptr_t minemaddr = -1, maxemaddr = 0;
|
||||
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZED], jitaddr2emuaddr.size());
|
||||
|
||||
for (auto addr : jitaddr2emuaddr)
|
||||
{
|
||||
minemaddr = min(minemaddr, addr.second.second);
|
||||
maxemaddr = max(maxemaddr, addr.second.second);
|
||||
}
|
||||
ConsoleOutput("%p %p", minemaddr, maxemaddr);
|
||||
ConsoleOutput("%p %p", sp.minAddress, sp.maxAddress);
|
||||
#if DUMP_JIT_ADDR_MAP
|
||||
auto f = fopen("1.txt", "a");
|
||||
for (auto addr : jitaddr2emuaddr)
|
||||
{
|
||||
fprintf(f, "%llx => %llx\n", addr.second.second, addr.first);
|
||||
}
|
||||
fclose(f);
|
||||
#endif
|
||||
for (auto addr : jitaddr2emuaddr)
|
||||
{
|
||||
// ConsoleOutput("%llx => %p", addr.second.second ,addr.first);
|
||||
if (addr.second.second > sp.maxAddress || addr.second.second < sp.minAddress)
|
||||
continue;
|
||||
|
||||
// addresses.push_back(addr.first);
|
||||
if (add_veh_hook((void *)addr.first, std::bind(SendJitVeh, std::placeholders::_1, addr.first, addr.second.second, addr.second.first, sp.padding)))
|
||||
successaddr.push_back(addr.first);
|
||||
if (successaddr.size() % 2500 == 0)
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZING], 1 + 98. * successaddr.size() / jitaddr2emuaddr.size());
|
||||
}
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZED], successaddr.size());
|
||||
ConsoleOutput(TR[MAKE_GAME_PROCESS_TEXT], sp.searchTime / 1000);
|
||||
Sleep(sp.searchTime);
|
||||
// for(auto addr:successaddr){
|
||||
// remove_veh_hook((void*)addr);
|
||||
// }
|
||||
safeautoleaveveh = true;
|
||||
}
|
||||
SearchForHooks_Return();
|
||||
}
|
||||
void SearchForHooks(SearchParam spUser)
|
||||
{
|
||||
std::thread([=]
|
||||
{
|
||||
static std::mutex m;
|
||||
std::scoped_lock lock(m);
|
||||
*(void**)(trampoline + send_offset) = Send;
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZING], 0.);
|
||||
|
||||
sp = spUser.length == 0 ? spDefault : spUser;
|
||||
sp.codepage=spUser.codepage;
|
||||
initrecords();
|
||||
|
||||
std::vector<uintptr_t> addresses;
|
||||
if( !sp.isjithook)
|
||||
{
|
||||
if (*sp.boundaryModule) {
|
||||
auto [minaddr,maxaddr]=Util::QueryModuleLimits(GetModuleHandleW(sp.boundaryModule));
|
||||
if(sp.address_method==0){
|
||||
sp.minAddress=min(max(minaddr,sp.minAddress),maxaddr);
|
||||
sp.maxAddress=max(min(maxaddr,sp.maxAddress),minaddr);
|
||||
}
|
||||
else if(sp.address_method==1){
|
||||
auto maxoff=maxaddr-minaddr;
|
||||
sp.minAddress=minaddr+min(sp.minAddress,maxoff);
|
||||
sp.maxAddress=minaddr+min(sp.maxAddress,maxoff);
|
||||
}
|
||||
//std::tie(sp.minAddress, sp.maxAddress) = Util::QueryModuleLimits(GetModuleHandleW(sp.boundaryModule));
|
||||
}
|
||||
if (*sp.exportModule) addresses = GetFunctions((uintptr_t)GetModuleHandleW(sp.exportModule));
|
||||
if (*sp.boundaryModule){
|
||||
auto _addresses = GetFunctions((uintptr_t)GetModuleHandleW(sp.boundaryModule));
|
||||
mergevector(addresses,_addresses);
|
||||
}
|
||||
std::vector<uintptr_t> addresses1;
|
||||
if(sp.search_method==0){
|
||||
for (auto& addr : addresses1 = Util::SearchMemory(sp.pattern, sp.length, PAGE_EXECUTE, sp.minAddress, sp.maxAddress))
|
||||
addr += sp.offset;
|
||||
}
|
||||
else if(sp.search_method==1){
|
||||
auto checklength=3;
|
||||
auto checker=[checklength](DWORD k){
|
||||
if (k == 0xcccccccc
|
||||
|| k == 0x90909090
|
||||
|| k == 0xccccccc3
|
||||
|| k == 0x909090c3
|
||||
)
|
||||
return true;
|
||||
DWORD t = k & 0xff0000ff;
|
||||
if (t == 0xcc0000c2 || t == 0x900000c2)
|
||||
return true;
|
||||
if(checklength==4)return false;
|
||||
k >>= 8;
|
||||
if (k == 0xccccc3 || k == 0x9090c3)
|
||||
return true;
|
||||
if(checklength==3)return false;
|
||||
// t = k & 0xff;
|
||||
// if (t == 0xc2)
|
||||
// return true;
|
||||
k >>= 8;
|
||||
if (k == 0xccc3 || k == 0x90c3)
|
||||
return true;
|
||||
if(checklength==2)return false;
|
||||
k >>= 8;
|
||||
if (k == 0xc3)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
for(uintptr_t addr=sp.minAddress& ~0xf;addr<sp.maxAddress;addr+=0x10){
|
||||
if(IsBadReadPtr((void*)(addr-0x10),0x110)){
|
||||
addr+=0x100-0x10;
|
||||
continue;
|
||||
}
|
||||
auto need=checker(*(DWORD *)(addr-4));
|
||||
if (need)
|
||||
addresses1.push_back(addr);
|
||||
|
||||
}
|
||||
}
|
||||
else if(sp.search_method==2){
|
||||
for(uintptr_t addr=sp.minAddress;addr<sp.maxAddress;addr++){
|
||||
if(IsBadReadPtr((void*)addr,0x100)){
|
||||
addr+=0x100-1;
|
||||
continue;
|
||||
}
|
||||
if(((*(BYTE*)addr)==0xe8)){
|
||||
auto off=*(DWORD*)(addr+1);
|
||||
auto funcaddr=addr+5+off;
|
||||
if(sp.minAddress<funcaddr && sp.maxAddress>funcaddr){
|
||||
auto it = std::find(addresses1.begin(), addresses1.end(), funcaddr);
|
||||
addresses1.push_back(funcaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mergevector(addresses,addresses1);
|
||||
|
||||
auto limits = Util::QueryModuleLimits(GetModuleHandleW(LUNA_HOOK_DLL));
|
||||
addresses.erase(std::remove_if(addresses.begin(), addresses.end(), [&](auto addr) { return addr > limits.first && addr < limits.second; }), addresses.end());
|
||||
|
||||
|
||||
auto trampolines = (decltype(trampoline)*)VirtualAlloc(NULL, sizeof(trampoline) * addresses.size(), MEM_COMMIT, PAGE_READWRITE);
|
||||
VirtualProtect(trampolines, addresses.size() * sizeof(trampoline), PAGE_EXECUTE_READWRITE, DUMMY);
|
||||
std::vector<uintptr_t>mherroridx;
|
||||
for (int i = 0; i < addresses.size(); ++i)
|
||||
{
|
||||
void* original;
|
||||
//避免MH_RemoveHook时移除原本已有hook
|
||||
if(MH_CreateHook((void*)addresses[i], trampolines[i], &original)!=MH_OK){
|
||||
mherroridx.push_back(i);
|
||||
}
|
||||
MH_QueueEnableHook((void*)addresses[i]);
|
||||
memcpy(trampolines[i], trampoline, sizeof(trampoline));
|
||||
*(uintptr_t*)(trampolines[i] + addr_offset) = addresses[i];
|
||||
*(void**)(trampolines[i] + original_offset) = original;
|
||||
if (i % 2500 == 0) ConsoleOutput(TR[HOOK_SEARCH_INITIALIZING], 1 + 98. * i / addresses.size());
|
||||
}
|
||||
//避免MH_RemoveHook时移除原本已有hook
|
||||
for(int i=0;i<mherroridx.size();i++){
|
||||
auto reverseidx=mherroridx[mherroridx.size()-1-i];
|
||||
addresses.erase(addresses.begin()+reverseidx);
|
||||
}
|
||||
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZED], addresses.size());
|
||||
MH_ApplyQueued();
|
||||
ConsoleOutput(TR[HOOK_SEARCH_STARTING]);
|
||||
ConsoleOutput(TR[MAKE_GAME_PROCESS_TEXT], sp.searchTime / 1000);
|
||||
Sleep(sp.searchTime);
|
||||
for (auto addr : addresses) MH_QueueDisableHook((void*)addr);
|
||||
MH_ApplyQueued();
|
||||
Sleep(1000);
|
||||
for (auto addr : addresses) MH_RemoveHook((void*)addr);
|
||||
VirtualFree(trampolines, 0, MEM_RELEASE);
|
||||
SearchForHooks_Return();
|
||||
}
|
||||
else
|
||||
{
|
||||
safeautoleaveveh=false;
|
||||
int i=0;
|
||||
std::vector<uint64_t>successaddr;
|
||||
uintptr_t minemaddr=-1,maxemaddr=0;
|
||||
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZED], jitaddr2emuaddr.size());
|
||||
|
||||
for(auto addr:jitaddr2emuaddr){
|
||||
minemaddr=min(minemaddr,addr.second.second);
|
||||
maxemaddr=max(maxemaddr,addr.second.second);
|
||||
}
|
||||
ConsoleOutput("%p %p",minemaddr,maxemaddr);
|
||||
ConsoleOutput("%p %p",sp.minAddress,sp.maxAddress);
|
||||
#if DUMP_JIT_ADDR_MAP
|
||||
auto f=fopen("1.txt","a");
|
||||
for(auto addr:jitaddr2emuaddr){
|
||||
fprintf(f,"%llx => %llx\n", addr.second.second ,addr.first);
|
||||
}
|
||||
fclose(f);
|
||||
#endif
|
||||
for(auto addr:jitaddr2emuaddr){
|
||||
//ConsoleOutput("%llx => %p", addr.second.second ,addr.first);
|
||||
if(addr.second.second>sp.maxAddress||addr.second.second<sp.minAddress)continue;
|
||||
i+=1;
|
||||
//addresses.push_back(addr.first);
|
||||
if(add_veh_hook((void*)addr.first,std::bind(SendJitVeh,std::placeholders::_1,addr.first,addr.second.second,addr.second.first,sp.padding)))
|
||||
successaddr.push_back(addr.first);
|
||||
if (i % 2500 == 0) ConsoleOutput(TR[HOOK_SEARCH_INITIALIZING], 1 + 98. * i / jitaddr2emuaddr.size());
|
||||
}
|
||||
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZED], i);
|
||||
ConsoleOutput(TR[MAKE_GAME_PROCESS_TEXT], sp.searchTime / 1000);
|
||||
Sleep(sp.searchTime);
|
||||
// for(auto addr:successaddr){
|
||||
// remove_veh_hook((void*)addr);
|
||||
// }
|
||||
safeautoleaveveh=true;
|
||||
SearchForHooks_Return();
|
||||
} })
|
||||
std::thread(_SearchForHooks, spUser)
|
||||
.detach();
|
||||
}
|
||||
|
||||
|
@ -278,6 +278,11 @@ bool NewHook(HookParam hp, LPCSTR name)
|
||||
return NewHook_1(hp, name);
|
||||
if (hp.jittype == JITTYPE::UNITY)
|
||||
{
|
||||
if (strcmp(hp.function, "?") == 0)
|
||||
{
|
||||
loop_all_methods(true);
|
||||
return false;
|
||||
}
|
||||
auto spls = strSplit(hp.function, ":");
|
||||
if (spls.size() != 5)
|
||||
{
|
||||
|
@ -15,6 +15,7 @@ bool NewHookJit(HookParam hp, LPCSTR name);
|
||||
void RemoveHook(uint64_t addr, int maxOffset = 9);
|
||||
std::string LoadResData(LPCWSTR pszResID, LPCWSTR _type);
|
||||
inline SearchParam spDefault;
|
||||
inline JITTYPE jittypedefault = JITTYPE::PC;
|
||||
// EOF
|
||||
int HookStrLen(HookParam *, BYTE *data);
|
||||
|
||||
|
@ -289,7 +289,7 @@ void TextHook::Send(hook_context *context)
|
||||
lpDataIn = jitgetaddr(context, &hp, true);
|
||||
plpdatain = &lpDataIn;
|
||||
}
|
||||
else if (hp.jittype == JITTYPE::UNITY)
|
||||
else if (hp.jittype == JITTYPE::UNITY || hp.type & CSHARP_STRING)
|
||||
{
|
||||
plpdatain = &context->argof(hp.offset);
|
||||
lpDataIn = *plpdatain;
|
||||
@ -299,10 +299,10 @@ void TextHook::Send(hook_context *context)
|
||||
{
|
||||
hp.text_fun(context, &hp, &buff, &lpSplit);
|
||||
}
|
||||
else if (hp.type & SPECIAL_JIT_STRING)
|
||||
else if (hp.type & CSHARP_STRING)
|
||||
{
|
||||
if (hp.jittype == JITTYPE::UNITY)
|
||||
commonsolvemonostring(lpDataIn, &buff);
|
||||
if (auto sw = commonsolvemonostring(lpDataIn))
|
||||
buff.from(sw.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -351,7 +351,7 @@ void TextHook::Send(hook_context *context)
|
||||
*(WORD *)buff.buff = lpDataIn & 0xffff;
|
||||
}
|
||||
}
|
||||
else if ((!hp.text_fun) && (!(hp.type & SPECIAL_JIT_STRING)))
|
||||
else if ((!hp.text_fun) && (!(hp.type & CSHARP_STRING)))
|
||||
{
|
||||
if (lpDataIn == 0)
|
||||
__leave;
|
||||
@ -423,10 +423,9 @@ void TextHook::Send(hook_context *context)
|
||||
}
|
||||
else if (hp.embed_fun)
|
||||
hp.embed_fun(context, buff);
|
||||
else if (hp.type & SPECIAL_JIT_STRING)
|
||||
else if (hp.type & CSHARP_STRING)
|
||||
{
|
||||
if (hp.jittype == JITTYPE::UNITY)
|
||||
unity_ui_string_embed_fun(context->argof(hp.offset), buff);
|
||||
unity_ui_string_embed_fun(context->argof(hp.offset), buff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +81,135 @@ namespace
|
||||
}
|
||||
return f64bitProc;
|
||||
}
|
||||
void __handlepipethread(HANDLE hookPipe, HANDLE hostPipe, HANDLE pipeAvailableEvent)
|
||||
{
|
||||
ConnectNamedPipe(hookPipe, nullptr);
|
||||
CloseHandle(pipeAvailableEvent);
|
||||
WORD hookversion[4];
|
||||
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||
DWORD bytesRead, processId;
|
||||
ReadFile(hookPipe, &processId, sizeof(processId), &bytesRead, nullptr);
|
||||
ReadFile(hookPipe, hookversion, sizeof(hookversion), &bytesRead, nullptr);
|
||||
if (memcmp(hookversion, LUNA_VERSION, sizeof(hookversion)) != 0)
|
||||
Host::InfoOutput(HOSTINFO::Warning, TR[UNMATCHABLEVERSION]);
|
||||
|
||||
processRecordsByIds->try_emplace(processId, processId, hostPipe);
|
||||
processRecordsByIds->at(processId).Send(curr_lang);
|
||||
OnConnect(processId);
|
||||
Host::AddConsoleOutput(FormatString(TR[PROC_CONN], processId));
|
||||
|
||||
while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
|
||||
switch (*(HostNotificationType *)buffer)
|
||||
{
|
||||
case HOST_NOTIFICATION_FOUND_HOOK:
|
||||
{
|
||||
auto info = *(HookFoundNotif *)buffer;
|
||||
auto OnHookFound = processRecordsByIds->at(processId).OnHookFound;
|
||||
std::wstring wide = info.text;
|
||||
if (wide.size() > STRING)
|
||||
{
|
||||
wcscpy_s(info.hp.hookcode, HOOKCODE_LEN, HookCode::Generate(info.hp, processId).c_str());
|
||||
OnHookFound(info.hp, std::move(info.text));
|
||||
}
|
||||
if (!(info.hp.type & CSHARP_STRING))
|
||||
{
|
||||
info.hp.type &= ~CODEC_UTF16;
|
||||
if (auto converted = StringToWideString((char *)info.text, info.hp.codepage))
|
||||
#if SEARCH_SJIS_UNSAFE
|
||||
if (converted->size())
|
||||
#else
|
||||
if (converted->size() > STRING)
|
||||
#endif
|
||||
{
|
||||
wcscpy_s(info.hp.hookcode, HOOKCODE_LEN, HookCode::Generate(info.hp, processId).c_str());
|
||||
OnHookFound(info.hp, std::move(converted.value()));
|
||||
}
|
||||
if (auto converted = StringToWideString((char *)info.text, info.hp.codepage = CP_UTF8))
|
||||
if (converted->size() > STRING)
|
||||
{
|
||||
wcscpy_s(info.hp.hookcode, HOOKCODE_LEN, HookCode::Generate(info.hp, processId).c_str());
|
||||
OnHookFound(info.hp, std::move(converted.value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOST_NOTIFICATION_RMVHOOK:
|
||||
{
|
||||
auto info = *(HookRemovedNotif *)buffer;
|
||||
auto sm = Host::GetCommonSharedMem(processId);
|
||||
if (sm)
|
||||
for (int i = 0; i < ARRAYSIZE(sm->embedtps); i++)
|
||||
if (sm->embedtps[i].use && (sm->embedtps[i].tp.addr == info.address) && (sm->embedtps[i].tp.processId == processId))
|
||||
ZeroMemory(sm->embedtps + i, sizeof(sm->embedtps[i]));
|
||||
RemoveThreads([&](ThreadParam tp)
|
||||
{ return tp.processId == processId && tp.addr == info.address; });
|
||||
}
|
||||
break;
|
||||
case HOST_NOTIFICATION_INSERTING_HOOK:
|
||||
{
|
||||
if (HookInsert)
|
||||
{
|
||||
auto info = (HookInsertingNotif *)buffer;
|
||||
HookInsert(processId, info->addr, info->hookcode);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOST_NOTIFICATION_TEXT:
|
||||
{
|
||||
auto info = *(HostInfoNotif *)buffer;
|
||||
Host::InfoOutput(info.type, StringToWideString(info.message));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
auto data = (TextOutput_T *)buffer;
|
||||
auto length = bytesRead - sizeof(TextOutput_T);
|
||||
auto tp = data->tp;
|
||||
auto hp = data->hp;
|
||||
auto _textThreadsByParams = textThreadsByParams.Acquire();
|
||||
|
||||
auto thread = _textThreadsByParams->find(tp);
|
||||
if (thread == _textThreadsByParams->end())
|
||||
{
|
||||
try
|
||||
{
|
||||
thread = _textThreadsByParams->try_emplace(tp, tp, hp).first;
|
||||
}
|
||||
catch (std::out_of_range)
|
||||
{
|
||||
continue;
|
||||
} // probably garbage data in pipe, try again
|
||||
OnCreate(thread->second);
|
||||
}
|
||||
|
||||
thread->second.hp.type = data->type;
|
||||
thread->second.Push(data->data, length);
|
||||
|
||||
if (embedcallback)
|
||||
{
|
||||
auto &hp = thread->second.hp;
|
||||
if (hp.type & EMBED_ABLE && Host::CheckIsUsingEmbed(thread->second.tp))
|
||||
{
|
||||
if (auto t = commonparsestring(data->data, length, &hp, Host::defaultCodepage))
|
||||
{
|
||||
auto text = t.value();
|
||||
if (text.size())
|
||||
{
|
||||
embedcallback(text, tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
RemoveThreads([&](ThreadParam tp)
|
||||
{ return tp.processId == processId; });
|
||||
OnDisconnect(processId);
|
||||
Host::AddConsoleOutput(FormatString(TR[PROC_DISCONN], processId));
|
||||
processRecordsByIds->erase(processId);
|
||||
}
|
||||
void CreatePipe(int pid)
|
||||
{
|
||||
HANDLE
|
||||
@ -89,119 +218,7 @@ namespace
|
||||
HANDLE pipeAvailableEvent = CreateEventW(&allAccess, FALSE, FALSE, (std::wstring(PIPE_AVAILABLE_EVENT) + std::to_wstring(pid)).c_str());
|
||||
|
||||
SetEvent(pipeAvailableEvent);
|
||||
std::thread([hookPipe, hostPipe, pipeAvailableEvent]
|
||||
{
|
||||
ConnectNamedPipe(hookPipe, nullptr);
|
||||
CloseHandle(pipeAvailableEvent);
|
||||
WORD hookversion[4];
|
||||
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||
DWORD bytesRead, processId;
|
||||
ReadFile(hookPipe, &processId, sizeof(processId), &bytesRead, nullptr);
|
||||
ReadFile(hookPipe, hookversion, sizeof(hookversion), &bytesRead, nullptr);
|
||||
if(memcmp(hookversion,LUNA_VERSION,sizeof(hookversion))!=0)
|
||||
Host::InfoOutput(HOSTINFO::Warning, TR[UNMATCHABLEVERSION]);
|
||||
|
||||
processRecordsByIds->try_emplace(processId, processId, hostPipe);
|
||||
processRecordsByIds->at(processId).Send(curr_lang);
|
||||
OnConnect(processId);
|
||||
Host::AddConsoleOutput(FormatString(TR[PROC_CONN],processId));
|
||||
|
||||
while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
|
||||
switch (*(HostNotificationType*)buffer)
|
||||
{
|
||||
case HOST_NOTIFICATION_FOUND_HOOK:
|
||||
{
|
||||
auto info = *(HookFoundNotif*)buffer;
|
||||
auto OnHookFound = processRecordsByIds->at(processId).OnHookFound;
|
||||
std::wstring wide = info.text;
|
||||
if (wide.size() > STRING) {
|
||||
wcscpy_s(info.hp.hookcode,HOOKCODE_LEN, HookCode::Generate(info.hp, processId).c_str());
|
||||
OnHookFound(info.hp, std::move(info.text));
|
||||
}
|
||||
info.hp.type &= ~CODEC_UTF16;
|
||||
if (auto converted = StringToWideString((char*)info.text, info.hp.codepage))
|
||||
#if SEARCH_SJIS_UNSAFE
|
||||
if (converted->size())
|
||||
#else
|
||||
if (converted->size() > STRING)
|
||||
#endif
|
||||
{
|
||||
wcscpy_s(info.hp.hookcode,HOOKCODE_LEN, HookCode::Generate(info.hp, processId).c_str());
|
||||
OnHookFound(info.hp, std::move(converted.value()));
|
||||
}
|
||||
if (auto converted = StringToWideString((char*)info.text, info.hp.codepage = CP_UTF8))
|
||||
if (converted->size() > STRING)
|
||||
{
|
||||
wcscpy_s(info.hp.hookcode,HOOKCODE_LEN, HookCode::Generate(info.hp, processId).c_str());
|
||||
OnHookFound(info.hp, std::move(converted.value()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOST_NOTIFICATION_RMVHOOK:
|
||||
{
|
||||
auto info = *(HookRemovedNotif*)buffer;
|
||||
auto sm = Host::GetCommonSharedMem(processId);
|
||||
if (sm)
|
||||
for (int i = 0; i < ARRAYSIZE(sm->embedtps); i++)
|
||||
if (sm->embedtps[i].use && (sm->embedtps[i].tp.addr==info.address)&&(sm->embedtps[i].tp.processId==processId))
|
||||
ZeroMemory(sm->embedtps + i, sizeof(sm->embedtps[i]));
|
||||
RemoveThreads([&](ThreadParam tp) { return tp.processId == processId && tp.addr == info.address; });
|
||||
}
|
||||
break;
|
||||
case HOST_NOTIFICATION_INSERTING_HOOK:
|
||||
{
|
||||
if(HookInsert){
|
||||
auto info = (HookInsertingNotif*)buffer;
|
||||
HookInsert(processId, info->addr,info->hookcode);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOST_NOTIFICATION_TEXT:
|
||||
{
|
||||
auto info = *(HostInfoNotif*)buffer;
|
||||
Host::InfoOutput(info.type, StringToWideString(info.message));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
auto data=(TextOutput_T*)buffer;
|
||||
auto length= bytesRead - sizeof(TextOutput_T);
|
||||
auto tp = data->tp;
|
||||
auto hp=data->hp;
|
||||
auto _textThreadsByParams=textThreadsByParams.Acquire();
|
||||
|
||||
auto thread = _textThreadsByParams->find(tp);
|
||||
if (thread == _textThreadsByParams->end())
|
||||
{
|
||||
try { thread = _textThreadsByParams->try_emplace(tp, tp, hp).first; }
|
||||
catch (std::out_of_range) { continue; } // probably garbage data in pipe, try again
|
||||
OnCreate(thread->second);
|
||||
}
|
||||
|
||||
thread->second.hp.type=data->type;
|
||||
thread->second.Push(data->data, length);
|
||||
|
||||
if(embedcallback){
|
||||
auto & hp=thread->second.hp;
|
||||
if(hp.type&EMBED_ABLE && Host::CheckIsUsingEmbed(thread->second.tp)){
|
||||
if (auto t=commonparsestring(data->data,length,&hp,Host::defaultCodepage)){
|
||||
auto text=t.value();
|
||||
if(text.size()){
|
||||
embedcallback(text,tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
RemoveThreads([&](ThreadParam tp) { return tp.processId == processId; });
|
||||
OnDisconnect(processId);
|
||||
Host::AddConsoleOutput(FormatString(TR[PROC_DISCONN],processId));
|
||||
processRecordsByIds->erase(processId); })
|
||||
.detach();
|
||||
std::thread(__handlepipethread, hookPipe, hostPipe, pipeAvailableEvent).detach();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ enum HookParamType : uint64_t
|
||||
|
||||
NEXT_MASK(USING_CHAR), // text_fun!=nullptr && (CODE_ANSI_BE||CODE_UTF16)
|
||||
NEXT_MASK(USING_STRING),
|
||||
NEXT_MASK(SPECIAL_JIT_STRING),
|
||||
NEXT_MASK(CSHARP_STRING),
|
||||
|
||||
NEXT_MASK(FULL_STRING),
|
||||
|
||||
|
@ -96,7 +96,7 @@ namespace
|
||||
hp.type |= USING_STRING | CODEC_UTF16;
|
||||
break;
|
||||
case L'M':
|
||||
hp.type |= USING_STRING | CODEC_UTF16 | SPECIAL_JIT_STRING;
|
||||
hp.type |= USING_STRING | CODEC_UTF16 | CSHARP_STRING;
|
||||
break;
|
||||
case L'U':
|
||||
hp.type |= USING_STRING | CODEC_UTF32;
|
||||
@ -313,7 +313,7 @@ namespace
|
||||
|
||||
if (hp.type & USING_STRING)
|
||||
{
|
||||
if (hp.type & SPECIAL_JIT_STRING)
|
||||
if (hp.type & CSHARP_STRING)
|
||||
HCode += L'M';
|
||||
else if (hp.type & CODEC_UTF16)
|
||||
HCode += L'Q';
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
set(VERSION_MAJOR 6)
|
||||
set(VERSION_MINOR 14)
|
||||
set(VERSION_PATCH 4)
|
||||
set(VERSION_PATCH 5)
|
||||
set(VERSION_REVISION 0)
|
||||
set(LUNA_VERSION "{${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_REVISION}}")
|
||||
add_library(VERSION_DEF ${CMAKE_CURRENT_LIST_DIR}/version_def.cpp)
|
||||
|
Loading…
x
Reference in New Issue
Block a user