forked from Public-Mirror/Textractor
more user friendly hook searching and refactors
This commit is contained in:
parent
b18fe3ddd0
commit
b8bd602474
@ -33,6 +33,7 @@ extern const char* SEARCH_DURATION;
|
|||||||
extern const char* PATTERN_OFFSET;
|
extern const char* PATTERN_OFFSET;
|
||||||
extern const char* MIN_ADDRESS;
|
extern const char* MIN_ADDRESS;
|
||||||
extern const char* MAX_ADDRESS;
|
extern const char* MAX_ADDRESS;
|
||||||
|
extern const char* HOOK_SEARCH_FILTER;
|
||||||
extern const char* START_HOOK_SEARCH;
|
extern const char* START_HOOK_SEARCH;
|
||||||
extern const char* SAVE_SEARCH_RESULTS;
|
extern const char* SAVE_SEARCH_RESULTS;
|
||||||
extern const char* TEXT_FILES;
|
extern const char* TEXT_FILES;
|
||||||
@ -336,11 +337,11 @@ void MainWindow::FindHooks()
|
|||||||
void launch()
|
void launch()
|
||||||
{
|
{
|
||||||
auto layout = new QFormLayout(this);
|
auto layout = new QFormLayout(this);
|
||||||
auto patternInput = new QLineEdit("8B FF 55 8B EC", this);
|
auto patternInput = new QLineEdit(x64 ? "CC CC 48 89" : "CC CC 55 8B EC", this);
|
||||||
layout->addRow(SEARCH_PATTERN, patternInput);
|
layout->addRow(SEARCH_PATTERN, patternInput);
|
||||||
for (auto[value, label] : Array<std::tuple<int&, const char*>>{
|
for (auto[value, label] : Array<std::tuple<int&, const char*>>{
|
||||||
{ sp.searchTime, SEARCH_DURATION },
|
{ sp.searchTime = 20000, SEARCH_DURATION },
|
||||||
{ sp.offset, PATTERN_OFFSET },
|
{ sp.offset = 2, PATTERN_OFFSET },
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
auto spinBox = new QSpinBox(this);
|
auto spinBox = new QSpinBox(this);
|
||||||
@ -350,8 +351,8 @@ void MainWindow::FindHooks()
|
|||||||
connect(spinBox, qOverload<int>(&QSpinBox::valueChanged), [=, &value] { value = spinBox->value(); });
|
connect(spinBox, qOverload<int>(&QSpinBox::valueChanged), [=, &value] { value = spinBox->value(); });
|
||||||
}
|
}
|
||||||
for (auto[value, label] : Array<std::tuple<uintptr_t&, const char*>>{
|
for (auto[value, label] : Array<std::tuple<uintptr_t&, const char*>>{
|
||||||
{ sp.minAddress, MIN_ADDRESS },
|
{ sp.minAddress = 0, MIN_ADDRESS },
|
||||||
{ sp.maxAddress, MAX_ADDRESS },
|
{ sp.maxAddress = -1ULL, MAX_ADDRESS },
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
auto input = new QLineEdit(QString::number(value, 16), this);
|
auto input = new QLineEdit(QString::number(value, 16), this);
|
||||||
@ -361,19 +362,23 @@ void MainWindow::FindHooks()
|
|||||||
bool ok;
|
bool ok;
|
||||||
if (uintptr_t newValue = input.toULongLong(&ok, 16); ok) value = newValue;
|
if (uintptr_t newValue = input.toULongLong(&ok, 16); ok) value = newValue;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
auto filterInput = new QLineEdit(this);
|
||||||
|
layout->addRow(HOOK_SEARCH_FILTER, filterInput);
|
||||||
auto save = new QPushButton(START_HOOK_SEARCH, this);
|
auto save = new QPushButton(START_HOOK_SEARCH, this);
|
||||||
layout->addWidget(save);
|
layout->addWidget(save);
|
||||||
connect(save, &QPushButton::clicked, this, &QDialog::accept);
|
connect(save, &QPushButton::clicked, this, &QDialog::accept);
|
||||||
connect(save, &QPushButton::clicked, [this, patternInput]
|
connect(save, &QPushButton::clicked, [this, patternInput, filterInput]
|
||||||
{
|
{
|
||||||
QByteArray pattern = QByteArray::fromHex(patternInput->text().toUtf8());
|
QByteArray pattern = QByteArray::fromHex(patternInput->text().replace("??", "11").toUtf8());
|
||||||
if (pattern.size() < 3) return;
|
if (pattern.size() < 3) return;
|
||||||
|
std::wregex filter(L".");
|
||||||
|
if (!filterInput->text().isEmpty()) try { filter = std::wregex(S(filterInput->text())); } catch (std::regex_error&) {};
|
||||||
memcpy(sp.pattern, pattern.data(), sp.length = min(pattern.size(), 25));
|
memcpy(sp.pattern, pattern.data(), sp.length = min(pattern.size(), 25));
|
||||||
auto hooks = std::make_shared<QString>();
|
auto hooks = std::make_shared<QString>();
|
||||||
Host::FindHooks(processId, sp, [hooks](HookParam hp, DWORD processId, const std::wstring& text)
|
Host::FindHooks(processId, sp, [hooks, filter](HookParam hp, DWORD processId, const std::wstring& text)
|
||||||
{
|
{
|
||||||
hooks->append(S(Util::GenerateCode(hp, processId)) + ": " + S(text) + "\n");
|
if (std::regex_search(text, filter)) hooks->append(S(Util::GenerateCode(hp, processId)) + ": " + S(text) + "\n");
|
||||||
});
|
});
|
||||||
QString fileName = QFileDialog::getSaveFileName(this, SAVE_SEARCH_RESULTS, "./Hooks.txt", TEXT_FILES);
|
QString fileName = QFileDialog::getSaveFileName(this, SAVE_SEARCH_RESULTS, "./Hooks.txt", TEXT_FILES);
|
||||||
if (fileName.isEmpty()) fileName = "Hooks.txt";
|
if (fileName.isEmpty()) fileName = "Hooks.txt";
|
||||||
|
@ -62,9 +62,9 @@ struct SearchParam
|
|||||||
{
|
{
|
||||||
BYTE pattern[25] = {}; // pattern in memory to search for
|
BYTE pattern[25] = {}; // pattern in memory to search for
|
||||||
int length, // length of pattern
|
int length, // length of pattern
|
||||||
offset = 0, // offset from start of pattern to add hook
|
offset, // offset from start of pattern to add hook
|
||||||
searchTime = 30000; // ms
|
searchTime; // ms
|
||||||
uintptr_t minAddress = 0, maxAddress = (uintptr_t)-1LL;
|
uintptr_t minAddress, maxAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InsertHookCmd // From host
|
struct InsertHookCmd // From host
|
||||||
|
19
text.cpp
19
text.cpp
@ -47,15 +47,16 @@ const char* INVALID_EXTENSION = u8"%1 is an invalid extension";
|
|||||||
const char* CONFIRM_EXTENSION_OVERWRITE = u8"Another version of this extension already exists, do you want to delete and overwrite it?";
|
const char* CONFIRM_EXTENSION_OVERWRITE = u8"Another version of this extension already exists, do you want to delete and overwrite it?";
|
||||||
const char* EXTENSION_WRITE_ERROR = u8"Failed to save extension";
|
const char* EXTENSION_WRITE_ERROR = u8"Failed to save extension";
|
||||||
const char* USE_JP_LOCALE = u8"Emulate japanese locale?";
|
const char* USE_JP_LOCALE = u8"Emulate japanese locale?";
|
||||||
extern const char* HOOH_SEARCH_UNSTABLE_WARNING = u8"Searching for hooks is unstable! Be prepared for your game to crash!";
|
const char* HOOH_SEARCH_UNSTABLE_WARNING = u8"Searching for hooks is unstable! Be prepared for your game to crash!";
|
||||||
extern const char* SEARCH_PATTERN = u8"Search pattern (hex byte array)";
|
const char* SEARCH_PATTERN = u8"Search pattern (hex byte array)";
|
||||||
extern const char* SEARCH_DURATION = u8"Search duration (ms)";
|
const char* SEARCH_DURATION = u8"Search duration (ms)";
|
||||||
extern const char* PATTERN_OFFSET = u8"Offset from pattern start";
|
const char* PATTERN_OFFSET = u8"Offset from pattern start";
|
||||||
extern const char* MIN_ADDRESS = u8"Minimum address (hex)";
|
const char* MIN_ADDRESS = u8"Minimum address (hex)";
|
||||||
extern const char* MAX_ADDRESS = u8"Maximum address (hex)";
|
const char* MAX_ADDRESS = u8"Maximum address (hex)";
|
||||||
extern const char* START_HOOK_SEARCH = u8"Start hook search";
|
const char* HOOK_SEARCH_FILTER = u8"Results must match this regex";
|
||||||
extern const char* SAVE_SEARCH_RESULTS = u8"Save search results";
|
const char* START_HOOK_SEARCH = u8"Start hook search";
|
||||||
extern const char* TEXT_FILES = u8"Text (*.txt)";
|
const char* SAVE_SEARCH_RESULTS = u8"Save search results";
|
||||||
|
const char* TEXT_FILES = u8"Text (*.txt)";
|
||||||
const char* FILTER_REPETITION = u8"Repetition Filter";
|
const char* FILTER_REPETITION = u8"Repetition Filter";
|
||||||
const char* DEFAULT_CODEPAGE = u8"Default Codepage";
|
const char* DEFAULT_CODEPAGE = u8"Default Codepage";
|
||||||
const char* FLUSH_DELAY = u8"Flush Delay";
|
const char* FLUSH_DELAY = u8"Flush Delay";
|
||||||
|
@ -5,6 +5,7 @@ set(texthook_src
|
|||||||
main.cc
|
main.cc
|
||||||
texthook.cc
|
texthook.cc
|
||||||
hookfinder.cc
|
hookfinder.cc
|
||||||
|
engine/match.cc
|
||||||
engine/match64.cc
|
engine/match64.cc
|
||||||
engine/native/pchooks.cc
|
engine/native/pchooks.cc
|
||||||
util/ithsys/ithsys.cc
|
util/ithsys/ithsys.cc
|
||||||
@ -17,6 +18,7 @@ set(texthook_src
|
|||||||
hookfinder.cc
|
hookfinder.cc
|
||||||
engine/engine.cc
|
engine/engine.cc
|
||||||
engine/match.cc
|
engine/match.cc
|
||||||
|
engine/match32.cc
|
||||||
engine/native/pchooks.cc
|
engine/native/pchooks.cc
|
||||||
util/util.cc
|
util/util.cc
|
||||||
util/ithsys/ithsys.cc
|
util/ithsys/ithsys.cc
|
||||||
|
@ -1618,7 +1618,7 @@ bool InsertBGI1Hook()
|
|||||||
|
|
||||||
//ConsoleOutput("Probably BGI. Wait for text.");
|
//ConsoleOutput("Probably BGI. Wait for text.");
|
||||||
//SwitchTrigger(true);
|
//SwitchTrigger(true);
|
||||||
//trigger_fun_=InsertBGIDynamicHook;
|
//trigger_fun=InsertBGIDynamicHook;
|
||||||
ConsoleOutput("vnreng:BGI: failed");
|
ConsoleOutput("vnreng:BGI: failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2232,7 +2232,7 @@ void InsertRealliveHook()
|
|||||||
{
|
{
|
||||||
//ConsoleOutput("Probably Reallive. Wait for text.");
|
//ConsoleOutput("Probably Reallive. Wait for text.");
|
||||||
ConsoleOutput("vnreng: TRIGGER Reallive");
|
ConsoleOutput("vnreng: TRIGGER Reallive");
|
||||||
trigger_fun_ = InsertRealliveDynamicHook;
|
trigger_fun = InsertRealliveDynamicHook;
|
||||||
SetTrigger();
|
SetTrigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5787,7 +5787,7 @@ bool InsertShinaHook()
|
|||||||
int ver = GetShinaRioVersion();
|
int ver = GetShinaRioVersion();
|
||||||
if (ver >= 50) {
|
if (ver >= 50) {
|
||||||
SetTrigger();
|
SetTrigger();
|
||||||
trigger_fun_ = StackSearchingTrigger<GetGlyphOutlineA, NULL>;
|
trigger_fun = StackSearchingTrigger<GetGlyphOutlineA, NULL>;
|
||||||
ConsoleOutput("Textractor: ShinaRio 2.50+: adding trigger");
|
ConsoleOutput("Textractor: ShinaRio 2.50+: adding trigger");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -5960,7 +5960,7 @@ void InsertWaffleHook()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//ConsoleOutput("Probably Waffle. Wait for text.");
|
//ConsoleOutput("Probably Waffle. Wait for text.");
|
||||||
trigger_fun_ = InsertWaffleDynamicHook;
|
trigger_fun = InsertWaffleDynamicHook;
|
||||||
SetTrigger();
|
SetTrigger();
|
||||||
//ConsoleOutput("vnreng:WAFFLE: failed");
|
//ConsoleOutput("vnreng:WAFFLE: failed");
|
||||||
}
|
}
|
||||||
@ -7656,7 +7656,7 @@ bool InsertLiveDynamicHook(LPVOID addr, DWORD frame, DWORD stack)
|
|||||||
//void InsertLiveHook()
|
//void InsertLiveHook()
|
||||||
//{
|
//{
|
||||||
// ConsoleOutput("Probably Live. Wait for text.");
|
// ConsoleOutput("Probably Live. Wait for text.");
|
||||||
// trigger_fun_=InsertLiveDynamicHook;
|
// trigger_fun=InsertLiveDynamicHook;
|
||||||
// SwitchTrigger(true);
|
// SwitchTrigger(true);
|
||||||
//}
|
//}
|
||||||
bool InsertLiveHook()
|
bool InsertLiveHook()
|
||||||
@ -8524,7 +8524,7 @@ bool InsertSystemAoiDynamic()
|
|||||||
{
|
{
|
||||||
ConsoleOutput("vnreng: DYNAMIC SystemAoi");
|
ConsoleOutput("vnreng: DYNAMIC SystemAoi");
|
||||||
//ConsoleOutput("Probably SoftHouseChara. Wait for text.");
|
//ConsoleOutput("Probably SoftHouseChara. Wait for text.");
|
||||||
trigger_fun_ = InsertSystemAoiDynamicHook;
|
trigger_fun = InsertSystemAoiDynamicHook;
|
||||||
SetTrigger();
|
SetTrigger();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -8811,7 +8811,7 @@ bool InsertIGSDynamicHook(LPVOID addr, DWORD frame, DWORD stack)
|
|||||||
void InsertIronGameSystemHook()
|
void InsertIronGameSystemHook()
|
||||||
{
|
{
|
||||||
//ConsoleOutput("Probably IronGameSystem. Wait for text.");
|
//ConsoleOutput("Probably IronGameSystem. Wait for text.");
|
||||||
trigger_fun_ = InsertIGSDynamicHook;
|
trigger_fun = InsertIGSDynamicHook;
|
||||||
SetTrigger();
|
SetTrigger();
|
||||||
ConsoleOutput("vnreng: TRIGGER IronGameSystem");
|
ConsoleOutput("vnreng: TRIGGER IronGameSystem");
|
||||||
}
|
}
|
||||||
@ -9448,7 +9448,7 @@ bool InsertRyokuchaDynamicHook(LPVOID addr, DWORD frame, DWORD stack)
|
|||||||
void InsertRyokuchaHook()
|
void InsertRyokuchaHook()
|
||||||
{
|
{
|
||||||
//ConsoleOutput("Probably Ryokucha. Wait for text.");
|
//ConsoleOutput("Probably Ryokucha. Wait for text.");
|
||||||
trigger_fun_ = InsertRyokuchaDynamicHook;
|
trigger_fun = InsertRyokuchaDynamicHook;
|
||||||
SetTrigger();
|
SetTrigger();
|
||||||
ConsoleOutput("vnreng: TRIGGER Ryokucha");
|
ConsoleOutput("vnreng: TRIGGER Ryokucha");
|
||||||
}
|
}
|
||||||
@ -16512,7 +16512,7 @@ void InsertMonoHook(HMODULE h)
|
|||||||
Mono calling convention uses 'this' as first argument on stack
|
Mono calling convention uses 'this' as first argument on stack
|
||||||
Must be dynamic hook bootstrapped from other mono api or mono_domain_get won't work
|
Must be dynamic hook bootstrapped from other mono api or mono_domain_get won't work
|
||||||
*/
|
*/
|
||||||
trigger_fun_ = [](LPVOID addr, DWORD, DWORD)
|
trigger_fun = [](LPVOID addr, DWORD, DWORD)
|
||||||
{
|
{
|
||||||
static auto getDomain = (MonoDomain*(*)())GetProcAddress(mono, "mono_domain_get");
|
static auto getDomain = (MonoDomain*(*)())GetProcAddress(mono, "mono_domain_get");
|
||||||
static auto getJitInfo = (MonoObject*(*)(MonoDomain*, uintptr_t))GetProcAddress(mono, "mono_jit_info_table_find");
|
static auto getJitInfo = (MonoObject*(*)(MonoDomain*, uintptr_t))GetProcAddress(mono, "mono_jit_info_table_find");
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
struct HookParam; // defined in ith types.h
|
struct HookParam; // defined in ith types.h
|
||||||
|
|
||||||
extern DWORD processStartAddress, processStopAddress;
|
extern uintptr_t processStartAddress, processStopAddress;
|
||||||
|
|
||||||
namespace Engine {
|
namespace Engine {
|
||||||
|
|
||||||
@ -16,9 +16,13 @@ namespace Engine {
|
|||||||
extern wchar_t *processName, // cached
|
extern wchar_t *processName, // cached
|
||||||
processPath[MAX_PATH]; // cached
|
processPath[MAX_PATH]; // cached
|
||||||
|
|
||||||
//extern LPVOID trigger_addr;
|
/** jichi 12/24/2014
|
||||||
typedef bool (* trigger_fun_t)(LPVOID addr, DWORD frame, DWORD stack);
|
* @param addr function address
|
||||||
extern trigger_fun_t trigger_fun_;
|
* @param frame real address of the function, supposed to be the same as addr
|
||||||
|
* @param stack address of current stack - 4
|
||||||
|
* @return If success, which is reverted
|
||||||
|
*/
|
||||||
|
inline bool (*trigger_fun)(LPVOID addr, DWORD frame, DWORD stack);
|
||||||
|
|
||||||
bool InsertMonoHooks(); // Mono
|
bool InsertMonoHooks(); // Mono
|
||||||
|
|
||||||
|
@ -1,887 +1,58 @@
|
|||||||
// match.cc
|
#include "match.h"
|
||||||
// 8/9/2013 jichi
|
#include "engine.h"
|
||||||
// Branch: ITH_Engine/engine.cpp, revision 133
|
|
||||||
|
|
||||||
#include "engine/match.h"
|
|
||||||
#include "engine/engine.h"
|
|
||||||
#include "engine/native/pchooks.h"
|
|
||||||
#include "util/util.h"
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "ithsys/ithsys.h"
|
#include "native/pchooks.h"
|
||||||
|
|
||||||
extern const char* HIJACK_ERROR;
|
extern const char* HIJACK_ERROR;
|
||||||
|
|
||||||
//#define ConsoleOutput(...) (void)0 // jichi 8/18/2013: I don't need ConsoleOutput
|
uintptr_t processStartAddress, processStopAddress;
|
||||||
|
|
||||||
enum { MAX_REL_ADDR = 0x200000 }; // jichi 8/18/2013: maximum relative address
|
namespace Engine
|
||||||
|
|
||||||
// - Global variables -
|
|
||||||
|
|
||||||
DWORD processStartAddress, processStopAddress;
|
|
||||||
|
|
||||||
namespace Engine {
|
|
||||||
|
|
||||||
WCHAR *processName, // cached
|
|
||||||
processPath[MAX_PATH]; // cached
|
|
||||||
|
|
||||||
//LPVOID trigger_addr;
|
|
||||||
/** jichi 12/24/2014
|
|
||||||
* @param addr function address
|
|
||||||
* @param frame real address of the function, supposed to be the same as addr
|
|
||||||
* @param stack address of current stack - 4
|
|
||||||
* @return If success, which is reverted
|
|
||||||
*/
|
|
||||||
trigger_fun_t trigger_fun_;
|
|
||||||
|
|
||||||
} // namespace Engine
|
|
||||||
|
|
||||||
// - Methods -
|
|
||||||
|
|
||||||
namespace Engine { namespace { // unnamed
|
|
||||||
|
|
||||||
bool DetermineGameHooks() // 7/19/2015
|
|
||||||
{
|
{
|
||||||
#if 0 // jichi 7/19/2015: Disabled as it will crash the game
|
WCHAR* processName, // cached
|
||||||
if (Util::CheckFile(L"UE3ShaderCompileWorker.exe") && Util::CheckFile(L"awesomium_process.exe")) {
|
processPath[MAX_PATH]; // cached
|
||||||
InsertLovaGameHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif // 0
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 7/17/2014: Disable GDI hooks for PPSSPP
|
bool UnsafeDetermineEngineType();
|
||||||
bool DeterminePCEngine()
|
|
||||||
{
|
|
||||||
if (DetermineGameHooks()) {
|
|
||||||
ConsoleOutput("vnreng: found game-specific hook");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"PPSSPP*.exe")) { // jichi 7/12/2014 PPSSPPWindows.exe, PPSSPPEX.exe PPSSPPSP.exe
|
// jichi 10/21/2014: Return whether found the game engine
|
||||||
//InsertPPSSPPHooks(); // Artikash 8/4/2018: removed for now as doesn't work for non ancient ppsspp versions
|
bool DetermineEngineType()
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"pcsx2*.exe")) { // jichi 7/19/2014 PCSX2.exe or PCSX2WX.exe
|
|
||||||
InsertPCSX2Hooks();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"Dolphin.exe")) { // jichi 7/20/2014
|
|
||||||
InsertGCHooks();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 5/14/2015: Skip hijacking BALDRSKY ZEROs
|
|
||||||
//if (Util::CheckFile(L"bsz_Data\\Mono\\mono.dll") || Util::CheckFile(L"bsz2_Data\\Mono\\mono.dll")) {
|
|
||||||
// ConsoleOutput("vnreng: IGNORE BALDRSKY ZEROs");
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
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 (GetProcAddress((HMODULE)processStartAddress, "?Write@String@v8@@QBEHPAGHHH@Z"))
|
|
||||||
InsertV8Hook((HMODULE)processStartAddress);
|
|
||||||
if (HMODULE module = GetModuleHandleW(L"node.dll"))
|
|
||||||
InsertV8Hook(module);
|
|
||||||
if (HMODULE module = GetModuleHandleW(L"nw.dll"))
|
|
||||||
InsertV8Hook(module);
|
|
||||||
|
|
||||||
if (InsertMonoHooks()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PC games
|
|
||||||
PcHooks::hookGDIFunctions();
|
|
||||||
PcHooks::hookGDIPlusFunctions();
|
|
||||||
const char check[] = "sdffffffkjldfjlhjweiumxnvq1204tergdmnxcq1111111111111111111111408t03kxjb40";
|
|
||||||
Util::SearchMemory((const BYTE*)check, sizeof(check)); // Not too sure about the stability of this guy, so test it here
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DetermineEngineByFile1()
|
|
||||||
{
|
|
||||||
// Artikash 7/14/2018: AIRNovel - sample game https://vndb.org/v18814
|
|
||||||
if (Util::CheckFile(L"*.swf"))
|
|
||||||
{
|
|
||||||
//InsertAdobeAirHook();
|
|
||||||
InsertAIRNovelHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Artikash 8/9/2018: Renpy - sample game https://vndb.org/v19843
|
|
||||||
if (Util::CheckFile(L"*.py"))
|
|
||||||
{
|
|
||||||
InsertRenpyHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"*.xp3") || Util::SearchResourceString(L"TVP(KIRIKIRI)")) {
|
|
||||||
if (Util::SearchResourceString(L"TVP(KIRIKIRI) Z ")) { // TVP(KIRIKIRI) Z CORE
|
|
||||||
// jichi 11/24/2014: Disabled that might crash VBH
|
|
||||||
//if (Util::CheckFile(L"plugin\\KAGParser.dll"))
|
|
||||||
// InsertKAGParserHook();
|
|
||||||
//else if (Util::CheckFile(L"plugin\\KAGParserEx.dll"))
|
|
||||||
// InsertKAGParserExHook();
|
|
||||||
if (InsertKiriKiriZHook())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
InsertKiriKiriHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 8/2/2014 jichi: Game name shown as 2RM - Adventure Engine, text also in GetGlyphOutlineA
|
|
||||||
if (Util::SearchResourceString(L"2RM") && Util::SearchResourceString(L"Adventure Engine")) {
|
|
||||||
Insert2RMHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 8/2/2014 jichi: Copyright is side-B, a conf.dat will be generated after the game is launched
|
|
||||||
// It also contains lua5.1.dll and lua5.dll
|
|
||||||
if (Util::SearchResourceString(L"side-B")) {
|
|
||||||
InsertSideBHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"bgi.*") || Util::CheckFile(L"sysgrp.arc")) {
|
|
||||||
InsertBGIHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"Bootup.dat") && InsertBootupHook()) // 5/22/2015 Bootup
|
|
||||||
// lstrlenW can also find text with repetition though
|
|
||||||
return true;
|
|
||||||
if (Util::CheckFile(L"AGERC.DLL")) { // 6/1/2014 jichi: Eushully, AGE.EXE
|
|
||||||
InsertEushullyHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"data*.arc") && Util::CheckFile(L"stream*.arc")) {
|
|
||||||
InsertMajiroHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 5/31/2014
|
|
||||||
if (//Util::CheckFile(L"Silkys.exe") || // It might or might not have Silkys.exe
|
|
||||||
// data, effect, layer, mes, music
|
|
||||||
Util::CheckFile(L"data.arc") && Util::CheckFile(L"effect.arc") && Util::CheckFile(L"mes.arc")) {
|
|
||||||
InsertElfHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 6/9/2015: Skip Silkys Sakura
|
|
||||||
if ( // Almost the same as Silkys except mes.arc is replaced by Script.arc
|
|
||||||
Util::CheckFile(L"data.arc") && Util::CheckFile(L"effect.arc") && Util::CheckFile(L"Script.arc")) {
|
|
||||||
InsertSilkysHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"data\\pack\\*.cpz")) {
|
|
||||||
InsertCMVSHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 10/12/2013: Restore wolf engine
|
|
||||||
// jichi 10/18/2013: Check for data/*.wolf
|
|
||||||
if (Util::CheckFile(L"data.wolf") || Util::CheckFile(L"data\\*.wolf") || Util::CheckFile(L"data\\basicdata\\cdatabase.dat")) {
|
|
||||||
InsertWolfHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"AdvData\\DAT\\NAMES.DAT")) {
|
|
||||||
InsertCircusHook1();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"AdvData\\GRP\\NAMES.DAT")) {
|
|
||||||
InsertCircusHook2();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.noa") || Util::CheckFile(L"data\\*.noa")) {
|
|
||||||
InsertCotophaHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.pfs")) { // jichi 10/1/2013
|
|
||||||
InsertArtemisHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.int")) {
|
|
||||||
InsertCatSystemHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"message.dat")) {
|
|
||||||
InsertAtelierHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"Check.mdx")) { // jichi 4/1/2014: AUGame
|
|
||||||
InsertTencoHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 12/25/2013: It may or may not be QLIE.
|
|
||||||
// AlterEgo also has GameData/sound.pack but is not QLIE
|
|
||||||
if (Util::CheckFile(L"GameData\\*.pack") && InsertQLIEHook())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"dll\\Pal.dll")) {
|
|
||||||
InsertPalHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"*.pac")) {
|
|
||||||
// jichi 6/3/2014: AMUSE CRAFT and SOFTPAL
|
|
||||||
// Selectively insert, so that lstrlenA can still get correct text if failed
|
|
||||||
//if (Util::CheckFile(L"dll\\resource.dll") && Util::CheckFile(L"dll\\pal.dll") && InsertAmuseCraftHook())
|
|
||||||
// return true;
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"Thumbnail.pac")) {
|
|
||||||
//ConsoleOutput("vnreng: IGNORE NeXAS");
|
|
||||||
InsertNeXASHook(); // jichi 7/6/2014: GIGA
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::SearchResourceString(L"SOFTPAL")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE SoftPal UNiSONSHIFT");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// jichi 12/27/2014: LunaSoft
|
|
||||||
if (Util::CheckFile(L"Pac\\*.pac")) {
|
|
||||||
InsertLunaSoftHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 9/16/2013: Add Gesen18
|
|
||||||
if (Util::CheckFile(L"*.szs") || Util::CheckFile(L"Data\\*.szs")) {
|
|
||||||
InsertUnicornHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 12/22/2013: Add rejet
|
|
||||||
if (Util::CheckFile(L"gd.dat") && Util::CheckFile(L"pf.dat") && Util::CheckFile(L"sd.dat")) {
|
|
||||||
InsertRejetHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Only examined with version 1.0
|
|
||||||
//if (Util::CheckFile(L"Adobe AIR\\Versions\\*\\Adobe AIR.dll")) { // jichi 4/15/2014: FIXME: Wildcard not working
|
|
||||||
if (Util::CheckFile(L"Adobe AIR\\Versions\\1.0\\Adobe AIR.dll")) { // jichi 4/15/2014: Adobe AIR
|
|
||||||
InsertAdobeAirHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DetermineEngineByFile2()
|
|
||||||
{
|
|
||||||
if (Util::CheckFile(L"resident.dll")) {
|
|
||||||
InsertRetouchHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"Malie.ini") || Util::CheckFile(L"Malie.exe")) { // jichi: 9/9/2014: Add malie.exe in case malie.ini is missing
|
|
||||||
InsertMalieHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"live.dll")) {
|
|
||||||
InsertLiveHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 9/5/2013 jichi
|
|
||||||
if (Util::CheckFile(L"aInfo.db")) {
|
|
||||||
InsertNextonHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.lpk")) {
|
|
||||||
InsertLucifenHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"cfg.pak")) {
|
|
||||||
InsertWaffleHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"Arc00.dat")) {
|
|
||||||
InsertTinkerBellHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.vfs")) { // jichi 7/6/2014: Better to test AoiLib.dll? ja.wikipedia.org/wiki/ソフトハウスキャラ
|
|
||||||
InsertSystemAoiHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.mbl")) {
|
|
||||||
InsertMBLHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 8/1/2014: YU-RIS engine, lots of clockup game also has this pattern
|
|
||||||
if (Util::CheckFile(L"pac\\*.ypf") || Util::CheckFile(L"*.ypf")) {
|
|
||||||
// jichi 8/14/2013: CLOCLUP: "ノーブレスオブリージュ" would crash the game.
|
|
||||||
if (!Util::CheckFile(L"noblesse.exe"))
|
|
||||||
InsertYurisHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.npa")) {
|
|
||||||
InsertNitroplusHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DetermineEngineByFile3()
|
|
||||||
{
|
|
||||||
//if (Util::CheckFile(L"libscr.dll")) { // already checked
|
|
||||||
// InsertBrunsHook();
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// jichi 10/12/2013: Sample args.txt:
|
|
||||||
// See: http://tieba.baidu.com/p/2631413816
|
|
||||||
// -workdir
|
|
||||||
// .
|
|
||||||
// -loadpath
|
|
||||||
// .
|
|
||||||
// am.cfg
|
|
||||||
if (Util::CheckFile(L"args.txt")) {
|
|
||||||
InsertBrunsHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"emecfg.ecf")) {
|
|
||||||
InsertEMEHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"rrecfg.rcf")) {
|
|
||||||
InsertRREHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.fpk") || Util::CheckFile(L"data\\*.fpk")) {
|
|
||||||
InsertCandyHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"arc.a*")) {
|
|
||||||
InsertApricoTHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.mpk")) {
|
|
||||||
InsertStuffScriptHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"USRDIR\\*.mpk")) { // jichi 12/2/2014
|
|
||||||
InsertStuffScriptHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"Execle.exe")) {
|
|
||||||
InsertTriangleHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 2/28/2015: No longer work for "大正×対称アリス episode I" from Primula
|
|
||||||
//if (Util::CheckFile(L"PSetup.exe")) {
|
|
||||||
// InsertPensilHook();
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
if (Util::CheckFile(L"Yanesdk.dll")) {
|
|
||||||
InsertAB2TryHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.med")) {
|
|
||||||
InsertMEDHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DetermineEngineByFile4()
|
|
||||||
{
|
|
||||||
if (Util::CheckFile(L"EAGLS.dll")) { // jichi 3/24/2014: E.A.G.L.S
|
|
||||||
//ConsoleOutput("vnreng: IGNORE EAGLS");
|
|
||||||
InsertEaglsHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"bmp.pak") && Util::CheckFile(L"dsetup.dll")) {
|
|
||||||
// 1/1/2016 jich: skip izumo4 from studio ego that is not supported by debonosu
|
|
||||||
if (Util::CheckFile(L"*izumo4*.exe")) {
|
|
||||||
PcHooks::hookOtherPcFunctions();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
InsertDebonosuHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"C4.EXE") || Util::CheckFile(L"XEX.EXE")) {
|
|
||||||
InsertC4Hook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"Rio.arc") && Util::CheckFile(L"Chip*.arc")) {
|
|
||||||
InsertWillPlusHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.tac")) {
|
|
||||||
InsertTanukiHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.gxp")) {
|
|
||||||
InsertGXPHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.aos")) { // jichi 4/2/2014: AOS hook
|
|
||||||
InsertAOSHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.at2")) { // jichi 12/23/2014: Mink, sample files: voice.at2, voice.det, voice.nme
|
|
||||||
InsertMinkHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"*.ykc")) { // jichi 7/15/2014: YukaSystem1 is not supported, though
|
|
||||||
//ConsoleOutput("vnreng: IGNORE YKC:Feng/HookSoft(SMEE)");
|
|
||||||
InsertYukaSystem2Hook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"model\\*.hed")) { // jichi 9/8/2014: EXP
|
|
||||||
InsertExpHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 2/6/2015 平安亭
|
|
||||||
// dPi.dat, dPih.dat, dSc.dat, dSch.dat, dSo.dat, dSoh.dat, dSy.dat
|
|
||||||
//if (Util::CheckFile(L"dSoh.dat")) { // no idea why this file does not work
|
|
||||||
if (Util::CheckFile(L"dSch.dat")) {
|
|
||||||
InsertSyuntadaHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 2/28/2015: Delay checking Pensil in case something went wrong
|
|
||||||
// File pattern observed in [Primula] 大正×対称アリス episode I
|
|
||||||
// - PSetup.exe no longer exists
|
|
||||||
// - MovieTexture.dll information shows MovieTex dynamic library, copyright Pensil 2013
|
|
||||||
// - ta_trial.exe information shows 2XT - Primula Adventure Engine
|
|
||||||
if (Util::CheckFile(L"PSetup.exe") || Util::CheckFile(L"PENCIL.*") || Util::SearchResourceString(L"2XT -")) {
|
|
||||||
InsertPensilHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DetermineEngineByProcessName()
|
|
||||||
{
|
|
||||||
WCHAR str[MAX_PATH];
|
|
||||||
wcscpy_s(str, processName);
|
|
||||||
_wcslwr_s(str); // lower case
|
|
||||||
|
|
||||||
if (wcsstr(str,L"reallive") || Util::CheckFile(L"Reallive.exe") || Util::CheckFile(L"REALLIVEDATA\\Start.ini")) {
|
|
||||||
InsertRealliveHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 8/19/2013: DO NOT WORK for games like「ハピメア」
|
|
||||||
//if (wcsstr(str,L"cmvs32") || wcsstr(str,L"cmvs64")) {
|
|
||||||
// InsertCMVSHook();
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// jichi 8/17/2013: Handle "~"
|
|
||||||
if (wcsstr(str, L"siglusengine") || !wcsncmp(str, L"siglus~", 7) || Util::CheckFile(L"SiglusEngine.exe")) {
|
|
||||||
InsertSiglusHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wcsstr(str, L"taskforce2") || !wcsncmp(str, L"taskfo~", 7) || Util::CheckFile(L"Taskforce2.exe")) {
|
|
||||||
InsertTaskforce2Hook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wcsstr(str,L"rugp") || Util::CheckFile(L"rugp.exe")) {
|
|
||||||
InsertRUGPHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 8/17/2013: Handle "~"
|
|
||||||
if (wcsstr(str, L"igs_sample") || !wcsncmp(str, L"igs_sa~", 7) || Util::CheckFile(L"igs_sample.exe")) {
|
|
||||||
InsertIronGameSystemHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wcsstr(str, L"bruns") || Util::CheckFile(L"bruns.exe")) {
|
|
||||||
InsertBrunsHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wcsstr(str, L"anex86") || Util::CheckFile(L"anex86.exe")) {
|
|
||||||
InsertAnex86Hook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 8/17/2013: Handle "~"
|
|
||||||
if (wcsstr(str, L"shinydays") || !wcsncmp(str, L"shinyd~", 7) || Util::CheckFile(L"ShinyDays.exe")) {
|
|
||||||
InsertShinyDaysGameHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wcsstr(processName, L"SAISYS") || Util::CheckFile(L"SaiSys.exe")) { // jichi 4/19/2014: Marine Heart
|
|
||||||
InsertMarineHeartHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD len = wcslen(str);
|
|
||||||
|
|
||||||
// jichi 8/24/2013: Checking for Rio.ini or $procname.ini
|
|
||||||
//wcscpy(str+len-4, L"_?.war");
|
|
||||||
//if (Util::CheckFile(str)) {
|
|
||||||
// InsertShinaHook();
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
if (Util::CheckFile(L"*.ini")) {
|
|
||||||
if (InsertShinaHook())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 8/10/2013: Since *.bin is common, move CaramelBox to the end
|
|
||||||
str[len - 3] = L'b';
|
|
||||||
str[len - 2] = L'i';
|
|
||||||
str[len - 1] = L'n';
|
|
||||||
str[len] = 0;
|
|
||||||
if ((Util::CheckFile(str) || Util::CheckFile(L"trial.bin")) // jichi 7/8/2014: add trial.bin
|
|
||||||
&& InsertCaramelBoxHook())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// jichi 7/23/2015 It also has gameexe.bin existed
|
|
||||||
if (Util::CheckFile(L"configure.cfg") && Util::CheckFile(L"gfx.bin")) {
|
|
||||||
InsertEscudeHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This must appear at last since str is modified
|
|
||||||
//wcscpy(str + len - 4, L"_checksum.exe");
|
|
||||||
if (Util::CheckFile(L"*_checksum.exe")) {
|
|
||||||
InsertRyokuchaHook();
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"*.iar") && Util::CheckFile(L"*.sec5")) // jichi 9/27/2014: For new Ryokucha games
|
|
||||||
InsertScenarioPlayerHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DetermineEngineOther()
|
|
||||||
{
|
|
||||||
if (InsertAliceHook())
|
|
||||||
return true;
|
|
||||||
// jichi 1/19/2015: Disable inserting Lstr for System40
|
|
||||||
// See: http://sakuradite.com/topic/618
|
|
||||||
if (Util::CheckFile(L"System40.ini")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE old System40.ini");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 12/26/2013: Add this after alicehook
|
|
||||||
if (Util::CheckFile(L"AliceStart.ini")) {
|
|
||||||
InsertSystem43Hook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Artikash 7/16/2018: Uses node/libuv: likely v8 - sample game https://vndb.org/v22975
|
|
||||||
//if (GetProcAddress(GetModuleHandleW(nullptr), "uv_uptime") || GetModuleHandleW(L"node.dll"))
|
|
||||||
//{
|
|
||||||
// InsertV8Hook();
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// jichi 8/24/2013: Move into functions
|
|
||||||
// Artikash 6/15/2018: Removed this detection for Abel Software games. IthGetFileInfo no longer works correctly
|
|
||||||
//static BYTE static_file_info[0x1000];
|
|
||||||
//if (IthGetFileInfo(L"*01", static_file_info))
|
|
||||||
// if (*(DWORD*)static_file_info == 0) {
|
|
||||||
// STATUS_INFO_LENGTH_MISMATCH;
|
|
||||||
// static WCHAR static_search_name[MAX_PATH];
|
|
||||||
// LPWSTR name=(LPWSTR)(static_file_info+0x5E);
|
|
||||||
// int len = wcslen(name);
|
|
||||||
// name[len-2] = L'.';
|
|
||||||
// name[len-1] = L'e';
|
|
||||||
// name[len] = L'x';
|
|
||||||
// name[len+1] = L'e';
|
|
||||||
// name[len+2] = 0;
|
|
||||||
// if (Util::CheckFile(name)) {
|
|
||||||
// sizeof(FILE_BOTH_DIR_INFORMATION);
|
|
||||||
// name[len-2] = L'*';
|
|
||||||
// name[len-1] = 0;
|
|
||||||
// wcscpy(static_search_name,name);
|
|
||||||
// IthGetFileInfo(static_search_name,static_file_info);
|
|
||||||
// union {
|
|
||||||
// FILE_BOTH_DIR_INFORMATION *both_info;
|
|
||||||
// DWORD addr;
|
|
||||||
// };
|
|
||||||
// both_info = (FILE_BOTH_DIR_INFORMATION *)static_file_info;
|
|
||||||
// //BYTE* ptr=static_file_info;
|
|
||||||
// len=0;
|
|
||||||
// while (both_info->NextEntryOffset) {
|
|
||||||
// addr += both_info->NextEntryOffset;
|
|
||||||
// len++;
|
|
||||||
// }
|
|
||||||
// if (len > 3) {
|
|
||||||
// InsertAbelHook();
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 8/17/2014
|
|
||||||
// Put the patterns that might break other games at last
|
|
||||||
bool DetermineEngineAtLast()
|
|
||||||
{
|
|
||||||
if (Util::CheckFile(L"MovieTexture.dll") && (InsertPensilHook() || Insert2RMHook())) // MovieTexture.dll also exists in 2RM games such as 母子愛2体験版, which is checked first
|
|
||||||
return true;
|
|
||||||
if ((Util::CheckFile(L"system") && Util::CheckFile(L"system.dat")) || Util::CheckFile(L"*01")) { // jichi 7/31/2015 & Artikash 6/15/2018
|
|
||||||
InsertAbelHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"data\\*.cpk")) { // jichi 12/2/2014
|
|
||||||
Insert5pbHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// jichi 7/6/2014: named as ScenarioPlayer since resource string could be: scenario player program for xxx
|
|
||||||
// Do this at last as it is common
|
|
||||||
if (Util::CheckFile(L"*.iar") && Util::CheckFile(L"*.sec5")) { // jichi 4/18/2014: Other game engine could also have *.iar such as Ryokucha
|
|
||||||
InsertScenarioPlayerHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//if (Util::CheckFile(L"arc0.dat") && Util::CheckFile(L"script.dat") // jichi 11/14/2014: too common
|
|
||||||
if (Util::SearchResourceString(L"HorkEye")) { // appear in copyright: Copyright (C) HorkEye, http://horkeye.com
|
|
||||||
InsertHorkEyeHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"comnArc.arc") // jichi 8/17/2014: this file might exist in multiple files
|
|
||||||
&& InsertNexton1Hook()) // old nexton game
|
|
||||||
return true;
|
|
||||||
if (Util::CheckFile(L"arc.dat") // jichi 9/27/2014: too common
|
|
||||||
&& InsertApricoTHook())
|
|
||||||
return true;
|
|
||||||
if (Util::CheckFile(L"*.pak") // jichi 12/25/2014: too common
|
|
||||||
&& InsertLeafHook())
|
|
||||||
return true;
|
|
||||||
if (Util::CheckFile(L"*.dat") // mireado 08/22/2016: too common
|
|
||||||
&& InsertNekopackHook())
|
|
||||||
return true;
|
|
||||||
// jichi 10/31/2014
|
|
||||||
// File description: Adobe Flash Player 10.2r153
|
|
||||||
// Product name: Shockwave Flash
|
|
||||||
// Original filename: SAFlashPlayer.exe
|
|
||||||
// Legal trademarks: Adobe Flash Player
|
|
||||||
// No idea why, this must appear at last or it will crash
|
|
||||||
if (Util::SearchResourceString(L"Adobe Flash Player 10")) {
|
|
||||||
InsertAdobeFlash10Hook(); // only v10 might be supported. Otherwise, fallback to Lstr hooks
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Util::CheckFile(L"dat\\*.arc")) { // jichi 2/6/2015
|
|
||||||
InsertFocasLensHook(); // Touhou
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 8/23/2015: Tamamo
|
|
||||||
if (Util::CheckFile(L"data.pck") && Util::CheckFile(L"image.pck") && Util::CheckFile(L"script.pck")) {
|
|
||||||
//if (Util::CheckFile(L"QtGui.dll"))
|
|
||||||
InsertTamamoHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 6/1/2014
|
|
||||||
// Artikash 9/3/2018 Hook wchar by default
|
|
||||||
//bool DetermineEngineGeneric()
|
|
||||||
//{
|
|
||||||
// bool ret = false;
|
|
||||||
//
|
|
||||||
// //if (Util::CheckFile(L"AlterEgo.exe")) {
|
|
||||||
// // ConsoleOutput("vnreng: AlterEgo, INSERT WideChar hooks");
|
|
||||||
// // ret = true;
|
|
||||||
// //} else if (Util::CheckFile(L"data\\Sky\\*")) {
|
|
||||||
// // ConsoleOutput("vnreng: TEATIME, INSERT WideChar hooks");
|
|
||||||
// // ret = true;
|
|
||||||
// //}
|
|
||||||
// ////} else if (Util::CheckFile(L"image\\*.po2") || Util::CheckFile(L"image\\*.jo2")) {
|
|
||||||
// //// ConsoleOutput("vnreng: HarukaKanata, INSERT WideChar hooks"); // はるかかなた
|
|
||||||
// //// ret = true;
|
|
||||||
// ////}
|
|
||||||
// //if (ret)
|
|
||||||
// // PcHooks::hookWcharFunctions();
|
|
||||||
// PcHooks::hookWcharFunctions();
|
|
||||||
// return ret;
|
|
||||||
//}
|
|
||||||
|
|
||||||
bool DetermineNoEngine()
|
|
||||||
{
|
|
||||||
//if (Util::CheckFile(L"*\\Managed\\UnityEngine.dll")) { // jichi 12/3/2013: Unity (BALDRSKY ZERO)
|
|
||||||
// ConsoleOutput("vnreng: IGNORE Unity");
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
//if (Util::CheckFile(L"bsz_Data\\Managed\\UnityEngine.dll") || Util::CheckFile(L"bsz2_Data\\Managed\\UnityEngine.dll")) {
|
|
||||||
// ConsoleOutput("vnreng: IGNORE Unity");
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// jichi 6/7/2015: RPGMaker v3
|
|
||||||
if (Util::CheckFile(L"*.rgss3a")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE RPGMaker RGSS3");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 11/22/2015: 凍京NECRO 体験版
|
|
||||||
if (Util::CheckFile(L"*.npk")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE new Nitroplus");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8/29/2015 jichi: minori, text in GetGlyphOutlineA
|
|
||||||
if (Util::CheckFile(L"*.paz")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE minori");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7/28/2015 jichi: Favorite games
|
|
||||||
if (Util::CheckFile(L"*.hcb")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE FVP");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 2/14/2015: Guilty+ RIN×SEN (PK)
|
|
||||||
if (/*Util::CheckFile(L"rio.ini") || */Util::CheckFile(L"*.war")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE unknown ShinaRio");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"AdvHD.exe") || Util::CheckFile(L"AdvHD.dll")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE Adv Player HD"); // supposed to be WillPlus
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"ScrPlayer.exe")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE ScrPlayer");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"nnnConfig2.exe")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE Nya NNNConfig");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 4/30/2015: Skip games made from らすこう, such as とある人妻のネトラレ事情
|
|
||||||
// It has garbage from lstrlenW. Correct text is supposed to be in TabbedTextOutA.
|
|
||||||
if (Util::CheckFile(L"data_cg.dpm")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE DPM data_cg.dpm");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (Util::CheckFile(L"AGERC.DLL")) { // jichi 3/17/2014: Eushully, AGE.EXE
|
|
||||||
// ConsoleOutput("vnreng: IGNORE Eushully");
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"game_sys.exe")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE Atelier Kaguya BY/TH");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"*.bsa")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE Bishop");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 3/19/2014: Escude game
|
|
||||||
// Example: bgm.bin gfx.bin maou.bin script.bin snd.bin voc.bin
|
|
||||||
if (Util::CheckFile(L"gfx.bin") && Util::CheckFile(L"snd.bin") && Util::CheckFile(L"voc.bin")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE Escude");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 2/18/2015: Ignore if there is Nitro+ copyright
|
|
||||||
if (Util::SearchResourceString(L"Nitro+")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE unknown Nitro+");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 12/28/2014: "Chartreux Inc." in Copyright.
|
|
||||||
// Sublimary brands include Rosebleu, MORE, etc.
|
|
||||||
// GetGlyphOutlineA already works.
|
|
||||||
if (Util::SearchResourceString(L"Chartreux")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE Chartreux");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Util::CheckFile(L"MovieTexture.dll")) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE MovieTexture");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wcsstr(processName, L"lcsebody") || !wcsncmp(processName, L"lcsebo~", 7) || Util::CheckFile(L"lcsebody*")) { // jichi 3/19/2014: LC-ScriptEngine, GetGlyphOutlineA
|
|
||||||
ConsoleOutput("vnreng: IGNORE lcsebody");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t str[MAX_PATH];
|
|
||||||
DWORD i;
|
|
||||||
for (i = 0; processName[i]; i++) {
|
|
||||||
str[i] = processName[i];
|
|
||||||
if (processName[i] == L'.')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*(DWORD *)(str + i + 1) = 0x630068; //.hcb
|
|
||||||
*(DWORD *)(str + i + 3) = 0x62;
|
|
||||||
if (Util::CheckFile(str)) {
|
|
||||||
ConsoleOutput("vnreng: IGNORE FVP"); // jichi 10/3/2013: such like アトリエかぐや
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 9/14/2013: Certain ITH functions like FindEntryAligned might raise exception without admin priv
|
|
||||||
// Return if succeeded.
|
|
||||||
bool UnsafeDetermineEngineType()
|
|
||||||
{
|
|
||||||
return DeterminePCEngine()
|
|
||||||
|| DetermineEngineByFile1()
|
|
||||||
|| DetermineEngineByFile2()
|
|
||||||
|| DetermineEngineByFile3()
|
|
||||||
|| DetermineEngineByFile4()
|
|
||||||
|| DetermineEngineByProcessName()
|
|
||||||
|| DetermineEngineOther()
|
|
||||||
|| DetermineEngineAtLast()
|
|
||||||
|| DetermineNoEngine()
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 10/21/2014: Return whether found the game engine
|
|
||||||
bool DetermineEngineType()
|
|
||||||
{
|
|
||||||
// jichi 9/27/2013: disable game engine for debugging use
|
|
||||||
bool found = false;
|
|
||||||
#ifndef ITH_DISABLE_ENGINE
|
|
||||||
__try { found = UnsafeDetermineEngineType(); }
|
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER) { ConsoleOutput(HIJACK_ERROR); }
|
|
||||||
#endif // ITH_DISABLE_ENGINE
|
|
||||||
if (!found) { // jichi 10/2/2013: Only enable it if no game engine is detected
|
|
||||||
PcHooks::hookOtherPcFunctions();
|
|
||||||
} //else
|
|
||||||
// ConsoleOutput("vnreng: found game engine, IGNORE non gui hooks");
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // unnamed
|
|
||||||
|
|
||||||
DWORD InsertDynamicHook(LPVOID addr, DWORD frame, DWORD stack)
|
|
||||||
{
|
|
||||||
return trigger_fun_ ? !trigger_fun_(addr, frame, stack) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Hijack()
|
|
||||||
{
|
|
||||||
static bool hijacked = false;
|
|
||||||
if (hijacked) return;
|
|
||||||
GetModuleFileNameW(nullptr, processPath, MAX_PATH);
|
|
||||||
processName = wcsrchr(processPath, L'\\') + 1;
|
|
||||||
|
|
||||||
::processStartAddress = ::processStopAddress = (DWORD)GetModuleHandleW(nullptr);
|
|
||||||
MEMORY_BASIC_INFORMATION info;
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
VirtualQuery((void*)::processStopAddress, &info, sizeof(info));
|
// jichi 9/27/2013: disable game engine for debugging use
|
||||||
::processStopAddress = (DWORD)info.BaseAddress + info.RegionSize;
|
bool found = false;
|
||||||
} while (info.Protect > PAGE_NOACCESS);
|
#ifndef ITH_DISABLE_ENGINE
|
||||||
processStopAddress -= info.RegionSize;
|
__try { found = UnsafeDetermineEngineType(); }
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER) { ConsoleOutput(HIJACK_ERROR); }
|
||||||
|
#endif // ITH_DISABLE_ENGINE
|
||||||
|
if (!found) { // jichi 10/2/2013: Only enable it if no game engine is detected
|
||||||
|
PcHooks::hookOtherPcFunctions();
|
||||||
|
} //else
|
||||||
|
// ConsoleOutput("vnreng: found game engine, IGNORE non gui hooks");
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
DetermineEngineType();
|
DWORD InsertDynamicHook(LPVOID addr, DWORD frame, DWORD stack)
|
||||||
hijacked = true;
|
{
|
||||||
|
return trigger_fun ? !trigger_fun(addr, frame, stack) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hijack()
|
||||||
|
{
|
||||||
|
static bool hijacked = false;
|
||||||
|
if (hijacked) return;
|
||||||
|
GetModuleFileNameW(nullptr, processPath, MAX_PATH);
|
||||||
|
processName = wcsrchr(processPath, L'\\') + 1;
|
||||||
|
|
||||||
|
processStartAddress = processStopAddress = (uintptr_t)GetModuleHandleW(nullptr);
|
||||||
|
MEMORY_BASIC_INFORMATION info;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
VirtualQuery((void*)processStopAddress, &info, sizeof(info));
|
||||||
|
processStopAddress = (uintptr_t)info.BaseAddress + info.RegionSize;
|
||||||
|
} while (info.Protect > PAGE_NOACCESS);
|
||||||
|
processStopAddress -= info.RegionSize;
|
||||||
|
|
||||||
|
DetermineEngineType();
|
||||||
|
hijacked = true;
|
||||||
|
ConsoleOutput("Textractor: finished hijacking %S located from 0x%p to 0x%p", processName, processStartAddress, processStopAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Engine
|
|
||||||
|
|
||||||
// - API -
|
|
||||||
|
|
||||||
// EOF
|
|
||||||
|
824
texthook/engine/match32.cc
Normal file
824
texthook/engine/match32.cc
Normal file
@ -0,0 +1,824 @@
|
|||||||
|
// match.cc
|
||||||
|
// 8/9/2013 jichi
|
||||||
|
// Branch: ITH_Engine/engine.cpp, revision 133
|
||||||
|
|
||||||
|
#include "engine/match.h"
|
||||||
|
#include "engine/engine.h"
|
||||||
|
#include "engine/native/pchooks.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "ithsys/ithsys.h"
|
||||||
|
|
||||||
|
//#define ConsoleOutput(...) (void)0 // jichi 8/18/2013: I don't need ConsoleOutput
|
||||||
|
|
||||||
|
enum { MAX_REL_ADDR = 0x200000 }; // jichi 8/18/2013: maximum relative address
|
||||||
|
|
||||||
|
// - Methods -
|
||||||
|
|
||||||
|
namespace Engine { namespace { // unnamed
|
||||||
|
|
||||||
|
bool DetermineGameHooks() // 7/19/2015
|
||||||
|
{
|
||||||
|
#if 0 // jichi 7/19/2015: Disabled as it will crash the game
|
||||||
|
if (Util::CheckFile(L"UE3ShaderCompileWorker.exe") && Util::CheckFile(L"awesomium_process.exe")) {
|
||||||
|
InsertLovaGameHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif // 0
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 7/17/2014: Disable GDI hooks for PPSSPP
|
||||||
|
bool DeterminePCEngine()
|
||||||
|
{
|
||||||
|
if (DetermineGameHooks()) {
|
||||||
|
ConsoleOutput("vnreng: found game-specific hook");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"PPSSPP*.exe")) { // jichi 7/12/2014 PPSSPPWindows.exe, PPSSPPEX.exe PPSSPPSP.exe
|
||||||
|
//InsertPPSSPPHooks(); // Artikash 8/4/2018: removed for now as doesn't work for non ancient ppsspp versions
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"pcsx2*.exe")) { // jichi 7/19/2014 PCSX2.exe or PCSX2WX.exe
|
||||||
|
InsertPCSX2Hooks();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"Dolphin.exe")) { // jichi 7/20/2014
|
||||||
|
InsertGCHooks();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 5/14/2015: Skip hijacking BALDRSKY ZEROs
|
||||||
|
//if (Util::CheckFile(L"bsz_Data\\Mono\\mono.dll") || Util::CheckFile(L"bsz2_Data\\Mono\\mono.dll")) {
|
||||||
|
// ConsoleOutput("vnreng: IGNORE BALDRSKY ZEROs");
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
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 (GetProcAddress((HMODULE)processStartAddress, "?Write@String@v8@@QBEHPAGHHH@Z"))
|
||||||
|
InsertV8Hook((HMODULE)processStartAddress);
|
||||||
|
if (HMODULE module = GetModuleHandleW(L"node.dll"))
|
||||||
|
InsertV8Hook(module);
|
||||||
|
if (HMODULE module = GetModuleHandleW(L"nw.dll"))
|
||||||
|
InsertV8Hook(module);
|
||||||
|
|
||||||
|
if (InsertMonoHooks()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PC games
|
||||||
|
PcHooks::hookGDIFunctions();
|
||||||
|
PcHooks::hookGDIPlusFunctions();
|
||||||
|
const char check[] = "sdffffffkjldfjlhjweiumxnvq1204tergdmnxcq1111111111111111111111408t03kxjb40";
|
||||||
|
Util::SearchMemory((const BYTE*)check, sizeof(check)); // Not too sure about the stability of this guy, so test it here
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DetermineEngineByFile1()
|
||||||
|
{
|
||||||
|
// Artikash 7/14/2018: AIRNovel - sample game https://vndb.org/v18814
|
||||||
|
if (Util::CheckFile(L"*.swf"))
|
||||||
|
{
|
||||||
|
//InsertAdobeAirHook();
|
||||||
|
InsertAIRNovelHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Artikash 8/9/2018: Renpy - sample game https://vndb.org/v19843
|
||||||
|
if (Util::CheckFile(L"*.py"))
|
||||||
|
{
|
||||||
|
InsertRenpyHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"*.xp3") || Util::SearchResourceString(L"TVP(KIRIKIRI)")) {
|
||||||
|
if (Util::SearchResourceString(L"TVP(KIRIKIRI) Z ")) { // TVP(KIRIKIRI) Z CORE
|
||||||
|
// jichi 11/24/2014: Disabled that might crash VBH
|
||||||
|
//if (Util::CheckFile(L"plugin\\KAGParser.dll"))
|
||||||
|
// InsertKAGParserHook();
|
||||||
|
//else if (Util::CheckFile(L"plugin\\KAGParserEx.dll"))
|
||||||
|
// InsertKAGParserExHook();
|
||||||
|
if (InsertKiriKiriZHook())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
InsertKiriKiriHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 8/2/2014 jichi: Game name shown as 2RM - Adventure Engine, text also in GetGlyphOutlineA
|
||||||
|
if (Util::SearchResourceString(L"2RM") && Util::SearchResourceString(L"Adventure Engine")) {
|
||||||
|
Insert2RMHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 8/2/2014 jichi: Copyright is side-B, a conf.dat will be generated after the game is launched
|
||||||
|
// It also contains lua5.1.dll and lua5.dll
|
||||||
|
if (Util::SearchResourceString(L"side-B")) {
|
||||||
|
InsertSideBHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"bgi.*") || Util::CheckFile(L"sysgrp.arc")) {
|
||||||
|
InsertBGIHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"Bootup.dat") && InsertBootupHook()) // 5/22/2015 Bootup
|
||||||
|
// lstrlenW can also find text with repetition though
|
||||||
|
return true;
|
||||||
|
if (Util::CheckFile(L"AGERC.DLL")) { // 6/1/2014 jichi: Eushully, AGE.EXE
|
||||||
|
InsertEushullyHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"data*.arc") && Util::CheckFile(L"stream*.arc")) {
|
||||||
|
InsertMajiroHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 5/31/2014
|
||||||
|
if (//Util::CheckFile(L"Silkys.exe") || // It might or might not have Silkys.exe
|
||||||
|
// data, effect, layer, mes, music
|
||||||
|
Util::CheckFile(L"data.arc") && Util::CheckFile(L"effect.arc") && Util::CheckFile(L"mes.arc")) {
|
||||||
|
InsertElfHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 6/9/2015: Skip Silkys Sakura
|
||||||
|
if ( // Almost the same as Silkys except mes.arc is replaced by Script.arc
|
||||||
|
Util::CheckFile(L"data.arc") && Util::CheckFile(L"effect.arc") && Util::CheckFile(L"Script.arc")) {
|
||||||
|
InsertSilkysHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"data\\pack\\*.cpz")) {
|
||||||
|
InsertCMVSHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 10/12/2013: Restore wolf engine
|
||||||
|
// jichi 10/18/2013: Check for data/*.wolf
|
||||||
|
if (Util::CheckFile(L"data.wolf") || Util::CheckFile(L"data\\*.wolf") || Util::CheckFile(L"data\\basicdata\\cdatabase.dat")) {
|
||||||
|
InsertWolfHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"AdvData\\DAT\\NAMES.DAT")) {
|
||||||
|
InsertCircusHook1();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"AdvData\\GRP\\NAMES.DAT")) {
|
||||||
|
InsertCircusHook2();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.noa") || Util::CheckFile(L"data\\*.noa")) {
|
||||||
|
InsertCotophaHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.pfs")) { // jichi 10/1/2013
|
||||||
|
InsertArtemisHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.int")) {
|
||||||
|
InsertCatSystemHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"message.dat")) {
|
||||||
|
InsertAtelierHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"Check.mdx")) { // jichi 4/1/2014: AUGame
|
||||||
|
InsertTencoHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 12/25/2013: It may or may not be QLIE.
|
||||||
|
// AlterEgo also has GameData/sound.pack but is not QLIE
|
||||||
|
if (Util::CheckFile(L"GameData\\*.pack") && InsertQLIEHook())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"dll\\Pal.dll")) {
|
||||||
|
InsertPalHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"*.pac")) {
|
||||||
|
// jichi 6/3/2014: AMUSE CRAFT and SOFTPAL
|
||||||
|
// Selectively insert, so that lstrlenA can still get correct text if failed
|
||||||
|
//if (Util::CheckFile(L"dll\\resource.dll") && Util::CheckFile(L"dll\\pal.dll") && InsertAmuseCraftHook())
|
||||||
|
// return true;
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"Thumbnail.pac")) {
|
||||||
|
//ConsoleOutput("vnreng: IGNORE NeXAS");
|
||||||
|
InsertNeXASHook(); // jichi 7/6/2014: GIGA
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::SearchResourceString(L"SOFTPAL")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE SoftPal UNiSONSHIFT");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// jichi 12/27/2014: LunaSoft
|
||||||
|
if (Util::CheckFile(L"Pac\\*.pac")) {
|
||||||
|
InsertLunaSoftHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 9/16/2013: Add Gesen18
|
||||||
|
if (Util::CheckFile(L"*.szs") || Util::CheckFile(L"Data\\*.szs")) {
|
||||||
|
InsertUnicornHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 12/22/2013: Add rejet
|
||||||
|
if (Util::CheckFile(L"gd.dat") && Util::CheckFile(L"pf.dat") && Util::CheckFile(L"sd.dat")) {
|
||||||
|
InsertRejetHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Only examined with version 1.0
|
||||||
|
//if (Util::CheckFile(L"Adobe AIR\\Versions\\*\\Adobe AIR.dll")) { // jichi 4/15/2014: FIXME: Wildcard not working
|
||||||
|
if (Util::CheckFile(L"Adobe AIR\\Versions\\1.0\\Adobe AIR.dll")) { // jichi 4/15/2014: Adobe AIR
|
||||||
|
InsertAdobeAirHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DetermineEngineByFile2()
|
||||||
|
{
|
||||||
|
if (Util::CheckFile(L"resident.dll")) {
|
||||||
|
InsertRetouchHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"Malie.ini") || Util::CheckFile(L"Malie.exe")) { // jichi: 9/9/2014: Add malie.exe in case malie.ini is missing
|
||||||
|
InsertMalieHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"live.dll")) {
|
||||||
|
InsertLiveHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 9/5/2013 jichi
|
||||||
|
if (Util::CheckFile(L"aInfo.db")) {
|
||||||
|
InsertNextonHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.lpk")) {
|
||||||
|
InsertLucifenHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"cfg.pak")) {
|
||||||
|
InsertWaffleHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"Arc00.dat")) {
|
||||||
|
InsertTinkerBellHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.vfs")) { // jichi 7/6/2014: Better to test AoiLib.dll? ja.wikipedia.org/wiki/ソフトハウスキャラ
|
||||||
|
InsertSystemAoiHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.mbl")) {
|
||||||
|
InsertMBLHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 8/1/2014: YU-RIS engine, lots of clockup game also has this pattern
|
||||||
|
if (Util::CheckFile(L"pac\\*.ypf") || Util::CheckFile(L"*.ypf")) {
|
||||||
|
// jichi 8/14/2013: CLOCLUP: "ノーブレスオブリージュ" would crash the game.
|
||||||
|
if (!Util::CheckFile(L"noblesse.exe"))
|
||||||
|
InsertYurisHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.npa")) {
|
||||||
|
InsertNitroplusHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DetermineEngineByFile3()
|
||||||
|
{
|
||||||
|
//if (Util::CheckFile(L"libscr.dll")) { // already checked
|
||||||
|
// InsertBrunsHook();
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// jichi 10/12/2013: Sample args.txt:
|
||||||
|
// See: http://tieba.baidu.com/p/2631413816
|
||||||
|
// -workdir
|
||||||
|
// .
|
||||||
|
// -loadpath
|
||||||
|
// .
|
||||||
|
// am.cfg
|
||||||
|
if (Util::CheckFile(L"args.txt")) {
|
||||||
|
InsertBrunsHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"emecfg.ecf")) {
|
||||||
|
InsertEMEHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"rrecfg.rcf")) {
|
||||||
|
InsertRREHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.fpk") || Util::CheckFile(L"data\\*.fpk")) {
|
||||||
|
InsertCandyHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"arc.a*")) {
|
||||||
|
InsertApricoTHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.mpk")) {
|
||||||
|
InsertStuffScriptHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"USRDIR\\*.mpk")) { // jichi 12/2/2014
|
||||||
|
InsertStuffScriptHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"Execle.exe")) {
|
||||||
|
InsertTriangleHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 2/28/2015: No longer work for "大正×対称アリス episode I" from Primula
|
||||||
|
//if (Util::CheckFile(L"PSetup.exe")) {
|
||||||
|
// InsertPensilHook();
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
if (Util::CheckFile(L"Yanesdk.dll")) {
|
||||||
|
InsertAB2TryHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.med")) {
|
||||||
|
InsertMEDHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DetermineEngineByFile4()
|
||||||
|
{
|
||||||
|
if (Util::CheckFile(L"EAGLS.dll")) { // jichi 3/24/2014: E.A.G.L.S
|
||||||
|
//ConsoleOutput("vnreng: IGNORE EAGLS");
|
||||||
|
InsertEaglsHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"bmp.pak") && Util::CheckFile(L"dsetup.dll")) {
|
||||||
|
// 1/1/2016 jich: skip izumo4 from studio ego that is not supported by debonosu
|
||||||
|
if (Util::CheckFile(L"*izumo4*.exe")) {
|
||||||
|
PcHooks::hookOtherPcFunctions();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
InsertDebonosuHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"C4.EXE") || Util::CheckFile(L"XEX.EXE")) {
|
||||||
|
InsertC4Hook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"Rio.arc") && Util::CheckFile(L"Chip*.arc")) {
|
||||||
|
InsertWillPlusHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.tac")) {
|
||||||
|
InsertTanukiHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.gxp")) {
|
||||||
|
InsertGXPHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.aos")) { // jichi 4/2/2014: AOS hook
|
||||||
|
InsertAOSHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.at2")) { // jichi 12/23/2014: Mink, sample files: voice.at2, voice.det, voice.nme
|
||||||
|
InsertMinkHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"*.ykc")) { // jichi 7/15/2014: YukaSystem1 is not supported, though
|
||||||
|
//ConsoleOutput("vnreng: IGNORE YKC:Feng/HookSoft(SMEE)");
|
||||||
|
InsertYukaSystem2Hook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"model\\*.hed")) { // jichi 9/8/2014: EXP
|
||||||
|
InsertExpHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 2/6/2015 平安亭
|
||||||
|
// dPi.dat, dPih.dat, dSc.dat, dSch.dat, dSo.dat, dSoh.dat, dSy.dat
|
||||||
|
//if (Util::CheckFile(L"dSoh.dat")) { // no idea why this file does not work
|
||||||
|
if (Util::CheckFile(L"dSch.dat")) {
|
||||||
|
InsertSyuntadaHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 2/28/2015: Delay checking Pensil in case something went wrong
|
||||||
|
// File pattern observed in [Primula] 大正×対称アリス episode I
|
||||||
|
// - PSetup.exe no longer exists
|
||||||
|
// - MovieTexture.dll information shows MovieTex dynamic library, copyright Pensil 2013
|
||||||
|
// - ta_trial.exe information shows 2XT - Primula Adventure Engine
|
||||||
|
if (Util::CheckFile(L"PSetup.exe") || Util::CheckFile(L"PENCIL.*") || Util::SearchResourceString(L"2XT -")) {
|
||||||
|
InsertPensilHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DetermineEngineByProcessName()
|
||||||
|
{
|
||||||
|
WCHAR str[MAX_PATH];
|
||||||
|
wcscpy_s(str, processName);
|
||||||
|
_wcslwr_s(str); // lower case
|
||||||
|
|
||||||
|
if (wcsstr(str,L"reallive") || Util::CheckFile(L"Reallive.exe") || Util::CheckFile(L"REALLIVEDATA\\Start.ini")) {
|
||||||
|
InsertRealliveHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 8/19/2013: DO NOT WORK for games like「ハピメア」
|
||||||
|
//if (wcsstr(str,L"cmvs32") || wcsstr(str,L"cmvs64")) {
|
||||||
|
// InsertCMVSHook();
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// jichi 8/17/2013: Handle "~"
|
||||||
|
if (wcsstr(str, L"siglusengine") || !wcsncmp(str, L"siglus~", 7) || Util::CheckFile(L"SiglusEngine.exe")) {
|
||||||
|
InsertSiglusHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wcsstr(str, L"taskforce2") || !wcsncmp(str, L"taskfo~", 7) || Util::CheckFile(L"Taskforce2.exe")) {
|
||||||
|
InsertTaskforce2Hook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wcsstr(str,L"rugp") || Util::CheckFile(L"rugp.exe")) {
|
||||||
|
InsertRUGPHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 8/17/2013: Handle "~"
|
||||||
|
if (wcsstr(str, L"igs_sample") || !wcsncmp(str, L"igs_sa~", 7) || Util::CheckFile(L"igs_sample.exe")) {
|
||||||
|
InsertIronGameSystemHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wcsstr(str, L"bruns") || Util::CheckFile(L"bruns.exe")) {
|
||||||
|
InsertBrunsHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wcsstr(str, L"anex86") || Util::CheckFile(L"anex86.exe")) {
|
||||||
|
InsertAnex86Hook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 8/17/2013: Handle "~"
|
||||||
|
if (wcsstr(str, L"shinydays") || !wcsncmp(str, L"shinyd~", 7) || Util::CheckFile(L"ShinyDays.exe")) {
|
||||||
|
InsertShinyDaysGameHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wcsstr(processName, L"SAISYS") || Util::CheckFile(L"SaiSys.exe")) { // jichi 4/19/2014: Marine Heart
|
||||||
|
InsertMarineHeartHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD len = wcslen(str);
|
||||||
|
|
||||||
|
// jichi 8/24/2013: Checking for Rio.ini or $procname.ini
|
||||||
|
//wcscpy(str+len-4, L"_?.war");
|
||||||
|
//if (Util::CheckFile(str)) {
|
||||||
|
// InsertShinaHook();
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
if (Util::CheckFile(L"*.ini")) {
|
||||||
|
if (InsertShinaHook())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 8/10/2013: Since *.bin is common, move CaramelBox to the end
|
||||||
|
str[len - 3] = L'b';
|
||||||
|
str[len - 2] = L'i';
|
||||||
|
str[len - 1] = L'n';
|
||||||
|
str[len] = 0;
|
||||||
|
if ((Util::CheckFile(str) || Util::CheckFile(L"trial.bin")) // jichi 7/8/2014: add trial.bin
|
||||||
|
&& InsertCaramelBoxHook())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// jichi 7/23/2015 It also has gameexe.bin existed
|
||||||
|
if (Util::CheckFile(L"configure.cfg") && Util::CheckFile(L"gfx.bin")) {
|
||||||
|
InsertEscudeHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This must appear at last since str is modified
|
||||||
|
//wcscpy(str + len - 4, L"_checksum.exe");
|
||||||
|
if (Util::CheckFile(L"*_checksum.exe")) {
|
||||||
|
InsertRyokuchaHook();
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"*.iar") && Util::CheckFile(L"*.sec5")) // jichi 9/27/2014: For new Ryokucha games
|
||||||
|
InsertScenarioPlayerHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DetermineEngineOther()
|
||||||
|
{
|
||||||
|
if (InsertAliceHook())
|
||||||
|
return true;
|
||||||
|
// jichi 1/19/2015: Disable inserting Lstr for System40
|
||||||
|
// See: http://sakuradite.com/topic/618
|
||||||
|
if (Util::CheckFile(L"System40.ini")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE old System40.ini");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 12/26/2013: Add this after alicehook
|
||||||
|
if (Util::CheckFile(L"AliceStart.ini")) {
|
||||||
|
InsertSystem43Hook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Artikash 7/16/2018: Uses node/libuv: likely v8 - sample game https://vndb.org/v22975
|
||||||
|
//if (GetProcAddress(GetModuleHandleW(nullptr), "uv_uptime") || GetModuleHandleW(L"node.dll"))
|
||||||
|
//{
|
||||||
|
// InsertV8Hook();
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// jichi 8/24/2013: Move into functions
|
||||||
|
// Artikash 6/15/2018: Removed this detection for Abel Software games. IthGetFileInfo no longer works correctly
|
||||||
|
//static BYTE static_file_info[0x1000];
|
||||||
|
//if (IthGetFileInfo(L"*01", static_file_info))
|
||||||
|
// if (*(DWORD*)static_file_info == 0) {
|
||||||
|
// STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
// static WCHAR static_search_name[MAX_PATH];
|
||||||
|
// LPWSTR name=(LPWSTR)(static_file_info+0x5E);
|
||||||
|
// int len = wcslen(name);
|
||||||
|
// name[len-2] = L'.';
|
||||||
|
// name[len-1] = L'e';
|
||||||
|
// name[len] = L'x';
|
||||||
|
// name[len+1] = L'e';
|
||||||
|
// name[len+2] = 0;
|
||||||
|
// if (Util::CheckFile(name)) {
|
||||||
|
// sizeof(FILE_BOTH_DIR_INFORMATION);
|
||||||
|
// name[len-2] = L'*';
|
||||||
|
// name[len-1] = 0;
|
||||||
|
// wcscpy(static_search_name,name);
|
||||||
|
// IthGetFileInfo(static_search_name,static_file_info);
|
||||||
|
// union {
|
||||||
|
// FILE_BOTH_DIR_INFORMATION *both_info;
|
||||||
|
// DWORD addr;
|
||||||
|
// };
|
||||||
|
// both_info = (FILE_BOTH_DIR_INFORMATION *)static_file_info;
|
||||||
|
// //BYTE* ptr=static_file_info;
|
||||||
|
// len=0;
|
||||||
|
// while (both_info->NextEntryOffset) {
|
||||||
|
// addr += both_info->NextEntryOffset;
|
||||||
|
// len++;
|
||||||
|
// }
|
||||||
|
// if (len > 3) {
|
||||||
|
// InsertAbelHook();
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 8/17/2014
|
||||||
|
// Put the patterns that might break other games at last
|
||||||
|
bool DetermineEngineAtLast()
|
||||||
|
{
|
||||||
|
if (Util::CheckFile(L"MovieTexture.dll") && (InsertPensilHook() || Insert2RMHook())) // MovieTexture.dll also exists in 2RM games such as 母子愛2体験版, which is checked first
|
||||||
|
return true;
|
||||||
|
if ((Util::CheckFile(L"system") && Util::CheckFile(L"system.dat")) || Util::CheckFile(L"*01")) { // jichi 7/31/2015 & Artikash 6/15/2018
|
||||||
|
InsertAbelHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"data\\*.cpk")) { // jichi 12/2/2014
|
||||||
|
Insert5pbHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// jichi 7/6/2014: named as ScenarioPlayer since resource string could be: scenario player program for xxx
|
||||||
|
// Do this at last as it is common
|
||||||
|
if (Util::CheckFile(L"*.iar") && Util::CheckFile(L"*.sec5")) { // jichi 4/18/2014: Other game engine could also have *.iar such as Ryokucha
|
||||||
|
InsertScenarioPlayerHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//if (Util::CheckFile(L"arc0.dat") && Util::CheckFile(L"script.dat") // jichi 11/14/2014: too common
|
||||||
|
if (Util::SearchResourceString(L"HorkEye")) { // appear in copyright: Copyright (C) HorkEye, http://horkeye.com
|
||||||
|
InsertHorkEyeHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"comnArc.arc") // jichi 8/17/2014: this file might exist in multiple files
|
||||||
|
&& InsertNexton1Hook()) // old nexton game
|
||||||
|
return true;
|
||||||
|
if (Util::CheckFile(L"arc.dat") // jichi 9/27/2014: too common
|
||||||
|
&& InsertApricoTHook())
|
||||||
|
return true;
|
||||||
|
if (Util::CheckFile(L"*.pak") // jichi 12/25/2014: too common
|
||||||
|
&& InsertLeafHook())
|
||||||
|
return true;
|
||||||
|
if (Util::CheckFile(L"*.dat") // mireado 08/22/2016: too common
|
||||||
|
&& InsertNekopackHook())
|
||||||
|
return true;
|
||||||
|
// jichi 10/31/2014
|
||||||
|
// File description: Adobe Flash Player 10.2r153
|
||||||
|
// Product name: Shockwave Flash
|
||||||
|
// Original filename: SAFlashPlayer.exe
|
||||||
|
// Legal trademarks: Adobe Flash Player
|
||||||
|
// No idea why, this must appear at last or it will crash
|
||||||
|
if (Util::SearchResourceString(L"Adobe Flash Player 10")) {
|
||||||
|
InsertAdobeFlash10Hook(); // only v10 might be supported. Otherwise, fallback to Lstr hooks
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Util::CheckFile(L"dat\\*.arc")) { // jichi 2/6/2015
|
||||||
|
InsertFocasLensHook(); // Touhou
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 8/23/2015: Tamamo
|
||||||
|
if (Util::CheckFile(L"data.pck") && Util::CheckFile(L"image.pck") && Util::CheckFile(L"script.pck")) {
|
||||||
|
//if (Util::CheckFile(L"QtGui.dll"))
|
||||||
|
InsertTamamoHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 6/1/2014
|
||||||
|
// Artikash 9/3/2018 Hook wchar by default
|
||||||
|
//bool DetermineEngineGeneric()
|
||||||
|
//{
|
||||||
|
// bool ret = false;
|
||||||
|
//
|
||||||
|
// //if (Util::CheckFile(L"AlterEgo.exe")) {
|
||||||
|
// // ConsoleOutput("vnreng: AlterEgo, INSERT WideChar hooks");
|
||||||
|
// // ret = true;
|
||||||
|
// //} else if (Util::CheckFile(L"data\\Sky\\*")) {
|
||||||
|
// // ConsoleOutput("vnreng: TEATIME, INSERT WideChar hooks");
|
||||||
|
// // ret = true;
|
||||||
|
// //}
|
||||||
|
// ////} else if (Util::CheckFile(L"image\\*.po2") || Util::CheckFile(L"image\\*.jo2")) {
|
||||||
|
// //// ConsoleOutput("vnreng: HarukaKanata, INSERT WideChar hooks"); // はるかかなた
|
||||||
|
// //// ret = true;
|
||||||
|
// ////}
|
||||||
|
// //if (ret)
|
||||||
|
// // PcHooks::hookWcharFunctions();
|
||||||
|
// PcHooks::hookWcharFunctions();
|
||||||
|
// return ret;
|
||||||
|
//}
|
||||||
|
|
||||||
|
bool DetermineNoEngine()
|
||||||
|
{
|
||||||
|
//if (Util::CheckFile(L"*\\Managed\\UnityEngine.dll")) { // jichi 12/3/2013: Unity (BALDRSKY ZERO)
|
||||||
|
// ConsoleOutput("vnreng: IGNORE Unity");
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
//if (Util::CheckFile(L"bsz_Data\\Managed\\UnityEngine.dll") || Util::CheckFile(L"bsz2_Data\\Managed\\UnityEngine.dll")) {
|
||||||
|
// ConsoleOutput("vnreng: IGNORE Unity");
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// jichi 6/7/2015: RPGMaker v3
|
||||||
|
if (Util::CheckFile(L"*.rgss3a")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE RPGMaker RGSS3");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 11/22/2015: 凍京NECRO 体験版
|
||||||
|
if (Util::CheckFile(L"*.npk")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE new Nitroplus");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8/29/2015 jichi: minori, text in GetGlyphOutlineA
|
||||||
|
if (Util::CheckFile(L"*.paz")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE minori");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7/28/2015 jichi: Favorite games
|
||||||
|
if (Util::CheckFile(L"*.hcb")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE FVP");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 2/14/2015: Guilty+ RIN×SEN (PK)
|
||||||
|
if (/*Util::CheckFile(L"rio.ini") || */Util::CheckFile(L"*.war")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE unknown ShinaRio");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"AdvHD.exe") || Util::CheckFile(L"AdvHD.dll")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE Adv Player HD"); // supposed to be WillPlus
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"ScrPlayer.exe")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE ScrPlayer");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"nnnConfig2.exe")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE Nya NNNConfig");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 4/30/2015: Skip games made from らすこう, such as とある人妻のネトラレ事情
|
||||||
|
// It has garbage from lstrlenW. Correct text is supposed to be in TabbedTextOutA.
|
||||||
|
if (Util::CheckFile(L"data_cg.dpm")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE DPM data_cg.dpm");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (Util::CheckFile(L"AGERC.DLL")) { // jichi 3/17/2014: Eushully, AGE.EXE
|
||||||
|
// ConsoleOutput("vnreng: IGNORE Eushully");
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"game_sys.exe")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE Atelier Kaguya BY/TH");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"*.bsa")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE Bishop");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 3/19/2014: Escude game
|
||||||
|
// Example: bgm.bin gfx.bin maou.bin script.bin snd.bin voc.bin
|
||||||
|
if (Util::CheckFile(L"gfx.bin") && Util::CheckFile(L"snd.bin") && Util::CheckFile(L"voc.bin")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE Escude");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 2/18/2015: Ignore if there is Nitro+ copyright
|
||||||
|
if (Util::SearchResourceString(L"Nitro+")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE unknown Nitro+");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// jichi 12/28/2014: "Chartreux Inc." in Copyright.
|
||||||
|
// Sublimary brands include Rosebleu, MORE, etc.
|
||||||
|
// GetGlyphOutlineA already works.
|
||||||
|
if (Util::SearchResourceString(L"Chartreux")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE Chartreux");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Util::CheckFile(L"MovieTexture.dll")) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE MovieTexture");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wcsstr(processName, L"lcsebody") || !wcsncmp(processName, L"lcsebo~", 7) || Util::CheckFile(L"lcsebody*")) { // jichi 3/19/2014: LC-ScriptEngine, GetGlyphOutlineA
|
||||||
|
ConsoleOutput("vnreng: IGNORE lcsebody");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t str[MAX_PATH];
|
||||||
|
DWORD i;
|
||||||
|
for (i = 0; processName[i]; i++) {
|
||||||
|
str[i] = processName[i];
|
||||||
|
if (processName[i] == L'.')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*(DWORD *)(str + i + 1) = 0x630068; //.hcb
|
||||||
|
*(DWORD *)(str + i + 3) = 0x62;
|
||||||
|
if (Util::CheckFile(str)) {
|
||||||
|
ConsoleOutput("vnreng: IGNORE FVP"); // jichi 10/3/2013: such like アトリエかぐや
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // unnamed
|
||||||
|
|
||||||
|
// jichi 9/14/2013: Certain ITH functions like FindEntryAligned might raise exception without admin priv
|
||||||
|
// Return if succeeded.
|
||||||
|
bool UnsafeDetermineEngineType()
|
||||||
|
{
|
||||||
|
return DeterminePCEngine()
|
||||||
|
|| DetermineEngineByFile1()
|
||||||
|
|| DetermineEngineByFile2()
|
||||||
|
|| DetermineEngineByFile3()
|
||||||
|
|| DetermineEngineByFile4()
|
||||||
|
|| DetermineEngineByProcessName()
|
||||||
|
|| DetermineEngineOther()
|
||||||
|
|| DetermineEngineAtLast()
|
||||||
|
|| DetermineNoEngine()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Engine
|
||||||
|
|
||||||
|
// - API -
|
||||||
|
|
||||||
|
// EOF
|
@ -2,30 +2,17 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "native/pchooks.h"
|
#include "native/pchooks.h"
|
||||||
|
|
||||||
extern const char* HIJACK_ERROR;
|
|
||||||
|
|
||||||
namespace Engine
|
namespace Engine
|
||||||
{
|
{
|
||||||
void HookDirectX()
|
bool UnsafeDetermineEngineType()
|
||||||
{
|
{
|
||||||
|
|
||||||
for (std::wstring DXVersion : { L"d3dx9", L"d3dx10" })
|
for (std::wstring DXVersion : { L"d3dx9", L"d3dx10" })
|
||||||
if (HMODULE module = GetModuleHandleW(DXVersion.c_str())) PcHooks::hookD3DXFunctions(module);
|
if (HMODULE module = GetModuleHandleW(DXVersion.c_str())) PcHooks::hookD3DXFunctions(module);
|
||||||
else for (int i = 0; i < 50; ++i)
|
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 + L"_" + std::to_wstring(i)).c_str())) PcHooks::hookD3DXFunctions(module);
|
||||||
}
|
|
||||||
void Hijack()
|
PcHooks::hookGDIFunctions();
|
||||||
{
|
PcHooks::hookGDIPlusFunctions();
|
||||||
static bool hijacked = false;
|
return false;
|
||||||
if (hijacked) return;
|
|
||||||
hijacked = true;
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
PcHooks::hookGDIFunctions();
|
|
||||||
PcHooks::hookGDIPlusFunctions();
|
|
||||||
PcHooks::hookOtherPcFunctions();
|
|
||||||
HookDirectX();
|
|
||||||
}
|
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER) { ConsoleOutput(HIJACK_ERROR); }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user