mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-26 23:34:01 +08:00
some
This commit is contained in:
parent
1016b82df0
commit
163835bec9
@ -61,7 +61,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
|
||||
include(generate_product_version)
|
||||
|
||||
set(VERSION_MAJOR 3)
|
||||
set(VERSION_MINOR 13)
|
||||
set(VERSION_MINOR 14)
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_REVISION 0)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
include_directories(. util engines)
|
||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
||||
set(enginessrc MKXPZ Ryujinx livecaptions Kincaid vita3k rpcs3 yuzusuyu TYPEMOON ENTERGRAM AGES7 mono Godot 5pb lucasystem LightVN V8 pchooks Artemis KiriKiri YOX PPSSPP CMVS Suika2 )
|
||||
set(enginessrc MKXPZ Ryujinx livecaptions Kincaid vita3k rpcs3 yuzu TYPEMOON ENTERGRAM AGES7 mono Godot 5pb lucasystem LightVN V8 pchooks Artemis KiriKiri YOX PPSSPP CMVS Suika2 )
|
||||
set(enginepath "engine64")
|
||||
set(collector "enginecollection64.cpp")
|
||||
else()
|
||||
|
@ -1,18 +1,22 @@
|
||||
#include "5pb.h"
|
||||
#include "mages/mages.h"
|
||||
namespace{
|
||||
namespace
|
||||
{
|
||||
// https://vndb.org/v46553
|
||||
// 新宿葬命
|
||||
bool _strncat(){
|
||||
bool _strncat()
|
||||
{
|
||||
HookParam hp;
|
||||
hp.address = (uintptr_t)GetProcAddress(GetModuleHandleA("ucrtbase.dll"), "strncat");
|
||||
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
|
||||
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
*data = stack->ARG2;
|
||||
*len = stack->ARG3;
|
||||
*split = stack->ARG1;
|
||||
};
|
||||
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
|
||||
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
strReplace(s, "%N", "\n");
|
||||
// sub_140096E80
|
||||
@ -22,7 +26,8 @@ namespace{
|
||||
return NewHook(hp, "strncat");
|
||||
}
|
||||
}
|
||||
bool _5pb::attach_function() {
|
||||
bool _5pb::attach_function()
|
||||
{
|
||||
// CHAOS;HEAD_NOAH
|
||||
bool b3 = hookmages::MAGES();
|
||||
return b3 || _strncat();
|
||||
|
@ -1,13 +1,13 @@
|
||||
|
||||
|
||||
class _5pb:public ENGINE{
|
||||
class _5pb : public ENGINE
|
||||
{
|
||||
public:
|
||||
_5pb(){
|
||||
_5pb()
|
||||
{
|
||||
is_engine_certain = false;
|
||||
check_by = CHECK_BY::FILE_ANY;
|
||||
check_by_target = check_by_list{L"data\\*.cpk", L"*.cpk"};
|
||||
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
@ -1,22 +1,28 @@
|
||||
#include "AGES7.h"
|
||||
namespace{
|
||||
namespace
|
||||
{
|
||||
// Muv-Luv Alternative - Total Eclipse
|
||||
// https://vndb.org/v7052
|
||||
bool _1(){
|
||||
bool _1()
|
||||
{
|
||||
// HSN65001#-44@234699:te-win64vc14-release.exe
|
||||
BYTE b1[] = {
|
||||
//clang-format off
|
||||
0x48, XX2, 0xb0, 0xfe, 0xff, 0xff,
|
||||
0x4c, XX2, 0xb8, 0x01, 0x00, 0x00,
|
||||
//clang-format on
|
||||
|
||||
};
|
||||
auto addr = MemDbg::findBytes(b1, sizeof(b1), processStartAddress, processStopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
|
||||
hp.offset = get_reg(regs::rdi);
|
||||
auto succ = NewHook(hp, "Ages7_1");
|
||||
if(addr=MemDbg::findEnclosingAlignedFunction(addr)){
|
||||
if (addr = MemDbg::findEnclosingAlignedFunction(addr))
|
||||
{
|
||||
hp.address = addr;
|
||||
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
|
||||
hp.offset = get_reg(regs::rbx);
|
||||
@ -24,22 +30,27 @@ namespace{
|
||||
}
|
||||
return succ;
|
||||
}
|
||||
bool _2(){
|
||||
bool _2()
|
||||
{
|
||||
// HSN65001#-44@2346AC:te-win64vc14-release.exe
|
||||
BYTE b1[] = {
|
||||
//clang-format off
|
||||
0x48, XX2, 0x10,
|
||||
0x48, XX2, 0xb0, 0x01, 0x00, 0x00,
|
||||
XX2, 0xc0, 0x08, 0x00, 0x00
|
||||
//clang-format on
|
||||
|
||||
};
|
||||
auto addr = MemDbg::findBytes(b1, sizeof(b1), processStartAddress, processStopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
|
||||
hp.offset = get_reg(regs::rdi);
|
||||
auto suc = NewHook(hp, "Ages7_2");
|
||||
if(addr=MemDbg::findEnclosingAlignedFunction(addr)){
|
||||
if (addr = MemDbg::findEnclosingAlignedFunction(addr))
|
||||
{
|
||||
hp.address = addr;
|
||||
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
|
||||
hp.offset = get_reg(regs::rbx);
|
||||
@ -47,9 +58,11 @@ namespace{
|
||||
}
|
||||
return suc;
|
||||
}
|
||||
bool _3(){
|
||||
bool _3()
|
||||
{
|
||||
// HSN65001#-14@3D9814:te-win64vc14-release.exe
|
||||
BYTE b1[] = {
|
||||
//clang-format off
|
||||
0x48, 0x8b, 0x1b,
|
||||
0x48, 0x8b, 0x01,
|
||||
0x48, 0x8b, 0xd3,
|
||||
@ -59,22 +72,26 @@ namespace{
|
||||
0x48, 0x2b, 0xc1,
|
||||
0x48, 0xc1, 0xf8, 0x03,
|
||||
0x48, 0x85, 0xc0,
|
||||
//clang-format on
|
||||
};
|
||||
auto addr = MemDbg::findBytes(b1, sizeof(b1), processStartAddress, processStopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr + 3;
|
||||
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
|
||||
hp.offset = get_reg(regs::rbx);
|
||||
return NewHook(hp, "Ages7_4");
|
||||
}
|
||||
bool all(){
|
||||
bool all()
|
||||
{
|
||||
auto _ = _1();
|
||||
_ = _2() || _;
|
||||
_ = _3() || _;
|
||||
return _;
|
||||
}
|
||||
}
|
||||
bool AGES7::attach_function(){
|
||||
bool AGES7::attach_function()
|
||||
{
|
||||
return all();
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
|
||||
|
||||
class AGES7:public ENGINE{
|
||||
class AGES7 : public ENGINE
|
||||
{
|
||||
public:
|
||||
AGES7(){
|
||||
AGES7()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE_ALL;
|
||||
check_by_target = check_by_list{L"obb\\pack.bin", L"erc_nospfx.dll"};
|
||||
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class Artemis:public ENGINE{
|
||||
class Artemis : public ENGINE
|
||||
{
|
||||
public:
|
||||
Artemis(){
|
||||
Artemis()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE;
|
||||
check_by_target = L"*.pfs";
|
||||
|
@ -1,30 +1,38 @@
|
||||
#include "CMVS.h"
|
||||
namespace{
|
||||
bool EMbed(){
|
||||
namespace
|
||||
{
|
||||
bool EMbed()
|
||||
{
|
||||
// 有多个,但是只有最后一个是有效的
|
||||
const uint8_t bytes[] = {
|
||||
//clang-format off
|
||||
0xB8, 0x42, 0x81, 0x00, 0x00,
|
||||
0x66, XX2, 0x74, XX,
|
||||
0xB8, 0x76, 0x81, 0x00, 0x00,
|
||||
0x66, XX2, 0x74, XX,
|
||||
0xB8, 0x78, 0x81, 0x00, 0x00,
|
||||
0x66, XX2, 0x74, XX,
|
||||
//clang-format on
|
||||
};
|
||||
bool res = false;
|
||||
auto addr = processStartAddress;
|
||||
|
||||
std::vector<uintptr_t> already;
|
||||
|
||||
while(addr){
|
||||
while (addr)
|
||||
{
|
||||
addr = MemDbg::findBytes(bytes, sizeof(bytes), addr + 1, processStopAddress);
|
||||
if(addr==0)continue;
|
||||
if (addr == 0)
|
||||
continue;
|
||||
auto f = MemDbg::findEnclosingAlignedFunction(addr);
|
||||
if(f==0)continue;
|
||||
if(std::find(already.begin(),already.end(),f)!=already.end())continue;
|
||||
if (f == 0)
|
||||
continue;
|
||||
if (std::find(already.begin(), already.end(), f) != already.end())
|
||||
continue;
|
||||
already.push_back(f);
|
||||
|
||||
}
|
||||
if(already.size()){
|
||||
if (already.size())
|
||||
{
|
||||
HookParam hp;
|
||||
hp.address = already.back();
|
||||
hp.offset = get_reg(regs::rdx);
|
||||
@ -36,11 +44,13 @@ bool EMbed(){
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CMVSh() {
|
||||
bool CMVSh()
|
||||
{
|
||||
|
||||
DWORD align = 0xCCCCCCCC;
|
||||
auto addr = MemDbg::findCallerAddress((uintptr_t)::GetGlyphOutlineA, align, processStartAddress, processStopAddress);
|
||||
if (!addr) return false;
|
||||
if (!addr)
|
||||
return false;
|
||||
|
||||
HookParam hp;
|
||||
hp.address = addr + 4;
|
||||
@ -50,7 +60,8 @@ bool CMVSh() {
|
||||
return NewHook(hp, "CMVS");
|
||||
}
|
||||
}
|
||||
bool CMVS::attach_function(){
|
||||
bool CMVS::attach_function()
|
||||
{
|
||||
bool b1 = CMVSh();
|
||||
bool b2 = EMbed();
|
||||
return b1 || b2;
|
||||
|
@ -1,13 +1,14 @@
|
||||
|
||||
|
||||
class CMVS:public ENGINE{
|
||||
class CMVS : public ENGINE
|
||||
{
|
||||
public:
|
||||
CMVS(){
|
||||
CMVS()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE;
|
||||
check_by_target = L"data\\pack\\*.cpz";
|
||||
|
||||
|
||||
// jichi 8/19/2013: DO NOT WORK for games like「ハピメア」
|
||||
// if (wcsstr(str,L"cmvs32") || wcsstr(str,L"cmvs64")) {
|
||||
// InsertCMVSHook();
|
||||
|
@ -1,10 +1,12 @@
|
||||
#include "Godot.h"
|
||||
|
||||
bool InsertGodotHook_X64() {
|
||||
bool InsertGodotHook_X64()
|
||||
{
|
||||
const BYTE bytes[] = {0x8B, 0x40, 0xFC, 0x83, 0xF8, 0x01, 0x83, 0xD0, 0xFF, 0x41, 0x39, 0xC6};
|
||||
|
||||
ULONG64 range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||||
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range)) {
|
||||
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range))
|
||||
{
|
||||
HookParam myhp;
|
||||
myhp.address = addr;
|
||||
|
||||
@ -16,7 +18,8 @@ bool InsertGodotHook_X64() {
|
||||
{
|
||||
*data = (stack->rax);
|
||||
int len = *(int *)(*data - 4);
|
||||
if(len!=wcslen((wchar_t*)*data))return;
|
||||
if (len != wcslen((wchar_t *)*data))
|
||||
return;
|
||||
*count = len * 2;
|
||||
};
|
||||
char nameForUser[HOOK_NAME_SIZE] = "RichTextLabel_add_text";
|
||||
@ -28,7 +31,8 @@ bool InsertGodotHook_X64() {
|
||||
ConsoleOutput("Godot_x64: pattern not found");
|
||||
return false;
|
||||
}
|
||||
bool InsertGodotHook2_X64() {
|
||||
bool InsertGodotHook2_X64()
|
||||
{
|
||||
|
||||
/*
|
||||
* Sample games:
|
||||
@ -45,7 +49,8 @@ bool InsertGodotHook2_X64() {
|
||||
};
|
||||
|
||||
ULONG64 range = min(processStopAddress - processStartAddress, X64_MAX_REL_ADDR);
|
||||
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range)) {
|
||||
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range))
|
||||
{
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.offset = get_reg(regs::rcx);
|
||||
@ -57,7 +62,8 @@ bool InsertGodotHook2_X64() {
|
||||
ConsoleOutput("Godot2_x64: pattern not found");
|
||||
return false;
|
||||
}
|
||||
bool Godot::attach_function(){
|
||||
bool Godot::attach_function()
|
||||
{
|
||||
auto _ = InsertGodotHook_X64();
|
||||
_ = InsertGodotHook2_X64() || _;
|
||||
return _;
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class Godot:public ENGINE{
|
||||
class Godot : public ENGINE
|
||||
{
|
||||
public:
|
||||
Godot(){
|
||||
Godot()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE;
|
||||
check_by_target = L"*.pck";
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "Kincaid.h"
|
||||
namespace{
|
||||
bool _1(){
|
||||
namespace
|
||||
{
|
||||
bool _1()
|
||||
{
|
||||
// .text:0000000140230D80 mov rsi, rax
|
||||
// .text:0000000140230D83 mov edx, 1
|
||||
// .text:0000000140230D88 mov rcx, rdi
|
||||
@ -17,15 +19,16 @@ namespace{
|
||||
0x8d, 0x58, 0xff,
|
||||
0xba, 0x02, 0x00, 0x00, 0x00,
|
||||
0x48, 0x8b, 0xcf,
|
||||
0xe8,XX4
|
||||
};
|
||||
0xe8, XX4};
|
||||
auto addr = MemDbg::findBytes(b1, sizeof(b1), processStartAddress, processStopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.type = USING_STRING | CODEC_UTF8;
|
||||
hp.offset = get_reg(regs::rax);
|
||||
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
*data = stack->rax;
|
||||
if (stack->retaddr == (DWORD)-1)
|
||||
*len = strlen((char *)*data);
|
||||
@ -33,6 +36,7 @@ namespace{
|
||||
return NewHook(hp, "Kincaid");
|
||||
}
|
||||
}
|
||||
bool Kincaid::attach_function(){
|
||||
bool Kincaid::attach_function()
|
||||
{
|
||||
return _1();
|
||||
}
|
@ -26,15 +26,17 @@
|
||||
// }
|
||||
// }
|
||||
|
||||
class Kincaid:public ENGINE{
|
||||
class Kincaid : public ENGINE
|
||||
{
|
||||
public:
|
||||
Kincaid(){
|
||||
Kincaid()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::CUSTOM;
|
||||
check_by_target=[](){
|
||||
check_by_target = []()
|
||||
{
|
||||
return Util::SearchResourceString(L"Cookiedraggy") || Util::SearchResourceString(L"The Adventures of Kincaid");
|
||||
};
|
||||
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
@ -22,7 +22,8 @@ bool InsertKiriKiriZHook()
|
||||
};
|
||||
|
||||
ULONG64 range = min(processStopAddress - processStartAddress, X64_MAX_REL_ADDR);
|
||||
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range)) {
|
||||
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range))
|
||||
{
|
||||
HookParam hp;
|
||||
hp.address = addr + 1;
|
||||
hp.offset = get_reg(regs::rcx);
|
||||
@ -40,15 +41,16 @@ bool Insertkrkrz64Hook()
|
||||
0x41, 0x0F, 0xB7, 0x44, 0x24, 0x06,
|
||||
0x89, 0x43, 0x24,
|
||||
0x41, 0x0F, 0xBF, 0x44, 0x24, 0x0C,
|
||||
0x89,0x43,0x14
|
||||
};
|
||||
0x89, 0x43, 0x14};
|
||||
auto addrs = Util::SearchMemory(BYTES, sizeof(BYTES), PAGE_EXECUTE_READ, processStartAddress, processStopAddress);
|
||||
ConsoleOutput("%p %p", processStartAddress, processStopAddress);
|
||||
for (auto addr : addrs) {
|
||||
for (auto addr : addrs)
|
||||
{
|
||||
ConsoleOutput("krkrz64 %p", addr);
|
||||
const BYTE funcstart[] = {0xcc, 0xcc, 0xcc, 0xcc};
|
||||
addr = reverseFindBytes(funcstart, sizeof(funcstart), addr - 0x1000, addr);
|
||||
if (addr == 0)continue;
|
||||
if (addr == 0)
|
||||
continue;
|
||||
addr += 4;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
@ -62,7 +64,7 @@ bool Insertkrkrz64Hook()
|
||||
ConsoleOutput("krkrz64 failed");
|
||||
return false;
|
||||
}
|
||||
bool KiriKiri::attach_function() {
|
||||
bool KiriKiri::attach_function()
|
||||
{
|
||||
return Insertkrkrz64Hook() || InsertKiriKiriZHook();
|
||||
}
|
||||
|
@ -1,15 +1,17 @@
|
||||
|
||||
|
||||
class KiriKiri:public ENGINE{
|
||||
class KiriKiri : public ENGINE
|
||||
{
|
||||
public:
|
||||
KiriKiri(){
|
||||
KiriKiri()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::CUSTOM;
|
||||
is_engine_certain = false;
|
||||
check_by_target=[](){
|
||||
check_by_target = []()
|
||||
{
|
||||
return Util::CheckFile(L"*.xp3") || Util::SearchResourceString(L"TVP(KIRIKIRI)");
|
||||
};
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class LightVN:public ENGINE{
|
||||
class LightVN : public ENGINE
|
||||
{
|
||||
public:
|
||||
LightVN(){
|
||||
LightVN()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE_ANY;
|
||||
is_engine_certain = false;
|
||||
@ -10,4 +12,3 @@ class LightVN:public ENGINE{
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class PPSSPPengine:public ENGINE{
|
||||
class PPSSPPengine : public ENGINE
|
||||
{
|
||||
public:
|
||||
PPSSPPengine(){
|
||||
PPSSPPengine()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE;
|
||||
is_engine_certain = false;
|
||||
|
@ -44,6 +44,8 @@ namespace
|
||||
}
|
||||
bool Ryujinx::attach_function()
|
||||
{
|
||||
WarningOutput("not support ryuujinx, please use yuzu/sudachi instead.");
|
||||
return true;
|
||||
auto invokeCompileMethodHelper = processStartAddress + 0x84CC0;
|
||||
getMethodNameFromMetadata = (decltype(getMethodNameFromMetadata))(processStartAddress + 0x7AED0);
|
||||
HookParam hp;
|
||||
|
@ -1,18 +1,21 @@
|
||||
#include "Suika2.h"
|
||||
|
||||
bool Suika2_msvcrt() {
|
||||
bool Suika2_msvcrt()
|
||||
{
|
||||
auto msvcrt = GetModuleHandle(L"msvcrt.dll");
|
||||
if(msvcrt==0)return 0;
|
||||
if (msvcrt == 0)
|
||||
return 0;
|
||||
auto _strdup = GetProcAddress(msvcrt, "_strdup");
|
||||
if(_strdup==0)return 0;
|
||||
if (_strdup == 0)
|
||||
return 0;
|
||||
HookParam hp;
|
||||
hp.address = (uintptr_t)_strdup;
|
||||
hp.type = USING_STRING | CODEC_UTF8;
|
||||
hp.offset = get_reg(regs::rcx);
|
||||
return NewHook(hp, "Suika2_msvcrt");
|
||||
|
||||
}
|
||||
bool Suika2::attach_function() {
|
||||
bool Suika2::attach_function()
|
||||
{
|
||||
auto _1 = Suika2_msvcrt();
|
||||
return _1;
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class Suika2:public ENGINE{
|
||||
class Suika2 : public ENGINE
|
||||
{
|
||||
public:
|
||||
Suika2(){
|
||||
Suika2()
|
||||
{
|
||||
is_engine_certain = false;
|
||||
check_by = CHECK_BY::FILE_ANY;
|
||||
check_by_target = check_by_list{L"suika.exe", L"conf/config.txt"};
|
||||
|
@ -1,17 +1,21 @@
|
||||
#include "TYPEMOON.h"
|
||||
namespace{
|
||||
bool _h() {
|
||||
namespace
|
||||
{
|
||||
bool _h()
|
||||
{
|
||||
// TYPE-MOON 魔法使いの夜 多国語版 中文-英文-日文
|
||||
BYTE bytes[] = {
|
||||
0xBA, 0x08, 0xFF, 0x00, 0x00,
|
||||
0x41, 0xB8, 0x1C, 0x20, 0x00, 0x00,
|
||||
0x66,0x90
|
||||
};
|
||||
0x66, 0x90};
|
||||
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||||
ConsoleOutput("%p", addr);
|
||||
if(addr==0)return false;
|
||||
addr=MemDbg::findEnclosingAlignedFunction(addr);ConsoleOutput("%p",addr);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
||||
ConsoleOutput("%p", addr);
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.type = CODEC_UTF16 | USING_STRING | EMBED_ABLE | EMBED_AFTER_NEW | EMBED_BEFORE_SIMPLE;
|
||||
@ -19,7 +23,7 @@ bool _h() {
|
||||
return NewHook(hp, "typemoon");
|
||||
}
|
||||
}
|
||||
bool TYPEMOON::attach_function() {
|
||||
bool TYPEMOON::attach_function()
|
||||
{
|
||||
return _h();
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class TYPEMOON:public ENGINE{
|
||||
class TYPEMOON : public ENGINE
|
||||
{
|
||||
public:
|
||||
TYPEMOON(){
|
||||
TYPEMOON()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE;
|
||||
is_engine_certain = false;
|
||||
@ -10,4 +12,3 @@ class TYPEMOON:public ENGINE{
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
@ -208,8 +208,8 @@ namespace{
|
||||
}
|
||||
|
||||
#endif
|
||||
bool V8::attach_function_() {
|
||||
bool V8::attach_function_()
|
||||
{
|
||||
|
||||
return tryhookv8();
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
|
||||
|
||||
class V8:public ENGINE{
|
||||
class V8 : public ENGINE
|
||||
{
|
||||
public:
|
||||
V8(){
|
||||
V8()
|
||||
{
|
||||
check_by = CHECK_BY::CUSTOM;
|
||||
check_by_target=[this](){return attach_function_();};
|
||||
check_by_target = [this]()
|
||||
{ return attach_function_(); };
|
||||
};
|
||||
bool attach_function_();
|
||||
bool attach_function() { return true; }
|
||||
};
|
||||
|
||||
|
@ -3,12 +3,13 @@ bool YOX::attach_function()
|
||||
{
|
||||
const BYTE BYTES[] = {
|
||||
0x48, 0x8B, 0x0F,
|
||||
0x48,0x8d,0x54,0x24,0x50
|
||||
};
|
||||
0x48, 0x8d, 0x54, 0x24, 0x50};
|
||||
auto addrs = Util::SearchMemory(BYTES, sizeof(BYTES), PAGE_EXECUTE_READ, processStartAddress, processStopAddress);
|
||||
ConsoleOutput("%p %p", processStartAddress, processStopAddress);
|
||||
for (auto addr : addrs) {
|
||||
if (addr == 0)continue;
|
||||
for (auto addr : addrs)
|
||||
{
|
||||
if (addr == 0)
|
||||
continue;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.type = USING_STRING;
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class YOX:public ENGINE{
|
||||
class YOX : public ENGINE
|
||||
{
|
||||
public:
|
||||
YOX(){
|
||||
YOX()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE;
|
||||
is_engine_certain = false;
|
||||
@ -10,4 +12,3 @@ class YOX:public ENGINE{
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "livecaptions.h"
|
||||
|
||||
|
||||
bool livecaptions::attach_function()
|
||||
{
|
||||
|
||||
@ -14,16 +13,18 @@ bool livecaptions::attach_function()
|
||||
// .text:0000000180001CAE retn
|
||||
HookParam hp;
|
||||
hp.address = (uintptr_t)GetProcAddress(GetModuleHandle(L"vcruntime140_app.dll"), "memmove");
|
||||
hp.text_fun=[](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len){
|
||||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
BYTE sig[] = {
|
||||
0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0xD9,
|
||||
0xE8,XX4
|
||||
};
|
||||
0xE8, XX4};
|
||||
auto a1 = stack->retaddr - sizeof(sig);
|
||||
if ((stack->retaddr > (uintptr_t)GetModuleHandle(L"Microsoft.CognitiveServices.Speech.extension.embedded.sr.dll")))
|
||||
if(memcmp((void*)a1,&sig,sizeof(sig)-4)==0){
|
||||
if (memcmp((void *)a1, &sig, sizeof(sig) - 4) == 0)
|
||||
{
|
||||
static std::set<uintptr_t> once;
|
||||
if(once.find(stack->retaddr)!=once.end())return;
|
||||
if (once.find(stack->retaddr) != once.end())
|
||||
return;
|
||||
once.insert(stack->retaddr);
|
||||
// hp->text_fun=nullptr;
|
||||
// hp->type=HOOK_EMPTY;
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class lucasystem:public ENGINE{
|
||||
class lucasystem : public ENGINE
|
||||
{
|
||||
public:
|
||||
lucasystem(){
|
||||
lucasystem()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE;
|
||||
is_engine_certain = false;
|
||||
@ -10,4 +12,3 @@ class lucasystem:public ENGINE{
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
@ -1,11 +1,14 @@
|
||||
#include "mono.h"
|
||||
#include "mono/monocommon.hpp"
|
||||
|
||||
namespace{
|
||||
bool monobdwgc() {
|
||||
namespace
|
||||
{
|
||||
bool monobdwgc()
|
||||
{
|
||||
|
||||
HMODULE module = GetModuleHandleW(L"mono-2.0-bdwgc.dll");
|
||||
if (module == 0)return false;
|
||||
if (module == 0)
|
||||
return false;
|
||||
auto [minAddress, maxAddress] = Util::QueryModuleLimits(module);
|
||||
BYTE bytes[] = {
|
||||
0x81, 0xF9, 0x80, 0x00, 0x00, 0x00,
|
||||
@ -39,26 +42,30 @@ _BYTE *__fastcall sub_18005B290(
|
||||
};
|
||||
auto addrs = Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, minAddress, maxAddress);
|
||||
auto suc = false;
|
||||
for (auto addr : addrs) {
|
||||
for (auto addr : addrs)
|
||||
{
|
||||
const BYTE align[] = {0xCC, 0xCC, 0xCC, 0xCC};
|
||||
addr = reverseFindBytes(align, sizeof(align), addr - 0x100, addr);
|
||||
if(addr==0)continue;
|
||||
if (addr == 0)
|
||||
continue;
|
||||
|
||||
ConsoleOutput("monobdwgcdll %p", addr);
|
||||
HookParam hp;
|
||||
hp.address = addr + 4;
|
||||
hp.offset = get_reg(regs::rcx);
|
||||
hp.type = CODEC_UTF16 | USING_STRING;
|
||||
hp.text_fun=[](auto, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
|
||||
hp.text_fun = [](auto, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
std::wstring str = std::wstring((LPWSTR)*data);
|
||||
*split = str.find(L"OnShowComplete") != str.npos;
|
||||
|
||||
*len = wcslen((wchar_t *)*data) * 2;
|
||||
};
|
||||
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
|
||||
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
std::wstring str = std::wstring((LPWSTR)data, *len / 2);
|
||||
if(str.find(L"OnShowComplete")!=str.npos){
|
||||
if (str.find(L"OnShowComplete") != str.npos)
|
||||
{
|
||||
str = std::regex_replace(str, std::wregex(L"\n"), L"");
|
||||
std::wregex reg1(L"\\((.*?)\\)");
|
||||
std::wsmatch match;
|
||||
@ -76,7 +83,8 @@ _BYTE *__fastcall sub_18005B290(
|
||||
return suc;
|
||||
}
|
||||
}
|
||||
bool mono::attach_function(){
|
||||
bool mono::attach_function()
|
||||
{
|
||||
bool common = monocommon::hook_mono_il2cpp();
|
||||
return common;
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class mono:public ENGINE{
|
||||
class mono : public ENGINE
|
||||
{
|
||||
public:
|
||||
mono(){
|
||||
mono()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::ALL_TRUE;
|
||||
};
|
||||
|
@ -1,10 +1,14 @@
|
||||
#include "pchooks.h"
|
||||
|
||||
bool pchooks::attach_function() {
|
||||
bool pchooks::attach_function()
|
||||
{
|
||||
for (std::wstring DXVersion : {L"d3dx9", L"d3dx10"})
|
||||
if (HMODULE module = GetModuleHandleW(DXVersion.c_str())) PcHooks::hookD3DXFunctions(module);
|
||||
else for (int i = 0; i < 50; ++i)
|
||||
if (HMODULE module = GetModuleHandleW((DXVersion + L"_" + std::to_wstring(i)).c_str())) PcHooks::hookD3DXFunctions(module);
|
||||
if (HMODULE module = GetModuleHandleW(DXVersion.c_str()))
|
||||
PcHooks::hookD3DXFunctions(module);
|
||||
else
|
||||
for (int i = 0; i < 50; ++i)
|
||||
if (HMODULE module = GetModuleHandleW((DXVersion + L"_" + std::to_wstring(i)).c_str()))
|
||||
PcHooks::hookD3DXFunctions(module);
|
||||
|
||||
PcHooks::hookGDIFunctions();
|
||||
PcHooks::hookGDIPlusFunctions();
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class pchooks:public ENGINE{
|
||||
class pchooks : public ENGINE
|
||||
{
|
||||
public:
|
||||
pchooks(){
|
||||
pchooks()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::ALL_TRUE;
|
||||
dontstop = true;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include"rpcs3.h"
|
||||
namespace{
|
||||
#include "rpcs3.h"
|
||||
namespace
|
||||
{
|
||||
#if 0 // only support0.0.20-0.0.27
|
||||
int emoffset;
|
||||
int jitoffset;
|
||||
@ -115,7 +116,8 @@ namespace{
|
||||
}
|
||||
#endif
|
||||
|
||||
uintptr_t getDoJitAddress() {
|
||||
uintptr_t getDoJitAddress()
|
||||
{
|
||||
// rpcs3/Emu/Cell/PPUThread.cpp
|
||||
/*
|
||||
extern void ppu_register_function_at(u32 addr, u32 size, ppu_intrp_func_t ptr = nullptr)
|
||||
@ -141,40 +143,49 @@ namespace{
|
||||
char log[] = "ppu_register_function_at(0x%x): empty range";
|
||||
auto logstrptr = MemDbg::findBytes(log, sizeof(log), processStartAddress, processStopAddress);
|
||||
ConsoleOutput("%p", logstrptr);
|
||||
if(logstrptr==0)return 0;
|
||||
if (logstrptr == 0)
|
||||
return 0;
|
||||
auto addr = MemDbg::findleaaddr(logstrptr, processStartAddress, processStopAddress);
|
||||
ConsoleOutput("%p", addr);
|
||||
if(addr==0)return 0;
|
||||
if (addr == 0)
|
||||
return 0;
|
||||
// ff cc cc cc,find不到。。
|
||||
BYTE start[] = {XX, 0xCC, 0xCC, 0xCC};
|
||||
addr = reverseFindBytes(start, sizeof(start), addr - 0x200, addr, 4, true);
|
||||
ConsoleOutput("%p", addr);
|
||||
return addr;
|
||||
|
||||
}
|
||||
struct emfuncinfo{
|
||||
struct emfuncinfo
|
||||
{
|
||||
uint64_t type;
|
||||
int argidx;int padding;
|
||||
int argidx;
|
||||
int padding;
|
||||
void *hookfunc;
|
||||
void *filterfun;
|
||||
const char *_id;
|
||||
};
|
||||
std::unordered_map<uintptr_t, emfuncinfo> emfunctionhooks;
|
||||
|
||||
bool checkiscurrentgame(const emfuncinfo& em){
|
||||
bool checkiscurrentgame(const emfuncinfo &em)
|
||||
{
|
||||
auto wininfos = get_proc_windows();
|
||||
for(auto&& info:wininfos){
|
||||
if(info.title.find(acastw(em._id))!=info.title.npos)return true;
|
||||
for (auto &&info : wininfos)
|
||||
{
|
||||
if (info.title.find(acastw(em._id)) != info.title.npos)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::set<std::pair<uintptr_t, uintptr_t>> timeoutbreaks;
|
||||
|
||||
void dohookemaddr(uintptr_t em_address,uintptr_t ret){
|
||||
void dohookemaddr(uintptr_t em_address, uintptr_t ret)
|
||||
{
|
||||
jitaddraddr(em_address, ret, JITTYPE::RPCS3);
|
||||
if(emfunctionhooks.find(em_address)==emfunctionhooks.end())return;
|
||||
if(!(checkiscurrentgame(emfunctionhooks.at(em_address))))return;
|
||||
if (emfunctionhooks.find(em_address) == emfunctionhooks.end())
|
||||
return;
|
||||
if (!(checkiscurrentgame(emfunctionhooks.at(em_address))))
|
||||
return;
|
||||
timeoutbreaks.insert(std::make_pair(em_address, ret));
|
||||
auto op = emfunctionhooks.at(em_address);
|
||||
HookParam hpinternal;
|
||||
@ -189,7 +200,8 @@ void dohookemaddr(uintptr_t em_address,uintptr_t ret){
|
||||
NewHook(hpinternal, op._id);
|
||||
}
|
||||
|
||||
bool unsafeinithooks(){
|
||||
bool unsafeinithooks()
|
||||
{
|
||||
// rpcs0.0.30,不知道为什么ppu_register_function_at不全。不过看代码得到映射表了,直接弄吧。
|
||||
// rpcs3/Emu/Cell/PPUThread.cpp
|
||||
// Get pointer to executable cache
|
||||
@ -204,48 +216,54 @@ bool unsafeinithooks(){
|
||||
hp.address = 0x500000000;
|
||||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
for(auto [addr,info]:emfunctionhooks){
|
||||
for (auto [addr, info] : emfunctionhooks)
|
||||
{
|
||||
auto table = addr * 2 + 0x500000000;
|
||||
if(IsBadReadPtr((void*)table,sizeof(uintptr_t)))continue;
|
||||
if (IsBadReadPtr((void *)table, sizeof(uintptr_t)))
|
||||
continue;
|
||||
auto funcaddr = *(uintptr_t *)table;
|
||||
funcaddr &= 0x0000ffffffffffff;
|
||||
if(!funcaddr)continue;
|
||||
if (!funcaddr)
|
||||
continue;
|
||||
auto p = std::make_pair(addr, funcaddr);
|
||||
if(timeoutbreaks.find(p)!=timeoutbreaks.end())continue;
|
||||
if (timeoutbreaks.find(p) != timeoutbreaks.end())
|
||||
continue;
|
||||
dohookemaddr(addr, funcaddr);
|
||||
delayinsertNewHook(addr);
|
||||
}
|
||||
};
|
||||
return NewHook(hp, "g_exec_addr");
|
||||
|
||||
}
|
||||
}
|
||||
bool rpcs3::attach_function()
|
||||
{
|
||||
ConsoleOutput("[Compatibility] RPCS3");
|
||||
auto DoJitPtr = getDoJitAddress();
|
||||
if(DoJitPtr==0)return false;
|
||||
if (DoJitPtr == 0)
|
||||
return false;
|
||||
unsafeinithooks();
|
||||
spDefault.jittype = JITTYPE::RPCS3;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1;
|
||||
HookParam hp;
|
||||
hp.address = DoJitPtr;
|
||||
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
|
||||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
auto em_address = stack->rcx; // *(uint32_t*)*(uintptr_t*)(stack->base+emoffset);
|
||||
auto entrypoint = stack->r8; //*(uintptr_t*)*(uintptr_t*)(stack->base+jitoffset)-0x0008000000000000;
|
||||
if(!em_address||!entrypoint)return;
|
||||
if (!em_address || !entrypoint)
|
||||
return;
|
||||
dohookemaddr(em_address, entrypoint);
|
||||
delayinsertNewHook(em_address);
|
||||
};
|
||||
return NewHook(hp, "vita3kjit");
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
namespace{
|
||||
|
||||
bool FBLJM61131(void* data, size_t* len, HookParam* hp){
|
||||
bool FBLJM61131(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
std::regex pattern("\\[[^\\]]+.");
|
||||
s = std::regex_replace(s, pattern, "");
|
||||
@ -254,7 +272,8 @@ bool FBLJM61131(void* data, size_t* len, HookParam* hp){
|
||||
s = std::regex_replace(s, std::regex("\\n+"), " ");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
auto _=[](){
|
||||
auto _ = []()
|
||||
{
|
||||
emfunctionhooks = {
|
||||
//'&' -Sora no Mukou de Sakimasu you ni-
|
||||
{0x46328, {CODEC_UTF8, 1, 0, 0, FBLJM61131, "BLJM61131"}},
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class rpcs3:public ENGINE{
|
||||
class rpcs3 : public ENGINE
|
||||
{
|
||||
public:
|
||||
rpcs3(){
|
||||
rpcs3()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE;
|
||||
is_engine_certain = false;
|
||||
@ -10,4 +12,3 @@ class rpcs3:public ENGINE{
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
@ -1,12 +1,15 @@
|
||||
#include"vita3k.h"
|
||||
namespace{
|
||||
#include "vita3k.h"
|
||||
namespace
|
||||
{
|
||||
auto isVirtual = true;
|
||||
auto idxDescriptor = isVirtual == true ? 2 : 1;
|
||||
auto idxEntrypoint = idxDescriptor + 1;
|
||||
uintptr_t getDoJitAddress() {
|
||||
uintptr_t getDoJitAddress()
|
||||
{
|
||||
auto RegisterBlockSig1 = "40 55 53 56 57 41 54 41 56 41 57 48 8D 6C 24 E9 48 81 EC 90 00 00 00 48 8B ?? ?? ?? ?? ?? 48 33 C4 48 89 45 07 4D 8B F1 49 8B F0 48 8B FA 48 8B D9 4C 8B 7D 77 48 8B 01 48 8D 55 C7 FF 50 10";
|
||||
auto first = find_pattern(RegisterBlockSig1, processStartAddress, processStopAddress);
|
||||
if (first) return first;
|
||||
if (first)
|
||||
return first;
|
||||
/*
|
||||
// DebugSymbol: RegisterBlock
|
||||
// ?RegisterBlock@EmitX64@X64@Backend@Dynarmic@@IEAA?AUBlockDescriptor@1234@AEBVLocationDescriptor@IR@4@PEBX_K@Z <- new
|
||||
@ -21,26 +24,32 @@ namespace{
|
||||
*/
|
||||
auto PatchBlockSig1 = "4C 8B DC 49 89 5B 10 49 89 6B 18 56 57 41 54 41 56 41 57"; // "4C 8B DC 49 89 5B ?? 49 89 6B ?? 56 57 41 54 41 56 41 57";
|
||||
first = find_pattern(PatchBlockSig1, processStartAddress, processStopAddress);
|
||||
if (first) {
|
||||
if (first)
|
||||
{
|
||||
idxDescriptor = 1;
|
||||
idxEntrypoint = 2;
|
||||
return first;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
struct emfuncinfo{
|
||||
struct emfuncinfo
|
||||
{
|
||||
uint64_t type;
|
||||
int argidx;int padding;
|
||||
int argidx;
|
||||
int padding;
|
||||
void *hookfunc;
|
||||
void *filterfun;
|
||||
const char *_id;
|
||||
};
|
||||
std::unordered_map<uintptr_t, emfuncinfo> emfunctionhooks;
|
||||
|
||||
bool checkiscurrentgame(const emfuncinfo& em){
|
||||
bool checkiscurrentgame(const emfuncinfo &em)
|
||||
{
|
||||
auto wininfos = get_proc_windows();
|
||||
for(auto&& info:wininfos){
|
||||
if(info.title.find(acastw(em._id))!=info.title.npos)return true;
|
||||
for (auto &&info : wininfos)
|
||||
{
|
||||
if (info.title.find(acastw(em._id)) != info.title.npos)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -50,24 +59,30 @@ bool vita3k::attach_function()
|
||||
{
|
||||
ConsoleOutput("[Compatibility] Vita3k 0.1.9 3520+");
|
||||
auto DoJitPtr = getDoJitAddress();
|
||||
if(DoJitPtr==0)return false;
|
||||
if (DoJitPtr == 0)
|
||||
return false;
|
||||
ConsoleOutput("DoJitPtr %p", DoJitPtr);
|
||||
spDefault.jittype = JITTYPE::VITA3K;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1;
|
||||
HookParam hp;
|
||||
hp.address = DoJitPtr;
|
||||
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
auto descriptor = *argidx(stack, idxDescriptor + 1); // r8
|
||||
auto entrypoint = *argidx(stack, idxEntrypoint + 1); // r9
|
||||
auto em_address = *(uint32_t *)descriptor;
|
||||
if(!entrypoint)return;
|
||||
if (!entrypoint)
|
||||
return;
|
||||
// ConsoleOutput("%p",em_address);
|
||||
jitaddraddr(em_address, entrypoint, JITTYPE::VITA3K);
|
||||
[&](){
|
||||
if(emfunctionhooks.find(em_address)==emfunctionhooks.end())return;
|
||||
[&]()
|
||||
{
|
||||
if (emfunctionhooks.find(em_address) == emfunctionhooks.end())
|
||||
return;
|
||||
auto op = emfunctionhooks.at(em_address);
|
||||
if(!(checkiscurrentgame(op)))return;
|
||||
if (!(checkiscurrentgame(op)))
|
||||
return;
|
||||
|
||||
HookParam hpinternal;
|
||||
hpinternal.address = entrypoint;
|
||||
@ -85,9 +100,10 @@ bool vita3k::attach_function()
|
||||
return NewHook(hp, "vita3kjit");
|
||||
}
|
||||
|
||||
|
||||
namespace{
|
||||
bool FPCSG01023(void* data, size_t* len, HookParam* hp){
|
||||
namespace
|
||||
{
|
||||
bool FPCSG01023(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("<br>"), "");
|
||||
s = std::regex_replace(s, std::regex("%CF11F"), "");
|
||||
@ -98,35 +114,45 @@ bool FPCSG01023(void* data, size_t* len, HookParam* hp){
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
template <int idx>
|
||||
bool FPCSG01282(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG01282(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("(\\n)+"), " ");
|
||||
s = std::regex_replace(s, std::regex("\\d$|^@[a-z]+|#.*?#|\\$"), "");
|
||||
static std::string last;
|
||||
if(last==s)return false;
|
||||
if (last == s)
|
||||
return false;
|
||||
last = s;
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
|
||||
template <int index>
|
||||
void ReadU16TextAndLenDW(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
void ReadU16TextAndLenDW(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
auto address = VITA3K::emu_arg(stack)[index];
|
||||
*len = (*(DWORD *)(address + 0x8)) * 2;
|
||||
*data = address + 0xC;
|
||||
}
|
||||
|
||||
bool FPCSG00410(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG00410(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("#[A-Za-z]+\\[(\\d*[.])?\\d+\\]"), "");
|
||||
s = std::regex_replace(s, std::regex("#Pos\\[[\\s\\S]*?\\]"), "");
|
||||
s = std::regex_replace(s, std::regex("#n"), " ");
|
||||
// .replaceAll("④", "!?").replaceAll("②", "!!").replaceAll("⑥", "。").replaceAll("⑪", "【")
|
||||
// .replaceAll("⑫", "】").replaceAll("⑤", "、").replaceAll("①", "・・・")
|
||||
strReplace(s,"\x87\x43","!?");strReplace(s,"\x87\x41","!!");strReplace(s,"\x87\x45","\x81\x42");strReplace(s,"\x87\x4a","\x81\x79");
|
||||
strReplace(s,"\x87\x4b","\x81\x7a");strReplace(s,"\x87\x44","\x81\x41");strReplace(s,"\x87\x40","\x81\x45\x81\x45\x81\x45");
|
||||
strReplace(s, "\x87\x43", "!?");
|
||||
strReplace(s, "\x87\x41", "!!");
|
||||
strReplace(s, "\x87\x45", "\x81\x42");
|
||||
strReplace(s, "\x87\x4a", "\x81\x79");
|
||||
strReplace(s, "\x87\x4b", "\x81\x7a");
|
||||
strReplace(s, "\x87\x44", "\x81\x41");
|
||||
strReplace(s, "\x87\x40", "\x81\x45\x81\x45\x81\x45");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00448(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG00448(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("[\\s]"), "");
|
||||
s = std::regex_replace(s, std::regex("(#n)+"), "");
|
||||
@ -134,35 +160,48 @@ bool FPCSG00448(void* data, size_t* len, HookParam* hp){
|
||||
s = std::regex_replace(s, std::regex("#Pos[\\s\\S]*?\\]"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG01008(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG01008(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("#Ruby\\[([^,]+)\\.([^\\]]+)\\]."), "$1");
|
||||
s = std::regex_replace(s, std::regex("(#n)+"), " ");
|
||||
s = std::regex_replace(s, std::regex("#[A-Za-z]+\\[(\\d*[.])?\\d+\\]"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
void TPCSG00903(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
void TPCSG00903(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
auto address = VITA3K::emu_arg(stack)[0];
|
||||
*len = (*(DWORD *)(address + 0x14));
|
||||
*data = address + 0x1C;
|
||||
}
|
||||
bool FPCSG00903(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG00903(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("\\\\n"), " ");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00839(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG01180(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex(R"(\\n)"), " ");
|
||||
s = std::regex_replace(s, std::regex(R"(,.*$)"), " ");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00839(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::wstring((wchar_t *)data, *len / 2);
|
||||
s = std::regex_replace(s, std::wregex(L"\\[[^\\]]+."), L"");
|
||||
s = std::regex_replace(s, std::wregex(L"\\\\k|\\\\x|%C|%B|%p-1;"), L"");
|
||||
s = std::regex_replace(s, std::wregex(L"#[0-9a-fA-F]+;([^%#]+)(%r)?"), L"$1");
|
||||
s = std::regex_replace(s, std::wregex(L"\\\\n"), L"");
|
||||
static std::wstring last;
|
||||
if(last.find(s)!=last.npos)return false;
|
||||
if (last.find(s) != last.npos)
|
||||
return false;
|
||||
last = s;
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00751(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG00751(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("[\\s]"), "");
|
||||
s = std::regex_replace(s, std::regex("@[a-z]"), "");
|
||||
@ -170,12 +209,28 @@ bool FPCSG00751(void* data, size_t* len, HookParam* hp){
|
||||
strReplace(s, "\x81\x90", "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00706(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG00401(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex(R"([\s])"), "");
|
||||
s = std::regex_replace(s, std::regex(R"(\c)"), "");
|
||||
s = std::regex_replace(s, std::regex(R"(\\n)"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00912(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("%N"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00706(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::wstring((wchar_t *)data, *len / 2);
|
||||
s = std::regex_replace(s, std::wregex(L"<br>"), L"");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00696(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG00696(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
//.replace(/㌔/g, '⁉')
|
||||
//.replace(/㍉/g, '!!')
|
||||
@ -183,7 +238,8 @@ bool FPCSG00696(void* data, size_t* len, HookParam* hp){
|
||||
strReplace(s, "\x87\x5f", "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00389(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG00389(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("[\\s]"), "");
|
||||
s = std::regex_replace(s, std::regex("(#n)+"), "");
|
||||
@ -191,7 +247,8 @@ bool FPCSG00389(void* data, size_t* len, HookParam* hp){
|
||||
s = std::regex_replace(s, std::regex("#Pos\\[[\\s\\S]*?\\]"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00216(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG00216(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("[\\s]"), "");
|
||||
s = std::regex_replace(s, std::regex("(#n)+"), "");
|
||||
@ -199,46 +256,52 @@ bool FPCSG00216(void* data, size_t* len, HookParam* hp){
|
||||
s = std::regex_replace(s, std::regex("#Pos\\[[\\s\\S]*?\\]"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00405(void* data, size_t* len, HookParam* hp){
|
||||
bool FPCSG00405(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex("[\\s]"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool PCSG00776(void* data, size_t* len, HookParam* hp){
|
||||
bool PCSG00776(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
auto ws = StringToWideString(s, 932).value();
|
||||
strReplace(ws, L"\x02", L"");
|
||||
Trim(ws);
|
||||
return write_string_overwrite(data, len, WideStringToString(ws));
|
||||
}
|
||||
|
||||
void PCSG00911(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
void PCSG00912(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
auto address = VITA3K::emu_arg(stack)[1];
|
||||
std::string final_string = "";
|
||||
BYTE pattern[] = {0x47, 0xff, 0xff};
|
||||
auto results = MemDbg::findBytes(pattern, sizeof(pattern), address, address + 0x50);
|
||||
if (!results) return;
|
||||
if (!results)
|
||||
return;
|
||||
|
||||
address = results + 5;
|
||||
|
||||
while (true) {
|
||||
while (true)
|
||||
{
|
||||
std::string text = (char *)address;
|
||||
final_string += text;
|
||||
address = address + (text.size() + 1);
|
||||
|
||||
auto bytes = (BYTE *)address;
|
||||
|
||||
if (!(bytes[0] == 0x48 && bytes[1] == 0xFF && bytes[2] == 0xFF)) break;
|
||||
if (!(bytes[0] == 0x48 && bytes[1] == 0xFF && bytes[2] == 0xFF))
|
||||
break;
|
||||
address = address + (3);
|
||||
bytes = (BYTE *)address;
|
||||
if (!(bytes[0] == 0x47 && bytes[1] == 0xFF && bytes[2] == 0xFF)) break;
|
||||
if (!(bytes[0] == 0x47 && bytes[1] == 0xFF && bytes[2] == 0xFF))
|
||||
break;
|
||||
|
||||
address = address + (5);
|
||||
|
||||
}
|
||||
write_string_new(data, len, final_string);
|
||||
}
|
||||
void TPCSG00291(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
void TPCSG00291(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
auto a2 = VITA3K::emu_arg(stack)[0];
|
||||
|
||||
auto vm = *(DWORD *)(a2 + (0x28));
|
||||
@ -247,7 +310,8 @@ void TPCSG00291(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* sp
|
||||
uintptr_t address = VITA3K::emu_addr(stack, vm);
|
||||
auto len1 = *(DWORD *)(address + 4);
|
||||
auto p = address + 0x20;
|
||||
if(len1>4 && *(WORD*)(p+2)==0){
|
||||
if (len1 > 4 && *(WORD *)(p + 2) == 0)
|
||||
{
|
||||
auto p1 = *(DWORD *)(address + 8);
|
||||
vm = *(DWORD *)VITA3K::emu_addr(stack, vm);
|
||||
vm = *(DWORD *)VITA3K::emu_addr(stack, vm + 0xC);
|
||||
@ -256,49 +320,142 @@ void TPCSG00291(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* sp
|
||||
static int fm = 0;
|
||||
static std::string pre;
|
||||
auto b = fm;
|
||||
auto s=[](uintptr_t address){
|
||||
auto s = [](uintptr_t address)
|
||||
{
|
||||
auto frist = *(WORD *)address;
|
||||
auto lo = frist & 0xFF; // uppercase: 41->5A
|
||||
auto hi = frist >> 8;
|
||||
if (hi == 0 && (lo > 0x5a || lo < 0x41) /* T,W,? */) {
|
||||
if (hi == 0 && (lo > 0x5a || lo < 0x41) /* T,W,? */)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
std::string s ;int i = 0;WORD c;
|
||||
std::string s;
|
||||
int i = 0;
|
||||
WORD c;
|
||||
char buf[3] = {0};
|
||||
while ((c = *(WORD*)(address+i)) != 0) {
|
||||
while ((c = *(WORD *)(address + i)) != 0)
|
||||
{
|
||||
// reverse endian: ShiftJIS BE => LE
|
||||
buf[0] = c >> 8;
|
||||
buf[1] = c & 0xFF;
|
||||
|
||||
if (c == 0x815e /* / */) {
|
||||
if (c == 0x815e /* / */)
|
||||
{
|
||||
s += ' '; // single line
|
||||
}
|
||||
else if (buf[0] == 0) {
|
||||
else if (buf[0] == 0)
|
||||
{
|
||||
//// UTF16 LE turned BE: 5700=>0057, 3100, 3500
|
||||
//// 4e00 6d00=>PLAYER
|
||||
// do nothing
|
||||
if (buf[1] == 0x4e) {
|
||||
if (buf[1] == 0x4e)
|
||||
{
|
||||
s += "PLAYER";
|
||||
fm++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
s += buf;
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
return s;
|
||||
}(p);
|
||||
if(b>0){
|
||||
if (b > 0)
|
||||
{
|
||||
fm--;
|
||||
return;
|
||||
}
|
||||
if(s==pre)return ;
|
||||
if (s == pre)
|
||||
return;
|
||||
pre = s;
|
||||
write_string_new(data, len, s);
|
||||
}
|
||||
|
||||
auto _=[](){
|
||||
bool FPCSG00468(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex(R"(\\n\u3000*|\\k)"), "");
|
||||
s = std::regex_replace(s, std::regex(R"(\[|\*[^\]]+])"), "");
|
||||
s = std::regex_replace(s, std::regex(u8"×"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00808(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex(R"(^\s+|\s+$)"), "");
|
||||
s = std::regex_replace(s, std::regex(R"(\s*(#n)*\s*)"), "");
|
||||
s = std::regex_replace(s, std::regex(R"(#\w+(\[.+?\])?)"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00855(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex(R"(#n\u3000*)"), "");
|
||||
s = std::regex_replace(s, std::regex(R"(#\w.+?])"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
template <int idx>
|
||||
bool FPCSG00855_2(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
static std::string last;
|
||||
if (last == s)
|
||||
return false;
|
||||
last = s;
|
||||
strReplace(s, u8"Χ", u8"、");
|
||||
strReplace(s, u8"Δ", u8"。");
|
||||
strReplace(s, u8"Λ", u8"っ");
|
||||
strReplace(s, u8"《", u8"(");
|
||||
strReplace(s, u8"》", u8")");
|
||||
strReplace(s, u8"∫", u8"「");
|
||||
strReplace(s, u8"∨", u8"」");
|
||||
strReplace(s, u8"∴", u8"『");
|
||||
strReplace(s, u8"∵", u8"』");
|
||||
strReplace(s, u8"П", u8"【");
|
||||
strReplace(s, u8"Ц", u8"】");
|
||||
if (write_string_overwrite(data, len, s))
|
||||
return FPCSG00855(data, len, hp);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
bool FPCSG00477(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
auto ws = StringToWideString(s, 932).value();
|
||||
ws = std::regex_replace(ws, std::wregex(LR"(#n\u3000*)"), L"");
|
||||
ws = std::regex_replace(ws, std::wregex(LR"(#\w.+?])"), L"");
|
||||
s = WideStringToString(ws, 932);
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG00852(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
auto ws = StringToWideString(s, 932).value();
|
||||
ws = std::regex_replace(ws, std::wregex(LR"(\^)"), L"");
|
||||
s = WideStringToString(ws, 932);
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG01066(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
s = std::regex_replace(s, std::regex(R"(\n\u3000*)"), "");
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
bool FPCSG01075(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
if (!FPCSG00808(data, len, hp))
|
||||
return false;
|
||||
auto s = std::string((char *)data, *len);
|
||||
static std::string last;
|
||||
if (last == s)
|
||||
return false;
|
||||
last = s;
|
||||
return true;
|
||||
}
|
||||
auto _ = []()
|
||||
{
|
||||
emfunctionhooks = {
|
||||
// Tsuihou Senkyo
|
||||
{0x8002e176, {0, 0, 0, 0, FPCSG01023, "PCSG01023"}}, // dialogue+name,sjis
|
||||
@ -316,8 +473,6 @@ auto _=[](){
|
||||
// Marginal #4 Road to Galaxy
|
||||
{0x8002ff90, {CODEC_UTF8, 0, 0, 0, FPCSG01008, "PCSG01008"}}, // text
|
||||
// BLACK WOLVES SAGA -Weiβ und Schwarz-
|
||||
// {0x8004ed22,{CODEC_UTF8,0,0,0,FPCSG01008,"PCSG00935"}},//name
|
||||
// {0x8006d202,{CODEC_UTF8,1,2,0,FPCSG01008,"PCSG00935"}},//text
|
||||
{0x800581a2, {CODEC_UTF8, 0, 0, 0, FPCSG01008, "PCSG00935"}}, // text
|
||||
// New Game! The Challenge Stage!
|
||||
{0x8012674c, {CODEC_UTF8, 0, 0, TPCSG00903, FPCSG00903, "PCSG00903"}},
|
||||
@ -341,8 +496,7 @@ auto _=[](){
|
||||
// Nekketsu Inou Bukatsu-tan Trigger Kiss
|
||||
{0x8004e44a, {0, 0, 0, 0, FPCSG00410, "PCSG00410"}}, // dialogue,sjis
|
||||
// バイナリースター Binary Star
|
||||
{0x80058608,{0,1,0,0,FPCSG00389,"PCSG00389"}},//dialogue,sjis
|
||||
{0x80021292,{0,0,0,0,FPCSG00389,"PCSG00389"}},//name
|
||||
{0x80058606, {0, 1, 0xd, 0, FPCSG00389, "PCSG00389"}}, // dialogue,sjis
|
||||
// Amagami
|
||||
{0x80070658, {0, 0, 0, TPCSG00291, 0, "PCSG00291"}},
|
||||
// Rui wa Tomo o Yobu
|
||||
@ -355,9 +509,56 @@ auto _=[](){
|
||||
// Re:Birthday Song ~Koi o Utau Shinigami~
|
||||
{0x80033af6, {0, 0, 2, 0, 0, "PCSG00911"}}, // dialogue
|
||||
// Un:Birthday Song ~Ai o Utau Shinigami~
|
||||
{0x80038538,{0,0,0,PCSG00911,0,"PCSG00911"}},
|
||||
{0x80004b52,{0,3,5,0,0,"PCSG00911"}},
|
||||
{0x80038538, {0, 0, 0, PCSG00912, 0, "PCSG00912"}},
|
||||
{0x80033d66, {0, 3, 4, 0, FPCSG00912, "PCSG00912"}},
|
||||
// Sora*yume
|
||||
{0x8000bad4, {0, 1, 0, 0, FPCSG00401, "PCSG00401"}},
|
||||
// Tengai ni Mau, Iki na Hana
|
||||
|
||||
{0x8006808e, {CODEC_UTF8, 0, 0, 0, FPCSG01180, "PCSG01180"}},
|
||||
{0x80089408, {CODEC_UTF8, 0, 0, 0, FPCSG01180, "PCSG01180"}},
|
||||
|
||||
// Kokuchou no Psychedelica (黒蝶のサイケデリカ)
|
||||
{0x80043538, {CODEC_UTF8, 1, 0, 0, FPCSG00468, "PCSG00468"}},
|
||||
// Haitaka no Psychedelica (灰鷹のサイケデリカ)
|
||||
{0x80022c06, {CODEC_UTF8, 4, 0, 0, FPCSG00468, "PCSG00812"}},
|
||||
// Yuukyuu no Tierblade -Lost Chronicle- (悠久のティアブレイド -Lost Chronicle-)
|
||||
{0x8003542a, {CODEC_UTF8, 10, 0, 0, FPCSG00808, "PCSG00808"}},
|
||||
{0x8002a95a, {CODEC_UTF8, 6, 0, 0, FPCSG00808, "PCSG00808"}},
|
||||
{0x801a98aa, {CODEC_UTF8, 9, 0, 0, FPCSG00808, "PCSG00808"}},
|
||||
{0x801a42bc, {CODEC_UTF8, 9, 0, 0, FPCSG00808, "PCSG00808"}},
|
||||
{0x801a42d0, {CODEC_UTF8, 7, 0, 0, FPCSG00808, "PCSG00808"}},
|
||||
// Yuukyuu no Tierblade -Fragments of Memory- (悠久のティアブレイド -Fragments of Memory-)
|
||||
{0x80035f44, {CODEC_UTF8, 10, 0, 0, FPCSG01075, "PCSG01075"}},
|
||||
{0x8000d868, {CODEC_UTF8, 9, 0, 0, FPCSG01075, "PCSG01075"}},
|
||||
{0x8004598e, {CODEC_UTF8, 0, 0, 0, FPCSG01075, "PCSG01075"}},
|
||||
{0x801b1d16, {CODEC_UTF8, 9, 0, 0, FPCSG01075, "PCSG01075"}},
|
||||
{0x801ac31e, {CODEC_UTF8, 9, 0, 0, FPCSG01075, "PCSG01075"}},
|
||||
{0x801ac33a, {CODEC_UTF8, 7, 0, 0, FPCSG01075, "PCSG01075"}},
|
||||
{0x801b879a, {CODEC_UTF8, 5, 0, 0, FPCSG01075, "PCSG01075"}},
|
||||
{0x8009f570, {CODEC_UTF8, 5, 0, 0, FPCSG01075, "PCSG01075"}},
|
||||
// Magic Kyun! Renaissance (マジきゅんっ!ルネッサンス)
|
||||
{0x8008375a, {0, 1, 0, 0, FPCSG00852, "PCSG00852"}},
|
||||
{0x8001c194, {0, 1, 0, 0, FPCSG00852, "PCSG00852"}},
|
||||
// Chouchou Jiken Lovesodic / Chouchou Jiken Rhapsodic (蝶々事件ラブソディック)
|
||||
{0x8008dea2, {CODEC_UTF8, 4, 0, 0, FPCSG01066, "PCSG01066"}},
|
||||
{0x8008eb38, {CODEC_UTF8, 0, 0, 0, FPCSG01066, "PCSG01066"}},
|
||||
// Hyakka Yakou (百華夜光)
|
||||
{0x80032b30, {0, 8, 0, 0, 0, "PCSG00477"}},
|
||||
{0x80019c5a, {0, 5, 0, 0, 0, "PCSG00477"}},
|
||||
{0x80031a46, {0, 6, 0, 0, 0, "PCSG00477"}},
|
||||
{0x8003a49a, {0, 0, 0, 0, FPCSG00477, "PCSG00477"}},
|
||||
{0x80182532, {0, 7, 0, 0, FPCSG00477, "PCSG00477"}},
|
||||
{0x8017d1da, {0, 5, 0, 0, 0, "PCSG00477"}},
|
||||
{0x8017d478, {0, 4, 0, 0, 0, "PCSG00477"}},
|
||||
{0x8017a6aa, {0, 6, 0, 0, 0, "PCSG00477"}},
|
||||
// Hana Oboro ~Sengoku-den Ranki~ (花朧 ~戦国伝乱奇~)
|
||||
{0x80037600, {CODEC_UTF8, 6, 0, 0, FPCSG00855, "PCSG00855"}},
|
||||
{0x80036580, {CODEC_UTF8, 6, 0, 0, FPCSG00855, "PCSG00855"}},
|
||||
{0x801a2ada, {CODEC_UTF8, 0, 0, 0, FPCSG00855_2<0>, "PCSG00855"}},
|
||||
{0x801a2ba8, {CODEC_UTF8, 0, 0, 0, FPCSG00855_2<1>, "PCSG00855"}},
|
||||
{0x801a2d9e, {CODEC_UTF8, 0, 0, 0, FPCSG00855_2<2>, "PCSG00855"}},
|
||||
{0x801a2e68, {CODEC_UTF8, 0, 0, 0, FPCSG00855_2<3>, "PCSG00855"}},
|
||||
};
|
||||
return 1;
|
||||
}();
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
|
||||
class vita3k:public ENGINE{
|
||||
class vita3k : public ENGINE
|
||||
{
|
||||
public:
|
||||
vita3k(){
|
||||
vita3k()
|
||||
{
|
||||
|
||||
check_by = CHECK_BY::FILE;
|
||||
is_engine_certain = false;
|
||||
@ -10,4 +12,3 @@ class vita3k:public ENGINE{
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
2904
LunaHook/engine64/yuzu.cpp
Normal file
2904
LunaHook/engine64/yuzu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
17
LunaHook/engine64/yuzu.h
Normal file
17
LunaHook/engine64/yuzu.h
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
class yuzu : public ENGINE
|
||||
{
|
||||
public:
|
||||
yuzu()
|
||||
{
|
||||
|
||||
is_engine_certain = false;
|
||||
check_by = CHECK_BY::CUSTOM;
|
||||
check_by_target = []()
|
||||
{
|
||||
return (wcscmp(processName_lower, L"suyu.exe") == 0 || wcscmp(processName_lower, L"yuzu.exe") == 0 || wcscmp(processName_lower, L"sudachi.exe") == 0);
|
||||
};
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
|
||||
|
||||
class yuzusuyu:public ENGINE{
|
||||
public:
|
||||
yuzusuyu(){
|
||||
|
||||
is_engine_certain=false;
|
||||
check_by=CHECK_BY::CUSTOM;
|
||||
check_by_target=[](){
|
||||
|
||||
return (wcscmp(processName_lower, L"suyu.exe")==0 || wcscmp(processName_lower, L"yuzu.exe")==0|| wcscmp(processName_lower, L"sudachi.exe")==0);
|
||||
};
|
||||
};
|
||||
bool attach_function();
|
||||
};
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "engine64/TYPEMOON.h"
|
||||
#include "engine64/Kincaid.h"
|
||||
#include "engine64/LightVN.h"
|
||||
#include "engine64/yuzusuyu.h"
|
||||
#include "engine64/yuzu.h"
|
||||
#include "engine64/Ryujinx.h"
|
||||
#include "engine64/vita3k.h"
|
||||
#include "engine64/rpcs3.h"
|
||||
@ -42,7 +42,7 @@ std::vector<ENGINE *> check_engines()
|
||||
new _5pb,
|
||||
new TYPEMOON,
|
||||
new ENTERGRAM,
|
||||
new yuzusuyu,
|
||||
new yuzu,
|
||||
new PPSSPPengine,
|
||||
new vita3k,
|
||||
new rpcs3,
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include <queue>
|
||||
#include "emujitarg.hpp"
|
||||
|
||||
namespace ppsspp{
|
||||
bool ULJS00403_filter(void* data, size_t* len, HookParam* hp){
|
||||
namespace ppsspp
|
||||
{
|
||||
bool ULJS00403_filter(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
std::string result = std::string((char *)data, *len);
|
||||
std::regex newlinePattern(R"((\\n)+)");
|
||||
result = std::regex_replace(result, newlinePattern, " ");
|
||||
@ -11,8 +13,8 @@ bool ULJS00403_filter(void* data, size_t* len, HookParam* hp){
|
||||
return write_string_overwrite(data, len, result);
|
||||
}
|
||||
|
||||
|
||||
void ULJS00339(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
void ULJS00339(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
auto a2 = PPSSPP::emu_arg(stack)[0];
|
||||
|
||||
auto vm = *(DWORD *)(a2 + (0x28));
|
||||
@ -21,7 +23,8 @@ void ULJS00339(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* spl
|
||||
uintptr_t address = PPSSPP::emu_addr(stack, vm);
|
||||
auto len1 = *(DWORD *)(address + 4);
|
||||
auto p = address + 0x20;
|
||||
if(len1>4 && *(WORD*)(p+2)==0){
|
||||
if (len1 > 4 && *(WORD *)(p + 2) == 0)
|
||||
{
|
||||
auto p1 = *(DWORD *)(address + 8);
|
||||
vm = *(DWORD *)PPSSPP::emu_addr(stack, vm);
|
||||
vm = *(DWORD *)PPSSPP::emu_addr(stack, vm + 0xC);
|
||||
@ -30,50 +33,61 @@ void ULJS00339(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* spl
|
||||
static int fm = 0;
|
||||
static std::string pre;
|
||||
auto b = fm;
|
||||
auto s=[](uintptr_t address){
|
||||
auto s = [](uintptr_t address)
|
||||
{
|
||||
auto frist = *(WORD *)address;
|
||||
auto lo = frist & 0xFF; // uppercase: 41->5A
|
||||
auto hi = frist >> 8;
|
||||
if (hi == 0 && (lo > 0x5a || lo < 0x41) /* T,W,? */) {
|
||||
if (hi == 0 && (lo > 0x5a || lo < 0x41) /* T,W,? */)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
std::string s ;int i = 0;WORD c;
|
||||
std::string s;
|
||||
int i = 0;
|
||||
WORD c;
|
||||
char buf[3] = {0};
|
||||
while ((c = *(WORD*)(address+i)) != 0) {
|
||||
while ((c = *(WORD *)(address + i)) != 0)
|
||||
{
|
||||
// reverse endian: ShiftJIS BE => LE
|
||||
buf[0] = c >> 8;
|
||||
buf[1] = c & 0xFF;
|
||||
|
||||
if (c == 0x815e /* / */) {
|
||||
if (c == 0x815e /* / */)
|
||||
{
|
||||
s += ' '; // single line
|
||||
}
|
||||
else if (buf[0] == 0) {
|
||||
else if (buf[0] == 0)
|
||||
{
|
||||
//// UTF16 LE turned BE: 5700=>0057, 3100, 3500
|
||||
//// 4e00 6d00=>PLAYER
|
||||
// do nothing
|
||||
if (buf[1] == 0x4e) {
|
||||
if (buf[1] == 0x4e)
|
||||
{
|
||||
s += "PLAYER";
|
||||
fm++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
s += buf;
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
return s;
|
||||
}(p);
|
||||
if(b>0){
|
||||
if (b > 0)
|
||||
{
|
||||
fm--;
|
||||
return;
|
||||
}
|
||||
if(s==pre)return ;
|
||||
if (s == pre)
|
||||
return;
|
||||
pre = s;
|
||||
write_string_new(data, len, s);
|
||||
}
|
||||
|
||||
|
||||
bool NPJH50909_filter(void* data, size_t* len, HookParam* hp){
|
||||
bool NPJH50909_filter(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
std::string result = std::string((char *)data, *len);
|
||||
auto ws = StringToWideString(result, 932).value();
|
||||
// Remove single line markers
|
||||
@ -84,7 +98,8 @@ bool NPJH50909_filter(void* data, size_t* len, HookParam* hp){
|
||||
|
||||
// Reformat name
|
||||
std::wsmatch match;
|
||||
if (std::regex_search(ws, match, std::wregex(L"(^[^「]+)「"))) {
|
||||
if (std::regex_search(ws, match, std::wregex(L"(^[^「]+)「")))
|
||||
{
|
||||
std::wstring name = match[1].str();
|
||||
ws = std::regex_replace(ws, std::wregex(L"^[^「]+"), L"");
|
||||
ws = name + L"\n" + ws;
|
||||
@ -92,7 +107,8 @@ bool NPJH50909_filter(void* data, size_t* len, HookParam* hp){
|
||||
return write_string_overwrite(data, len, WideStringToString(ws, 932));
|
||||
}
|
||||
|
||||
bool ULJM06119_filter(void* data, size_t* len, HookParam* hp){
|
||||
bool ULJM06119_filter(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
std::string s = std::string((char *)data, *len);
|
||||
|
||||
std::regex pattern(R"(/\[[^\]]+./g)");
|
||||
@ -109,7 +125,8 @@ bool ULJM06119_filter(void* data, size_t* len, HookParam* hp){
|
||||
return write_string_overwrite(data, len, s);
|
||||
}
|
||||
|
||||
bool ULJM06036_filter(void* data, size_t* len, HookParam* hp){
|
||||
bool ULJM06036_filter(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
std::wstring result = std::wstring((wchar_t *)data, *len / 2);
|
||||
std::wregex pattern(LR"(<R([^\/]+).([^>]+).>)");
|
||||
result = std::regex_replace(result, pattern, L"$2");
|
||||
@ -118,16 +135,23 @@ bool ULJM06036_filter(void* data, size_t* len, HookParam* hp){
|
||||
return write_string_overwrite(data, len, result);
|
||||
}
|
||||
|
||||
namespace Corda{
|
||||
std::string readBinaryString(uintptr_t address,bool* haveName){
|
||||
namespace Corda
|
||||
{
|
||||
std::string readBinaryString(uintptr_t address, bool *haveName)
|
||||
{
|
||||
*haveName = false;
|
||||
if ((*(WORD*)address & 0xF0FF) == 0x801b) {
|
||||
if ((*(WORD *)address & 0xF0FF) == 0x801b)
|
||||
{
|
||||
*haveName = true;
|
||||
address = address + 2; // (1)
|
||||
}
|
||||
std::string s;int i=0;uint8_t c;
|
||||
while ((c = *(uint8_t*)(address+i)) != 0) {
|
||||
if (c == 0x1b) {
|
||||
std::string s;
|
||||
int i = 0;
|
||||
uint8_t c;
|
||||
while ((c = *(uint8_t *)(address + i)) != 0)
|
||||
{
|
||||
if (c == 0x1b)
|
||||
{
|
||||
if (*haveName)
|
||||
return s; // (1) skip junk after name
|
||||
|
||||
@ -137,15 +161,18 @@ namespace Corda{
|
||||
else
|
||||
i += 2;
|
||||
}
|
||||
else if (c == 0x0a) {
|
||||
else if (c == 0x0a)
|
||||
{
|
||||
s += '\n';
|
||||
i += 1;
|
||||
}
|
||||
else if (c == 0x20) {
|
||||
else if (c == 0x20)
|
||||
{
|
||||
s += ' ';
|
||||
i += 1;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
auto len = 1 + (IsDBCSLeadByteEx(932, *(BYTE *)(address + i)));
|
||||
s += std::string((char *)(address + i), len);
|
||||
i += len; // encoder.encode(c).byteLength;
|
||||
@ -155,7 +182,8 @@ namespace Corda{
|
||||
}
|
||||
}
|
||||
|
||||
void ULJM05428(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
void ULJM05428(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
auto address = PPSSPP::emu_arg(stack)[1];
|
||||
bool haveNamve;
|
||||
auto s = Corda::readBinaryString(address, &haveNamve);
|
||||
@ -163,10 +191,13 @@ void ULJM05428(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* spl
|
||||
write_string_new(data, len, s);
|
||||
}
|
||||
|
||||
void ULJM05054(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
if (hp->emu_addr != 0x886162c) {
|
||||
void ULJM05054(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
if (hp->emu_addr != 0x886162c)
|
||||
{
|
||||
auto addr = PPSSPP::emu_arg(stack)[0] + 0x3c;
|
||||
*data=addr;*len=strlen((char*)addr);
|
||||
*data = addr;
|
||||
*len = strlen((char *)addr);
|
||||
return;
|
||||
}
|
||||
auto address = PPSSPP::emu_arg(stack)[1];
|
||||
@ -176,8 +207,8 @@ void ULJM05054(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* spl
|
||||
write_string_new(data, len, s);
|
||||
}
|
||||
|
||||
|
||||
bool ULJM05943F(void* data, size_t* len, HookParam* hp){
|
||||
bool ULJM05943F(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
std::regex pattern1("#n+");
|
||||
std::string replacement1 = " ";
|
||||
@ -199,7 +230,8 @@ bool FULJM05603(LPVOID data, size_t* size, HookParam*)
|
||||
|
||||
return true;
|
||||
}
|
||||
namespace NPJH50530{
|
||||
namespace NPJH50530
|
||||
{
|
||||
std::string current;
|
||||
bool T(LPVOID data, size_t *size, HookParam *)
|
||||
{
|
||||
@ -212,12 +244,20 @@ bool N(LPVOID data, size_t* size, HookParam*)
|
||||
return current != current1;
|
||||
}
|
||||
}
|
||||
bool FNPJH50243(LPVOID data, size_t *size, HookParam *)
|
||||
{
|
||||
auto s = std::wstring((wchar_t *)data, *size / 2);
|
||||
s = std::regex_replace(s, std::wregex(LR"(<(.*?)\|(.*?)>)"), L"$1");
|
||||
return write_string_overwrite(data, size, s);
|
||||
}
|
||||
bool FULJM05889(LPVOID data, size_t *size, HookParam *)
|
||||
{
|
||||
auto text = reinterpret_cast<LPSTR>(data);
|
||||
auto len = reinterpret_cast<size_t *>(size);
|
||||
for(size_t i=0;i<*len;){
|
||||
if(IsDBCSLeadByteEx(932,(text[i]))){
|
||||
for (size_t i = 0; i < *len;)
|
||||
{
|
||||
if (IsDBCSLeadByteEx(932, (text[i])))
|
||||
{
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
@ -229,7 +269,8 @@ bool FULJM05889(LPVOID data, size_t* size, HookParam*)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NPJH50619F(void* data, size_t* len, HookParam* hp){
|
||||
bool NPJH50619F(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
std::regex pattern1("[\\r\\n]+");
|
||||
std::string replacement1 = "";
|
||||
@ -246,8 +287,8 @@ bool NPJH50619F(void* data, size_t* len, HookParam* hp){
|
||||
return write_string_overwrite(data, len, result4);
|
||||
}
|
||||
|
||||
|
||||
bool NPJH50505F(void* data, size_t* len, HookParam* hp){
|
||||
bool NPJH50505F(void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
auto s = std::string((char *)data, *len);
|
||||
|
||||
std::regex pattern2("#RUBS(#[A-Z0-9]+)*[^#]+");
|
||||
@ -273,13 +314,16 @@ bool NPJH50505F(void* data, size_t* len, HookParam* hp){
|
||||
return write_string_overwrite(data, len, result6);
|
||||
}
|
||||
|
||||
void QNPJH50909(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
void QNPJH50909(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
uintptr_t addr = PPSSPP::emu_addr(stack, 0x08975110);
|
||||
*data = addr + 0x20;
|
||||
*len = *(DWORD *)(addr + 0x14) * 2;
|
||||
|
||||
if(0x6e87==*(WORD*)*data)*len=0;
|
||||
if(0x000a==*(WORD*)*data)*len=0;
|
||||
if (0x6e87 == *(WORD *)*data)
|
||||
*len = 0;
|
||||
if (0x000a == *(WORD *)*data)
|
||||
*len = 0;
|
||||
}
|
||||
std::unordered_map<uintptr_t, emfuncinfo> emfunctionhooks = {
|
||||
// Shinigami to Shoujo
|
||||
@ -324,6 +368,10 @@ std::unordered_map<uintptr_t,emfuncinfo>emfunctionhooks= {
|
||||
// シャイニング・ブレイド
|
||||
{0x8AA3B70, {0, 0xC, 0, 0, NPJH50530::T, "NPJH50530"}}, // text only
|
||||
{0x884DB44, {0, 1, 0, 0, NPJH50530::N, "NPJH50530"}}, // text+name
|
||||
// ティアーズ・トゥ・ティアラ 外伝 アヴァロンの謎 PORTABLE
|
||||
{0x890A4BC, {CODEC_UTF16, 1, 0, 0, FNPJH50243, "NPJH50243"}},
|
||||
// 薔薇ノ木ニ薔薇ノ花咲ク
|
||||
{0x881E560, {0, 1, 0, 0, 0, "ULJM05802"}},
|
||||
};
|
||||
|
||||
}
|
@ -222,7 +222,6 @@ void SafeSendJitVeh(hook_stack *stack, uintptr_t address, uintptr_t em_addr, JIT
|
||||
}
|
||||
}
|
||||
std::unordered_map<uintptr_t, uint64_t> addresscalledtime;
|
||||
bool safeautoleaveveh = false;
|
||||
bool SendJitVeh(PCONTEXT context, uintptr_t address, uintptr_t em_addr, JITTYPE jittype)
|
||||
{
|
||||
if (safeautoleaveveh)
|
||||
@ -295,7 +294,7 @@ void SearchForHooks_Return()
|
||||
if (!records[i].em_addr)
|
||||
continue;
|
||||
hp.emu_addr = records[i].em_addr;
|
||||
hp.type = CODEC_UTF16 | USING_STRING | BREAK_POINT;
|
||||
hp.type = CODEC_UTF16 | USING_STRING | BREAK_POINT | NO_CONTEXT;
|
||||
hp.argidx = records[i].argidx;
|
||||
}
|
||||
NotifyHookFound(hp, (wchar_t *)records[i].text);
|
||||
|
@ -101,6 +101,15 @@ void ConsoleOutput(LPCSTR text, ...)
|
||||
vsnprintf(buffer.message, MESSAGE_SIZE, text, args);
|
||||
WriteFile(hookPipe, &buffer, sizeof(buffer), DUMMY, nullptr);
|
||||
}
|
||||
|
||||
void WarningOutput(LPCSTR text, ...)
|
||||
{
|
||||
WarningNotif buffer;
|
||||
va_list args;
|
||||
va_start(args, text);
|
||||
vsnprintf(buffer.message, MESSAGE_SIZE, text, args);
|
||||
WriteFile(hookPipe, &buffer, sizeof(buffer), DUMMY, nullptr);
|
||||
}
|
||||
Synchronized<std::unordered_map<uintptr_t, std::wstring>> modulecache;
|
||||
std::wstring &querymodule(uintptr_t addr)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
void TextOutput(const ThreadParam &tp, const HookParam &hp, TextOutput_T(*buffer), int len);
|
||||
void ConsoleOutput(LPCSTR text, ...);
|
||||
void WarningOutput(LPCSTR text, ...);
|
||||
void NotifyHookFound(HookParam hp, wchar_t *text);
|
||||
void NotifyHookRemove(uint64_t addr, LPCSTR name);
|
||||
bool NewHook(HookParam hp, LPCSTR name);
|
||||
@ -27,6 +28,6 @@ void context_set(hook_stack *, PCONTEXT);
|
||||
inline std::map<uintptr_t, std::pair<std::string, HookParam>> delayinserthook;
|
||||
void delayinsertadd(HookParam, std::string);
|
||||
void delayinsertNewHook(uintptr_t);
|
||||
|
||||
inline bool safeautoleaveveh = false;
|
||||
inline bool dont_detach = false;
|
||||
inline bool host_connected = false;
|
@ -127,7 +127,13 @@ bool TextHook::Insert(HookParam hp)
|
||||
if (hp.type & DIRECT_READ)
|
||||
return InsertReadCode();
|
||||
if (hp.type & BREAK_POINT)
|
||||
return InsertBreakPoint();
|
||||
{
|
||||
if (InsertBreakPoint())
|
||||
return true;
|
||||
if (safeautoleaveveh)
|
||||
return InsertBreakPoint(); // 搜索特殊码后,不会释放,导致virtualprotect查询失败,重试。
|
||||
return false;
|
||||
}
|
||||
return InsertHookCode();
|
||||
}
|
||||
uintptr_t win64find0000(uintptr_t addr)
|
||||
|
@ -292,12 +292,16 @@ LunaHost::LunaHost()
|
||||
hooksearchwindow->show();
|
||||
};
|
||||
|
||||
Host::Start(
|
||||
Host::StartEx(
|
||||
std::bind(&LunaHost::on_proc_connect, this, std::placeholders::_1),
|
||||
std::bind(&LunaHost::on_proc_disconnect, this, std::placeholders::_1),
|
||||
std::bind(&LunaHost::on_thread_create, this, std::placeholders::_1),
|
||||
std::bind(&LunaHost::on_thread_delete, this, std::placeholders::_1),
|
||||
std::bind(&LunaHost::on_text_recv, this, std::placeholders::_1, std::placeholders::_2));
|
||||
std::bind(&LunaHost::on_text_recv, this, std::placeholders::_1, std::placeholders::_2),
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
std::bind(&LunaHost::on_warning, this, std::placeholders::_1));
|
||||
|
||||
mainlayout = new gridlayout();
|
||||
mainlayout->addcontrol(g_selectprocessbutton, 0, 0);
|
||||
@ -448,6 +452,10 @@ bool LunaHost::on_text_recv(TextThread &thread, std::wstring &output)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void LunaHost::on_warning(const std::wstring &warning)
|
||||
{
|
||||
MessageBoxW(winId, warning.c_str(), L"warning", 0);
|
||||
}
|
||||
void LunaHost::on_thread_create(TextThread &thread)
|
||||
{
|
||||
wchar_t buff[65535];
|
||||
|
@ -116,6 +116,7 @@ class LunaHost : public mainwindow
|
||||
void on_thread_delete(TextThread &thread);
|
||||
void on_proc_connect(DWORD pid);
|
||||
void on_proc_disconnect(DWORD pid);
|
||||
void on_warning(const std::wstring &);
|
||||
|
||||
void showtext(const std::wstring &text, bool clear);
|
||||
void updatelisttext(const std::wstring &text, LONG_PTR data);
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
_setmode(_fileno(stdout), _O_U16TEXT);
|
||||
@ -22,51 +21,65 @@ int main()
|
||||
output.c_str()
|
||||
);
|
||||
fflush(stdout);
|
||||
return false;
|
||||
});
|
||||
return false; });
|
||||
wchar_t input[500] = {};
|
||||
SearchParam sp = {};
|
||||
sp.codepage = Host::defaultCodepage;
|
||||
sp.length = 0;
|
||||
while (fgetws(input, 500, stdin))
|
||||
{
|
||||
if(wcslen(input)<=1)continue;//\r\n,第二行会直接只有一个\n
|
||||
if (wcslen(input) <= 1)
|
||||
continue; //\r\n,第二行会直接只有一个\n
|
||||
wchar_t command[500] = {};
|
||||
DWORD processId = 0;
|
||||
|
||||
int split;
|
||||
for (split = wcslen(input) - 1; split >= 1; split--) {
|
||||
if (input[split] == L'P' && input[split-1]=='-') {
|
||||
for (split = wcslen(input) - 1; split >= 1; split--)
|
||||
{
|
||||
if (input[split] == L'P' && input[split - 1] == '-')
|
||||
{
|
||||
processId = _wtoi(input + split + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (split == 1)continue;// ExitProcess(0);
|
||||
if (split == 1)
|
||||
continue; // ExitProcess(0);
|
||||
split -= 2;
|
||||
while (split > 0 && input[split] == L' ')split -= 1;
|
||||
if (split == 0)continue;//ExitProcess(0);
|
||||
while (split > 0 && input[split] == L' ')
|
||||
split -= 1;
|
||||
if (split == 0)
|
||||
continue; // ExitProcess(0);
|
||||
input[split + 1] = 0;
|
||||
wcscpy(command, input);
|
||||
// if (swscanf(input, L"%500s -P%d", command, &processId) != 2) ExitProcess(0);
|
||||
if (_wcsicmp(command, L"attach") == 0) Host::InjectProcess(processId);
|
||||
else if (_wcsicmp(command, L"detach") == 0) { Host::DetachProcess(processId); }
|
||||
else if (_wcsicmp(command, L"find") == 0) {
|
||||
if (_wcsicmp(command, L"attach") == 0)
|
||||
Host::InjectProcess(processId);
|
||||
else if (_wcsicmp(command, L"detach") == 0)
|
||||
{
|
||||
Host::DetachProcess(processId);
|
||||
}
|
||||
else if (_wcsicmp(command, L"find") == 0)
|
||||
{
|
||||
std::shared_ptr<std::vector<std::wstring>> hooks = std::make_shared<std::vector<std::wstring>>();
|
||||
|
||||
try
|
||||
{
|
||||
Host::FindHooks(processId, sp,
|
||||
[hooks](HookParam hp, std::wstring text) {
|
||||
[hooks](HookParam hp, std::wstring text)
|
||||
{
|
||||
// if (std::regex_search(text, std::wregex(L"[\u3000-\ua000]"))) {
|
||||
if (std::regex_search(text, std::wregex(L"[\u3000-\ua000]"))) {
|
||||
if (std::regex_search(text, std::wregex(L"[\u3000-\ua000]")))
|
||||
{
|
||||
hooks->push_back(std::wstring(hp.hookcode) + L"=>" + text + L"\n");
|
||||
|
||||
|
||||
// *hooks << sanitize(S(HookCode::Generate(hp) + L" => " + text));
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (wchar_t c) { std::wcout << c; }
|
||||
catch (wchar_t c)
|
||||
{
|
||||
std::wcout << c;
|
||||
}
|
||||
std::thread([hooks]
|
||||
{
|
||||
for (int lastSize = 0; hooks->size() == 0 || hooks->size() != lastSize; Sleep(2000)) lastSize = hooks->size();
|
||||
@ -76,34 +89,40 @@ int main()
|
||||
|
||||
fwrite(hook.c_str(), wcslen(hook.c_str()) * sizeof(wchar_t), 1, out);
|
||||
}
|
||||
fclose(out);
|
||||
}).detach();
|
||||
|
||||
fclose(out); })
|
||||
.detach();
|
||||
}
|
||||
|
||||
else {
|
||||
if (command[0] == L'-') {
|
||||
else
|
||||
{
|
||||
if (command[0] == L'-')
|
||||
{
|
||||
try
|
||||
{
|
||||
unsigned long long address;
|
||||
swscanf_s(command, L"-%llu", &address);
|
||||
Host::RemoveHook(processId, address);
|
||||
|
||||
}
|
||||
catch (std::out_of_range) {}
|
||||
catch (std::out_of_range)
|
||||
{
|
||||
}
|
||||
else if (command[0] == L'=') {
|
||||
}
|
||||
else if (command[0] == L'=')
|
||||
{
|
||||
int codepage;
|
||||
swscanf_s(command, L"=%d", &codepage);
|
||||
Host::defaultCodepage = codepage;
|
||||
}
|
||||
else if (command[0] == L'+') {
|
||||
else if (command[0] == L'+')
|
||||
{
|
||||
int flushDelay;
|
||||
swscanf_s(command, L"+%d", &flushDelay);
|
||||
TextThread::flushDelay = flushDelay;
|
||||
}
|
||||
else if (auto hp = HookCode::Parse(command)) Host::InsertHook(processId, hp.value());
|
||||
else ExitProcess(0);
|
||||
else if (auto hp = HookCode::Parse(command))
|
||||
Host::InsertHook(processId, hp.value());
|
||||
else
|
||||
ExitProcess(0);
|
||||
}
|
||||
}
|
||||
ExitProcess(0);
|
||||
|
@ -26,7 +26,7 @@ typedef void (*EmbedCallback)(const wchar_t *, ThreadParam);
|
||||
wchar_t hookcode[HOOKCODE_LEN]; \
|
||||
wcscpy_s(hookcode, HOOKCODE_LEN, thread.hp.hookcode); \
|
||||
strcpy_s(name, HOOK_NAME_SIZE, thread.hp.name);
|
||||
C_LUNA_API void Luna_Start(ProcessEvent Connect, ProcessEvent Disconnect, ThreadEvent Create, ThreadEvent Destroy, OutputCallback Output, ConsoleHandler console, HookInsertHandler hookinsert, EmbedCallback embed)
|
||||
C_LUNA_API void Luna_Start(ProcessEvent Connect, ProcessEvent Disconnect, ThreadEvent Create, ThreadEvent Destroy, OutputCallback Output, ConsoleHandler console, HookInsertHandler hookinsert, EmbedCallback embed, ConsoleHandler Warning)
|
||||
{
|
||||
Host::StartEx(
|
||||
Connect,
|
||||
@ -56,6 +56,10 @@ C_LUNA_API void Luna_Start(ProcessEvent Connect, ProcessEvent Disconnect, Thread
|
||||
[=](const std::wstring &output, const ThreadParam &tp)
|
||||
{
|
||||
embed(output.c_str(), tp);
|
||||
},
|
||||
[=](const std::wstring &output)
|
||||
{
|
||||
Warning(output.c_str());
|
||||
});
|
||||
}
|
||||
C_LUNA_API void Luna_Inject(DWORD pid, LPCWSTR basepath)
|
||||
|
@ -7,8 +7,7 @@ namespace
|
||||
class ProcessRecord
|
||||
{
|
||||
public:
|
||||
ProcessRecord(DWORD processId, HANDLE pipe) :
|
||||
pipe(pipe),
|
||||
ProcessRecord(DWORD processId, HANDLE pipe) : pipe(pipe),
|
||||
mappedFile2(OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, (EMBED_SHARED_MEM + std::to_wstring(processId)).c_str())),
|
||||
viewMutex(ITH_HOOKMAN_MUTEX_ + std::to_wstring(processId))
|
||||
|
||||
@ -27,9 +26,8 @@ namespace
|
||||
{
|
||||
static_assert(sizeof(data) < PIPE_BUFFER_SIZE);
|
||||
std::thread([=]
|
||||
{
|
||||
WriteFile(pipe, &data, sizeof(data), DUMMY, nullptr);
|
||||
}).detach();
|
||||
{ WriteFile(pipe, &data, sizeof(data), DUMMY, nullptr); })
|
||||
.detach();
|
||||
}
|
||||
|
||||
Host::HookEventHandler OnHookFound = [](HookParam hp, std::wstring text)
|
||||
@ -37,8 +35,8 @@ namespace
|
||||
Host::AddConsoleOutput(std::wstring(hp.hookcode) + L": " + text);
|
||||
};
|
||||
|
||||
|
||||
EmbedSharedMem *embedsharedmem;
|
||||
|
||||
private:
|
||||
HANDLE pipe;
|
||||
AutoHandle<> mappedFile2;
|
||||
@ -52,12 +50,15 @@ namespace
|
||||
Host::ProcessEventHandler OnConnect, OnDisconnect;
|
||||
Host::ThreadEventHandler OnCreate, OnDestroy;
|
||||
Host::ConsoleHandler OnConsole = 0;
|
||||
Host::ConsoleHandler OnWarning = 0;
|
||||
Host::HookInsertHandler HookInsert = 0;
|
||||
Host::EmbedCallback embedcallback = 0;
|
||||
void RemoveThreads(std::function<bool(ThreadParam)> removeIf)
|
||||
{
|
||||
std::vector<TextThread *> threadsToRemove;
|
||||
for (auto& [tp, thread] : textThreadsByParams.Acquire().contents) if (removeIf(tp)) threadsToRemove.push_back(&thread);
|
||||
for (auto &[tp, thread] : textThreadsByParams.Acquire().contents)
|
||||
if (removeIf(tp))
|
||||
threadsToRemove.push_back(&thread);
|
||||
for (auto thread : threadsToRemove)
|
||||
{
|
||||
OnDestroy(*thread);
|
||||
@ -141,6 +142,12 @@ namespace
|
||||
Host::AddConsoleOutput(StringToWideString(info.message));
|
||||
}
|
||||
break;
|
||||
case HOST_NOTIFICATION_WARNING:
|
||||
{
|
||||
auto info = *(WarningNotif*)buffer;
|
||||
Host::Warning(StringToWideString(info.message));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
auto data=(TextOutput_T*)buffer;
|
||||
@ -179,8 +186,8 @@ namespace
|
||||
RemoveThreads([&](ThreadParam tp) { return tp.processId == processId; });
|
||||
OnDisconnect(processId);
|
||||
Host::AddConsoleOutput(FormatString(PROC_DISCONN,processId));
|
||||
processRecordsByIds->erase(processId);
|
||||
}).detach();
|
||||
processRecordsByIds->erase(processId); })
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,34 +198,47 @@ namespace Host
|
||||
std::mutex procmutex;
|
||||
void Start(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output, bool createconsole)
|
||||
{
|
||||
OnConnect = [=](auto &&...args){std::lock_guard _(procmutex);Connect(std::forward<decltype(args)>(args)...);};
|
||||
OnDisconnect = [=](auto &&...args){std::lock_guard _(procmutex);Disconnect(std::forward<decltype(args)>(args)...);};
|
||||
OnCreate = [=](TextThread& thread) {{std::lock_guard _(threadmutex); Create(thread);} thread.Start(); };
|
||||
OnDestroy = [=](TextThread& thread) {thread.Stop(); {std::lock_guard _(threadmutex); Destroy(thread);} };
|
||||
TextThread::Output = [=](auto &&...args){std::lock_guard _(outputmutex);return Output(std::forward<decltype(args)>(args)...);};
|
||||
OnConnect = [=](auto &&...args)
|
||||
{std::lock_guard _(procmutex);Connect(std::forward<decltype(args)>(args)...); };
|
||||
OnDisconnect = [=](auto &&...args)
|
||||
{std::lock_guard _(procmutex);Disconnect(std::forward<decltype(args)>(args)...); };
|
||||
OnCreate = [=](TextThread &thread)
|
||||
{{std::lock_guard _(threadmutex); Create(thread);} thread.Start(); };
|
||||
OnDestroy = [=](TextThread &thread)
|
||||
{thread.Stop(); {std::lock_guard _(threadmutex); Destroy(thread);} };
|
||||
TextThread::Output = [=](auto &&...args)
|
||||
{std::lock_guard _(outputmutex);return Output(std::forward<decltype(args)>(args)...); };
|
||||
|
||||
if(createconsole){
|
||||
if (createconsole)
|
||||
{
|
||||
OnCreate(textThreadsByParams->try_emplace(console, console, HookParam{}, CONSOLE).first->second);
|
||||
Host::AddConsoleOutput(ProjectHomePage);
|
||||
}
|
||||
|
||||
// CreatePipe();
|
||||
|
||||
}
|
||||
void StartEx(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output,ConsoleHandler console,HookInsertHandler hookinsert,EmbedCallback embed){
|
||||
Start(Connect,Disconnect,Create,Destroy,Output,false);
|
||||
|
||||
OnConsole=[=](auto &&...args){std::lock_guard _(outputmutex);console(std::forward<decltype(args)>(args)...);};
|
||||
HookInsert=[=](auto &&...args){std::lock_guard _(threadmutex);hookinsert(std::forward<decltype(args)>(args)...);};
|
||||
embedcallback=[=](auto &&...args){std::lock_guard _(outputmutex);embed(std::forward<decltype(args)>(args)...);};
|
||||
void StartEx(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output, std::optional<ConsoleHandler> console, std::optional<HookInsertHandler> hookinsert, std::optional<EmbedCallback> embed, std::optional<ConsoleHandler> warning)
|
||||
{
|
||||
Start(Connect, Disconnect, Create, Destroy, Output, !console.has_value());
|
||||
if (warning.has_value())
|
||||
OnWarning = warning.value();
|
||||
if (console.has_value())
|
||||
OnConsole = [=](auto &&...args)
|
||||
{std::lock_guard _(outputmutex);console.value()(std::forward<decltype(args)>(args)...); };
|
||||
if (hookinsert.has_value())
|
||||
HookInsert = [=](auto &&...args)
|
||||
{std::lock_guard _(threadmutex);hookinsert.value()(std::forward<decltype(args)>(args)...); };
|
||||
if (embed.has_value())
|
||||
embedcallback = [=](auto &&...args)
|
||||
{std::lock_guard _(outputmutex);embed.value()(std::forward<decltype(args)>(args)...); };
|
||||
}
|
||||
constexpr auto PROCESS_INJECT_ACCESS=(
|
||||
PROCESS_CREATE_THREAD |
|
||||
constexpr auto PROCESS_INJECT_ACCESS = (PROCESS_CREATE_THREAD |
|
||||
PROCESS_QUERY_INFORMATION |
|
||||
PROCESS_VM_OPERATION |
|
||||
PROCESS_VM_WRITE |
|
||||
PROCESS_VM_READ);
|
||||
bool SafeInject(HANDLE process,const std::wstring &location){
|
||||
bool SafeInject(HANDLE process, const std::wstring &location)
|
||||
{
|
||||
// #ifdef _WIN64
|
||||
#if 0
|
||||
BOOL invalidProcess = FALSE;
|
||||
@ -229,51 +249,66 @@ namespace Host
|
||||
if (LPVOID remoteData = VirtualAllocEx(process, nullptr, (location.size() + 1) * sizeof(wchar_t), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))
|
||||
{
|
||||
WriteProcessMemory(process, remoteData, location.c_str(), (location.size() + 1) * sizeof(wchar_t), nullptr);
|
||||
if (AutoHandle<> thread = CreateRemoteThread(process, nullptr, 0, (LPTHREAD_START_ROUTINE)LoadLibraryW, remoteData, 0, nullptr)){
|
||||
if (AutoHandle<> thread = CreateRemoteThread(process, nullptr, 0, (LPTHREAD_START_ROUTINE)LoadLibraryW, remoteData, 0, nullptr))
|
||||
{
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
succ = true;
|
||||
}
|
||||
else if (GetLastError() == ERROR_ACCESS_DENIED){
|
||||
else if (GetLastError() == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
AddConsoleOutput(NEED_64_BIT); // https://stackoverflow.com/questions/16091141/createremotethread-access-denied
|
||||
succ = false;
|
||||
}
|
||||
VirtualFreeEx(process, remoteData, 0, MEM_RELEASE);
|
||||
|
||||
}
|
||||
return succ;
|
||||
}
|
||||
bool UnSafeInject(HANDLE process,const std::wstring &location){
|
||||
bool UnSafeInject(HANDLE process, const std::wstring &location)
|
||||
{
|
||||
|
||||
DWORD64 injectedDll;
|
||||
yapi::YAPICall LoadLibraryW(process, _T("kernel32.dll"), "LoadLibraryW");
|
||||
if(x64)injectedDll = LoadLibraryW.Dw64()(location.c_str());
|
||||
else injectedDll = LoadLibraryW(location.c_str());
|
||||
if(injectedDll)return true;
|
||||
if (x64)
|
||||
injectedDll = LoadLibraryW.Dw64()(location.c_str());
|
||||
else
|
||||
injectedDll = LoadLibraryW(location.c_str());
|
||||
if (injectedDll)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool CheckProcess(DWORD processId)
|
||||
{
|
||||
if (processId == GetCurrentProcessId())
|
||||
return false;
|
||||
|
||||
}
|
||||
bool CheckProcess(DWORD processId){
|
||||
if (processId == GetCurrentProcessId()) return false;
|
||||
|
||||
WinMutex(ITH_HOOKMAN_MUTEX_ + std::to_wstring(processId));
|
||||
if (GetLastError() == ERROR_ALREADY_EXISTS){AddConsoleOutput(ALREADY_INJECTED); return false;}
|
||||
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
AddConsoleOutput(ALREADY_INJECTED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool InjectDll(DWORD processId,const std::wstring locationX){
|
||||
bool InjectDll(DWORD processId, const std::wstring locationX)
|
||||
{
|
||||
AutoHandle<> process = OpenProcess(PROCESS_INJECT_ACCESS, FALSE, processId);
|
||||
if(!process)return false;
|
||||
if (!process)
|
||||
return false;
|
||||
bool proc64 = Is64BitProcess(process);
|
||||
auto dllname = proc64 ? LUNA_HOOK_DLL_64 : LUNA_HOOK_DLL_32;
|
||||
std::wstring location = locationX.size() ? (locationX + L"\\" + dllname) : std::filesystem::path(getModuleFilename().value()).replace_filename(dllname);
|
||||
AddConsoleOutput(location);
|
||||
if(proc64==x64){
|
||||
if (proc64 == x64)
|
||||
{
|
||||
return (SafeInject(process, location));
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
return (UnSafeInject(process, location));
|
||||
}
|
||||
}
|
||||
bool CreatePipeAndCheck(DWORD processId){
|
||||
bool CreatePipeAndCheck(DWORD processId)
|
||||
{
|
||||
CreatePipe(processId);
|
||||
return CheckProcess(processId);
|
||||
}
|
||||
@ -281,41 +316,47 @@ namespace Host
|
||||
{
|
||||
|
||||
auto check = CreatePipeAndCheck(processId);
|
||||
if(check==false)return;
|
||||
if (check == false)
|
||||
return;
|
||||
|
||||
std::thread([=]
|
||||
{
|
||||
if(InjectDll(processId,locationX))return ;
|
||||
AddConsoleOutput(INJECT_FAILED);
|
||||
}).detach();
|
||||
AddConsoleOutput(INJECT_FAILED); })
|
||||
.detach();
|
||||
}
|
||||
|
||||
void DetachProcess(DWORD processId)
|
||||
{
|
||||
auto &prs = processRecordsByIds.Acquire().contents;
|
||||
if(prs.find(processId)==prs.end())return;
|
||||
if (prs.find(processId) == prs.end())
|
||||
return;
|
||||
prs.at(processId).Send(HOST_COMMAND_DETACH);
|
||||
}
|
||||
|
||||
void InsertHook(DWORD processId, HookParam hp)
|
||||
{
|
||||
auto &prs = processRecordsByIds.Acquire().contents;
|
||||
if(prs.find(processId)==prs.end())return;
|
||||
if (prs.find(processId) == prs.end())
|
||||
return;
|
||||
prs.at(processId).Send(InsertHookCmd(hp));
|
||||
}
|
||||
|
||||
void RemoveHook(DWORD processId, uint64_t address)
|
||||
{
|
||||
auto &prs = processRecordsByIds.Acquire().contents;
|
||||
if(prs.find(processId)==prs.end())return;
|
||||
if (prs.find(processId) == prs.end())
|
||||
return;
|
||||
prs.at(processId).Send(RemoveHookCmd(address));
|
||||
}
|
||||
|
||||
void FindHooks(DWORD processId, SearchParam sp, HookEventHandler HookFound)
|
||||
{
|
||||
auto &prs = processRecordsByIds.Acquire().contents;
|
||||
if(prs.find(processId)==prs.end())return;
|
||||
if (HookFound) prs.at(processId).OnHookFound = HookFound;
|
||||
if (prs.find(processId) == prs.end())
|
||||
return;
|
||||
if (HookFound)
|
||||
prs.at(processId).OnHookFound = HookFound;
|
||||
prs.at(processId).Send(FindHookCmd(sp));
|
||||
}
|
||||
|
||||
@ -326,12 +367,16 @@ namespace Host
|
||||
|
||||
TextThread *GetThread(int64_t handle)
|
||||
{
|
||||
for (auto& [tp, thread] : textThreadsByParams.Acquire().contents) if (thread.handle == handle) return &thread;
|
||||
for (auto &[tp, thread] : textThreadsByParams.Acquire().contents)
|
||||
if (thread.handle == handle)
|
||||
return &thread;
|
||||
return nullptr;
|
||||
}
|
||||
EmbedSharedMem* GetEmbedSharedMem(DWORD processId){
|
||||
EmbedSharedMem *GetEmbedSharedMem(DWORD processId)
|
||||
{
|
||||
auto &prs = processRecordsByIds.Acquire().contents;
|
||||
if(prs.find(processId)==prs.end())return 0;
|
||||
if (prs.find(processId) == prs.end())
|
||||
return 0;
|
||||
return prs.at(processId).embedsharedmem;
|
||||
}
|
||||
void AddConsoleOutput(std::wstring text)
|
||||
@ -341,4 +386,10 @@ namespace Host
|
||||
else
|
||||
GetThread(console).AddSentence(std::move(text));
|
||||
}
|
||||
void Warning(std::wstring text)
|
||||
{
|
||||
if (OnWarning)
|
||||
OnWarning(text);
|
||||
AddConsoleOutput(L"[Warning] " + text);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ namespace Host
|
||||
using HookInsertHandler = std::function<void(uint64_t, const std::wstring &)>;
|
||||
using EmbedCallback = std::function<void(const std::wstring &, const ThreadParam &)>;
|
||||
void Start(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output, bool createconsole = true);
|
||||
void StartEx(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output,ConsoleHandler console,HookInsertHandler hookinsert,EmbedCallback embed);
|
||||
void StartEx(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output, std::optional<ConsoleHandler> console, std::optional<HookInsertHandler> hookinsert, std::optional<EmbedCallback> embed, std::optional<ConsoleHandler> warning);
|
||||
void InjectProcess(DWORD processId, const std::wstring locationX = L"");
|
||||
bool CreatePipeAndCheck(DWORD processId);
|
||||
|
||||
@ -24,6 +24,7 @@ namespace Host
|
||||
TextThread &GetThread(ThreadParam tp);
|
||||
|
||||
void AddConsoleOutput(std::wstring text);
|
||||
void Warning(std::wstring text);
|
||||
|
||||
inline int defaultCodepage = SHIFT_JIS;
|
||||
|
||||
|
@ -12,16 +12,17 @@ static bool RemoveRepetition(std::wstring& text)
|
||||
return false;
|
||||
}
|
||||
|
||||
TextThread::TextThread(ThreadParam tp, HookParam hp, std::optional<std::wstring> name) :
|
||||
handle(threadCounter++),
|
||||
TextThread::TextThread(ThreadParam tp, HookParam hp, std::optional<std::wstring> name) : handle(threadCounter++),
|
||||
name(name.value_or(StringToWideString(hp.name))),
|
||||
tp(tp),
|
||||
hp(hp)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void TextThread::Start()
|
||||
{
|
||||
CreateTimerQueueTimer(&timer, NULL, [](void* This, auto) { ((TextThread*)This)->Flush(); }, this, 10, 10, WT_EXECUTELONGFUNCTION);
|
||||
CreateTimerQueueTimer(&timer, NULL, [](void *This, auto)
|
||||
{ ((TextThread *)This)->Flush(); }, this, 10, 10, WT_EXECUTELONGFUNCTION);
|
||||
}
|
||||
|
||||
void TextThread::Stop()
|
||||
@ -36,7 +37,8 @@ void TextThread::AddSentence(std::wstring sentence)
|
||||
|
||||
void TextThread::Push(BYTE *data, int length)
|
||||
{
|
||||
if (length < 0) return;
|
||||
if (length < 0)
|
||||
return;
|
||||
std::scoped_lock lock(bufferMutex);
|
||||
|
||||
BYTE doubleByteChar[2];
|
||||
@ -60,15 +62,19 @@ void TextThread::Push(BYTE* data, int length)
|
||||
if (converted)
|
||||
{
|
||||
buffer.append(converted.value());
|
||||
if (hp.type & FULL_STRING && converted.value().size()>1) buffer.push_back(L'\n');
|
||||
if (hp.type & FULL_STRING && converted.value().size() > 1)
|
||||
buffer.push_back(L'\n');
|
||||
}
|
||||
else Host::AddConsoleOutput(INVALID_CODEPAGE);
|
||||
else
|
||||
Host::AddConsoleOutput(INVALID_CODEPAGE);
|
||||
|
||||
lastPushTime = GetTickCount64();
|
||||
|
||||
if (filterRepetition)
|
||||
{
|
||||
if (std::all_of(buffer.begin(), buffer.end(), [&](wchar_t ch) { return repeatingChars.find(ch) != repeatingChars.end(); })) buffer.clear();
|
||||
if (std::all_of(buffer.begin(), buffer.end(), [&](wchar_t ch)
|
||||
{ return repeatingChars.find(ch) != repeatingChars.end(); }))
|
||||
buffer.clear();
|
||||
if (RemoveRepetition(buffer)) // sentence repetition detected, which means the entire sentence has already been received
|
||||
{
|
||||
repeatingChars = std::unordered_set(buffer.begin(), buffer.end());
|
||||
@ -96,7 +102,8 @@ void TextThread::Flush()
|
||||
{
|
||||
{
|
||||
auto storage = this->storage.Acquire();
|
||||
if (storage->size() > maxHistorySize) storage->erase(0, storage->size() - maxHistorySize); // https://github.com/Artikash/Textractor/issues/127#issuecomment-486882983
|
||||
if (storage->size() > maxHistorySize)
|
||||
storage->erase(0, storage->size() - maxHistorySize); // https://github.com/Artikash/Textractor/issues/127#issuecomment-486882983
|
||||
}
|
||||
|
||||
std::vector<std::wstring> sentences;
|
||||
@ -106,11 +113,13 @@ void TextThread::Flush()
|
||||
{
|
||||
totalSize += sentence.size();
|
||||
sentence.erase(std::remove(sentence.begin(), sentence.end(), 0), sentence.end());
|
||||
if (Output(*this, sentence)) storage->append(sentence+L"\n");
|
||||
if (Output(*this, sentence))
|
||||
storage->append(sentence + L"\n");
|
||||
}
|
||||
|
||||
std::scoped_lock lock(bufferMutex);
|
||||
if (buffer.empty()) return;
|
||||
if (buffer.empty())
|
||||
return;
|
||||
if (buffer.size() > maxBufferSize || GetTickCount64() - lastPushTime > flushDelay)
|
||||
{
|
||||
AddSentence(std::move(buffer));
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
class TextThread
|
||||
{
|
||||
public:
|
||||
@ -37,6 +36,9 @@ private:
|
||||
std::mutex bufferMutex;
|
||||
DWORD64 lastPushTime = 0;
|
||||
Synchronized<std::vector<std::wstring>> queuedSentences;
|
||||
struct TimerDeleter { void operator()(HANDLE h) { DeleteTimerQueueTimer(NULL, h, INVALID_HANDLE_VALUE); } };
|
||||
struct TimerDeleter
|
||||
{
|
||||
void operator()(HANDLE h) { DeleteTimerQueueTimer(NULL, h, INVALID_HANDLE_VALUE); }
|
||||
};
|
||||
AutoHandle<TimerDeleter> timer = NULL;
|
||||
};
|
||||
|
@ -38,7 +38,8 @@ enum HostNotificationType
|
||||
HOST_NOTIFICATION_FOUND_HOOK,
|
||||
HOST_NOTIFICATION_RMVHOOK,
|
||||
HOST_NOTIFICATION_INSERTING_HOOK,
|
||||
HOST_SETTEXTTHREADTYPE
|
||||
HOST_SETTEXTTHREADTYPE,
|
||||
HOST_NOTIFICATION_WARNING
|
||||
};
|
||||
#define NEXT_MASK(x) \
|
||||
DUMMY1_##x, \
|
||||
|
@ -183,6 +183,12 @@ struct ConsoleOutputNotif // From dll
|
||||
HostNotificationType command = HOST_NOTIFICATION_TEXT;
|
||||
char message[MESSAGE_SIZE] = {};
|
||||
};
|
||||
struct WarningNotif // From dll
|
||||
{
|
||||
WarningNotif(std::string message = "") { strncpy_s(this->message, message.c_str(), MESSAGE_SIZE - 1); }
|
||||
HostNotificationType command = HOST_NOTIFICATION_WARNING;
|
||||
char message[MESSAGE_SIZE] = {};
|
||||
};
|
||||
|
||||
struct HookFoundNotif // From dll
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user