mirror of
https://github.com/Artikash/Textractor.git
synced 2024-12-23 17:04:12 +08:00
refactor. less global variables
This commit is contained in:
parent
f351148b3d
commit
d0f48a67a4
@ -5,7 +5,7 @@
|
|||||||
#include "host.h"
|
#include "host.h"
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "../vnrhook/hijack/texthook.h"
|
#include "../vnrhook/texthook.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -51,7 +51,7 @@ namespace
|
|||||||
|
|
||||||
std::recursive_mutex hostMutex;
|
std::recursive_mutex hostMutex;
|
||||||
|
|
||||||
DWORD DUMMY[1];
|
DWORD DUMMY;
|
||||||
ThreadParam CONSOLE{ 0, -1ULL, -1ULL, -1ULL }, CLIPBOARD{ 0, 0, -1ULL, -1ULL };
|
ThreadParam CONSOLE{ 0, -1ULL, -1ULL, -1ULL }, CLIPBOARD{ 0, 0, -1ULL, -1ULL };
|
||||||
|
|
||||||
void DispatchText(ThreadParam tp, const BYTE* text, int len)
|
void DispatchText(ThreadParam tp, const BYTE* text, int len)
|
||||||
@ -111,7 +111,7 @@ namespace
|
|||||||
CreatePipe();
|
CreatePipe();
|
||||||
|
|
||||||
while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
|
while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
|
||||||
switch (*(int*)buffer)
|
switch (*(HostNotificationType*)buffer)
|
||||||
{
|
{
|
||||||
case HOST_NOTIFICATION_RMVHOOK:
|
case HOST_NOTIFICATION_RMVHOOK:
|
||||||
{
|
{
|
||||||
@ -242,22 +242,22 @@ namespace Host
|
|||||||
void DetachProcess(DWORD processId)
|
void DetachProcess(DWORD processId)
|
||||||
{
|
{
|
||||||
LOCK(hostMutex);
|
LOCK(hostMutex);
|
||||||
auto command = HOST_COMMAND_DETACH;
|
HostCommandType buffer(HOST_COMMAND_DETACH);
|
||||||
WriteFile(processRecordsByIds.at(processId)->hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
WriteFile(processRecordsByIds.at(processId)->hostPipe, &buffer, sizeof(buffer), &DUMMY, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertHook(DWORD processId, HookParam hp, std::string name)
|
void InsertHook(DWORD processId, HookParam hp, std::string name)
|
||||||
{
|
{
|
||||||
LOCK(hostMutex);
|
LOCK(hostMutex);
|
||||||
auto command = InsertHookCmd(hp, name);
|
InsertHookCmd buffer(hp, name);
|
||||||
WriteFile(processRecordsByIds.at(processId)->hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
WriteFile(processRecordsByIds.at(processId)->hostPipe, &buffer, sizeof(buffer), &DUMMY, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveHook(DWORD processId, uint64_t addr)
|
void RemoveHook(DWORD processId, uint64_t addr)
|
||||||
{
|
{
|
||||||
LOCK(hostMutex);
|
LOCK(hostMutex);
|
||||||
auto command = RemoveHookCmd(addr);
|
RemoveHookCmd buffer(addr);
|
||||||
WriteFile(processRecordsByIds.at(processId)->hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
WriteFile(processRecordsByIds.at(processId)->hostPipe, &buffer, sizeof(buffer), &DUMMY, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
HookParam GetHookParam(DWORD processId, uint64_t addr)
|
HookParam GetHookParam(DWORD processId, uint64_t addr)
|
||||||
|
@ -3,18 +3,16 @@ include_directories(. util)
|
|||||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||||
set(vnrhook_src
|
set(vnrhook_src
|
||||||
main.cc
|
main.cc
|
||||||
pipe.cc
|
texthook.cc
|
||||||
util/ithsys/ithsys.cc
|
util/ithsys/ithsys.cc
|
||||||
hijack/texthook.cc
|
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
set(vnrhook_src
|
set(vnrhook_src
|
||||||
main.cc
|
main.cc
|
||||||
pipe.cc
|
texthook.cc
|
||||||
engine/engine.cc
|
engine/engine.cc
|
||||||
engine/match.cc
|
engine/match.cc
|
||||||
engine/native/pchooks.cc
|
engine/native/pchooks.cc
|
||||||
hijack/texthook.cc
|
|
||||||
util/util.cc
|
util/util.cc
|
||||||
util/ithsys/ithsys.cc
|
util/ithsys/ithsys.cc
|
||||||
util/disasm/disasm.cc
|
util/disasm/disasm.cc
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "engine/match.h"
|
#include "engine/match.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "texthook.h"
|
||||||
#include "engine/mono/funcinfo.h"
|
#include "engine/mono/funcinfo.h"
|
||||||
#include "engine/ppsspp/funcinfo.h"
|
#include "engine/ppsspp/funcinfo.h"
|
||||||
#include "ithsys/ithsys.h"
|
#include "ithsys/ithsys.h"
|
||||||
@ -2232,7 +2233,7 @@ void InsertRealliveHook()
|
|||||||
//ConsoleOutput("Probably Reallive. Wait for text.");
|
//ConsoleOutput("Probably Reallive. Wait for text.");
|
||||||
ConsoleOutput("vnreng: TRIGGER Reallive");
|
ConsoleOutput("vnreng: TRIGGER Reallive");
|
||||||
trigger_fun_ = InsertRealliveDynamicHook;
|
trigger_fun_ = InsertRealliveDynamicHook;
|
||||||
SwitchTrigger(true);
|
SetTrigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace { // unnamed
|
namespace { // unnamed
|
||||||
@ -5766,7 +5767,8 @@ int GetShinaRioVersion()
|
|||||||
//char *buffer,*version;//,*ptr;
|
//char *buffer,*version;//,*ptr;
|
||||||
enum { BufferSize = 0x40 };
|
enum { BufferSize = 0x40 };
|
||||||
char buffer[BufferSize];
|
char buffer[BufferSize];
|
||||||
ReadFile(hFile, buffer, BufferSize, (DWORD*)buffer, nullptr);
|
DWORD DUMMY;
|
||||||
|
ReadFile(hFile, buffer, BufferSize, &DUMMY, nullptr);
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
if (buffer[0] == '[') {
|
if (buffer[0] == '[') {
|
||||||
buffer[0x3f] = 0; // jichi 8/24/2013: prevent strstr from overflow
|
buffer[0x3f] = 0; // jichi 8/24/2013: prevent strstr from overflow
|
||||||
@ -5785,7 +5787,7 @@ bool InsertShinaHook()
|
|||||||
{
|
{
|
||||||
int ver = GetShinaRioVersion();
|
int ver = GetShinaRioVersion();
|
||||||
if (ver >= 50) {
|
if (ver >= 50) {
|
||||||
SwitchTrigger(true);
|
SetTrigger();
|
||||||
trigger_fun_ = StackSearchingTrigger<GetGlyphOutlineA, NULL>;
|
trigger_fun_ = StackSearchingTrigger<GetGlyphOutlineA, NULL>;
|
||||||
ConsoleOutput("Textractor: ShinaRio 2.50+: adding trigger");
|
ConsoleOutput("Textractor: ShinaRio 2.50+: adding trigger");
|
||||||
return true;
|
return true;
|
||||||
@ -5960,7 +5962,7 @@ void InsertWaffleHook()
|
|||||||
}
|
}
|
||||||
//ConsoleOutput("Probably Waffle. Wait for text.");
|
//ConsoleOutput("Probably Waffle. Wait for text.");
|
||||||
trigger_fun_ = InsertWaffleDynamicHook;
|
trigger_fun_ = InsertWaffleDynamicHook;
|
||||||
SwitchTrigger(true);
|
SetTrigger();
|
||||||
//ConsoleOutput("vnreng:WAFFLE: failed");
|
//ConsoleOutput("vnreng:WAFFLE: failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8503,7 +8505,7 @@ bool InsertSystemAoiDynamic()
|
|||||||
ConsoleOutput("vnreng: DYNAMIC SystemAoi");
|
ConsoleOutput("vnreng: DYNAMIC SystemAoi");
|
||||||
//ConsoleOutput("Probably SoftHouseChara. Wait for text.");
|
//ConsoleOutput("Probably SoftHouseChara. Wait for text.");
|
||||||
trigger_fun_ = InsertSystemAoiDynamicHook;
|
trigger_fun_ = InsertSystemAoiDynamicHook;
|
||||||
SwitchTrigger(true);
|
SetTrigger();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8818,7 +8820,7 @@ void InsertIronGameSystemHook()
|
|||||||
{
|
{
|
||||||
//ConsoleOutput("Probably IronGameSystem. Wait for text.");
|
//ConsoleOutput("Probably IronGameSystem. Wait for text.");
|
||||||
trigger_fun_ = InsertIGSDynamicHook;
|
trigger_fun_ = InsertIGSDynamicHook;
|
||||||
SwitchTrigger(true);
|
SetTrigger();
|
||||||
ConsoleOutput("vnreng: TRIGGER IronGameSystem");
|
ConsoleOutput("vnreng: TRIGGER IronGameSystem");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9454,7 +9456,7 @@ void InsertRyokuchaHook()
|
|||||||
{
|
{
|
||||||
//ConsoleOutput("Probably Ryokucha. Wait for text.");
|
//ConsoleOutput("Probably Ryokucha. Wait for text.");
|
||||||
trigger_fun_ = InsertRyokuchaDynamicHook;
|
trigger_fun_ = InsertRyokuchaDynamicHook;
|
||||||
SwitchTrigger(true);
|
SetTrigger();
|
||||||
ConsoleOutput("vnreng: TRIGGER Ryokucha");
|
ConsoleOutput("vnreng: TRIGGER Ryokucha");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
133
vnrhook/main.cc
133
vnrhook/main.cc
@ -11,18 +11,107 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "MinHook.h"
|
#include "MinHook.h"
|
||||||
#include "pipe.h"
|
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "engine/match.h"
|
#include "engine/match.h"
|
||||||
#include "hijack/texthook.h"
|
#include "texthook.h"
|
||||||
#include "util/growl.h"
|
#include "util/growl.h"
|
||||||
|
|
||||||
HANDLE hSection;
|
HANDLE hSection, hookPipe;
|
||||||
|
TextHook* hooks;
|
||||||
bool running;
|
bool running;
|
||||||
int currentHook = 0, userhookCount = 0;
|
int currentHook = 0, userhookCount = 0;
|
||||||
DWORD trigger = 0;
|
DWORD DUMMY;
|
||||||
std::unique_ptr<WinMutex> sectionMutex;
|
std::unique_ptr<WinMutex> sectionMutex;
|
||||||
|
|
||||||
|
DWORD WINAPI Pipe(LPVOID)
|
||||||
|
{
|
||||||
|
while (running)
|
||||||
|
{
|
||||||
|
DWORD count = 0;
|
||||||
|
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||||
|
HANDLE hostPipe = hookPipe = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
while (hookPipe == INVALID_HANDLE_VALUE || hostPipe == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
if (hookPipe == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
hookPipe = CreateFileW(HOOK_PIPE, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
}
|
||||||
|
if (hookPipe != INVALID_HANDLE_VALUE && hostPipe == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
hostPipe = CreateFileW(HOST_PIPE, GENERIC_READ | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
DWORD mode = PIPE_READMODE_MESSAGE;
|
||||||
|
SetNamedPipeHandleState(hostPipe, &mode, NULL, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
*(DWORD*)buffer = GetCurrentProcessId();
|
||||||
|
WriteFile(hookPipe, buffer, sizeof(DWORD), &count, nullptr);
|
||||||
|
|
||||||
|
ConsoleOutput("Textractor: pipe connected");
|
||||||
|
#ifdef _WIN64
|
||||||
|
ConsoleOutput("Hooks don't work on x64, only read codes work. Engine disabled.");
|
||||||
|
#else
|
||||||
|
Engine::Hijack();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (running && ReadFile(hostPipe, buffer, PIPE_BUFFER_SIZE, &count, nullptr))
|
||||||
|
switch (*(HostCommandType*)buffer)
|
||||||
|
{
|
||||||
|
case HOST_COMMAND_NEW_HOOK:
|
||||||
|
{
|
||||||
|
auto info = *(InsertHookCmd*)buffer;
|
||||||
|
NewHook(info.hp, info.name, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HOST_COMMAND_REMOVE_HOOK:
|
||||||
|
{
|
||||||
|
auto info = *(RemoveHookCmd*)buffer;
|
||||||
|
RemoveHook(info.address);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HOST_COMMAND_DETACH:
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hostPipe);
|
||||||
|
CloseHandle(hookPipe);
|
||||||
|
}
|
||||||
|
FreeLibraryAndExitThread(GetModuleHandleW(ITH_DLL), 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextOutput(ThreadParam tp, BYTE* text, int len)
|
||||||
|
{
|
||||||
|
if (len < 0) return;
|
||||||
|
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||||
|
*(ThreadParam*)buffer = tp;
|
||||||
|
memcpy_s(buffer + sizeof(ThreadParam), sizeof(buffer) - sizeof(ThreadParam), text, len);
|
||||||
|
WriteFile(hookPipe, buffer, sizeof(ThreadParam) + len, &DUMMY, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleOutput(LPCSTR text)
|
||||||
|
{
|
||||||
|
ConsoleOutputNotif buffer(text);
|
||||||
|
WriteFile(hookPipe, &buffer, sizeof(buffer), &DUMMY, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleOutput(std::string text)
|
||||||
|
{
|
||||||
|
ConsoleOutput(text.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifyHookRemove(uint64_t addr)
|
||||||
|
{
|
||||||
|
HookRemovedNotif buffer(addr);
|
||||||
|
WriteFile(hookPipe, &buffer, sizeof(buffer), &DUMMY, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
|
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
|
||||||
{
|
{
|
||||||
switch (fdwReason)
|
switch (fdwReason)
|
||||||
@ -35,23 +124,22 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
|
|||||||
|
|
||||||
// jichi 9/25/2013: Interprocedural communication with vnrsrv.
|
// jichi 9/25/2013: Interprocedural communication with vnrsrv.
|
||||||
hSection = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_EXECUTE_READWRITE, 0, HOOK_SECTION_SIZE, (ITH_SECTION_ + std::to_wstring(GetCurrentProcessId())).c_str());
|
hSection = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_EXECUTE_READWRITE, 0, HOOK_SECTION_SIZE, (ITH_SECTION_ + std::to_wstring(GetCurrentProcessId())).c_str());
|
||||||
::hookman = (TextHook*)MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, HOOK_BUFFER_SIZE);
|
hooks = (TextHook*)MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, HOOK_BUFFER_SIZE);
|
||||||
memset(::hookman, 0, HOOK_BUFFER_SIZE);
|
memset(hooks, 0, HOOK_BUFFER_SIZE);
|
||||||
|
|
||||||
MH_Initialize();
|
MH_Initialize();
|
||||||
|
running = true;
|
||||||
|
|
||||||
::running = true;
|
CreateThread(nullptr, 0, Pipe, nullptr, 0, nullptr);
|
||||||
|
|
||||||
CreatePipe();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
{
|
{
|
||||||
::running = false;
|
running = false;
|
||||||
MH_Uninitialize();
|
MH_Uninitialize();
|
||||||
for (TextHook *man = ::hookman; man < ::hookman + MAX_HOOK; man++) if (man->hp.insertion_address) man->ClearHook();
|
for (int i = 0; i < MAX_HOOK; ++i) if (hooks[i].hp.insertion_address) hooks[i].ClearHook();
|
||||||
//if (ith_has_section)
|
//if (ith_has_section)
|
||||||
UnmapViewOfFile(::hookman);
|
UnmapViewOfFile(hooks);
|
||||||
CloseHandle(hSection);
|
CloseHandle(hSection);
|
||||||
//} ITH_EXCEPT {}
|
//} ITH_EXCEPT {}
|
||||||
}
|
}
|
||||||
@ -61,17 +149,17 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//extern "C" {
|
//extern "C" {
|
||||||
void NewHook(const HookParam &hp, LPCSTR lpname, DWORD flag)
|
void NewHook(HookParam hp, LPCSTR lpname, DWORD flag)
|
||||||
{
|
{
|
||||||
std::string name = lpname;
|
std::string name = lpname;
|
||||||
if (++currentHook < MAX_HOOK)
|
if (++currentHook < MAX_HOOK)
|
||||||
{
|
{
|
||||||
if (name[0] == '\0') name = "UserHook" + std::to_string(userhookCount++);
|
if (name.empty()) name = "UserHook" + std::to_string(userhookCount++);
|
||||||
ConsoleOutput(("Textractor: try inserting hook: " + name).c_str());
|
ConsoleOutput("Textractor: try inserting hook: " + name);
|
||||||
|
|
||||||
// jichi 7/13/2014: This function would raise when too many hooks added
|
// jichi 7/13/2014: This function would raise when too many hooks added
|
||||||
::hookman[currentHook].InitHook(hp, name.c_str(), flag);
|
hooks[currentHook].InitHook(hp, name.c_str(), flag);
|
||||||
if (::hookman[currentHook].InsertHook()) ConsoleOutput(("Textractor: inserted hook: " + name).c_str());
|
if (hooks[currentHook].InsertHook()) ConsoleOutput("Textractor: inserted hook: " + name);
|
||||||
else ConsoleOutput("Textractor:WARNING: failed to insert hook");
|
else ConsoleOutput("Textractor:WARNING: failed to insert hook");
|
||||||
}
|
}
|
||||||
else ConsoleOutput("Textractor: too many hooks: can't insert");
|
else ConsoleOutput("Textractor: too many hooks: can't insert");
|
||||||
@ -80,16 +168,7 @@ void NewHook(const HookParam &hp, LPCSTR lpname, DWORD flag)
|
|||||||
void RemoveHook(uint64_t addr)
|
void RemoveHook(uint64_t addr)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_HOOK; i++)
|
for (int i = 0; i < MAX_HOOK; i++)
|
||||||
if (abs((long long)(::hookman[i].hp.insertion_address - addr)) < 9)
|
if (abs((long long)(hooks[i].hp.insertion_address - addr)) < 9) return hooks[i].ClearHook();
|
||||||
{
|
|
||||||
::hookman[i].ClearHook();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitchTrigger(DWORD t)
|
|
||||||
{
|
|
||||||
trigger = t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
@ -6,11 +6,12 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "pipe.h"
|
|
||||||
|
|
||||||
void NewHook(const HookParam &hp, LPCSTR name, DWORD flag = HOOK_ENGINE);
|
void TextOutput(ThreadParam tp, BYTE* text, int len);
|
||||||
|
void ConsoleOutput(LPCSTR text);
|
||||||
|
void NotifyHookRemove(uint64_t addr);
|
||||||
|
void NewHook(HookParam hp, LPCSTR name, DWORD flag = HOOK_ENGINE);
|
||||||
void RemoveHook(uint64_t addr);
|
void RemoveHook(uint64_t addr);
|
||||||
void SwitchTrigger(DWORD on);
|
|
||||||
|
|
||||||
#define ITH_RAISE (*(int*)0 = 0) // raise C000005, for debugging only
|
#define ITH_RAISE (*(int*)0 = 0) // raise C000005, for debugging only
|
||||||
#define ITH_TRY __try
|
#define ITH_TRY __try
|
||||||
|
100
vnrhook/pipe.cc
100
vnrhook/pipe.cc
@ -1,100 +0,0 @@
|
|||||||
// pipe.cc
|
|
||||||
// 8/24/2013 jichi
|
|
||||||
// Branch: ITH_DLL/pipe.cpp, rev 66
|
|
||||||
// 8/24/2013 TODO: Clean up this file
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# pragma warning (disable:4100) // C4100: unreference formal parameter
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
#include "pipe.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "hijack/texthook.h"
|
|
||||||
#include "engine/match.h"
|
|
||||||
#include "defs.h"
|
|
||||||
#include "const.h"
|
|
||||||
#include "growl.h"
|
|
||||||
|
|
||||||
HANDLE hookPipe;
|
|
||||||
|
|
||||||
DWORD DUMMY[100];
|
|
||||||
|
|
||||||
void CreatePipe()
|
|
||||||
{
|
|
||||||
CreateThread(nullptr, 0, [](LPVOID)
|
|
||||||
{
|
|
||||||
while (::running)
|
|
||||||
{
|
|
||||||
DWORD count = 0;
|
|
||||||
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
|
||||||
HANDLE hostPipe = ::hookPipe = INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
while (::hookPipe == INVALID_HANDLE_VALUE || hostPipe == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
if (::hookPipe == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
::hookPipe = CreateFileW(HOOK_PIPE, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
||||||
}
|
|
||||||
if (::hookPipe != INVALID_HANDLE_VALUE && hostPipe == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
hostPipe = CreateFileW(HOST_PIPE, GENERIC_READ | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
||||||
DWORD mode = PIPE_READMODE_MESSAGE;
|
|
||||||
SetNamedPipeHandleState(hostPipe, &mode, NULL, NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Sleep(50);
|
|
||||||
}
|
|
||||||
|
|
||||||
*(DWORD*)buffer = GetCurrentProcessId();
|
|
||||||
WriteFile(::hookPipe, buffer, sizeof(DWORD), &count, nullptr);
|
|
||||||
|
|
||||||
ConsoleOutput("Textractor: pipe connected");
|
|
||||||
#ifdef _WIN64
|
|
||||||
ConsoleOutput("Hooks don't work on x64, only read codes work. Engine disabled.");
|
|
||||||
#else
|
|
||||||
Engine::Hijack();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (::running && ReadFile(hostPipe, buffer, PIPE_BUFFER_SIZE, &count, nullptr))
|
|
||||||
switch (*(int*)buffer)
|
|
||||||
{
|
|
||||||
case HOST_COMMAND_NEW_HOOK:
|
|
||||||
{
|
|
||||||
auto info = *(InsertHookCmd*)buffer;
|
|
||||||
NewHook(info.hp, info.name, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HOST_COMMAND_REMOVE_HOOK:
|
|
||||||
{
|
|
||||||
auto info = *(RemoveHookCmd*)buffer;
|
|
||||||
RemoveHook(info.address);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HOST_COMMAND_DETACH:
|
|
||||||
{
|
|
||||||
::running = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(hostPipe);
|
|
||||||
CloseHandle(::hookPipe);
|
|
||||||
}
|
|
||||||
FreeLibraryAndExitThread(GetModuleHandleW(ITH_DLL), 0);
|
|
||||||
return (DWORD)0;
|
|
||||||
}, nullptr, 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConsoleOutput(LPCSTR text)
|
|
||||||
{
|
|
||||||
auto info = ConsoleOutputNotif(text);
|
|
||||||
WriteFile(::hookPipe, &info, strlen(text) + sizeof(info), DUMMY, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyHookRemove(uint64_t addr)
|
|
||||||
{
|
|
||||||
auto info = HookRemovedNotif(addr);
|
|
||||||
WriteFile(::hookPipe, &info, sizeof(info), DUMMY, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
void CreatePipe();
|
|
||||||
void NotifyHookRemove(uint64_t addr);
|
|
||||||
void ConsoleOutput(LPCSTR text); // jichi 12/25/2013: Used to return length of sent text
|
|
@ -9,17 +9,22 @@
|
|||||||
//# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler
|
//# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
#include "hijack/texthook.h"
|
#include "texthook.h"
|
||||||
#include "MinHook.h"
|
#include "MinHook.h"
|
||||||
#include "engine/match.h"
|
#include "engine/match.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "pipe.h"
|
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
#include "ithsys/ithsys.h"
|
#include "ithsys/ithsys.h"
|
||||||
#include "growl.h"
|
#include "growl.h"
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
|
|
||||||
TextHook *hookman;
|
extern std::unique_ptr<WinMutex> sectionMutex;
|
||||||
|
|
||||||
|
bool trigger = 0;
|
||||||
|
void SetTrigger()
|
||||||
|
{
|
||||||
|
trigger = true;
|
||||||
|
}
|
||||||
|
|
||||||
// - Unnamed helpers -
|
// - Unnamed helpers -
|
||||||
|
|
||||||
@ -125,8 +130,8 @@ void TextHook::Send(DWORD dwDataBase)
|
|||||||
* @param stack address of current stack - 4
|
* @param stack address of current stack - 4
|
||||||
* @return If success, which is reverted
|
* @return If success, which is reverted
|
||||||
*/
|
*/
|
||||||
if (::trigger)
|
if (trigger)
|
||||||
::trigger = Engine::InsertDynamicHook((LPVOID)dwAddr, *(DWORD *)(dwDataBase - 0x1c), *(DWORD *)(dwDataBase - 0x18));
|
trigger = Engine::InsertDynamicHook((LPVOID)dwAddr, *(DWORD *)(dwDataBase - 0x1c), *(DWORD *)(dwDataBase - 0x18));
|
||||||
|
|
||||||
// jichi 10/24/2014: generic hook function
|
// jichi 10/24/2014: generic hook function
|
||||||
if (hp.hook_fun && !hp.hook_fun(dwDataBase, &hp))
|
if (hp.hook_fun && !hp.hook_fun(dwDataBase, &hp))
|
||||||
@ -168,25 +173,18 @@ void TextHook::Send(DWORD dwDataBase)
|
|||||||
dwDataIn = _byteswap_ushort(dwDataIn & 0xffff);
|
dwDataIn = _byteswap_ushort(dwDataIn & 0xffff);
|
||||||
if (dwCount == 1)
|
if (dwCount == 1)
|
||||||
dwDataIn &= 0xff;
|
dwDataIn &= 0xff;
|
||||||
*(WORD *)(pbData + sizeof(ThreadParam)) = dwDataIn & 0xffff;
|
*(WORD*)pbData = dwDataIn & 0xffff;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
::memcpy(pbData + sizeof(ThreadParam), (void *)dwDataIn, dwCount);
|
::memcpy(pbData, (void*)dwDataIn, dwCount);
|
||||||
|
|
||||||
// jichi 10/14/2014: Add filter function
|
// jichi 10/14/2014: Add filter function
|
||||||
if (hp.filter_fun && !hp.filter_fun(pbData + sizeof(ThreadParam), &dwCount, &hp, 0) || dwCount <= 0) return;
|
if (hp.filter_fun && !hp.filter_fun(pbData, &dwCount, &hp, 0) || dwCount <= 0) return;
|
||||||
|
|
||||||
if (dwType & (NO_CONTEXT | FIXING_SPLIT))
|
if (dwType & (NO_CONTEXT | FIXING_SPLIT))
|
||||||
dwRetn = 0;
|
dwRetn = 0;
|
||||||
|
|
||||||
*(ThreadParam*)pbData = { GetCurrentProcessId(), dwAddr, dwRetn, dwSplit };
|
TextOutput({ GetCurrentProcessId(), dwAddr, dwRetn, dwSplit }, pbData, dwCount);
|
||||||
if (dwCount) {
|
|
||||||
DWORD unused;
|
|
||||||
|
|
||||||
//CliLockPipe();
|
|
||||||
WriteFile(::hookPipe, pbData, dwCount + sizeof(ThreadParam), &unused, nullptr);
|
|
||||||
//CliUnlockPipe();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
@ -205,9 +203,9 @@ bool TextHook::InsertHookCode()
|
|||||||
else if (HMODULE moduleBase = GetModuleHandleW(hp.module)) hp.insertion_address += (uint64_t)moduleBase;
|
else if (HMODULE moduleBase = GetModuleHandleW(hp.module)) hp.insertion_address += (uint64_t)moduleBase;
|
||||||
else return ConsoleOutput("Textractor: InsertHookCode FAILED: module not present"), false;
|
else return ConsoleOutput("Textractor: InsertHookCode FAILED: module not present"), false;
|
||||||
|
|
||||||
BYTE* original;
|
void* original;
|
||||||
insert:
|
insert:
|
||||||
if (MH_STATUS err = MH_CreateHook((void*)hp.insertion_address, (void*)trampoline, (void**)&original))
|
if (MH_STATUS err = MH_CreateHook((void*)hp.insertion_address, (void*)trampoline, &original))
|
||||||
if (err == MH_ERROR_ALREADY_CREATED)
|
if (err == MH_ERROR_ALREADY_CREATED)
|
||||||
{
|
{
|
||||||
RemoveHook(hp.insertion_address);
|
RemoveHook(hp.insertion_address);
|
||||||
@ -222,7 +220,7 @@ insert:
|
|||||||
|
|
||||||
*(TextHook**)(common_hook + 9) = this;
|
*(TextHook**)(common_hook + 9) = this;
|
||||||
*(void(TextHook::**)(DWORD))(common_hook + 14) = &TextHook::Send;
|
*(void(TextHook::**)(DWORD))(common_hook + 14) = &TextHook::Send;
|
||||||
*(BYTE**)(common_hook + 24) = original;
|
*(void**)(common_hook + 24) = original;
|
||||||
memcpy(trampoline, common_hook, sizeof(common_hook));
|
memcpy(trampoline, common_hook, sizeof(common_hook));
|
||||||
|
|
||||||
//BYTE* original;
|
//BYTE* original;
|
||||||
@ -240,7 +238,7 @@ insert:
|
|||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
DWORD WINAPI ReaderThread(LPVOID hookPtr)
|
DWORD WINAPI Reader(LPVOID hookPtr)
|
||||||
{
|
{
|
||||||
TextHook* hook = (TextHook*)hookPtr;
|
TextHook* hook = (TextHook*)hookPtr;
|
||||||
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||||
@ -253,7 +251,7 @@ DWORD WINAPI ReaderThread(LPVOID hookPtr)
|
|||||||
{
|
{
|
||||||
if (hook->hp.type & DATA_INDIRECT) currentAddress = *((char**)hook->hp.insertion_address + hook->hp.index);
|
if (hook->hp.type & DATA_INDIRECT) currentAddress = *((char**)hook->hp.insertion_address + hook->hp.index);
|
||||||
Sleep(500);
|
Sleep(500);
|
||||||
if (memcmp(buffer + sizeof(ThreadParam), currentAddress, dataLen + 1) == 0)
|
if (memcmp(buffer, currentAddress, dataLen + 1) == 0)
|
||||||
{
|
{
|
||||||
changeCount = 0;
|
changeCount = 0;
|
||||||
continue;
|
continue;
|
||||||
@ -269,15 +267,13 @@ DWORD WINAPI ReaderThread(LPVOID hookPtr)
|
|||||||
else
|
else
|
||||||
dataLen = strlen((const char*)currentAddress);
|
dataLen = strlen((const char*)currentAddress);
|
||||||
|
|
||||||
*(ThreadParam*)buffer = { GetCurrentProcessId(), hook->hp.insertion_address, 0, 0 };
|
memcpy(buffer, currentAddress, dataLen + 1);
|
||||||
memcpy(buffer + sizeof(ThreadParam), currentAddress, dataLen + 1);
|
TextOutput({ GetCurrentProcessId(), hook->hp.insertion_address, 0, 0 }, buffer, dataLen);
|
||||||
DWORD unused;
|
|
||||||
WriteFile(::hookPipe, buffer, dataLen + sizeof(ThreadParam), &unused, nullptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
ConsoleOutput("Textractor: ReaderThread ERROR (likely an incorrect R-code)");
|
ConsoleOutput("Textractor: Reader ERROR (likely an incorrect R-code)");
|
||||||
}
|
}
|
||||||
ConsoleOutput("Textractor: remove read code");
|
ConsoleOutput("Textractor: remove read code");
|
||||||
hook->ClearHook();
|
hook->ClearHook();
|
||||||
@ -287,14 +283,14 @@ DWORD WINAPI ReaderThread(LPVOID hookPtr)
|
|||||||
bool TextHook::InsertReadCode()
|
bool TextHook::InsertReadCode()
|
||||||
{
|
{
|
||||||
//RemoveHook(hp.address); // Artikash 8/25/2018: clear existing
|
//RemoveHook(hp.address); // Artikash 8/25/2018: clear existing
|
||||||
readerHandle = CreateThread(nullptr, 0, ReaderThread, this, 0, nullptr);
|
readerHandle = CreateThread(nullptr, 0, Reader, this, 0, nullptr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHook::InitHook(const HookParam &h, LPCSTR name, DWORD set_flag)
|
void TextHook::InitHook(HookParam h, LPCSTR name, DWORD set_flag)
|
||||||
{
|
{
|
||||||
LOCK(*sectionMutex);
|
LOCK(*sectionMutex);
|
||||||
hp = h;
|
this->hp = h;
|
||||||
hp.insertion_address = hp.address;
|
hp.insertion_address = hp.address;
|
||||||
hp.type |= set_flag;
|
hp.type |= set_flag;
|
||||||
strcpy_s<HOOK_NAME_SIZE>(hookName, name);
|
strcpy_s<HOOK_NAME_SIZE>(hookName, name);
|
@ -10,8 +10,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
extern int currentHook;
|
void SetTrigger();
|
||||||
extern DWORD trigger;
|
|
||||||
|
|
||||||
// jichi 9/25/2013: This class will be used by NtMapViewOfSectionfor
|
// jichi 9/25/2013: This class will be used by NtMapViewOfSectionfor
|
||||||
// interprocedure communication, where constructor/destructor will NOT work.
|
// interprocedure communication, where constructor/destructor will NOT work.
|
||||||
@ -23,6 +22,7 @@ class TextHook
|
|||||||
int GetLength(DWORD base, DWORD in); // jichi 12/25/2013: Return 0 if failed
|
int GetLength(DWORD base, DWORD in); // jichi 12/25/2013: Return 0 if failed
|
||||||
void RemoveHookCode();
|
void RemoveHookCode();
|
||||||
void RemoveReadCode();
|
void RemoveReadCode();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HookParam hp;
|
HookParam hp;
|
||||||
char hookName[HOOK_NAME_SIZE];
|
char hookName[HOOK_NAME_SIZE];
|
||||||
@ -30,17 +30,11 @@ public:
|
|||||||
HANDLE readerHandle;
|
HANDLE readerHandle;
|
||||||
|
|
||||||
bool InsertHook();
|
bool InsertHook();
|
||||||
void InitHook(const HookParam &hp, LPCSTR name, DWORD set_flag);
|
void InitHook(HookParam hp, LPCSTR name, DWORD set_flag);
|
||||||
void Send(DWORD dwDataBase);
|
void Send(DWORD dwDataBase);
|
||||||
void ClearHook();
|
void ClearHook();
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { MAX_HOOK = 300 };
|
enum { MAX_HOOK = 300, HOOK_BUFFER_SIZE = MAX_HOOK * sizeof(TextHook), HOOK_SECTION_SIZE = HOOK_BUFFER_SIZE * 2 };
|
||||||
enum { HOOK_SECTION_SIZE = MAX_HOOK * sizeof(TextHook) * 2, HOOK_BUFFER_SIZE = MAX_HOOK * sizeof(TextHook) };
|
|
||||||
|
|
||||||
extern TextHook *hookman;
|
|
||||||
extern bool running;
|
|
||||||
extern HANDLE hookPipe;
|
|
||||||
extern std::unique_ptr<WinMutex> sectionMutex;
|
|
||||||
|
|
||||||
// EOF
|
// EOF
|
Loading…
x
Reference in New Issue
Block a user