This commit is contained in:
恍兮惚兮 2024-07-21 21:04:12 +08:00
parent 0fe834dd27
commit b0b1fe4417
21 changed files with 2114 additions and 1802 deletions

View File

@ -92,7 +92,7 @@
#define HS_SEARCH_FOR_TEXT L"Search for specific text" #define HS_SEARCH_FOR_TEXT L"Search for specific text"
#define VersionLatest L"Latest version" #define VersionLatest L"Latest version"
#define VersionCurrent L"Current version" #define VersionCurrent L"Current version"
#define ProjectHomePage L"Github: https://github.com/HIllya51/LunaHook\nHomepage: https://lunatranslator.xyz\npatreon: https://patreon.com/HIllya51\nDiscord: https://discord.gg/f8NSvaDU\n\nThis program is a core submodule of LunaTranslator and is fully integrated in Lunatranslator. This program contains only some simple functions, if you need more functions, please use LunaTranslator.\n\nIf you find unsupported games, please submit an issue\nhttps://github.com/HIllya51/LunaHook/issues/new?assignees=&labels=enhancement&projects=&template=01_game_request.yaml" #define ProjectHomePage L"Github: https://github.com/HIllya51/LunaHook\nHomepage: https://lunatranslator.xyz\npatreon: https://patreon.com/HIllya51\nDiscord: https://discord.gg/f8NSvaDU\n\nThis program is a core submodule of LunaTranslator and is fully integrated in Lunatranslator. This program contains only some simple functions, if you need more functions, please use LunaTranslator.\nIf you find unsupported games, please submit an issue\nhttps://github.com/HIllya51/LunaHook/issues"
#define LIST_HOOK L"Hook" #define LIST_HOOK L"Hook"
#define LIST_TEXT L"Text" #define LIST_TEXT L"Text"
#define PROC_CONN L"process connected %d" #define PROC_CONN L"process connected %d"

View File

@ -92,7 +92,7 @@
#define HS_SEARCH_FOR_TEXT L"Искать определенный текст" #define HS_SEARCH_FOR_TEXT L"Искать определенный текст"
#define VersionLatest L"Последняя версия" #define VersionLatest L"Последняя версия"
#define VersionCurrent L"Текущая версия" #define VersionCurrent L"Текущая версия"
#define ProjectHomePage L"Github: https://github.com/HIllya51/LunaHook\nСтраница проекта: https://lunatranslator.xyz\npatreon: https://patreon.com/HIllya51\nDiscord: https://discord.gg/f8NSvaDU\nПеревод на русский: https://github.com/NekoIriyaRu\n\nЭта программа является основным подмодулем LunaTranslator и полностью интегрирована в Lunatranslator. Эта программа содержит только некоторые простые функции. Если вам нужны дополнительные функции, используйте LunaTranslator.\n\nЕсли вы обнаружите какие-либо неподдерживаемые игры, сообщите о проблеме.\nhttps://github.com/HIllya51/LunaHook/issues/new?assignees=&labels=enhancement&projects=&template=01_game_request.yaml" #define ProjectHomePage L"Github: https://github.com/HIllya51/LunaHook\nСтраница проекта: https://lunatranslator.xyz\npatreon: https://patreon.com/HIllya51\nDiscord: https://discord.gg/f8NSvaDU\nПеревод на русский: https://github.com/NekoIriyaRu\n\nЭта программа является основным подмодулем LunaTranslator и полностью интегрирована в Lunatranslator. Эта программа содержит только некоторые простые функции. Если вам нужны дополнительные функции, используйте LunaTranslator.\nЕсли вы обнаружите какие-либо неподдерживаемые игры, сообщите о проблеме.\nhttps://github.com/HIllya51/LunaHook/issues"
#define LIST_HOOK L"Хук" #define LIST_HOOK L"Хук"
#define LIST_TEXT L"Текст" #define LIST_TEXT L"Текст"
#define PROC_CONN L"Процесс подключен %d" #define PROC_CONN L"Процесс подключен %d"

View File

@ -92,7 +92,7 @@
#define HS_SEARCH_FOR_TEXT L"搜索指定文本" #define HS_SEARCH_FOR_TEXT L"搜索指定文本"
#define VersionLatest L"最新版本" #define VersionLatest L"最新版本"
#define VersionCurrent L"当前版本" #define VersionCurrent L"当前版本"
#define ProjectHomePage L"Github https://github.com/HIllya51/LunaHook\n项目主页 https://lunatranslator.xyz\npatreonhttps://patreon.com/HIllya51\nDiscordhttps://discord.gg/f8NSvaDU\n\n本程序是LunaTranslator 的核心子模块并完全集成在Lunatranslator中。本程序仅包含一些简单功能如果您需要更多功能请使用 LunaTranslator。\n\n如果你发现有不支持的游戏请提交issue\nhttps://github.com/HIllya51/LunaHook/issues/new?assignees=&labels=enhancement&projects=&template=01_game_request.yaml" #define ProjectHomePage L"Github https://github.com/HIllya51/LunaHook\n项目主页 https://lunatranslator.xyz\npatreonhttps://patreon.com/HIllya51\nDiscordhttps://discord.gg/f8NSvaDU\n\n本程序是LunaTranslator 的核心子模块并完全集成在Lunatranslator中。本程序仅包含一些简单功能如果您需要更多功能请使用 LunaTranslator。\n如果你发现有不支持的游戏请提交issue\nhttps://github.com/HIllya51/LunaHook/issues"
#define LIST_HOOK L"Hook" #define LIST_HOOK L"Hook"
#define LIST_TEXT L"文本" #define LIST_TEXT L"文本"
#define PROC_CONN L"进程已连接 %d" #define PROC_CONN L"进程已连接 %d"

View File

@ -1,14 +1,18 @@
class NoEngine:public ENGINE{ class NoEngine : public ENGINE
{
public: public:
bool attach_function(){ bool attach_function()
{
ConsoleOutput("IGNORE %s", getenginename()); ConsoleOutput("IGNORE %s", getenginename());
// ConsoleOutput("IGNORE engine"); // ConsoleOutput("IGNORE engine");
return true; return true;
} }
}; };
class oldSystem40ini:public NoEngine{ class oldSystem40ini : public NoEngine
{
public: public:
oldSystem40ini(){ oldSystem40ini()
{
// jichi 1/19/2015: Disable inserting Lstr for System40 // jichi 1/19/2015: Disable inserting Lstr for System40
// See: http://sakuradite.com/topic/618 // See: http://sakuradite.com/topic/618
@ -26,7 +30,6 @@ class oldSystem40ini:public NoEngine{
// }; // };
// }; // };
// class FVP:public NoEngine{ // class FVP:public NoEngine{
// public: // public:
// FVP(){ // FVP(){
@ -37,11 +40,11 @@ class oldSystem40ini:public NoEngine{
// }; // };
// }; // };
class AdvPlayerHD : public NoEngine
{
class AdvPlayerHD:public NoEngine{
public: public:
AdvPlayerHD(){ AdvPlayerHD()
{
// supposed to be WillPlus // supposed to be WillPlus
check_by = CHECK_BY::FILE_ANY; check_by = CHECK_BY::FILE_ANY;
@ -49,11 +52,11 @@ class AdvPlayerHD:public NoEngine{
}; };
}; };
class DPM : public NoEngine
{
class DPM:public NoEngine{
public: public:
DPM(){ DPM()
{
// jichi 4/30/2015: Skip games made from らすこう, such as とある人妻のネトラレ事情 // jichi 4/30/2015: Skip games made from らすこう, such as とある人妻のネトラレ事情
// It has garbage from lstrlenW. Correct text is supposed to be in TabbedTextOutA. // It has garbage from lstrlenW. Correct text is supposed to be in TabbedTextOutA.
@ -62,10 +65,11 @@ class DPM:public NoEngine{
}; };
}; };
class Escude_ignore : public NoEngine
class Escude_ignore:public NoEngine{ {
public: public:
Escude_ignore(){ Escude_ignore()
{
// jichi 3/19/2014: Escude game // jichi 3/19/2014: Escude game
// Example: bgm.bin gfx.bin maou.bin script.bin snd.bin voc.bin // Example: bgm.bin gfx.bin maou.bin script.bin snd.bin voc.bin
@ -74,10 +78,11 @@ class Escude_ignore:public NoEngine{
}; };
}; };
class Chartreux : public NoEngine
class Chartreux:public NoEngine{ {
public: public:
Chartreux(){ Chartreux()
{
// jichi 12/28/2014: "Chartreux Inc." in Copyright. // jichi 12/28/2014: "Chartreux Inc." in Copyright.
// Sublimary brands include Rosebleu, MORE, etc. // Sublimary brands include Rosebleu, MORE, etc.
@ -87,13 +92,16 @@ class Chartreux:public NoEngine{
check_by_target = L"Chartreux"; check_by_target = L"Chartreux";
}; };
}; };
class lcsebody:public NoEngine{ class lcsebody : public NoEngine
{
public: public:
lcsebody(){ lcsebody()
{
check_by = CHECK_BY::CUSTOM; check_by = CHECK_BY::CUSTOM;
// jichi 3/19/2014: LC-ScriptEngine, GetGlyphOutlineA // jichi 3/19/2014: LC-ScriptEngine, GetGlyphOutlineA
check_by_target=[](){ check_by_target = []()
{
return (wcsstr(processName, L"lcsebody") || !wcsncmp(processName, L"lcsebo~", 7) || Util::CheckFile(L"lcsebody*")); return (wcsstr(processName, L"lcsebody") || !wcsncmp(processName, L"lcsebo~", 7) || Util::CheckFile(L"lcsebody*"));
}; };
}; };
@ -106,7 +114,6 @@ class lcsebody:public NoEngine{
// // jichi 3/19/2014: LC-ScriptEngine, GetGlyphOutlineA // // jichi 3/19/2014: LC-ScriptEngine, GetGlyphOutlineA
// check_by_target=[](){ // check_by_target=[](){
// wchar_t str[MAX_PATH]; // wchar_t str[MAX_PATH];
// DWORD i; // DWORD i;
// for (i = 0; processName[i]; i++) { // for (i = 0; processName[i]; i++) {
@ -122,7 +129,6 @@ class lcsebody:public NoEngine{
// }; // };
// }; // };
// if (Util::CheckFile(L"AGERC.DLL")) { // jichi 3/17/2014: Eushully, AGE.EXE // if (Util::CheckFile(L"AGERC.DLL")) { // jichi 3/17/2014: Eushully, AGE.EXE
// ConsoleOutput("IGNORE Eushully"); // ConsoleOutput("IGNORE Eushully");
// return true; // return true;

View File

@ -1,24 +1,29 @@
DynamicShiftJISCodec *dynamiccodec = new DynamicShiftJISCodec(932); DynamicShiftJISCodec *dynamiccodec = new DynamicShiftJISCodec(932);
void cast_back(const HookParam &hp, void *data, size_t *len, const std::wstring &trans, bool normal)
{
void cast_back(const HookParam& hp,void*data ,size_t *len,const std::wstring& trans,bool normal){ if ((hp.type & EMBED_CODEC_UTF16) || (hp.type & CODEC_UTF16))
{ // renpy
if((hp.type&EMBED_CODEC_UTF16)||(hp.type&CODEC_UTF16)){//renpy
write_string_overwrite(data, len, trans); write_string_overwrite(data, len, trans);
} }
else{ else
{
std::string astr; std::string astr;
if(hp.type&EMBED_DYNA_SJIS&&!normal){ if (hp.type & EMBED_DYNA_SJIS && !normal)
{
astr = dynamiccodec->encodeSTD(trans, 0); astr = dynamiccodec->encodeSTD(trans, 0);
} }
else{ else
{
astr = WideStringToString(trans, hp.codepage ? hp.codepage : ((hp.type & CODEC_UTF8) ? CP_UTF8 : embedsharedmem->codepage)); astr = WideStringToString(trans, hp.codepage ? hp.codepage : ((hp.type & CODEC_UTF8) ? CP_UTF8 : embedsharedmem->codepage));
} }
write_string_overwrite(data, len, astr); write_string_overwrite(data, len, astr);
} }
} }
struct FunctionInfo { struct FunctionInfo
{
const char *name; // for debugging purpose const char *name; // for debugging purpose
uintptr_t *oldFunction, uintptr_t *oldFunction,
newFunction; newFunction;
@ -26,9 +31,9 @@ struct FunctionInfo {
uintptr_t addr; uintptr_t addr;
explicit FunctionInfo(const uintptr_t _addr = 0, const char *name = "", uintptr_t *oldFunction = nullptr, uintptr_t newFunction = 0, explicit FunctionInfo(const uintptr_t _addr = 0, const char *name = "", uintptr_t *oldFunction = nullptr, uintptr_t newFunction = 0,
bool attached = false) bool attached = false)
: name(name), oldFunction(oldFunction), newFunction(newFunction) : name(name), oldFunction(oldFunction), newFunction(newFunction), attached(attached), addr(_addr)
, attached(attached),addr(_addr) {
{} }
}; };
std::unordered_map<uintptr_t, FunctionInfo> funcs; // attached functions std::unordered_map<uintptr_t, FunctionInfo> funcs; // attached functions
std::vector<uintptr_t> replacedfuns; // attached functions std::vector<uintptr_t> replacedfuns; // attached functions
@ -67,7 +72,8 @@ bool _1f()
return 0; return 0;
} }
bool _1 = _1f(); bool _1 = _1f();
void ReplaceFunction(PVOID* oldf,PVOID newf){ void ReplaceFunction(PVOID *oldf, PVOID newf)
{
RemoveHook((uintptr_t)*oldf); RemoveHook((uintptr_t)*oldf);
DetourTransactionBegin(); DetourTransactionBegin();
@ -77,9 +83,12 @@ void ReplaceFunction(PVOID* oldf,PVOID newf){
} }
void attachFunction(uintptr_t _hook_font_flag) void attachFunction(uintptr_t _hook_font_flag)
{ {
for(auto & _func:funcs){ for (auto &_func : funcs)
if(_func.first&_hook_font_flag){ {
if(_func.second.attached)continue; if (_func.first & _hook_font_flag)
{
if (_func.second.attached)
continue;
_func.second.attached = true; _func.second.attached = true;
*_func.second.oldFunction = _func.second.addr; *_func.second.oldFunction = _func.second.addr;
replacedfuns.push_back(_func.first); replacedfuns.push_back(_func.first);
@ -91,15 +100,17 @@ void detachall( )
{ {
DetourTransactionBegin(); DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread()); DetourUpdateThread(GetCurrentThread());
for(auto _flag:replacedfuns){ for (auto _flag : replacedfuns)
{
auto info = funcs.at(_flag); auto info = funcs.at(_flag);
DetourDetach((PVOID *)info.oldFunction, (PVOID)info.newFunction); DetourDetach((PVOID *)info.oldFunction, (PVOID)info.newFunction);
} }
DetourTransactionCommit(); DetourTransactionCommit();
} }
void solvefont(HookParam hp){ void solvefont(HookParam hp)
if(hp.hook_font){ {
if (hp.hook_font)
{
attachFunction(hp.hook_font); attachFunction(hp.hook_font);
} }
if (hp.hook_font & F_MultiByteToWideChar) if (hp.hook_font & F_MultiByteToWideChar)
@ -107,7 +118,8 @@ void solvefont(HookParam hp){
if (hp.hook_font & F_WideCharToMultiByte) if (hp.hook_font & F_WideCharToMultiByte)
disable_wcmb = true; disable_wcmb = true;
if (auto current_patch_fun = patch_fun.exchange(nullptr)){ if (auto current_patch_fun = patch_fun.exchange(nullptr))
{
current_patch_fun(); current_patch_fun();
dont_detach = true; dont_detach = true;
} }
@ -115,7 +127,8 @@ void solvefont(HookParam hp){
static std::wstring alwaysInsertSpacesSTD(const std::wstring &text) static std::wstring alwaysInsertSpacesSTD(const std::wstring &text)
{ {
std::wstring ret; std::wstring ret;
for(auto c: text) { for (auto c : text)
{
ret.push_back(c); ret.push_back(c);
if (c >= 32) // ignore non-printable characters if (c >= 32) // ignore non-printable characters
ret.push_back(L' '); // or insert \u3000 if needed ret.push_back(L' '); // or insert \u3000 if needed
@ -135,7 +148,8 @@ static std::wstring alwaysInsertSpacesSTD(const std::wstring& text)
{ {
std::wstring ret; std::wstring ret;
for(const wchar_t & c: text) { for (const wchar_t &c : text)
{
ret.push_back(c); ret.push_back(c);
if (!charEncodableSTD(c, hp.codepage ? hp.codepage : embedsharedmem->codepage)) if (!charEncodableSTD(c, hp.codepage ? hp.codepage : embedsharedmem->codepage))
ret.push_back(L' '); ret.push_back(L' ');
@ -147,16 +161,21 @@ std::wstring adjustSpacesSTD(const std::wstring& text,HookParam hp)
switch (embedsharedmem->spaceadjustpolicy) switch (embedsharedmem->spaceadjustpolicy)
{ {
case 0: return text; case 0:
case 1:return alwaysInsertSpacesSTD(text); return text;
case 2:return insertSpacesAfterUnencodableSTD(text, hp); case 1:
default:return text; return alwaysInsertSpacesSTD(text);
case 2:
return insertSpacesAfterUnencodableSTD(text, hp);
default:
return text;
} }
} }
std::wstring limitTextWidth(const std::wstring &text, int size) std::wstring limitTextWidth(const std::wstring &text, int size)
{ {
auto lines = strSplit(text, L"\n"); auto lines = strSplit(text, L"\n");
std::for_each(lines.begin(),lines.end(),[=](auto &line){ std::for_each(lines.begin(), lines.end(), [=](auto &line)
{
if(line.size()<=size) if(line.size()<=size)
return; return;
std::wstring ret; std::wstring ret;
@ -166,47 +185,54 @@ std::wstring limitTextWidth(const std::wstring& text, int size)
ret+=L'\n'; ret+=L'\n';
} }
} }
line=ret; line=ret; });
});
std::wstring ret; std::wstring ret;
for(int i=0;i<lines.size();i++){ for (int i = 0; i < lines.size(); i++)
{
ret += lines[i]; ret += lines[i];
if(i<lines.size()-1)ret+=L'\n'; if (i < lines.size() - 1)
ret += L'\n';
} }
return ret; return ret;
} }
bool isPauseKeyPressed() bool isPauseKeyPressed()
{ {
return WinKey::isKeyControlPressed() return WinKey::isKeyControlPressed() || WinKey::isKeyShiftPressed() && !WinKey::isKeyReturnPressed();
|| WinKey::isKeyShiftPressed() && !WinKey::isKeyReturnPressed();
} }
inline UINT64 djb2_n2(const unsigned char *str, size_t len, UINT64 hash = 5381) inline UINT64 djb2_n2(const unsigned char *str, size_t len, UINT64 hash = 5381)
{ {
int i = 0; int i = 0;
while (len--){ while (len--)
{
hash = ((hash << 5) + hash) + (*str++); // hash * 33 + c hash = ((hash << 5) + hash) + (*str++); // hash * 33 + c
} }
return hash; return hash;
} }
std::unordered_map<UINT64, std::wstring> translatecache; std::unordered_map<UINT64, std::wstring> translatecache;
bool check_is_thread_selected(const ThreadParam& tp){ bool check_is_thread_selected(const ThreadParam &tp)
{
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
if (embedsharedmem->use[i]) if (embedsharedmem->use[i])
if ((embedsharedmem->addr[i] == tp.addr) && (embedsharedmem->ctx1[i] == tp.ctx) && (embedsharedmem->ctx2[i] == tp.ctx2)) if ((embedsharedmem->addr[i] == tp.addr) && (embedsharedmem->ctx1[i] == tp.ctx) && (embedsharedmem->ctx2[i] == tp.ctx2))
return true; return true;
return false; return false;
} }
bool check_embed_able(const ThreadParam& tp){ bool check_embed_able(const ThreadParam &tp)
{
return host_connected && check_is_thread_selected(tp) && ((isPauseKeyPressed() == false) ? true : !embedsharedmem->fastskipignore); return host_connected && check_is_thread_selected(tp) && ((isPauseKeyPressed() == false) ? true : !embedsharedmem->fastskipignore);
} }
bool waitforevent(UINT32 timems,const ThreadParam& tp,const std::wstring &origin){ bool waitforevent(UINT32 timems, const ThreadParam &tp, const std::wstring &origin)
{
char eventname[1000]; char eventname[1000];
sprintf(eventname, LUNA_EMBED_notify_event, GetCurrentProcessId(), djb2_n2((const unsigned char *)(origin.c_str()), origin.size() * 2)); sprintf(eventname, LUNA_EMBED_notify_event, GetCurrentProcessId(), djb2_n2((const unsigned char *)(origin.c_str()), origin.size() * 2));
auto event = win_event(eventname); auto event = win_event(eventname);
while(timems){ while (timems)
if(check_embed_able(tp)==false)return false; {
if (check_embed_able(tp) == false)
return false;
auto sleepstep = min(100, timems); auto sleepstep = min(100, timems);
if(event.wait(sleepstep))return true; if (event.wait(sleepstep))
return true;
timems -= sleepstep; timems -= sleepstep;
} }
return false; return false;
@ -214,18 +240,21 @@ bool waitforevent(UINT32 timems,const ThreadParam& tp,const std::wstring &origin
void TextHook::parsenewlineseperator(void *data, size_t *len) void TextHook::parsenewlineseperator(void *data, size_t *len)
{ {
if(!(hp.newlineseperator))return; if (!(hp.newlineseperator))
return;
if (hp.type & CODEC_UTF16) if (hp.type & CODEC_UTF16)
{ {
StringReplacer((wchar_t *)data, len, hp.newlineseperator, wcslen(hp.newlineseperator), L"\n", 1); StringReplacer((wchar_t *)data, len, hp.newlineseperator, wcslen(hp.newlineseperator), L"\n", 1);
} }
else if(hp.type&CODEC_UTF32) return; else if (hp.type & CODEC_UTF32)
return;
else else
{ {
// ansi/utf8newlineseperator都是简单字符 // ansi/utf8newlineseperator都是简单字符
std::string newlineseperatorA; std::string newlineseperatorA;
for(int i=0;i<wcslen(hp.newlineseperator);i++)newlineseperatorA+=(char)hp.newlineseperator[i]; for (int i = 0; i < wcslen(hp.newlineseperator); i++)
newlineseperatorA += (char)hp.newlineseperator[i];
StringReplacer((char *)data, len, newlineseperatorA.c_str(), newlineseperatorA.size(), "\n", 1); StringReplacer((char *)data, len, newlineseperatorA.c_str(), newlineseperatorA.size(), "\n", 1);
} }
} }
@ -233,7 +262,8 @@ UINT64 texthash(void*data,size_t len)
{ {
UINT64 sum = 0; UINT64 sum = 0;
auto u8data = (UINT8 *)data; auto u8data = (UINT8 *)data;
for(int i=0;i< len;i++){ for (int i = 0; i < len; i++)
{
sum += u8data[i]; sum += u8data[i];
sum = sum << 1; sum = sum << 1;
} }
@ -242,29 +272,40 @@ UINT64 texthash(void*data,size_t len)
bool checktranslatedok(void *data, size_t len) bool checktranslatedok(void *data, size_t len)
{ {
ZeroMemory(embedsharedmem->text, sizeof(embedsharedmem->text)); // clear trans before call ZeroMemory(embedsharedmem->text, sizeof(embedsharedmem->text)); // clear trans before call
if(len>1000)return true; if (len > 1000)
return true;
return (translatecache.find(texthash(data, len)) != translatecache.end()); return (translatecache.find(texthash(data, len)) != translatecache.end());
} }
bool TextHook::waitfornotify(TextOutput_T* buffer,void*data ,size_t*len,ThreadParam tp){ bool TextHook::waitfornotify(TextOutput_T *buffer, void *data, size_t *len, ThreadParam tp)
{
std::wstring origin; std::wstring origin;
if (auto t=commonparsestring(data,*len,&hp,embedsharedmem->codepage)) origin=t.value(); if (auto t = commonparsestring(data, *len, &hp, embedsharedmem->codepage))
else return false; origin = t.value();
else
return false;
std::wstring translate; std::wstring translate;
auto hash = texthash(data, *len); auto hash = texthash(data, *len);
if(translatecache.find(hash)!=translatecache.end()){ if (translatecache.find(hash) != translatecache.end())
{
translate = translatecache.at(hash); translate = translatecache.at(hash);
} }
else{ else
if(waitforevent(embedsharedmem->waittime,tp,origin)==false)return false; {
if (waitforevent(embedsharedmem->waittime, tp, origin) == false)
return false;
translate = embedsharedmem->text; translate = embedsharedmem->text;
if((translate.size()==0))return false; if ((translate.size() == 0))
return false;
translatecache.insert(std::make_pair(hash, translate)); translatecache.insert(std::make_pair(hash, translate));
} }
if(embedsharedmem->line_text_length_limit)translate=limitTextWidth(translate,embedsharedmem->line_text_length_limit); if (embedsharedmem->line_text_length_limit)
if(hp.newlineseperator)strReplace(translate,L"\n",hp.newlineseperator); translate = limitTextWidth(translate, embedsharedmem->line_text_length_limit);
if (hp.newlineseperator)
strReplace(translate, L"\n", hp.newlineseperator);
translate = adjustSpacesSTD(translate, hp); translate = adjustSpacesSTD(translate, hp);
if(embedsharedmem->keeprawtext)translate=origin+L" "+translate; if (embedsharedmem->keeprawtext)
translate = origin + L" " + translate;
solvefont(hp); solvefont(hp);
cast_back(hp, data, len, translate, false); cast_back(hp, data, len, translate, false);
return true; return true;

View File

@ -4,7 +4,8 @@
extern EmbedSharedMem *embedsharedmem; extern EmbedSharedMem *embedsharedmem;
extern DynamicShiftJISCodec *dynamiccodec; extern DynamicShiftJISCodec *dynamiccodec;
namespace WinKey { namespace WinKey
{
inline bool isKeyPressed(int vk) { return ::GetKeyState(vk) & 0xf0; } inline bool isKeyPressed(int vk) { return ::GetKeyState(vk) & 0xf0; }
inline bool isKeyToggled(int vk) { return ::GetKeyState(vk) & 0x0f; } inline bool isKeyToggled(int vk) { return ::GetKeyState(vk) & 0x0f; }
@ -13,10 +14,18 @@ namespace WinKey {
inline bool isKeyShiftPressed() { return isKeyPressed(VK_SHIFT); } inline bool isKeyShiftPressed() { return isKeyPressed(VK_SHIFT); }
inline bool isKeyAltPressed() { return isKeyPressed(VK_MENU); } inline bool isKeyAltPressed() { return isKeyPressed(VK_MENU); }
} }
namespace Engine{ namespace Engine
enum TextRole { UnknownRole = 0, ScenarioRole, NameRole, OtherRole, {
ChoiceRole = OtherRole, HistoryRole = OtherRole, enum TextRole
RoleCount }; {
UnknownRole = 0,
ScenarioRole,
NameRole,
OtherRole,
ChoiceRole = OtherRole,
HistoryRole = OtherRole,
RoleCount
};
} }
inline std::atomic<void (*)()> patch_fun = nullptr; inline std::atomic<void (*)()> patch_fun = nullptr;
void ReplaceFunction(PVOID *oldf, PVOID newf); void ReplaceFunction(PVOID *oldf, PVOID newf);

View File

@ -1,20 +1,23 @@
#ifndef __LUNA_ENGINE_H #ifndef __LUNA_ENGINE_H
#define __LUNA_ENGINE_H #define __LUNA_ENGINE_H
extern WCHAR *processName, processPath[MAX_PATH], processName_lower[MAX_PATH]; // cached extern WCHAR *processName, processPath[MAX_PATH], processName_lower[MAX_PATH]; // cached
extern uintptr_t processStartAddress, processStopAddress; extern uintptr_t processStartAddress, processStopAddress;
extern uintptr_t processStartAddress, processStopAddress; extern uintptr_t processStartAddress, processStopAddress;
class ENGINE{ class ENGINE
{
public: public:
const char *enginename; const char *enginename;
bool dontstop; // dont stop even if attached a engine bool dontstop; // dont stop even if attached a engine
bool is_engine_certain; // stop when match a engine ,even if not attached bool is_engine_certain; // stop when match a engine ,even if not attached
enum class CHECK_BY { enum class CHECK_BY
{
ALL_TRUE, ALL_TRUE,
FILE, FILE_ALL,FILE_ANY, FILE,
FILE_ALL,
FILE_ANY,
RESOURCE_STR, RESOURCE_STR,
CUSTOM, CUSTOM,
}; };
@ -28,8 +31,10 @@ class ENGINE{
std::variant<check_by_single, check_by_list, check_by_custom_function> check_by_target; std::variant<check_by_single, check_by_list, check_by_custom_function> check_by_target;
// virtual bool check_by_target(){return false;}; // virtual bool check_by_target(){return false;};
virtual bool attach_function() = 0; virtual bool attach_function() = 0;
virtual const char* getenginename(){ virtual const char *getenginename()
if(enginename)return enginename; {
if (enginename)
return enginename;
return typeid(*this).name() + 6; return typeid(*this).name() + 6;
} }
ENGINE() : enginename(nullptr), dontstop(false), is_engine_certain(true), check_by(CHECK_BY::ALL_TRUE){}; ENGINE() : enginename(nullptr), dontstop(false), is_engine_certain(true), check_by(CHECK_BY::ALL_TRUE){};

View File

@ -173,7 +173,8 @@
#include "NoEngine.h" #include "NoEngine.h"
#include "engines/lua/lua51.h" #include "engines/lua/lua51.h"
#include "engines/python/Renpy.h" #include "engines/python/Renpy.h"
std::vector<ENGINE*> check_engines(){ std::vector<ENGINE *> check_engines()
{
return { return {
new LovaGame, new LovaGame,
new PPSSPPengine, new PPSSPPengine,
@ -344,12 +345,11 @@ std::vector<ENGINE*> check_engines(){
new A98SYS, new A98SYS,
new godot, new godot,
new Erogos, new Erogos,
new Silkysveryveryold new Silkysveryveryold};
};
} }
std::vector<ENGINE*> ignore_engines(){ std::vector<ENGINE *> ignore_engines()
{
return { return {
new oldSystem40ini, new oldSystem40ini,
@ -359,7 +359,8 @@ std::vector<ENGINE*> ignore_engines(){
new Chartreux, new Chartreux,
}; };
} }
std::vector<ENGINE*> unsafe_check_atlast(){ std::vector<ENGINE *> unsafe_check_atlast()
{
// Put the patterns that might break other games at last // Put the patterns that might break other games at last
return { return {
@ -395,7 +396,5 @@ std::vector<ENGINE*> unsafe_check_atlast(){
new ShinaRio, new ShinaRio,
new Suika2, new Suika2,
new KISS, new KISS,
new EntisGLS new EntisGLS};
};
} }

View File

@ -24,7 +24,8 @@
std::vector<ENGINE *> ignore_engines() { return {}; } std::vector<ENGINE *> ignore_engines() { return {}; }
std::vector<ENGINE *> unsafe_check_atlast() { return {}; } std::vector<ENGINE *> unsafe_check_atlast() { return {}; }
std::vector<ENGINE*> check_engines(){ std::vector<ENGINE *> check_engines()
{
return { return {
new Godot, new Godot,
new V8, new V8,
@ -50,5 +51,4 @@ std::vector<ENGINE*> check_engines(){
new livecaptions, new livecaptions,
new lua51, new lua51,
}; };
} }

View File

@ -4,67 +4,76 @@ processPath[MAX_PATH]; // cached
WCHAR processName_lower[MAX_PATH]; WCHAR processName_lower[MAX_PATH];
uintptr_t processStartAddress, processStopAddress; uintptr_t processStartAddress, processStopAddress;
std::vector<ENGINE *> check_engines(); std::vector<ENGINE *> check_engines();
std::vector<ENGINE *> ignore_engines(); std::vector<ENGINE *> ignore_engines();
std::vector<ENGINE *> unsafe_check_atlast(); std::vector<ENGINE *> unsafe_check_atlast();
bool ENGINE::check_function(){ bool ENGINE::check_function()
{
switch (check_by) switch (check_by)
{ {
case CHECK_BY::ALL_TRUE:{ case CHECK_BY::ALL_TRUE:
{
is_engine_certain = false; is_engine_certain = false;
return true; return true;
} }
case CHECK_BY::FILE:{ case CHECK_BY::FILE:
{
return (Util::CheckFile(std::get<check_by_single>(check_by_target))); return (Util::CheckFile(std::get<check_by_single>(check_by_target)));
} }
case CHECK_BY::FILE_ALL:{ case CHECK_BY::FILE_ALL:
{
auto _list = std::get<check_by_list>(check_by_target); auto _list = std::get<check_by_list>(check_by_target);
return std::all_of(_list.begin(), _list.end(), Util::CheckFile); return std::all_of(_list.begin(), _list.end(), Util::CheckFile);
} }
case CHECK_BY::FILE_ANY:{ case CHECK_BY::FILE_ANY:
{
auto _list = std::get<check_by_list>(check_by_target); auto _list = std::get<check_by_list>(check_by_target);
return std::any_of(_list.begin(), _list.end(), Util::CheckFile); return std::any_of(_list.begin(), _list.end(), Util::CheckFile);
} }
case CHECK_BY::RESOURCE_STR:{ case CHECK_BY::RESOURCE_STR:
{
return (Util::SearchResourceString(std::get<check_by_single>(check_by_target))); return (Util::SearchResourceString(std::get<check_by_single>(check_by_target)));
} }
case CHECK_BY::CUSTOM:{ case CHECK_BY::CUSTOM:
{
return std::get<check_by_custom_function>(check_by_target)(); return std::get<check_by_custom_function>(check_by_target)();
} }
default: default:
return false; return false;
} }
} }
bool safematch(ENGINE* m){ bool safematch(ENGINE *m)
{
bool matched = false; bool matched = false;
__try { __try
{
matched = m->check_function(); matched = m->check_function();
} }
__except (EXCEPTION_EXECUTE_HANDLER) { __except (EXCEPTION_EXECUTE_HANDLER)
{
ConsoleOutput(Match_Error, m->getenginename()); ConsoleOutput(Match_Error, m->getenginename());
// ConsoleOutput("match ERROR"); // ConsoleOutput("match ERROR");
} }
return matched; return matched;
} }
bool safeattach(ENGINE* m){ bool safeattach(ENGINE *m)
{
bool attached = false; bool attached = false;
__try { __try
{
attached = m->attach_function(); attached = m->attach_function();
} }
__except (EXCEPTION_EXECUTE_HANDLER) { __except (EXCEPTION_EXECUTE_HANDLER)
{
ConsoleOutput(Attach_Error, m->getenginename()); ConsoleOutput(Attach_Error, m->getenginename());
// ConsoleOutput("attach ERROR"); // ConsoleOutput("attach ERROR");
} }
return attached; return attached;
} }
bool checkengine(){ bool checkengine()
{
auto engines = check_engines(); auto engines = check_engines();
auto engineatlast = unsafe_check_atlast(); auto engineatlast = unsafe_check_atlast();
@ -72,13 +81,15 @@ bool checkengine(){
std::vector<const char *> infomations = { std::vector<const char *> infomations = {
"match failed", "match failed",
"attach failed", "attach failed",
"attach success" "attach success"};
};
auto allengines = {engines, engineignore, engineatlast}; auto allengines = {engines, engineignore, engineatlast};
int total=[allengines](){int _=0;for(auto eng:allengines)_+=eng.size();return _;}(); int total = [allengines]()
{int _=0;for(auto eng:allengines)_+=eng.size();return _; }();
int current = 0; int current = 0;
for(auto eng:allengines){ for (auto eng : allengines)
for(auto m:eng) { {
for (auto m : eng)
{
current += 1; current += 1;
bool matched = safematch(m); bool matched = safematch(m);
@ -86,18 +97,22 @@ bool checkengine(){
// ConsoleOutput("Progress %d/%d, checked engine %s, %s",current,total,m->getenginename(),infomations[matched+attached]); // ConsoleOutput("Progress %d/%d, checked engine %s, %s",current,total,m->getenginename(),infomations[matched+attached]);
// ConsoleOutput("Progress %d/%d, %s",current,total,infomations[matched+attached]); // ConsoleOutput("Progress %d/%d, %s",current,total,infomations[matched+attached]);
if(matched==false)continue; if (matched == false)
continue;
ConsoleOutput(MatchedEngine, m->getenginename()); ConsoleOutput(MatchedEngine, m->getenginename());
if(m->dontstop){ if (m->dontstop)
{
continue; continue;
} }
if(m->is_engine_certain){ if (m->is_engine_certain)
{
ConsoleOutput(ConfirmStop, m->getenginename()); ConsoleOutput(ConfirmStop, m->getenginename());
return attached; return attached;
} }
if(attached){ if (attached)
{
ConsoleOutput(Attach_Stop, m->getenginename()); ConsoleOutput(Attach_Stop, m->getenginename());
return true; return true;
} }
@ -106,9 +121,11 @@ bool checkengine(){
return false; return false;
} }
void HIJACK(){ void HIJACK()
{
static bool once = false; static bool once = false;
if(once)return; if (once)
return;
once = true; once = true;
GetModuleFileNameW(nullptr, processPath, MAX_PATH); GetModuleFileNameW(nullptr, processPath, MAX_PATH);
processName = wcsrchr(processPath, L'\\') + 1; processName = wcsrchr(processPath, L'\\') + 1;
@ -116,22 +133,26 @@ void HIJACK(){
wcscpy_s(processName_lower, processName); wcscpy_s(processName_lower, processName);
_wcslwr_s(processName_lower); // lower case _wcslwr_s(processName_lower); // lower case
std::tie(processStartAddress, processStopAddress) = Util::QueryModuleLimits(GetModuleHandleW(nullptr), 0, 1 + PAGE_NOACCESS); std::tie(processStartAddress, processStopAddress) = Util::QueryModuleLimits(GetModuleHandleW(nullptr), 0, 1 + PAGE_NOACCESS);
spDefault.minAddress = processStartAddress; spDefault.minAddress = processStartAddress;
spDefault.maxAddress = processStopAddress; spDefault.maxAddress = processStopAddress;
ConsoleOutput(ProcessRange, processStartAddress, processStopAddress); ConsoleOutput(ProcessRange, processStartAddress, processStopAddress);
if (processStartAddress + 0x40000 > processStopAddress) ConsoleOutput(WarningDummy); if (processStartAddress + 0x40000 > processStopAddress)
ConsoleOutput(WarningDummy);
bool result = false; bool result = false;
__try { __try
{
result = checkengine(); result = checkengine();
} }
__except (EXCEPTION_EXECUTE_HANDLER) { ConsoleOutput(HIJACK_ERROR); } __except (EXCEPTION_EXECUTE_HANDLER)
{
ConsoleOutput(HIJACK_ERROR);
}
if (result == false)
if(result==false){ {
PcHooks::hookOtherPcFunctions(); PcHooks::hookOtherPcFunctions();
} }
} }

View File

@ -38,50 +38,79 @@
/** Helper */ /** Helper */
namespace { // unnamed namespace
UINT8 systemCharSet(){ { // unnamed
enum CodePage { UINT8 systemCharSet()
NullCodePage = 0 {
, Utf8CodePage = 65001 // UTF-8 enum CodePage
, Utf16CodePage = 1200 // UTF-16 {
, SjisCodePage = 932 // SHIFT-JIS NullCodePage = 0,
, GbkCodePage = 936 // GB2312 Utf8CodePage = 65001 // UTF-8
, KscCodePage = 949 // EUC-KR ,
, Big5CodePage = 950 // BIG5 Utf16CodePage = 1200 // UTF-16
, TisCodePage = 874 // TIS-620 ,
, Koi8CodePage = 866 // KOI8-R SjisCodePage = 932 // SHIFT-JIS
,
GbkCodePage = 936 // GB2312
,
KscCodePage = 949 // EUC-KR
,
Big5CodePage = 950 // BIG5
,
TisCodePage = 874 // TIS-620
,
Koi8CodePage = 866 // KOI8-R
}; };
auto systemCodePage = ::GetACP(); auto systemCodePage = ::GetACP();
switch (systemCodePage) { switch (systemCodePage)
case TisCodePage: return THAI_CHARSET; {
case Koi8CodePage: return RUSSIAN_CHARSET; case TisCodePage:
case SjisCodePage: return SHIFTJIS_CHARSET; return THAI_CHARSET;
case GbkCodePage: return GB2312_CHARSET; case Koi8CodePage:
case Big5CodePage: return CHINESEBIG5_CHARSET; return RUSSIAN_CHARSET;
case SjisCodePage:
return SHIFTJIS_CHARSET;
case GbkCodePage:
return GB2312_CHARSET;
case Big5CodePage:
return CHINESEBIG5_CHARSET;
case KscCodePage: return HANGUL_CHARSET; case KscCodePage:
case 1361: return JOHAB_CHARSET; // alternative Korean character set return HANGUL_CHARSET;
case 1361:
return JOHAB_CHARSET; // alternative Korean character set
case 1250: return EASTEUROPE_CHARSET; case 1250:
case 1251: return RUSSIAN_CHARSET; // cyrillic return EASTEUROPE_CHARSET;
case 1253: return GREEK_CHARSET; case 1251:
case 1254: return TURKISH_CHARSET; return RUSSIAN_CHARSET; // cyrillic
case 1253:
return GREEK_CHARSET;
case 1254:
return TURKISH_CHARSET;
case 862: return HEBREW_CHARSET; // obsolete case 862:
case 1255: return HEBREW_CHARSET; return HEBREW_CHARSET; // obsolete
case 1255:
return HEBREW_CHARSET;
case 1256: return ARABIC_CHARSET; case 1256:
case 1257: return BALTIC_CHARSET; return ARABIC_CHARSET;
case 1258: return VIETNAMESE_CHARSET; case 1257:
return BALTIC_CHARSET;
case 1258:
return VIETNAMESE_CHARSET;
// default: return DEFAULT_CHARSET; // default: return DEFAULT_CHARSET;
default: return 0; default:
return 0;
} }
} }
void customizeLogFontA(LOGFONTA *lplf) void customizeLogFontA(LOGFONTA *lplf)
{ {
if (embedsharedmem->fontCharSetEnabled) { if (embedsharedmem->fontCharSetEnabled)
{
auto charSet = embedsharedmem->fontCharSet; auto charSet = embedsharedmem->fontCharSet;
if (!charSet) if (!charSet)
charSet = systemCharSet(); charSet = systemCharSet();
@ -103,7 +132,8 @@ void customizeLogFontW(LOGFONTW *lplf)
customizeLogFontA((LOGFONTA *)lplf); customizeLogFontA((LOGFONTA *)lplf);
std::wstring s = embedsharedmem->fontFamily; std::wstring s = embedsharedmem->fontFamily;
if (! s.empty()) { if (!s.empty())
{
lplf->lfFaceName[s.size()] = 0; lplf->lfFaceName[s.size()] = 0;
// s->fontFamily.toWCharArray(lplf->lfFaceName); // s->fontFamily.toWCharArray(lplf->lfFaceName);
memcpy(lplf->lfFaceName, s.c_str(), s.size()); memcpy(lplf->lfFaceName, s.c_str(), s.size());
@ -128,25 +158,24 @@ public:
bool LogFontManager::eq(const LOGFONTW &x, const LOGFONTW &y) bool LogFontManager::eq(const LOGFONTW &x, const LOGFONTW &y)
{ // I assume there is no padding { // I assume there is no padding
return ::wcscmp(x.lfFaceName, y.lfFaceName) == 0 return ::wcscmp(x.lfFaceName, y.lfFaceName) == 0 && ::memcmp(&x, &y, sizeof(x) - sizeof(x.lfFaceName)) == 0;
&& ::memcmp(&x, &y, sizeof(x) - sizeof(x.lfFaceName)) == 0;
} }
void LogFontManager::add(HFONT hf, const LOGFONTW &lf) void LogFontManager::add(HFONT hf, const LOGFONTW &lf)
{ fonts_.push_back(std::make_pair(hf, lf)); } {
fonts_.push_back(std::make_pair(hf, lf));
}
void LogFontManager::remove(HFONT hf) void LogFontManager::remove(HFONT hf)
{ {
auto _=std::remove_if(fonts_.begin(), fonts_.end(), [&hf](const font_pair &it) { auto _ = std::remove_if(fonts_.begin(), fonts_.end(), [&hf](const font_pair &it)
return it.first == hf; { return it.first == hf; });
});
} }
void LogFontManager::remove(const LOGFONTW &lf) void LogFontManager::remove(const LOGFONTW &lf)
{ {
auto _=std::remove_if(fonts_.begin(), fonts_.end(), [&lf](const font_pair &it) { auto _ = std::remove_if(fonts_.begin(), fonts_.end(), [&lf](const font_pair &it)
return eq(it.second, lf); { return eq(it.second, lf); });
});
} }
HFONT LogFontManager::get(const LOGFONTW &lf) const HFONT LogFontManager::get(const LOGFONTW &lf) const
@ -167,6 +196,7 @@ class DCFontSwitcher
HFONT oldFont_, HFONT oldFont_,
newFont_; newFont_;
std::wstring newfontname; std::wstring newfontname;
public: public:
explicit DCFontSwitcher(HDC hdc); // pass 0 to disable this class explicit DCFontSwitcher(HDC hdc); // pass 0 to disable this class
~DCFontSwitcher(); ~DCFontSwitcher();
@ -185,7 +215,8 @@ DCFontSwitcher::~DCFontSwitcher()
// if (newFont_) // if (newFont_)
// ::DeleteObject(newFont_); // ::DeleteObject(newFont_);
} }
bool isFontCustomized(){ bool isFontCustomized()
{
return embedsharedmem->fontCharSetEnabled || wcslen(embedsharedmem->fontFamily); return embedsharedmem->fontCharSetEnabled || wcslen(embedsharedmem->fontFamily);
} }
DCFontSwitcher::DCFontSwitcher(HDC hdc) DCFontSwitcher::DCFontSwitcher(HDC hdc)
@ -218,17 +249,18 @@ DCFontSwitcher::DCFontSwitcher(HDC hdc)
if (std::wstring(embedsharedmem->fontFamily).empty()) if (std::wstring(embedsharedmem->fontFamily).empty())
::GetTextFaceW(hdc_, LF_FACESIZE, lf.lfFaceName); ::GetTextFaceW(hdc_, LF_FACESIZE, lf.lfFaceName);
else{ else
{
wcscpy(lf.lfFaceName, embedsharedmem->fontFamily); wcscpy(lf.lfFaceName, embedsharedmem->fontFamily);
} }
newFont_ = fonts_.get(lf); newFont_ = fonts_.get(lf);
if ((!newFont_ )||(newfontname!=std::wstring(embedsharedmem->fontFamily))) { if ((!newFont_) || (newfontname != std::wstring(embedsharedmem->fontFamily)))
{
newFont_ = Hijack::oldCreateFontIndirectW(&lf); newFont_ = Hijack::oldCreateFontIndirectW(&lf);
fonts_.add(newFont_, lf); fonts_.add(newFont_, lf);
newfontname = std::wstring(embedsharedmem->fontFamily); newfontname = std::wstring(embedsharedmem->fontFamily);
} }
oldFont_ = (HFONT)SelectObject(hdc_, newFont_); oldFont_ = (HFONT)SelectObject(hdc_, newFont_);
} }
} // unnamed namespace } // unnamed namespace
@ -244,16 +276,20 @@ HFONT WINAPI Hijack::newCreateFontIndirectA(const LOGFONTA *lplf)
// if (auto p = HijackHelper::instance()) { // if (auto p = HijackHelper::instance()) {
// auto s = p->settings(); // auto s = p->settings();
std::wstring fontFamily = embedsharedmem->fontFamily; std::wstring fontFamily = embedsharedmem->fontFamily;
if (lplf && isFontCustomized()) { if (lplf && isFontCustomized())
union { {
union
{
LOGFONTA a; LOGFONTA a;
LOGFONTW w; LOGFONTW w;
} lf = {*lplf}; // only initialize the first member of LOGFONTA } lf = {*lplf}; // only initialize the first member of LOGFONTA
customizeLogFontA(&lf.a); customizeLogFontA(&lf.a);
if (!fontFamily.empty()) { if (!fontFamily.empty())
{
if (all_ascii(fontFamily.c_str(), fontFamily.size())) if (all_ascii(fontFamily.c_str(), fontFamily.size()))
::strcpy(lf.a.lfFaceName, WideStringToString(fontFamily, CP_ACP).c_str()); ::strcpy(lf.a.lfFaceName, WideStringToString(fontFamily, CP_ACP).c_str());
else { else
{
lf.w.lfFaceName[fontFamily.size()] = 0; lf.w.lfFaceName[fontFamily.size()] = 0;
// s->fontFamily.toWCharArray(lf.w.lfFaceName); // s->fontFamily.toWCharArray(lf.w.lfFaceName);
memcpy(lf.w.lfFaceName, fontFamily.c_str(), fontFamily.size()); memcpy(lf.w.lfFaceName, fontFamily.c_str(), fontFamily.size());
@ -272,7 +308,8 @@ HFONT WINAPI Hijack::newCreateFontIndirectW(const LOGFONTW *lplf)
// DOUT("width:" << lplf->lfWidth << ", height:" << lplf->lfHeight << ", weight:" << lplf->lfWeight); // DOUT("width:" << lplf->lfWidth << ", height:" << lplf->lfHeight << ", weight:" << lplf->lfWeight);
// if (auto p = HijackHelper::instance()) { // if (auto p = HijackHelper::instance()) {
// auto s = p->settings(); // auto s = p->settings();
if (lplf && isFontCustomized()) { if (lplf && isFontCustomized())
{
LOGFONTW lf(*lplf); LOGFONTW lf(*lplf);
customizeLogFontW(&lf); customizeLogFontW(&lf);
return oldCreateFontIndirectW(&lf); return oldCreateFontIndirectW(&lf);
@ -285,10 +322,10 @@ HFONT WINAPI Hijack::newCreateFontIndirectW(const LOGFONTW *lplf)
HFONT WINAPI Hijack::newCreateFontA(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCSTR lpszFace) HFONT WINAPI Hijack::newCreateFontA(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCSTR lpszFace)
{ {
if (isFontCustomized())
{
if ( isFontCustomized()) { if (embedsharedmem->fontCharSetEnabled)
if (embedsharedmem->fontCharSetEnabled) { {
auto charSet = embedsharedmem->fontCharSet; auto charSet = embedsharedmem->fontCharSet;
if (!charSet) if (!charSet)
charSet = systemCharSet(); charSet = systemCharSet();
@ -304,11 +341,15 @@ HFONT WINAPI Hijack::newCreateFontA(int nHeight, int nWidth, int nEscapement, in
} }
*/ */
std::wstring fontFamily = embedsharedmem->fontFamily; std::wstring fontFamily = embedsharedmem->fontFamily;
if (!fontFamily.empty()) { if (!fontFamily.empty())
if (all_ascii(fontFamily.c_str(),fontFamily.size())) { {
if (all_ascii(fontFamily.c_str(), fontFamily.size()))
{
lpszFace = WideStringToString(fontFamily, CP_ACP).c_str(); lpszFace = WideStringToString(fontFamily, CP_ACP).c_str();
return oldCreateFontA(CREATE_FONT_ARGS); return oldCreateFontA(CREATE_FONT_ARGS);
} else { }
else
{
auto lpszFace = (LPCWSTR)fontFamily.c_str(); auto lpszFace = (LPCWSTR)fontFamily.c_str();
return oldCreateFontW(CREATE_FONT_ARGS); return oldCreateFontW(CREATE_FONT_ARGS);
} }
@ -320,9 +361,10 @@ HFONT WINAPI Hijack::newCreateFontA(int nHeight, int nWidth, int nEscapement, in
HFONT WINAPI Hijack::newCreateFontW(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCWSTR lpszFace) HFONT WINAPI Hijack::newCreateFontW(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCWSTR lpszFace)
{ {
if (isFontCustomized())
if (isFontCustomized()) { {
if (embedsharedmem->fontCharSetEnabled) { if (embedsharedmem->fontCharSetEnabled)
{
auto charSet = embedsharedmem->fontCharSet; auto charSet = embedsharedmem->fontCharSet;
if (!charSet) if (!charSet)
charSet = systemCharSet(); charSet = systemCharSet();
@ -372,11 +414,13 @@ int WINAPI Hijack::newMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR l
if (CodePage == CP_THREAD_ACP || CodePage == CP_OEMCP) if (CodePage == CP_THREAD_ACP || CodePage == CP_OEMCP)
CodePage = CP_ACP; CodePage = CP_ACP;
// CP_ACP(0), CP_MACCP(1), CP_OEMCP(2), CP_THREAD_ACP(3) // CP_ACP(0), CP_MACCP(1), CP_OEMCP(2), CP_THREAD_ACP(3)
if ((CodePage <= 3 || CodePage == 932) && cchWideChar > 0 && cbMultiByte > 1) { if ((CodePage <= 3 || CodePage == 932) && cchWideChar > 0 && cbMultiByte > 1)
{
bool dynamic; bool dynamic;
std::string data(lpMultiByteStr, cbMultiByte); std::string data(lpMultiByteStr, cbMultiByte);
auto text = dynamiccodec->decode(data, &dynamic); auto text = dynamiccodec->decode(data, &dynamic);
if (dynamic && !text.empty()) { if (dynamic && !text.empty())
{
int size = min(text.size() + 1, cchWideChar); int size = min(text.size() + 1, cchWideChar);
::memcpy(lpWideCharStr, text.c_str(), size * 2); ::memcpy(lpWideCharStr, text.c_str(), size * 2);
// lpWideCharStr[size - 1] = 0; // enforce trailing zero // lpWideCharStr[size - 1] = 0; // enforce trailing zero
@ -392,11 +436,13 @@ int WINAPI Hijack::newWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR
if (CodePage == CP_THREAD_ACP || CodePage == CP_OEMCP) if (CodePage == CP_THREAD_ACP || CodePage == CP_OEMCP)
CodePage = CP_ACP; CodePage = CP_ACP;
if ((CodePage <= 3 || CodePage == 932) && cchWideChar > 0 && cbMultiByte >= 0) { if ((CodePage <= 3 || CodePage == 932) && cchWideChar > 0 && cbMultiByte >= 0)
{
bool dynamic; bool dynamic;
auto text = std::wstring(lpWideCharStr, cchWideChar); auto text = std::wstring(lpWideCharStr, cchWideChar);
auto data = dynamiccodec->encodeSTD(text, &dynamic); auto data = dynamiccodec->encodeSTD(text, &dynamic);
if (dynamic && !data.empty()) { if (dynamic && !data.empty())
{
int size = data.size() + 1; int size = data.size() + 1;
if (cbMultiByte && cbMultiByte < size) if (cbMultiByte && cbMultiByte < size)
@ -414,11 +460,13 @@ UINT decodeChar(UINT ch, bool *dynamic)
{ {
if (dynamic) if (dynamic)
*dynamic = false; *dynamic = false;
if (ch > 0xff) { if (ch > 0xff)
{
bool t; bool t;
char data[3] = {(BYTE)(ch >> 8) & 0xff, (BYTE)ch & 0xff, 0}; char data[3] = {(BYTE)(ch >> 8) & 0xff, (BYTE)ch & 0xff, 0};
auto text = dynamiccodec->decode(data, &t); auto text = dynamiccodec->decode(data, &t);
if (t && text.size() == 1) { if (t && text.size() == 1)
{
if (dynamic) if (dynamic)
*dynamic = true; *dynamic = true;
return text[0]; return text[0];
@ -429,10 +477,12 @@ UINT decodeChar(UINT ch, bool *dynamic)
#define DECODE_CHAR(uChar, ...) \ #define DECODE_CHAR(uChar, ...) \
{ \ { \
if (uChar > 0xff) \ if (uChar > 0xff) \
if (1) { \ if (1) \
{ \
bool dynamic; \ bool dynamic; \
UINT ch = decodeChar(uChar, &dynamic); \ UINT ch = decodeChar(uChar, &dynamic); \
if (dynamic && ch) { \ if (dynamic && ch) \
{ \
uChar = ch; \ uChar = ch; \
return (__VA_ARGS__); \ return (__VA_ARGS__); \
} \ } \
@ -442,12 +492,15 @@ UINT decodeChar(UINT ch, bool *dynamic)
#define DECODE_TEXT(lpString, cchString, ...) \ #define DECODE_TEXT(lpString, cchString, ...) \
{ \ { \
if (cchString == -1 || cchString > 1) \ if (cchString == -1 || cchString > 1) \
if (1) { \ if (1) \
{ \
bool dynamic; \ bool dynamic; \
auto data = std::string(lpString, cchString == -1 ? ::strlen(lpString) : cchString); \ auto data = std::string(lpString, cchString == -1 ? ::strlen(lpString) : cchString); \
if (data.size() > 1) { \ if (data.size() > 1) \
{ \
auto text = dynamiccodec->decode(data, &dynamic); \ auto text = dynamiccodec->decode(data, &dynamic); \
if (dynamic && !text.empty()) { \ if (dynamic && !text.empty()) \
{ \
LPCWSTR lpString = (LPCWSTR)text.c_str(); \ LPCWSTR lpString = (LPCWSTR)text.c_str(); \
cchString = text.size(); \ cchString = text.size(); \
return (__VA_ARGS__); \ return (__VA_ARGS__); \
@ -457,15 +510,21 @@ UINT decodeChar(UINT ch, bool *dynamic)
} }
#define TRANSLATE_TEXT_A(lpString, cchString, ...) \ #define TRANSLATE_TEXT_A(lpString, cchString, ...) \
{ \ { \
if (auto q = EngineController::instance()) { \ if (auto q = EngineController::instance()) \
{ \
auto data = std::string(lpString, cchString == -1 ? ::strlen(lpString) : cchString); \ auto data = std::string(lpString, cchString == -1 ? ::strlen(lpString) : cchString); \
std::wstring oldText = q->decode(data); \ std::wstring oldText = q->decode(data); \
if (!oldText.empty()) { \ if (!oldText.empty()) \
enum { role = Engine::OtherRole }; \ { \
enum \
{ \
role = Engine::OtherRole \
}; \
ULONG split = (ULONG)_ReturnAddress(); \ ULONG split = (ULONG)_ReturnAddress(); \
auto sig = Engine::hashThreadSignature(role, split); \ auto sig = Engine::hashThreadSignature(role, split); \
auto newText = q->dispatchTextWSTD(oldText, role, sig); \ auto newText = q->dispatchTextWSTD(oldText, role, sig); \
if (newText != oldText) { \ if (newText != oldText) \
{ \
LPCWSTR lpString = (LPCWSTR)newText.c_str(); \ LPCWSTR lpString = (LPCWSTR)newText.c_str(); \
cchString = newText.size(); \ cchString = newText.size(); \
return (__VA_ARGS__); \ return (__VA_ARGS__); \
@ -476,10 +535,15 @@ UINT decodeChar(UINT ch, bool *dynamic)
#define TRANSLATE_TEXT_W(lpString, cchString, ...) \ #define TRANSLATE_TEXT_W(lpString, cchString, ...) \
{ \ { \
if (auto q = EngineController::instance()) { \ if (auto q = EngineController::instance()) \
{ \
auto text = std::wstring(lpString, cchString); \ auto text = std::wstring(lpString, cchString); \
if (!text.empty()) { \ if (!text.empty()) \
enum { role = Engine::OtherRole }; \ { \
enum \
{ \
role = Engine::OtherRole \
}; \
ULONG split = (ULONG)_ReturnAddress(); \ ULONG split = (ULONG)_ReturnAddress(); \
auto sig = Engine::hashThreadSignature(role, split); \ auto sig = Engine::hashThreadSignature(role, split); \
text = q->dispatchTextWSTD(text, role, sig); \ text = q->dispatchTextWSTD(text, role, sig); \
@ -508,7 +572,6 @@ DWORD WINAPI Hijack::newGetGlyphOutlineW(HDC hdc, UINT uChar, UINT uFormat, LPGL
BOOL WINAPI Hijack::newGetTextExtentPoint32A(HDC hdc, LPCSTR lpString, int cchString, LPSIZE lpSize) BOOL WINAPI Hijack::newGetTextExtentPoint32A(HDC hdc, LPCSTR lpString, int cchString, LPSIZE lpSize)
{ {
DCFontSwitcher fs(hdc); DCFontSwitcher fs(hdc);
// TRANSLATE_TEXT_A(lpString, cchString, oldGetTextExtentPoint32W(hdc, lpString, cchString, lpSize)) // TRANSLATE_TEXT_A(lpString, cchString, oldGetTextExtentPoint32W(hdc, lpString, cchString, lpSize))
DECODE_TEXT(lpString, cchString, oldGetTextExtentPoint32W(hdc, lpString, cchString, lpSize)) DECODE_TEXT(lpString, cchString, oldGetTextExtentPoint32W(hdc, lpString, cchString, lpSize))
@ -564,7 +627,8 @@ int WINAPI Hijack::newDrawTextExA(HDC hdc, LPSTR lpString, int cchString, LPRECT
{ {
DCFontSwitcher fs(hdc); DCFontSwitcher fs(hdc);
if (!(dwDTFormat & DT_MODIFYSTRING)) { if (!(dwDTFormat & DT_MODIFYSTRING))
{
// if (HijackManager::instance()->isFunctionTranslated((uintptr_t)::DrawTextExA)) // if (HijackManager::instance()->isFunctionTranslated((uintptr_t)::DrawTextExA))
// TRANSLATE_TEXT_A(lpString, cchString, oldDrawTextExW(hdc, const_cast<LPWSTR>(lpString), cchString, lpRect, dwDTFormat, lpDTParams)) // TRANSLATE_TEXT_A(lpString, cchString, oldDrawTextExW(hdc, const_cast<LPWSTR>(lpString), cchString, lpRect, dwDTFormat, lpDTParams))
// else // else
@ -622,6 +686,4 @@ BOOL WINAPI Hijack::newExtTextOutW(HDC hdc, int X, int Y, UINT fuOptions, const
return oldExtTextOutW(hdc, X, Y, fuOptions, lprc, lpString, cchString, lpDx); return oldExtTextOutW(hdc, X, Y, fuOptions, lprc, lpString, cchString, lpDx);
} }
// EOF // EOF

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
namespace Hijack
namespace Hijack { {
#define DEF_FUN(_fun, _return, ...) \ #define DEF_FUN(_fun, _return, ...) \
typedef _return(WINAPI *_fun##_fun_t)(__VA_ARGS__); \ typedef _return(WINAPI *_fun##_fun_t)(__VA_ARGS__); \
@ -35,7 +35,6 @@ namespace Hijack {
DEF_FUN(ExtTextOutA, BOOL, HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCSTR lpString, UINT cbCount, const INT *lpDx) DEF_FUN(ExtTextOutA, BOOL, HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCSTR lpString, UINT cbCount, const INT *lpDx)
DEF_FUN(ExtTextOutW, BOOL, HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCWSTR lpString, UINT cbCount, const INT *lpDx) DEF_FUN(ExtTextOutW, BOOL, HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCWSTR lpString, UINT cbCount, const INT *lpDx)
DEF_FUN(DrawTextA, int, HDC hdc, LPCSTR lpString, int nCount, LPRECT lpRect, UINT uFormat) DEF_FUN(DrawTextA, int, HDC hdc, LPCSTR lpString, int nCount, LPRECT lpRect, UINT uFormat)
DEF_FUN(DrawTextW, int, HDC hdc, LPCWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat) DEF_FUN(DrawTextW, int, HDC hdc, LPCWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat)

View File

@ -98,11 +98,14 @@ namespace
bool IsBadReadPtr(void *data) bool IsBadReadPtr(void *data)
{ {
if (data > records.get() && data < records.get() + sp.maxRecords) return true; if (data > records.get() && data < records.get() + sp.maxRecords)
return true;
uintptr_t BAD_PAGE = (uintptr_t)data >> 12; uintptr_t BAD_PAGE = (uintptr_t)data >> 12;
auto &cacheEntry = pageCache[BAD_PAGE % CACHE_SIZE]; auto &cacheEntry = pageCache[BAD_PAGE % CACHE_SIZE];
if (cacheEntry == BAD_PAGE) return true; if (cacheEntry == BAD_PAGE)
if (cacheEntry == GOOD_PAGE) return false; return true;
if (cacheEntry == GOOD_PAGE)
return false;
__try __try
{ {
@ -124,20 +127,24 @@ bool IsBadReadPtr(void* data)
void DoSend(int i, uintptr_t address, char *str, uintptr_t padding, JITTYPE jittype = JITTYPE::PC, uintptr_t em_addr = 0) void DoSend(int i, uintptr_t address, char *str, uintptr_t padding, JITTYPE jittype = JITTYPE::PC, uintptr_t em_addr = 0)
{ {
str += padding; str += padding;
if (IsBadReadPtr(str) || IsBadReadPtr(str + MAX_STRING_SIZE)) return; if (IsBadReadPtr(str) || IsBadReadPtr(str + MAX_STRING_SIZE))
return;
__try __try
{ {
int length = 0, sum = 0; int length = 0, sum = 0;
for (; (str[length] || str[length + 1]) && length < MAX_STRING_SIZE; length += 2) sum += *(uint16_t*)(str + length); for (; (str[length] || str[length + 1]) && length < MAX_STRING_SIZE; length += 2)
sum += *(uint16_t *)(str + length);
if (length > STRING && length < MAX_STRING_SIZE - 1) if (length > STRING && length < MAX_STRING_SIZE - 1)
{ {
// many duplicate results with same address, offset, and third/fourth character will be found: filter them out // many duplicate results with same address, offset, and third/fourth character will be found: filter them out
uint64_t signature = ((uint64_t)i << 56) | ((uint64_t)(str[2] + str[3]) << 48) | address; uint64_t signature = ((uint64_t)i << 56) | ((uint64_t)(str[2] + str[3]) << 48) | address;
if (signatureCache[signature % CACHE_SIZE] == signature) return; if (signatureCache[signature % CACHE_SIZE] == signature)
return;
signatureCache[signature % CACHE_SIZE] = signature; signatureCache[signature % CACHE_SIZE] = signature;
// if there are huge amount of strings that are the same, it's probably garbage: filter them out // if there are huge amount of strings that are the same, it's probably garbage: filter them out
// can't store all the strings, so use sum as heuristic instead // can't store all the strings, so use sum as heuristic instead
if (_InterlockedIncrement(sumCache + (sum % CACHE_SIZE)) > 25) return; if (_InterlockedIncrement(sumCache + (sum % CACHE_SIZE)) > 25)
return;
long n = sp.maxRecords - _InterlockedDecrement(&recordsAvailable); long n = sp.maxRecords - _InterlockedDecrement(&recordsAvailable);
if (n < sp.maxRecords) if (n < sp.maxRecords)
{ {
@ -154,7 +161,8 @@ void DoSend(int i,uintptr_t address,char* str,uintptr_t padding,JITTYPE jittype=
records[n].argidx = i; records[n].argidx = i;
} }
for (int j = 0; j < length; ++j) records[n].text[j] = str[j]; for (int j = 0; j < length; ++j)
records[n].text[j] = str[j];
records[n].text[length] = 0; records[n].text[length] = 0;
} }
if (n == sp.maxRecords) if (n == sp.maxRecords)
@ -164,20 +172,24 @@ void DoSend(int i,uintptr_t address,char* str,uintptr_t padding,JITTYPE jittype=
} }
} }
} }
__except (EXCEPTION_EXECUTE_HANDLER) {} __except (EXCEPTION_EXECUTE_HANDLER)
{
}
} }
void Send(char **stack, uintptr_t address) void Send(char **stack, uintptr_t address)
{ {
// it is unsafe to call ANY external functions from this, as they may have been hooked (if called the hook would call this function making an infinite loop) // it is unsafe to call ANY external functions from this, as they may have been hooked (if called the hook would call this function making an infinite loop)
// the exceptions are compiler intrinsics like _InterlockedDecrement // the exceptions are compiler intrinsics like _InterlockedDecrement
if (recordsAvailable <= 0) return; if (recordsAvailable <= 0)
for (int i = -registers; i < 10; ++i) for (auto padding : { uintptr_t{}, sp.padding }) return;
for (int i = -registers; i < 10; ++i)
for (auto padding : {uintptr_t{}, sp.padding})
{ {
DoSend(i, address, stack[i], padding); DoSend(i, address, stack[i], padding);
} }
} }
void SafeSendJitVeh(hook_stack* stack,uintptr_t address,uintptr_t em_addr,JITTYPE jittype){ void SafeSendJitVeh(hook_stack *stack, uintptr_t address, uintptr_t em_addr, JITTYPE jittype)
{
__try __try
{ {
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
@ -204,16 +216,24 @@ void SafeSendJitVeh(hook_stack* stack,uintptr_t address,uintptr_t em_addr,JITTYP
} }
DoSend(i, address, str, 0, jittype, em_addr); DoSend(i, address, str, 0, jittype, em_addr);
} }
}__except (EXCEPTION_EXECUTE_HANDLER) {} }
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
} }
std::unordered_map<uintptr_t, uint64_t> addresscalledtime; std::unordered_map<uintptr_t, uint64_t> addresscalledtime;
bool safeautoleaveveh = false; bool safeautoleaveveh = false;
bool SendJitVeh(PCONTEXT context,uintptr_t address,uintptr_t em_addr,JITTYPE jittype){ bool SendJitVeh(PCONTEXT context, uintptr_t address, uintptr_t em_addr, JITTYPE jittype)
if(safeautoleaveveh)return true; {
if (recordsAvailable <= 0) return false; if (safeautoleaveveh)
if(addresscalledtime.find(address)==addresscalledtime.end())addresscalledtime[address]=0; return true;
if (recordsAvailable <= 0)
return false;
if (addresscalledtime.find(address) == addresscalledtime.end())
addresscalledtime[address] = 0;
auto tm = GetTickCount64(); auto tm = GetTickCount64();
if(tm-addresscalledtime[address]<100)return false; if (tm - addresscalledtime[address] < 100)
return false;
addresscalledtime[address] = tm; addresscalledtime[address] = tm;
auto stack = std::make_unique<hook_stack>(); auto stack = std::make_unique<hook_stack>();
context_get(stack.get(), context); context_get(stack.get(), context);
@ -222,13 +242,17 @@ bool SendJitVeh(PCONTEXT context,uintptr_t address,uintptr_t em_addr,JITTYPE jit
} }
std::vector<uintptr_t> GetFunctions(uintptr_t module) std::vector<uintptr_t> GetFunctions(uintptr_t module)
{ {
if (!module) return {}; if (!module)
return {};
IMAGE_DOS_HEADER *dosHeader = (IMAGE_DOS_HEADER *)module; IMAGE_DOS_HEADER *dosHeader = (IMAGE_DOS_HEADER *)module;
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) return {}; if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
return {};
IMAGE_NT_HEADERS *ntHeader = (IMAGE_NT_HEADERS *)(module + dosHeader->e_lfanew); IMAGE_NT_HEADERS *ntHeader = (IMAGE_NT_HEADERS *)(module + dosHeader->e_lfanew);
if (ntHeader->Signature != IMAGE_NT_SIGNATURE) return {}; if (ntHeader->Signature != IMAGE_NT_SIGNATURE)
return {};
DWORD exportAddress = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; DWORD exportAddress = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
if (!exportAddress) return {}; if (!exportAddress)
return {};
IMAGE_EXPORT_DIRECTORY *exportDirectory = (IMAGE_EXPORT_DIRECTORY *)(module + exportAddress); IMAGE_EXPORT_DIRECTORY *exportDirectory = (IMAGE_EXPORT_DIRECTORY *)(module + exportAddress);
std::vector<uintptr_t> functions; std::vector<uintptr_t> functions;
for (int i = 0; i < exportDirectory->NumberOfNames; ++i) for (int i = 0; i < exportDirectory->NumberOfNames; ++i)
@ -237,15 +261,19 @@ std::vector<uintptr_t> GetFunctions(uintptr_t module)
sizeof(DWORD) * *(WORD *)(module + exportDirectory->AddressOfNameOrdinals + i * sizeof(WORD)))); sizeof(DWORD) * *(WORD *)(module + exportDirectory->AddressOfNameOrdinals + i * sizeof(WORD))));
return functions; return functions;
} }
void mergevector(std::vector<uintptr_t> &v1,std::vector<uintptr_t> &v2){ void mergevector(std::vector<uintptr_t> &v1, std::vector<uintptr_t> &v2)
for(auto addr:v2){ {
for (auto addr : v2)
{
auto it = std::find(v1.begin(), v1.end(), addr); auto it = std::find(v1.begin(), v1.end(), addr);
if (it == v1.end()) { if (it == v1.end())
{
v1.push_back(addr); v1.push_back(addr);
} }
} }
} }
void SearchForHooks_Return(){ void SearchForHooks_Return()
{
ConsoleOutput(HOOK_SEARCH_FINISHED, sp.maxRecords - recordsAvailable); ConsoleOutput(HOOK_SEARCH_FINISHED, sp.maxRecords - recordsAvailable);
for (int i = 0, results = 0; i < sp.maxRecords; ++i) for (int i = 0, results = 0; i < sp.maxRecords; ++i)
{ {
@ -256,30 +284,40 @@ void SearchForHooks_Return(){
if (records[i].jittype == JITTYPE::PC) if (records[i].jittype == JITTYPE::PC)
{ {
if (!records[i].address) continue; if (!records[i].address)
continue;
hp.offset = records[i].offset; hp.offset = records[i].offset;
hp.type = CODEC_UTF16 | USING_STRING; hp.type = CODEC_UTF16 | USING_STRING;
hp.address = records[i].address; hp.address = records[i].address;
} }
else else
{ {
if (!records[i].em_addr) continue; if (!records[i].em_addr)
continue;
hp.emu_addr = records[i].em_addr; hp.emu_addr = records[i].em_addr;
hp.type = CODEC_UTF16 | USING_STRING | BREAK_POINT; hp.type = CODEC_UTF16 | USING_STRING | BREAK_POINT;
hp.argidx = records[i].argidx; hp.argidx = records[i].argidx;
} }
NotifyHookFound(hp, (wchar_t *)records[i].text); NotifyHookFound(hp, (wchar_t *)records[i].text);
if (++results % 100'000 == 0) ConsoleOutput(ResultsNum, results); if (++results % 100'000 == 0)
ConsoleOutput(ResultsNum, results);
} }
records.reset(); records.reset();
for (int i = 0; i < CACHE_SIZE; ++i) signatureCache[i] = sumCache[i] = 0; for (int i = 0; i < CACHE_SIZE; ++i)
signatureCache[i] = sumCache[i] = 0;
} }
void initrecords(){ void initrecords()
{
do do
try { records = std::make_unique<HookRecord[]>(recordsAvailable = sp.maxRecords); } try
catch (std::bad_alloc) { ConsoleOutput(SearchForHooks_ERROR, sp.maxRecords /= 2); } {
records = std::make_unique<HookRecord[]>(recordsAvailable = sp.maxRecords);
}
catch (std::bad_alloc)
{
ConsoleOutput(SearchForHooks_ERROR, sp.maxRecords /= 2);
}
while (!records && sp.maxRecords); while (!records && sp.maxRecords);
} }
void SearchForHooks(SearchParam spUser) void SearchForHooks(SearchParam spUser)
{ {
@ -421,8 +459,8 @@ void SearchForHooks(SearchParam spUser)
// } // }
safeautoleaveveh=true; safeautoleaveveh=true;
SearchForHooks_Return(); SearchForHooks_Return();
} } })
}).detach(); .detach();
} }
void SearchForText(wchar_t *text, UINT codepage) void SearchForText(wchar_t *text, UINT codepage)
@ -434,14 +472,15 @@ void SearchForText(wchar_t* text, UINT codepage)
if (codepage != CP_UTF8) if (codepage != CP_UTF8)
WideCharToMultiByte(codepage, 0, text, PATTERN_SIZE, codepageText, PATTERN_SIZE * 4, nullptr, nullptr); WideCharToMultiByte(codepage, 0, text, PATTERN_SIZE, codepageText, PATTERN_SIZE * 4, nullptr, nullptr);
if (strlen(utf8Text) < 4 || ((codepage != CP_UTF8) && (strlen(codepageText) < 4)) || wcslen(text) < 4)
if (strlen(utf8Text) < 4 || ((codepage!=CP_UTF8)&&(strlen(codepageText) < 4)) || wcslen(text) < 4) return ConsoleOutput(NOT_ENOUGH_TEXT); return ConsoleOutput(NOT_ENOUGH_TEXT);
ConsoleOutput(HOOK_SEARCH_STARTING); ConsoleOutput(HOOK_SEARCH_STARTING);
auto GenerateHooks = [&](std::vector<uintptr_t> addresses, HookParamType type) auto GenerateHooks = [&](std::vector<uintptr_t> addresses, HookParamType type)
{ {
for (auto addr : addresses) for (auto addr : addresses)
{ {
if (abs((long long)(utf8Text - addr)) < 20000) continue; // don't add read code if text is on this thread's stack if (abs((long long)(utf8Text - addr)) < 20000)
continue; // don't add read code if text is on this thread's stack
found = true; found = true;
HookParam hp; HookParam hp;
hp.type = DIRECT_READ | type; hp.type = DIRECT_READ | type;
@ -454,5 +493,6 @@ void SearchForText(wchar_t* text, UINT codepage)
if (codepage != CP_UTF8) if (codepage != CP_UTF8)
GenerateHooks(Util::SearchMemory(codepageText, strlen(codepageText), PAGE_READWRITE), USING_STRING); GenerateHooks(Util::SearchMemory(codepageText, strlen(codepageText), PAGE_READWRITE), USING_STRING);
GenerateHooks(Util::SearchMemory(text, wcslen(text) * sizeof(wchar_t), PAGE_READWRITE), CODEC_UTF16); GenerateHooks(Util::SearchMemory(text, wcslen(text) * sizeof(wchar_t), PAGE_READWRITE), CODEC_UTF16);
if (!found) ConsoleOutput(COULD_NOT_FIND); if (!found)
ConsoleOutput(COULD_NOT_FIND);
} }

View File

@ -57,8 +57,10 @@ DWORD WINAPI Pipe(LPVOID)
case HOST_COMMAND_FIND_HOOK: case HOST_COMMAND_FIND_HOOK:
{ {
auto info = *(FindHookCmd *)buffer; auto info = *(FindHookCmd *)buffer;
if (*info.sp.text) SearchForText(info.sp.text, info.sp.codepage); if (*info.sp.text)
else SearchForHooks(info.sp); SearchForText(info.sp.text, info.sp.codepage);
else
SearchForHooks(info.sp);
} }
break; break;
case HOST_COMMAND_DETACH: case HOST_COMMAND_DETACH:
@ -69,13 +71,17 @@ DWORD WINAPI Pipe(LPVOID)
} }
} }
if(dont_detach){ if (dont_detach)
{
host_connected = false; host_connected = false;
return Pipe(0); return Pipe(0);
}else{ }
else
{
MH_Uninitialize(); MH_Uninitialize();
for (auto& hook : *hooks) hook.Clear(); for (auto &hook : *hooks)
hook.Clear();
FreeLibraryAndExitThread(GetModuleHandleW(LUNA_HOOK_DLL), 0); FreeLibraryAndExitThread(GetModuleHandleW(LUNA_HOOK_DLL), 0);
} }
} }
@ -104,7 +110,8 @@ void NotifyHookFound(HookParam hp,wchar_t*text)
} }
void NotifyHookRemove(uint64_t addr, LPCSTR name) void NotifyHookRemove(uint64_t addr, LPCSTR name)
{ {
if (name) ConsoleOutput(REMOVING_HOOK, name); if (name)
ConsoleOutput(REMOVING_HOOK, name);
HookRemovedNotif buffer(addr); HookRemovedNotif buffer(addr);
WriteFile(hookPipe, &buffer, sizeof(buffer), DUMMY, nullptr); WriteFile(hookPipe, &buffer, sizeof(buffer), DUMMY, nullptr);
} }
@ -122,10 +129,12 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
{ {
hLUNAHOOKDLL = hModule; hLUNAHOOKDLL = hModule;
viewMutex = WinMutex(ITH_HOOKMAN_MUTEX_ + std::to_wstring(GetCurrentProcessId()), &allAccess); viewMutex = WinMutex(ITH_HOOKMAN_MUTEX_ + std::to_wstring(GetCurrentProcessId()), &allAccess);
if (GetLastError() == ERROR_ALREADY_EXISTS) return FALSE; if (GetLastError() == ERROR_ALREADY_EXISTS)
return FALSE;
DisableThreadLibraryCalls(hModule); DisableThreadLibraryCalls(hModule);
auto createfm=[](AutoHandle<> &handle,void**ptr,DWORD sz,std::wstring&name ){ auto createfm = [](AutoHandle<> &handle, void **ptr, DWORD sz, std::wstring &name)
{
handle = CreateFileMappingW(INVALID_HANDLE_VALUE, &allAccess, PAGE_EXECUTE_READWRITE, 0, sz, (name).c_str()); handle = CreateFileMappingW(INVALID_HANDLE_VALUE, &allAccess, PAGE_EXECUTE_READWRITE, 0, sz, (name).c_str());
*ptr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, sz); *ptr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, sz);
memset(*ptr, 0, sz); memset(*ptr, 0, sz);
@ -150,8 +159,10 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
} }
return TRUE; return TRUE;
} }
int HookStrLen(HookParam* hp,BYTE* data){ int HookStrLen(HookParam *hp, BYTE *data)
if(data==0)return 0; {
if (data == 0)
return 0;
if (hp->type & CODEC_UTF16) if (hp->type & CODEC_UTF16)
return wcsnlen((wchar_t *)data, TEXT_BUFFER_SIZE) * 2; return wcsnlen((wchar_t *)data, TEXT_BUFFER_SIZE) * 2;
@ -159,10 +170,10 @@ int HookStrLen(HookParam* hp,BYTE* data){
return u32strlen((uint32_t *)data) * 4; return u32strlen((uint32_t *)data) * 4;
else else
return strnlen((char *)data, TEXT_BUFFER_SIZE); return strnlen((char *)data, TEXT_BUFFER_SIZE);
} }
static std::mutex maplock; static std::mutex maplock;
void jitaddraddr(uintptr_t em_addr,uintptr_t jitaddr,JITTYPE jittype){ void jitaddraddr(uintptr_t em_addr, uintptr_t jitaddr, JITTYPE jittype)
{
std::lock_guard _(maplock); std::lock_guard _(maplock);
emuaddr2jitaddr[em_addr] = {jittype, jitaddr}; emuaddr2jitaddr[em_addr] = {jittype, jitaddr};
jitaddr2emuaddr[jitaddr] = {jittype, em_addr}; jitaddr2emuaddr[jitaddr] = {jittype, em_addr};
@ -172,11 +183,13 @@ bool NewHook_1(HookParam& hp, LPCSTR lpname)
if (hp.emu_addr) if (hp.emu_addr)
ConsoleOutput("%p => %p", hp.emu_addr, hp.address); ConsoleOutput("%p => %p", hp.emu_addr, hp.address);
if (++currentHook >= MAX_HOOK){ if (++currentHook >= MAX_HOOK)
{
ConsoleOutput(TOO_MANY_HOOKS); ConsoleOutput(TOO_MANY_HOOKS);
return false; return false;
} }
if (lpname && *lpname) strncpy_s(hp.name, lpname, HOOK_NAME_SIZE - 1); if (lpname && *lpname)
strncpy_s(hp.name, lpname, HOOK_NAME_SIZE - 1);
wcscpy_s(hp.hookcode, HOOKCODE_LEN, HookCode::Generate(hp, GetCurrentProcessId()).c_str()); wcscpy_s(hp.hookcode, HOOKCODE_LEN, HookCode::Generate(hp, GetCurrentProcessId()).c_str());
if (!(*hooks)[currentHook].Insert(hp)) if (!(*hooks)[currentHook].Insert(hp))
@ -185,43 +198,52 @@ bool NewHook_1(HookParam& hp, LPCSTR lpname)
(*hooks)[currentHook].Clear(); (*hooks)[currentHook].Clear();
return false; return false;
} }
else{ else
{
NotifyHookInserting(hp.address, hp.hookcode); NotifyHookInserting(hp.address, hp.hookcode);
return true; return true;
} }
} }
static std::mutex delayinsertlock; static std::mutex delayinsertlock;
void delayinsertadd(HookParam hp,std::string name){ void delayinsertadd(HookParam hp, std::string name)
{
std::lock_guard _(maplock); std::lock_guard _(maplock);
delayinserthook[hp.emu_addr] = {name, hp}; delayinserthook[hp.emu_addr] = {name, hp};
ConsoleOutput(INSERTING_HOOK, name.c_str(), hp.emu_addr); ConsoleOutput(INSERTING_HOOK, name.c_str(), hp.emu_addr);
} }
void delayinsertNewHook(uintptr_t em_address){ void delayinsertNewHook(uintptr_t em_address)
if(delayinserthook.find(em_address)==delayinserthook.end())return; {
if (delayinserthook.find(em_address) == delayinserthook.end())
return;
std::lock_guard _(maplock); std::lock_guard _(maplock);
auto h = delayinserthook[em_address]; auto h = delayinserthook[em_address];
delayinserthook.erase(em_address); delayinserthook.erase(em_address);
NewHook(h.second, h.first.c_str()); NewHook(h.second, h.first.c_str());
} }
bool NewHook(HookParam hp, LPCSTR name){ bool NewHook(HookParam hp, LPCSTR name)
{
if (hp.address || hp.jittype == JITTYPE::PC) if (hp.address || hp.jittype == JITTYPE::PC)
return NewHook_1(hp, name); return NewHook_1(hp, name);
if(hp.jittype==JITTYPE::UNITY){ if (hp.jittype == JITTYPE::UNITY)
{
auto spls = strSplit(hp.unityfunctioninfo, ":"); auto spls = strSplit(hp.unityfunctioninfo, ":");
if(spls.size()!=5){ if (spls.size() != 5)
{
ConsoleOutput("invalid"); ConsoleOutput("invalid");
return false; return false;
} }
hp.address = tryfindmonoil2cpp(spls[0].c_str(), spls[1].c_str(), spls[2].c_str(), spls[3].c_str(), std::stoi(spls[4])); hp.address = tryfindmonoil2cpp(spls[0].c_str(), spls[1].c_str(), spls[2].c_str(), spls[3].c_str(), std::stoi(spls[4]));
if(!hp.address){ if (!hp.address)
{
ConsoleOutput("not find"); ConsoleOutput("not find");
return false; return false;
} }
return NewHook_1(hp, name); return NewHook_1(hp, name);
} }
// 下面的是手动插入 // 下面的是手动插入
if(emuaddr2jitaddr.find(hp.emu_addr)==emuaddr2jitaddr.end()){ if (emuaddr2jitaddr.find(hp.emu_addr) == emuaddr2jitaddr.end())
{
delayinsertadd(hp, name); delayinsertadd(hp, name);
return true; return true;
} }
@ -235,7 +257,9 @@ bool NewHook(HookParam hp, LPCSTR name){
} }
void RemoveHook(uint64_t addr, int maxOffset) void RemoveHook(uint64_t addr, int maxOffset)
{ {
for (auto& hook : *hooks) if (abs((long long)(hook.address - addr)) <= maxOffset) return hook.Clear(); for (auto &hook : *hooks)
if (abs((long long)(hook.address - addr)) <= maxOffset)
return hook.Clear();
} }
std::string LoadResData(LPCWSTR pszResID, LPCWSTR _type) std::string LoadResData(LPCWSTR pszResID, LPCWSTR _type)
{ {
@ -257,8 +281,8 @@ std::string LoadResData(LPCWSTR pszResID,LPCWSTR _type)
return data; return data;
} }
void context_get(hook_stack *stack, PCONTEXT context)
void context_get(hook_stack* stack,PCONTEXT context){ {
#ifndef _WIN64 #ifndef _WIN64
stack->eax = context->Eax; stack->eax = context->Eax;
stack->ecx = context->Ecx; stack->ecx = context->Ecx;
@ -291,7 +315,8 @@ void context_get(hook_stack* stack,PCONTEXT context){
stack->retaddr = *(DWORD64 *)context->Rsp; stack->retaddr = *(DWORD64 *)context->Rsp;
#endif #endif
} }
void context_set(hook_stack* stack,PCONTEXT context){ void context_set(hook_stack *stack, PCONTEXT context)
{
#ifndef _WIN64 #ifndef _WIN64
context->Eax = stack->eax; context->Eax = stack->eax;
context->Ecx = stack->ecx; context->Ecx = stack->ecx;

View File

@ -4,7 +4,6 @@
// 8/23/2013 jichi // 8/23/2013 jichi
// Branch: ITH/IHF_DLL.h, rev 66 // Branch: ITH/IHF_DLL.h, rev 66
void TextOutput(const ThreadParam &tp, const HookParam &hp, TextOutput_T(*buffer), int len); void TextOutput(const ThreadParam &tp, const HookParam &hp, TextOutput_T(*buffer), int len);
void ConsoleOutput(LPCSTR text, ...); void ConsoleOutput(LPCSTR text, ...);
void NotifyHookFound(HookParam hp, wchar_t *text); void NotifyHookFound(HookParam hp, wchar_t *text);
@ -29,6 +28,5 @@ inline std::map<uintptr_t,std::pair<std::string,HookParam>>delayinserthook;
void delayinsertadd(HookParam, std::string); void delayinsertadd(HookParam, std::string);
void delayinsertNewHook(uintptr_t); void delayinsertNewHook(uintptr_t);
inline bool dont_detach = false; inline bool dont_detach = false;
inline bool host_connected = false; inline bool host_connected = false;

View File

@ -1,11 +1,13 @@
#include "../include/pch.h" #include "../include/pch.h"
enum { TEXT_BUFFER_SIZE = PIPE_BUFFER_SIZE - sizeof(TextOutput_T) }; enum
{
TEXT_BUFFER_SIZE = PIPE_BUFFER_SIZE - sizeof(TextOutput_T)
};
// #define wcslen(XX) wcsnlen((XX), TEXT_BUFFER_SIZE*2) // #define wcslen(XX) wcsnlen((XX), TEXT_BUFFER_SIZE*2)
// #define strlen(XX) strnlen((XX), TEXT_BUFFER_SIZE*2) // #define strlen(XX) strnlen((XX), TEXT_BUFFER_SIZE*2)
#include "main.h" #include "main.h"
#include "stackoffset.hpp" #include "stackoffset.hpp"
#include "util/stringfilters.h" #include "util/stringfilters.h"

View File

@ -33,14 +33,16 @@ enum class regs
invalid invalid
}; };
inline int get_stack(int s){ inline int get_stack(int s)
{
#ifdef _WIN64 #ifdef _WIN64
return s * 8; return s * 8;
#else #else
return s * 4; return s * 4;
#endif #endif
} }
inline int get_reg(regs reg){ inline int get_reg(regs reg)
{
#ifdef _WIN64 #ifdef _WIN64
return -8 * (int)reg - 8; return -8 * (int)reg - 8;
#else #else
@ -48,36 +50,60 @@ inline int get_reg(regs reg){
#endif #endif
} }
inline uintptr_t regof(regs reg, hook_stack *stack)
inline uintptr_t regof(regs reg,hook_stack* stack){ {
switch (reg) switch (reg)
{ {
#ifndef _WIN64 #ifndef _WIN64
case regs::eax:return stack->eax; case regs::eax:
case regs::ecx:return stack->ecx; return stack->eax;
case regs::edx:return stack->edx; case regs::ecx:
case regs::ebx:return stack->ebx; return stack->ecx;
case regs::esp:return stack->esp; case regs::edx:
case regs::ebp:return stack->ebp; return stack->edx;
case regs::esi:return stack->esi; case regs::ebx:
case regs::edi:return stack->edi; return stack->ebx;
case regs::esp:
return stack->esp;
case regs::ebp:
return stack->ebp;
case regs::esi:
return stack->esi;
case regs::edi:
return stack->edi;
#else #else
case regs::rax:return stack->rax; case regs::rax:
case regs::rbx:return stack->rbx; return stack->rax;
case regs::rcx:return stack->rcx; case regs::rbx:
case regs::rdx:return stack->rdx; return stack->rbx;
case regs::rsp:return stack->rsp; case regs::rcx:
case regs::rbp:return stack->rbp; return stack->rcx;
case regs::rsi:return stack->rsi; case regs::rdx:
case regs::rdi:return stack->rdi; return stack->rdx;
case regs::r8:return stack->r8; case regs::rsp:
case regs::r9:return stack->r9; return stack->rsp;
case regs::r10:return stack->r10; case regs::rbp:
case regs::r11:return stack->r11; return stack->rbp;
case regs::r12:return stack->r12; case regs::rsi:
case regs::r13:return stack->r13; return stack->rsi;
case regs::r14:return stack->r14; case regs::rdi:
case regs::r15:return stack->r15; return stack->rdi;
case regs::r8:
return stack->r8;
case regs::r9:
return stack->r9;
case regs::r10:
return stack->r10;
case regs::r11:
return stack->r11;
case regs::r12:
return stack->r12;
case regs::r13:
return stack->r13;
case regs::r14:
return stack->r14;
case regs::r15:
return stack->r15;
#endif #endif
} }
return 0; return 0;
@ -110,17 +136,26 @@ inline uintptr_t regof(regs reg,hook_stack* stack){
#endif #endif
inline uintptr_t *argidx(hook_stack *stack, int idx)
inline uintptr_t *argidx(hook_stack* stack,int idx){ {
#ifdef _WIN64 #ifdef _WIN64
auto offset = 0; auto offset = 0;
switch (idx) switch (idx)
{ {
case 1:offset=get_reg(regs::rcx);break; case 1:
case 2:offset=get_reg(regs::rdx);break; offset = get_reg(regs::rcx);
case 3:offset=get_reg(regs::r8);break; break;
case 4:offset=get_reg(regs::r9);break; case 2:
default:offset=get_stack(idx); offset = get_reg(regs::rdx);
break;
case 3:
offset = get_reg(regs::r8);
break;
case 4:
offset = get_reg(regs::r9);
break;
default:
offset = get_stack(idx);
} }
return (uintptr_t *)((uintptr_t)stack + sizeof(hook_stack) - sizeof(uintptr_t) + offset); return (uintptr_t *)((uintptr_t)stack + sizeof(hook_stack) - sizeof(uintptr_t) + offset);
#else #else

View File

@ -4,7 +4,8 @@ extern WinMutex viewMutex;
// - Unnamed helpers - // - Unnamed helpers -
namespace { // unnamed namespace
{ // unnamed
#ifndef _WIN64 #ifndef _WIN64
BYTE common_hook[] = { BYTE common_hook[] = {
0x9c, // pushfd 0x9c, // pushfd
@ -85,19 +86,24 @@ namespace { // unnamed
// - TextHook methods - // - TextHook methods -
uintptr_t getasbaddr(const HookParam &hp){ uintptr_t getasbaddr(const HookParam &hp)
{
auto address = hp.address; auto address = hp.address;
if (hp.type & MODULE_OFFSET) if (hp.type & MODULE_OFFSET)
{ {
if (hp.type & FUNCTION_OFFSET) if (hp.type & FUNCTION_OFFSET)
{ {
if (FARPROC function = GetProcAddress(GetModuleHandleW(hp.module), hp.function)) address += (uint64_t)function; if (FARPROC function = GetProcAddress(GetModuleHandleW(hp.module), hp.function))
else return ConsoleOutput(FUNC_MISSING), 0; address += (uint64_t)function;
else
return ConsoleOutput(FUNC_MISSING), 0;
} }
else else
{ {
if (HMODULE moduleBase = GetModuleHandleW(hp.module)) address += (uint64_t)moduleBase; if (HMODULE moduleBase = GetModuleHandleW(hp.module))
else return ConsoleOutput(MODULE_MISSING), 0; address += (uint64_t)moduleBase;
else
return ConsoleOutput(MODULE_MISSING), 0;
} }
} }
return address; return address;
@ -106,7 +112,8 @@ bool TextHook::Insert(HookParam hp)
{ {
auto addr = getasbaddr(hp); auto addr = getasbaddr(hp);
if(!addr)return false; if (!addr)
return false;
RemoveHook(addr, 0); RemoveHook(addr, 0);
ConsoleOutput(INSERTING_HOOK, hp.name, addr); ConsoleOutput(INSERTING_HOOK, hp.name, addr);
@ -117,38 +124,49 @@ bool TextHook::Insert(HookParam hp)
address = addr; address = addr;
} }
savetypeforremove = hp.type; savetypeforremove = hp.type;
if (hp.type & DIRECT_READ) return InsertReadCode(); if (hp.type & DIRECT_READ)
if (hp.type & BREAK_POINT) return InsertBreakPoint(); return InsertReadCode();
if (hp.type & BREAK_POINT)
return InsertBreakPoint();
return InsertHookCode(); return InsertHookCode();
} }
uintptr_t win64find0000(uintptr_t addr){ uintptr_t win64find0000(uintptr_t addr)
{
uintptr_t r = 0; uintptr_t r = 0;
__try{ __try
{
addr &= ~0xf; addr &= ~0xf;
for (uintptr_t i = addr, j = addr - 0x10000; i > j; i-=0x10) { for (uintptr_t i = addr, j = addr - 0x10000; i > j; i -= 0x10)
{
DWORD k = *(DWORD *)(i - 4); DWORD k = *(DWORD *)(i - 4);
if (k == 0x00000000 if (k == 0x00000000)
)
return i; return i;
} }
return 0; return 0;
}__except(EXCEPTION_EXECUTE_HANDLER) {} }
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
return r; return r;
} }
Synchronized<std::unordered_map<uintptr_t, uintptr_t>> retaddr2relative; // 很奇怪这个放到函数里用static在xp上会报错。 Synchronized<std::unordered_map<uintptr_t, uintptr_t>> retaddr2relative; // 很奇怪这个放到函数里用static在xp上会报错。
uintptr_t queryrelativeret(HookParam&hp, uintptr_t retaddr){ uintptr_t queryrelativeret(HookParam &hp, uintptr_t retaddr)
{
// 不需要区分是相对于哪个module的偏移只需要得到偏移就可以了用来确保重启程序后ret值恒定 // 不需要区分是相对于哪个module的偏移只需要得到偏移就可以了用来确保重启程序后ret值恒定
auto &re = retaddr2relative.Acquire().contents; auto &re = retaddr2relative.Acquire().contents;
if(re.find(retaddr)!=re.end())return re.at(retaddr); if (re.find(retaddr) != re.end())
return re.at(retaddr);
uintptr_t relative = retaddr; uintptr_t relative = retaddr;
if(hp.jittype==JITTYPE::UNITY){ if (hp.jittype == JITTYPE::UNITY)
{
#ifndef _WIN64 #ifndef _WIN64
relative = retaddr - SafeFindEnclosingAlignedFunction(retaddr, 0x10000); relative = retaddr - SafeFindEnclosingAlignedFunction(retaddr, 0x10000);
#else #else
relative = retaddr - win64find0000(retaddr); relative = retaddr - win64find0000(retaddr);
#endif #endif
} }
else{ else
{
if (MEMORY_BASIC_INFORMATION info = {}; VirtualQuery((LPCVOID)retaddr, &info, sizeof(info))) if (MEMORY_BASIC_INFORMATION info = {}; VirtualQuery((LPCVOID)retaddr, &info, sizeof(info)))
relative -= (uintptr_t)info.AllocationBase; relative -= (uintptr_t)info.AllocationBase;
} }
@ -156,7 +174,8 @@ uintptr_t queryrelativeret(HookParam&hp, uintptr_t retaddr){
return relative; return relative;
} }
uintptr_t jitgetaddr(hook_stack* stack, HookParam* hp){ uintptr_t jitgetaddr(hook_stack *stack, HookParam *hp)
{
switch (hp->jittype) switch (hp->jittype)
{ {
#ifdef _WIN64 #ifdef _WIN64
@ -173,7 +192,8 @@ uintptr_t jitgetaddr(hook_stack* stack, HookParam* hp){
return 0; return 0;
} }
} }
bool checklengthembedable(const HookParam&hp,size_t size){ bool checklengthembedable(const HookParam &hp, size_t size)
{
size_t len; size_t len;
if (hp.type & CODEC_UTF16) if (hp.type & CODEC_UTF16)
len = 2; len = 2;
@ -185,13 +205,19 @@ bool checklengthembedable(const HookParam&hp,size_t size){
} }
return size > len; return size > len;
} }
bool commonfilter(void* data, size_t* len, HookParam* hp){ bool commonfilter(void *data, size_t *len, HookParam *hp)
{
if(hp->type & CODEC_UTF16); if (hp->type & CODEC_UTF16)
else if(hp->type & CODEC_UTF32); ;
else if(hp->type & CODEC_UTF8); else if (hp->type & CODEC_UTF32)
else{ ;
if(*len==2){ else if (hp->type & CODEC_UTF8)
;
else
{
if (*len == 2)
{
StringFilter((char *)data, len, "\x81\xa4", 2); StringFilter((char *)data, len, "\x81\xa4", 2);
StringFilter((char *)data, len, "\x81\xa5", 2); StringFilter((char *)data, len, "\x81\xa5", 2);
} }
@ -208,9 +234,11 @@ void TextHook::Send(uintptr_t lpDataBase)
auto stack = get_hook_stack(lpDataBase); auto stack = get_hook_stack(lpDataBase);
if (auto current_trigger_fun = trigger_fun.exchange(nullptr)) if (auto current_trigger_fun = trigger_fun.exchange(nullptr))
if (!current_trigger_fun(location, stack)) trigger_fun = current_trigger_fun; if (!current_trigger_fun(location, stack))
trigger_fun = current_trigger_fun;
if(hp.type&HOOK_RETURN){ if (hp.type & HOOK_RETURN)
{
hp.type &= ~HOOK_RETURN; hp.type &= ~HOOK_RETURN;
hp.address = stack->retaddr; hp.address = stack->retaddr;
strcat(hp.name, "_Return"); strcat(hp.name, "_Return");
@ -227,7 +255,8 @@ void TextHook::Send(uintptr_t lpDataBase)
hp.type |= HOOK_EMPTY; hp.type |= HOOK_EMPTY;
__leave; __leave;
} }
if (hp.type & HOOK_EMPTY) __leave; // jichi 10/24/2014: dummy hook only for dynamic hook if (hp.type & HOOK_EMPTY)
__leave; // jichi 10/24/2014: dummy hook only for dynamic hook
size_t lpCount = 0; size_t lpCount = 0;
uintptr_t lpSplit = 0, uintptr_t lpSplit = 0,
@ -240,7 +269,8 @@ void TextHook::Send(uintptr_t lpDataBase)
lpDataIn = jitgetaddr(stack, &hp); lpDataIn = jitgetaddr(stack, &hp);
plpdatain = (uintptr_t)&lpDataIn; plpdatain = (uintptr_t)&lpDataIn;
} }
else if(hp.jittype==JITTYPE::UNITY){ else if (hp.jittype == JITTYPE::UNITY)
{
plpdatain = (uintptr_t)argidx(stack, hp.argidx); plpdatain = (uintptr_t)argidx(stack, hp.argidx);
lpDataIn = *(uintptr_t *)plpdatain; lpDataIn = *(uintptr_t *)plpdatain;
} }
@ -249,8 +279,10 @@ void TextHook::Send(uintptr_t lpDataBase)
if (use_custom_embed_fun) if (use_custom_embed_fun)
{ {
isstring = true; isstring = true;
lpSplit=Engine::ScenarioRole;lpRetn=0; lpSplit = Engine::ScenarioRole;
if(hp.hook_before(stack,pbData,&lpCount,&lpSplit)==false)__leave; lpRetn = 0;
if (hp.hook_before(stack, pbData, &lpCount, &lpSplit) == false)
__leave;
} }
else if (hp.text_fun) else if (hp.text_fun)
{ {
@ -264,12 +296,16 @@ void TextHook::Send(uintptr_t lpDataBase)
} }
else else
{ {
if (hp.type & FIXING_SPLIT) lpSplit = FIXED_SPLIT_VALUE; // fuse all threads, and prevent floating if (hp.type & FIXING_SPLIT)
else if (hp.type & USING_SPLIT) { lpSplit = FIXED_SPLIT_VALUE; // fuse all threads, and prevent floating
else if (hp.type & USING_SPLIT)
{
lpSplit = *(uintptr_t *)(lpDataBase + hp.split); lpSplit = *(uintptr_t *)(lpDataBase + hp.split);
if (hp.type & SPLIT_INDIRECT) lpSplit = *(uintptr_t *)(lpSplit + hp.split_index); if (hp.type & SPLIT_INDIRECT)
lpSplit = *(uintptr_t *)(lpSplit + hp.split_index);
} }
if (hp.type & DATA_INDIRECT) { if (hp.type & DATA_INDIRECT)
{
plpdatain = (lpDataIn + hp.index); plpdatain = (lpDataIn + hp.index);
lpDataIn = *(uintptr_t *)plpdatain; lpDataIn = *(uintptr_t *)plpdatain;
} }
@ -277,8 +313,8 @@ void TextHook::Send(uintptr_t lpDataBase)
lpCount = GetLength(stack, lpDataIn); lpCount = GetLength(stack, lpDataIn);
} }
if (lpCount <= 0)
if (lpCount <= 0) __leave; __leave;
if (lpCount > TEXT_BUFFER_SIZE) if (lpCount > TEXT_BUFFER_SIZE)
{ {
ConsoleOutput(InvalidLength, lpCount, hp.name); ConsoleOutput(InvalidLength, lpCount, hp.name);
@ -289,7 +325,8 @@ void TextHook::Send(uintptr_t lpDataBase)
{ {
if ((!(hp.type & USING_CHAR)) && (isstring || (hp.type & USING_STRING))) if ((!(hp.type & USING_CHAR)) && (isstring || (hp.type & USING_STRING)))
{ {
if(lpDataIn == 0)__leave; if (lpDataIn == 0)
__leave;
::memcpy(pbData, (void *)lpDataIn, lpCount); ::memcpy(pbData, (void *)lpDataIn, lpCount);
} }
else else
@ -301,16 +338,21 @@ void TextHook::Send(uintptr_t lpDataBase)
else else
{ // CHAR_LITTEL_ENDIAN,CODEC_ANSI_BE,CODEC_UTF16 { // CHAR_LITTEL_ENDIAN,CODEC_ANSI_BE,CODEC_UTF16
lpDataIn &= 0xffff; lpDataIn &= 0xffff;
if ((hp.type & CODEC_ANSI_BE) && (lpDataIn >> 8)) lpDataIn = _byteswap_ushort(lpDataIn & 0xffff); if ((hp.type & CODEC_ANSI_BE) && (lpDataIn >> 8))
if (lpCount == 1) lpDataIn &= 0xff; lpDataIn = _byteswap_ushort(lpDataIn & 0xffff);
if (lpCount == 1)
lpDataIn &= 0xff;
*(WORD *)pbData = lpDataIn & 0xffff; *(WORD *)pbData = lpDataIn & 0xffff;
} }
} }
} }
if(!commonfilter(pbData, &lpCount, &hp) ||lpCount <= 0) __leave; if (!commonfilter(pbData, &lpCount, &hp) || lpCount <= 0)
if (hp.filter_fun && !hp.filter_fun(pbData, &lpCount, &hp) || lpCount <= 0) __leave; __leave;
if (hp.filter_fun && !hp.filter_fun(pbData, &lpCount, &hp) || lpCount <= 0)
__leave;
if (hp.type & (NO_CONTEXT | FIXING_SPLIT)) lpRetn = 0; if (hp.type & (NO_CONTEXT | FIXING_SPLIT))
lpRetn = 0;
buffer->type = hp.type; buffer->type = hp.type;
@ -319,17 +361,22 @@ void TextHook::Send(uintptr_t lpDataBase)
parsenewlineseperator(pbData, &lpCount); parsenewlineseperator(pbData, &lpCount);
bool canembed;; bool canembed;
if(hp.type&EMBED_ABLE){ ;
if(!checklengthembedable(hp,lpCount)){ if (hp.type & EMBED_ABLE)
{
if (!checklengthembedable(hp, lpCount))
{
buffer->type &= (~EMBED_ABLE); buffer->type &= (~EMBED_ABLE);
canembed = false; canembed = false;
} }
else if(checktranslatedok(pbData,lpCount)){ else if (checktranslatedok(pbData, lpCount))
{
buffer->type &= (~EMBED_ABLE); buffer->type &= (~EMBED_ABLE);
canembed = true; canembed = true;
} }
else{ else
{
canembed = true; canembed = true;
} }
} }
@ -357,7 +404,8 @@ void TextHook::Send(uintptr_t lpDataBase)
} }
else if (hp.hook_after) else if (hp.hook_after)
hp.hook_after(stack, pbData, lpCount); hp.hook_after(stack, pbData, lpCount);
else if(hp.type&SPECIAL_JIT_STRING){ else if (hp.type & SPECIAL_JIT_STRING)
{
if (hp.jittype == JITTYPE::UNITY) if (hp.jittype == JITTYPE::UNITY)
unity_ui_string_hook_after(argidx(stack, hp.argidx), pbData, lpCount); unity_ui_string_hook_after(argidx(stack, hp.argidx), pbData, lpCount);
} }
@ -375,7 +423,8 @@ void TextHook::Send(uintptr_t lpDataBase)
_InterlockedDecrement((long *)&useCount); _InterlockedDecrement((long *)&useCount);
} }
bool TextHook::breakpointcontext(PCONTEXT context){ bool TextHook::breakpointcontext(PCONTEXT context)
{
auto stack = std::make_unique<hook_stack>(); auto stack = std::make_unique<hook_stack>();
context_get(stack.get(), context); context_get(stack.get(), context);
auto lpDataBase = stack->get_base(); auto lpDataBase = stack->get_base();
@ -395,13 +444,14 @@ bool TextHook::RemoveBreakPoint()
bool TextHook::InsertHookCode() bool TextHook::InsertHookCode()
{ {
VirtualProtect(location, 10, PAGE_EXECUTE_READWRITE, DUMMY); VirtualProtect(location, 10, PAGE_EXECUTE_READWRITE, DUMMY);
void *original; void *original;
MH_STATUS error; MH_STATUS error;
while ((error = MH_CreateHook(location, trampoline, &original)) != MH_OK) while ((error = MH_CreateHook(location, trampoline, &original)) != MH_OK)
if (error == MH_ERROR_ALREADY_CREATED) RemoveHook(address); if (error == MH_ERROR_ALREADY_CREATED)
else return ConsoleOutput(MH_StatusToString(error)), false; RemoveHook(address);
else
return ConsoleOutput(MH_StatusToString(error)), false;
*(TextHook **)(common_hook + this_offset) = this; *(TextHook **)(common_hook + this_offset) = this;
*(void(TextHook::**)(uintptr_t))(common_hook + send_offset) = &TextHook::Send; *(void(TextHook::**)(uintptr_t))(common_hook + send_offset) = &TextHook::Send;
@ -429,20 +479,21 @@ void TextHook::Read()
{ {
while (WaitForSingleObject(readerEvent, 500) == WAIT_TIMEOUT) while (WaitForSingleObject(readerEvent, 500) == WAIT_TIMEOUT)
{ {
if(!location)continue; if (!location)
continue;
int currentLen = HookStrlen((BYTE *)location); int currentLen = HookStrlen((BYTE *)location);
bool changed = memcmp(pbData, location, dataLen) != 0; bool changed = memcmp(pbData, location, dataLen) != 0;
if (changed || (currentLen != dataLen)) if (changed || (currentLen != dataLen))
{ {
dataLen = min(currentLen, TEXT_BUFFER_SIZE); dataLen = min(currentLen, TEXT_BUFFER_SIZE);
memcpy(pbData, location, dataLen); memcpy(pbData, location, dataLen);
if (hp.filter_fun && !hp.filter_fun(pbData, &dataLen, &hp) || dataLen <= 0) continue; if (hp.filter_fun && !hp.filter_fun(pbData, &dataLen, &hp) || dataLen <= 0)
continue;
TextOutput({GetCurrentProcessId(), address, 0, 0}, hp, buffer, dataLen); TextOutput({GetCurrentProcessId(), address, 0, 0}, hp, buffer, dataLen);
memcpy(pbData, location, dataLen); memcpy(pbData, location, dataLen);
} }
} }
} }
} }
__except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
@ -453,7 +504,8 @@ void TextHook::Read()
bool TextHook::InsertReadCode() bool TextHook::InsertReadCode()
{ {
readerThread = CreateThread(nullptr, 0, [](void* This) { ((TextHook*)This)->Read(); return 0UL; }, this, 0, nullptr); readerThread = CreateThread(nullptr, 0, [](void *This)
{ ((TextHook*)This)->Read(); return 0UL; }, this, 0, nullptr);
readerEvent = CreateEventW(nullptr, FALSE, FALSE, NULL); readerEvent = CreateEventW(nullptr, FALSE, FALSE, NULL);
return true; return true;
} }
@ -461,29 +513,36 @@ bool TextHook::InsertReadCode()
void TextHook::RemoveHookCode() void TextHook::RemoveHookCode()
{ {
MH_DisableHook(location); MH_DisableHook(location);
while (useCount != 0); while (useCount != 0)
;
MH_RemoveHook(location); MH_RemoveHook(location);
} }
void TextHook::RemoveReadCode() void TextHook::RemoveReadCode()
{ {
SetEvent(readerEvent); SetEvent(readerEvent);
if (GetThreadId(readerThread) != GetCurrentThreadId()) WaitForSingleObject(readerThread, 1000); if (GetThreadId(readerThread) != GetCurrentThreadId())
WaitForSingleObject(readerThread, 1000);
CloseHandle(readerEvent); CloseHandle(readerEvent);
CloseHandle(readerThread); CloseHandle(readerThread);
} }
void TextHook::Clear() void TextHook::Clear()
{ {
if (address == 0) return; if (address == 0)
if (savetypeforremove & DIRECT_READ) RemoveReadCode(); return;
else if (savetypeforremove & BREAK_POINT) RemoveBreakPoint(); if (savetypeforremove & DIRECT_READ)
else RemoveHookCode(); RemoveReadCode();
else if (savetypeforremove & BREAK_POINT)
RemoveBreakPoint();
else
RemoveHookCode();
NotifyHookRemove(address, hp.name); NotifyHookRemove(address, hp.name);
std::scoped_lock lock(viewMutex); std::scoped_lock lock(viewMutex);
memset(&hp, 0, sizeof(HookParam)); memset(&hp, 0, sizeof(HookParam));
address = 0; address = 0;
if(local_buffer)delete []local_buffer; if (local_buffer)
delete[] local_buffer;
} }
int TextHook::GetLength(hook_stack *stack, uintptr_t in) int TextHook::GetLength(hook_stack *stack, uintptr_t in)
@ -500,11 +559,9 @@ int TextHook::GetLength(hook_stack* stack, uintptr_t in)
len <<= 1; len <<= 1;
else if (hp.type & CODEC_UTF32) else if (hp.type & CODEC_UTF32)
len <<= 2; len <<= 2;
} }
else if (len != -1) else if (len != -1)
{ {
} }
else else
{ // len==-1 { // len==-1

View File

@ -15,12 +15,16 @@ bool add_veh_hook(void* origFunc, newFuncType newFunc, DWORD hook_type)
std::lock_guard _(vehlistlock); std::lock_guard _(vehlistlock);
// static veh_list_t* list = NULL; // static veh_list_t* list = NULL;
DWORD oldProtect; DWORD oldProtect;
if (list == NULL) list = new_veh_list(); if (list == NULL)
if (list == NULL) return false; list = new_veh_list();
if(get_veh_node(list,origFunc))return false; if (list == NULL)
return false;
if (get_veh_node(list, origFunc))
return false;
void *handle = AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)veh_dispatch); void *handle = AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)veh_dispatch);
auto newnode = create_veh_node(origFunc, newFunc, handle, hook_type); auto newnode = create_veh_node(origFunc, newFunc, handle, hook_type);
if(newnode==NULL)return false; if (newnode == NULL)
return false;
// For memory hooks especially, we need to know the address of the start of the relevant page. // For memory hooks especially, we need to know the address of the start of the relevant page.
MEMORY_BASIC_INFORMATION mem_info; MEMORY_BASIC_INFORMATION mem_info;
VirtualQuery(origFunc, &mem_info, sizeof(MEMORY_BASIC_INFORMATION)); VirtualQuery(origFunc, &mem_info, sizeof(MEMORY_BASIC_INFORMATION));
@ -36,7 +40,8 @@ bool add_veh_hook(void* origFunc, newFuncType newFunc, DWORD hook_type)
insert_veh_node(list, newnode); insert_veh_node(list, newnode);
return true; return true;
} }
void repair_origin(veh_node_t *node){ void repair_origin(veh_node_t *node)
{
DWORD _p; DWORD _p;
if (!VirtualProtect(node->origFunc, sizeof(int), PAGE_EXECUTE_READWRITE, &_p)) if (!VirtualProtect(node->origFunc, sizeof(int), PAGE_EXECUTE_READWRITE, &_p))
return; return;
@ -46,9 +51,11 @@ void repair_origin(veh_node_t *node){
bool remove_veh_hook(void *origFunc) bool remove_veh_hook(void *origFunc)
{ {
std::lock_guard _(vehlistlock); std::lock_guard _(vehlistlock);
if (list == NULL) return false; if (list == NULL)
return false;
veh_node_t *node = get_veh_node(list, origFunc); veh_node_t *node = get_veh_node(list, origFunc);
if (node == NULL) return false; if (node == NULL)
return false;
repair_origin(node); repair_origin(node);
RemoveVectoredExceptionHandler(node->handle); RemoveVectoredExceptionHandler(node->handle);
return remove_veh_node(list, origFunc), true; return remove_veh_node(list, origFunc), true;
@ -85,7 +92,8 @@ LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo)
void *Addr = ExceptionInfo->ExceptionRecord->ExceptionAddress; void *Addr = ExceptionInfo->ExceptionRecord->ExceptionAddress;
ULONG Code = ExceptionInfo->ExceptionRecord->ExceptionCode; ULONG Code = ExceptionInfo->ExceptionRecord->ExceptionCode;
if (Code != STATUS_BREAKPOINT && Code != STATUS_SINGLE_STEP) return EXCEPTION_CONTINUE_SEARCH; if (Code != STATUS_BREAKPOINT && Code != STATUS_SINGLE_STEP)
return EXCEPTION_CONTINUE_SEARCH;
// Try to find the node associated with the address of the current exception, continue searching for handlers if not found; // Try to find the node associated with the address of the current exception, continue searching for handlers if not found;
if (Code == STATUS_BREAKPOINT) //&& hooktype == VEH_HK_INT3) if (Code == STATUS_BREAKPOINT) //&& hooktype == VEH_HK_INT3)
@ -95,7 +103,8 @@ LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo)
std::lock_guard _(vehlistlock); std::lock_guard _(vehlistlock);
currnode = get_veh_node(list, Addr); currnode = get_veh_node(list, Addr);
} }
if (currnode == NULL) return EXCEPTION_CONTINUE_SEARCH; if (currnode == NULL)
return EXCEPTION_CONTINUE_SEARCH;
if (currnode->newFunc(ExceptionInfo->ContextRecord)) if (currnode->newFunc(ExceptionInfo->ContextRecord))
{ {
@ -111,13 +120,13 @@ LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo)
{ {
std::lock_guard _(vehlistlock); std::lock_guard _(vehlistlock);
veh_node_t *currnode = get_veh_node(list, Addr, 0x10); veh_node_t *currnode = get_veh_node(list, Addr, 0x10);
if (currnode == NULL) return EXCEPTION_CONTINUE_SEARCH; if (currnode == NULL)
return EXCEPTION_CONTINUE_SEARCH;
VirtualProtect(Addr, sizeof(int), PAGE_EXECUTE_READWRITE, &currnode->OldProtect); VirtualProtect(Addr, sizeof(int), PAGE_EXECUTE_READWRITE, &currnode->OldProtect);
memcpy((void *)currnode->origFunc, (const void *)&int3bp, sizeof(BYTE)); memcpy((void *)currnode->origFunc, (const void *)&int3bp, sizeof(BYTE));
VirtualProtect(Addr, sizeof(int), currnode->OldProtect, &oldProtect); VirtualProtect(Addr, sizeof(int), currnode->OldProtect, &oldProtect);
ExceptionInfo->ContextRecord->EFlags &= ~0x00000100; // Remove TRACE from EFLAGS ExceptionInfo->ContextRecord->EFlags &= ~0x00000100; // Remove TRACE from EFLAGS
} }
// else if (Code == STATUS_SINGLE_STEP && hooktype == VEH_HK_HW) // else if (Code == STATUS_SINGLE_STEP && hooktype == VEH_HK_HW)
// { // {
@ -134,7 +143,8 @@ LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo)
veh_list_t *new_veh_list() veh_list_t *new_veh_list()
{ {
veh_list_t *newlist = (veh_list_t *)malloc(sizeof(veh_list_t)); veh_list_t *newlist = (veh_list_t *)malloc(sizeof(veh_list_t));
if (newlist == NULL) return NULL; if (newlist == NULL)
return NULL;
newlist->head = NULL; newlist->head = NULL;
newlist->tail = NULL; newlist->tail = NULL;
return newlist; return newlist;
@ -142,7 +152,8 @@ veh_list_t* new_veh_list()
veh_node_t *create_veh_node(void *origFunc, newFuncType newFunc, void *handle, DWORD hook_type) veh_node_t *create_veh_node(void *origFunc, newFuncType newFunc, void *handle, DWORD hook_type)
{ {
veh_node_t *newnode = new veh_node_t; veh_node_t *newnode = new veh_node_t;
if (newnode == NULL) return NULL; if (newnode == NULL)
return NULL;
newnode->last = NULL; newnode->last = NULL;
newnode->origFunc = origFunc; newnode->origFunc = origFunc;
newnode->newFunc = newFunc; newnode->newFunc = newFunc;
@ -154,7 +165,8 @@ veh_node_t* create_veh_node(void* origFunc, newFuncType newFunc, void* handle, D
} }
void insert_veh_node(veh_list_t *list, veh_node_t *newnode) void insert_veh_node(veh_list_t *list, veh_node_t *newnode)
{ {
if (list == NULL) return; if (list == NULL)
return;
if (list->head == NULL) if (list->head == NULL)
{ {
list->head = newnode; list->head = newnode;
@ -171,14 +183,16 @@ veh_node_t* get_veh_node(veh_list_t* list, void* origFunc, int range)
{ {
veh_node_t *newnode; veh_node_t *newnode;
veh_node_t *closestnode = NULL; veh_node_t *closestnode = NULL;
if (list == NULL) return NULL; if (list == NULL)
return NULL;
newnode = list->head; newnode = list->head;
while (newnode != NULL) while (newnode != NULL)
{ {
if (((uintptr_t)origFunc - (uintptr_t)newnode->origFunc) <= range) if (((uintptr_t)origFunc - (uintptr_t)newnode->origFunc) <= range)
{ {
closestnode = newnode; closestnode = newnode;
if(range==0)break; if (range == 0)
break;
range = ((uintptr_t)origFunc - (uintptr_t)newnode->origFunc); range = ((uintptr_t)origFunc - (uintptr_t)newnode->origFunc);
} }
newnode = newnode->next; newnode = newnode->next;

View File

@ -17,7 +17,6 @@ Version: 24-March-2008
#define OPCODE_INT3 "\xCC" #define OPCODE_INT3 "\xCC"
// typedef void (*pfvoid)(); // typedef void (*pfvoid)();
// typedef void (*newFuncType)(PCONTEXT); // typedef void (*newFuncType)(PCONTEXT);
using newFuncType = std::function<bool(PCONTEXT)>; using newFuncType = std::function<bool(PCONTEXT)>;