mirror of
https://github.com/Artikash/Textractor.git
synced 2024-12-23 17:04:12 +08:00
add basic support for x64
This commit is contained in:
parent
959d7c2dd5
commit
aba5dadc6a
@ -29,5 +29,9 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Build)
|
|||||||
set(CMAKE_CONFIGURATION_TYPES Debug Release)
|
set(CMAKE_CONFIGURATION_TYPES Debug Release)
|
||||||
|
|
||||||
add_subdirectory(host)
|
add_subdirectory(host)
|
||||||
add_subdirectory(vnrhook)
|
if (${x64})
|
||||||
|
add_subdirectory(vnrhook64)
|
||||||
|
else(${x64})
|
||||||
|
add_subdirectory(vnrhook)
|
||||||
|
endif(${x64})
|
||||||
add_subdirectory(GUI)
|
add_subdirectory(GUI)
|
||||||
|
@ -27,10 +27,10 @@
|
|||||||
"name": "x64-Debug",
|
"name": "x64-Debug",
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
"configurationType": "Debug",
|
"configurationType": "Debug",
|
||||||
"inheritEnvironments": [ "msvc_x86_x64" ],
|
"inheritEnvironments": [ "msvc_x64" ],
|
||||||
"buildRoot": "${workspaceRoot}\\Builds\\${name}",
|
"buildRoot": "${workspaceRoot}\\Builds\\${name}",
|
||||||
"installRoot": "${workspaceRoot}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
|
"installRoot": "${workspaceRoot}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
|
||||||
"cmakeCommandArgs": "",
|
"cmakeCommandArgs": "-Dx64=1",
|
||||||
"buildCommandArgs": "-v",
|
"buildCommandArgs": "-v",
|
||||||
"ctestCommandArgs": ""
|
"ctestCommandArgs": ""
|
||||||
},
|
},
|
||||||
@ -38,10 +38,10 @@
|
|||||||
"name": "x64-Release",
|
"name": "x64-Release",
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
"configurationType": "Release",
|
"configurationType": "Release",
|
||||||
"inheritEnvironments": [ "msvc_x86_x64" ],
|
"inheritEnvironments": [ "msvc_x64" ],
|
||||||
"buildRoot": "${workspaceRoot}\\Builds\\${name}",
|
"buildRoot": "${workspaceRoot}\\Builds\\${name}",
|
||||||
"installRoot": "${workspaceRoot}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
|
"installRoot": "${workspaceRoot}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
|
||||||
"cmakeCommandArgs": "",
|
"cmakeCommandArgs": "-Dx64=1",
|
||||||
"buildCommandArgs": "-v",
|
"buildCommandArgs": "-v",
|
||||||
"ctestCommandArgs": ""
|
"ctestCommandArgs": ""
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
// vnrhook/const.h
|
// vnrhook/const.h
|
||||||
// 8/23/2013 jichi
|
// 8/23/2013 jichi
|
||||||
@ -50,7 +51,7 @@ enum { MAX_HOOK = 64 }; // must be larger than HOOK_FUN_COUNT
|
|||||||
//enum { HOOK_SECTION_SIZE = 0x2000 }; // default ITH value
|
//enum { HOOK_SECTION_SIZE = 0x2000 }; // default ITH value
|
||||||
// jichi 1/16/2015: Change to a very large number to prevent crash
|
// jichi 1/16/2015: Change to a very large number to prevent crash
|
||||||
//enum { MAX_HOOK = 0x100 }; // must be larger than HookFunCount
|
//enum { MAX_HOOK = 0x100 }; // must be larger than HookFunCount
|
||||||
enum { HOOK_SECTION_SIZE = MAX_HOOK * 0x100 }; // default ITH value is 0x2000 for 32 hook (0x100 per hook)
|
enum { HOOK_SECTION_SIZE = MAX_HOOK * sizeof(Hook) * 2 }; // default ITH value is 0x2000 for 32 hook (0x100 per hook)
|
||||||
|
|
||||||
// jichi 375/2014: Add offset of pusha/pushad
|
// jichi 375/2014: Add offset of pusha/pushad
|
||||||
// http://faydoc.tripod.com/cpu/pushad.htm
|
// http://faydoc.tripod.com/cpu/pushad.htm
|
||||||
|
@ -340,7 +340,7 @@ DWORD WINAPI ReaderThread(LPVOID threadParam)
|
|||||||
{
|
{
|
||||||
TextHook* hook = (TextHook*)threadParam;
|
TextHook* hook = (TextHook*)threadParam;
|
||||||
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||||
char testChar;
|
char testChar = 0;
|
||||||
unsigned int changeCount = 0;
|
unsigned int changeCount = 0;
|
||||||
const char* currentAddress = (char*)hook->hp.address;
|
const char* currentAddress = (char*)hook->hp.address;
|
||||||
while (true)
|
while (true)
|
||||||
|
46
vnrhook64/CMakeLists.txt
Normal file
46
vnrhook64/CMakeLists.txt
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
project(vnrhook)
|
||||||
|
|
||||||
|
include_directories(../vnrhook)
|
||||||
|
|
||||||
|
set(vnrhook_src
|
||||||
|
../vnrhook/include/const.h
|
||||||
|
../vnrhook/include/defs.h
|
||||||
|
../vnrhook/include/types.h
|
||||||
|
src/main.cc
|
||||||
|
src/main.h
|
||||||
|
src/pipe.cc
|
||||||
|
src/hijack/texthook.cc
|
||||||
|
src/hijack/texthook.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(vnrhook SHARED ${vnrhook_src})
|
||||||
|
|
||||||
|
set_source_files_properties(
|
||||||
|
${PROJECT_SOURCE_DIR}/winseh/safeseh.asm
|
||||||
|
PROPERTIES
|
||||||
|
# CMAKE_ASM_MASM_FLAGS /safeseh # CMake bug 14711: http://www.cmake.org/Bug/view.php?id=14711
|
||||||
|
COMPILE_FLAGS /safeseh
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(vnrhook PROPERTIES
|
||||||
|
LINK_FLAGS "/SUBSYSTEM:WINDOWS /MANIFEST:NO"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_options(vnrhook PRIVATE
|
||||||
|
/EHa
|
||||||
|
$<$<CONFIG:Release>:>
|
||||||
|
$<$<CONFIG:Debug>:>
|
||||||
|
)
|
||||||
|
|
||||||
|
set(vnrhook_libs
|
||||||
|
Version.lib
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(vnrhook ${vnrhook_libs})
|
||||||
|
|
||||||
|
target_compile_definitions(vnrhook
|
||||||
|
PRIVATE
|
||||||
|
ITH_HAS_CRT
|
||||||
|
ITH_HAS_SEH
|
||||||
|
_CRT_NON_CONFORMING_SWPRINTFS
|
||||||
|
)
|
187
vnrhook64/src/hijack/texthook.cc
Normal file
187
vnrhook64/src/hijack/texthook.cc
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
// texthook.cc
|
||||||
|
// 8/24/2013 jichi
|
||||||
|
// Branch: ITH_DLL/texthook.cpp, rev 128
|
||||||
|
// 8/24/2013 TODO: Clean up this file
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning (disable:4100) // C4100: unreference formal parameter
|
||||||
|
# pragma warning (disable:4018) // C4018: sign/unsigned mismatch
|
||||||
|
//# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
#include "../main.h"
|
||||||
|
#include "texthook.h"
|
||||||
|
#include "include/const.h"
|
||||||
|
//#include "winseh/winseh.h"
|
||||||
|
|
||||||
|
//#define ConsoleOutput(...) (void)0 // jichi 9/17/2013: I don't need this ><
|
||||||
|
|
||||||
|
// - Global variables -
|
||||||
|
|
||||||
|
// 10/14/2014 jichi: disable GDI hooks
|
||||||
|
static bool gdi_hook_enabled_ = true; // enable GDI by default
|
||||||
|
static bool gdiplus_hook_enabled_ = false; // disable GDIPlus by default
|
||||||
|
bool GDIHooksEnabled() { return ::gdi_hook_enabled_; }
|
||||||
|
bool GDIPlusHooksEnabled() { return ::gdiplus_hook_enabled_; }
|
||||||
|
void EnableGDIHooks() { ::gdi_hook_enabled_ = true; }
|
||||||
|
void EnableGDIPlusHooks() { ::gdiplus_hook_enabled_ = true; }
|
||||||
|
void DisableGDIHooks() { ::gdi_hook_enabled_ = false; }
|
||||||
|
void DisableGDIPlusHooks() { ::gdiplus_hook_enabled_ = false; }
|
||||||
|
|
||||||
|
//FilterRange filter[8];
|
||||||
|
|
||||||
|
DWORD flag,
|
||||||
|
enter_count;
|
||||||
|
|
||||||
|
TextHook *hookman,
|
||||||
|
*current_available;
|
||||||
|
|
||||||
|
// - TextHook methods -
|
||||||
|
|
||||||
|
// jichi 12/2/2013: This function mostly return 0.
|
||||||
|
// It return the hook address only for auxiliary case.
|
||||||
|
// However, because no known hooks are auxiliary, this function always return 0.
|
||||||
|
//
|
||||||
|
// jichi 5/11/2014:
|
||||||
|
// - dwDataBase: the stack address
|
||||||
|
// - dwRetn: the return address of the hook
|
||||||
|
|
||||||
|
|
||||||
|
int TextHook::InsertHook()
|
||||||
|
{
|
||||||
|
int ok = 1;
|
||||||
|
//ConsoleOutput("vnrcli:InsertHook: enter");
|
||||||
|
WaitForSingleObject(hmMutex, 0);
|
||||||
|
if (hp.type & DIRECT_READ) ok = InsertReadCode();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConsoleOutput("only /R (read) codes supported in 64 bit");
|
||||||
|
}
|
||||||
|
ReleaseMutex(hmMutex);
|
||||||
|
//ConsoleOutput("vnrcli:InsertHook: leave");
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI ReaderThread(LPVOID threadParam)
|
||||||
|
{
|
||||||
|
TextHook* hook = (TextHook*)threadParam;
|
||||||
|
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||||
|
char testChar = 0;
|
||||||
|
unsigned int changeCount = 0;
|
||||||
|
const char* currentAddress = (char*)hook->hp.address;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Sleep(50);
|
||||||
|
if (testChar == *currentAddress)
|
||||||
|
{
|
||||||
|
changeCount = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
testChar = *currentAddress;
|
||||||
|
if (++changeCount > 10)
|
||||||
|
{
|
||||||
|
ConsoleOutput("NextHooker: memory constantly changing, useless to read");
|
||||||
|
ConsoleOutput("NextHooker: remove read code");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dataLen;
|
||||||
|
if (hook->hp.type & USING_UNICODE)
|
||||||
|
dataLen = wcslen((const wchar_t*)currentAddress) * 2;
|
||||||
|
else
|
||||||
|
dataLen = strlen(currentAddress);
|
||||||
|
|
||||||
|
*(DWORD*)buffer = hook->hp.address;
|
||||||
|
*(DWORD*)(buffer + 4) = 0;
|
||||||
|
*(DWORD*)(buffer + 8) = 0;
|
||||||
|
memcpy(buffer + HEADER_SIZE, currentAddress, dataLen);
|
||||||
|
DWORD unused;
|
||||||
|
WriteFile(::hookPipe, buffer, dataLen + HEADER_SIZE, &unused, nullptr);
|
||||||
|
|
||||||
|
if (hook->hp.offset == 0) continue;
|
||||||
|
currentAddress += dataLen + hook->hp.offset;
|
||||||
|
testChar = *currentAddress;
|
||||||
|
}
|
||||||
|
hook->ClearHook();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextHook::InsertReadCode()
|
||||||
|
{
|
||||||
|
hp.hook_len = 0x40;
|
||||||
|
//Check if the new hook range conflict with existing ones. Clear older if conflict.
|
||||||
|
TextHook *it = hookman;
|
||||||
|
for (int i = 0; i < currentHook; it++) {
|
||||||
|
if (it->Address())
|
||||||
|
i++;
|
||||||
|
if (it == this)
|
||||||
|
continue;
|
||||||
|
if ((it->Address() >= hp.address && it->Address() < hp.hook_len + hp.address) || (it->Address() <= hp.address && it->Address() + it->Length() > hp.address))
|
||||||
|
it->ClearHook();
|
||||||
|
}
|
||||||
|
//if (!IthGetMemoryRange((LPCVOID)hp.address, 0, 0))
|
||||||
|
//{
|
||||||
|
// ConsoleOutput("cannot access read address");
|
||||||
|
// return no;
|
||||||
|
//}
|
||||||
|
hp.readerHandle = CreateThread(nullptr, 0, ReaderThread, this, 0, nullptr);
|
||||||
|
return yes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextHook::InitHook(const HookParam &h, LPCSTR name, WORD set_flag)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(hmMutex, 0);
|
||||||
|
hp = h;
|
||||||
|
hp.type |= set_flag;
|
||||||
|
if (name && name != hook_name) {
|
||||||
|
SetHookName(name);
|
||||||
|
}
|
||||||
|
currentHook++;
|
||||||
|
current_available = this+1;
|
||||||
|
while (current_available->Address())
|
||||||
|
current_available++;
|
||||||
|
ReleaseMutex(hmMutex);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextHook::RemoveReadCode()
|
||||||
|
{
|
||||||
|
if (!hp.address) return no;
|
||||||
|
TerminateThread(hp.readerHandle, 0);
|
||||||
|
CloseHandle(hp.readerHandle);
|
||||||
|
return yes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextHook::ClearHook()
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
WaitForSingleObject(hmMutex, 0);
|
||||||
|
ConsoleOutput("vnrcli:RemoveHook: enter");
|
||||||
|
err = RemoveReadCode();
|
||||||
|
NotifyHookRemove(hp.address);
|
||||||
|
if (hook_name) {
|
||||||
|
delete[] hook_name;
|
||||||
|
hook_name = nullptr;
|
||||||
|
}
|
||||||
|
memset(this, 0, sizeof(TextHook)); // jichi 11/30/2013: This is the original code of ITH
|
||||||
|
//if (current_available>this)
|
||||||
|
// current_available = this;
|
||||||
|
currentHook--;
|
||||||
|
ConsoleOutput("vnrcli:RemoveHook: leave");
|
||||||
|
ReleaseMutex(hmMutex);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextHook::SetHookName(LPCSTR name)
|
||||||
|
{
|
||||||
|
name_length = strlen(name) + 1;
|
||||||
|
if (hook_name)
|
||||||
|
delete[] hook_name;
|
||||||
|
hook_name = new char[name_length];
|
||||||
|
//ITH_MEMSET_HEAP(hook_name, 0, sizeof(wchar_t) * name_length); // jichi 9/26/2013: zero memory
|
||||||
|
strcpy(hook_name, name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
78
vnrhook64/src/hijack/texthook.h
Normal file
78
vnrhook64/src/hijack/texthook.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// texthook.h
|
||||||
|
// 8/24/2013 jichi
|
||||||
|
// Branch: IHF_DLL/IHF_CLIENT.h, rev 133
|
||||||
|
//
|
||||||
|
// 8/24/2013 TODO:
|
||||||
|
// - Clean up this file
|
||||||
|
// - Reduce global variables. Use namespaces or singleton classes instead.
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "include/types.h"
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
extern int currentHook;
|
||||||
|
extern WCHAR dll_mutex[];
|
||||||
|
//extern WCHAR dll_name[];
|
||||||
|
extern DWORD trigger;
|
||||||
|
//extern DWORD current_process_id;
|
||||||
|
|
||||||
|
// jichi 6/3/2014: Get memory range of the current module
|
||||||
|
extern DWORD processStartAddress,
|
||||||
|
processStopAddress;
|
||||||
|
|
||||||
|
void InitFilterTable();
|
||||||
|
|
||||||
|
// jichi 9/25/2013: This class will be used by NtMapViewOfSectionfor
|
||||||
|
// interprocedure communication, where constructor/destructor will NOT work.
|
||||||
|
class TextHook : public Hook
|
||||||
|
{
|
||||||
|
int InsertHookCode();
|
||||||
|
int InsertReadCode();
|
||||||
|
int UnsafeInsertHookCode();
|
||||||
|
DWORD UnsafeSend(DWORD dwDataBase, DWORD dwRetn);
|
||||||
|
int RemoveHookCode();
|
||||||
|
int RemoveReadCode();
|
||||||
|
int SetHookName(LPCSTR name);
|
||||||
|
public:
|
||||||
|
int InsertHook();
|
||||||
|
int InitHook(const HookParam &hp, LPCSTR name = 0, WORD set_flag = 0);
|
||||||
|
DWORD Send(DWORD dwDataBase, DWORD dwRetn);
|
||||||
|
int ClearHook();
|
||||||
|
int GetLength(DWORD base, DWORD in); // jichi 12/25/2013: Return 0 if failed
|
||||||
|
};
|
||||||
|
|
||||||
|
extern TextHook *hookman,
|
||||||
|
*current_available;
|
||||||
|
|
||||||
|
//void InitDefaultHook();
|
||||||
|
|
||||||
|
struct FilterRange { DWORD lower, upper; };
|
||||||
|
extern FilterRange *filter;
|
||||||
|
|
||||||
|
extern bool running,
|
||||||
|
live;
|
||||||
|
|
||||||
|
extern HANDLE hookPipe,
|
||||||
|
hmMutex;
|
||||||
|
|
||||||
|
DWORD WINAPI WaitForPipe(LPVOID lpThreadParameter);
|
||||||
|
DWORD WINAPI CommandPipe(LPVOID lpThreadParameter);
|
||||||
|
DWORD WINAPI PipeManager(LPVOID unused);
|
||||||
|
|
||||||
|
//void RequestRefreshProfile();
|
||||||
|
|
||||||
|
//typedef DWORD (*InsertHookFun)(DWORD);
|
||||||
|
//typedef DWORD (*IdentifyEngineFun)();
|
||||||
|
//typedef DWORD (*InsertDynamicHookFun)(LPVOID addr, DWORD frame, DWORD stack);
|
||||||
|
//extern IdentifyEngineFun IdentifyEngine;
|
||||||
|
//extern InsertDynamicHookFun InsertDynamicHook;
|
||||||
|
|
||||||
|
// jichi 9/28/2013: Protect pipeline in wine
|
||||||
|
void CliLockPipe();
|
||||||
|
void CliUnlockPipe();
|
||||||
|
|
||||||
|
enum : int { yes = 0, no = 1 };
|
||||||
|
|
||||||
|
// EOF
|
150
vnrhook64/src/main.cc
Normal file
150
vnrhook64/src/main.cc
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
// main.cc
|
||||||
|
// 8/24/2013 jichi
|
||||||
|
// Branch: ITH_DLL/main.cpp, rev 128
|
||||||
|
// 8/24/2013 TODO: Clean up this file
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning (disable:4100) // C4100: unreference formal parameter
|
||||||
|
//# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "hijack/texthook.h"
|
||||||
|
#include "include/defs.h"
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
|
||||||
|
// jichi 6/3/2014: memory range of the current module
|
||||||
|
DWORD processStartAddress,
|
||||||
|
processStopAddress;
|
||||||
|
|
||||||
|
enum { HOOK_BUFFER_SIZE = MAX_HOOK * sizeof(TextHook) };
|
||||||
|
//#define MAX_HOOK (HOOK_BUFFER_SIZE/sizeof(TextHook))
|
||||||
|
DWORD hook_buff_len = HOOK_BUFFER_SIZE;
|
||||||
|
|
||||||
|
WCHAR hm_section[0x100];
|
||||||
|
HANDLE hSection;
|
||||||
|
bool running;
|
||||||
|
int currentHook = 0,
|
||||||
|
user_hook_count = 0;
|
||||||
|
HANDLE
|
||||||
|
hFile,
|
||||||
|
hMutex,
|
||||||
|
hmMutex;
|
||||||
|
HMODULE currentModule;
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID unused)
|
||||||
|
{
|
||||||
|
static HANDLE pipeThread;
|
||||||
|
|
||||||
|
|
||||||
|
switch (fdwReason) {
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
{
|
||||||
|
static bool attached_ = false;
|
||||||
|
if (attached_) // already attached
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
attached_ = true;
|
||||||
|
|
||||||
|
DisableThreadLibraryCalls(hModule);
|
||||||
|
|
||||||
|
swprintf(hm_section, ITH_SECTION_ L"%d", GetCurrentProcessId());
|
||||||
|
|
||||||
|
// jichi 9/25/2013: Interprocedural communication with vnrsrv.
|
||||||
|
hSection = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_EXECUTE_READWRITE, 0, HOOK_SECTION_SIZE, hm_section);
|
||||||
|
::hookman = nullptr;
|
||||||
|
// Artikash 6/20/2018: This crashes certain games (https://vndb.org/v7738). No idea why.
|
||||||
|
::hookman = (TextHook*)MapViewOfFile(hSection, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, HOOK_SECTION_SIZE / 2);
|
||||||
|
|
||||||
|
::processStartAddress = (DWORD)GetModuleHandleW(nullptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
wchar_t hm_mutex[0x100];
|
||||||
|
swprintf(hm_mutex, ITH_HOOKMAN_MUTEX_ L"%d", GetCurrentProcessId());
|
||||||
|
::hmMutex = CreateMutexW(nullptr, FALSE, hm_mutex);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
wchar_t dll_mutex[0x100];
|
||||||
|
swprintf(dll_mutex, ITH_PROCESS_MUTEX_ L"%d", GetCurrentProcessId());
|
||||||
|
DWORD exists;
|
||||||
|
::hMutex = CreateMutexW(nullptr, TRUE, dll_mutex); // jichi 9/18/2013: own is true, make sure the injected dll is singleton
|
||||||
|
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
::running = true;
|
||||||
|
::current_available = ::hookman;
|
||||||
|
::currentModule = hModule;
|
||||||
|
|
||||||
|
pipeThread = CreateThread(nullptr, 0, PipeManager, 0, 0, nullptr);
|
||||||
|
} break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
{
|
||||||
|
static bool detached_ = false;
|
||||||
|
if (detached_) // already detached
|
||||||
|
return TRUE;
|
||||||
|
detached_ = true;
|
||||||
|
|
||||||
|
// jichi 10/2/2103: Cannot use __try in functions that require object unwinding
|
||||||
|
//ITH_TRY {
|
||||||
|
::running = false;
|
||||||
|
|
||||||
|
if (pipeThread) {
|
||||||
|
WaitForSingleObject(pipeThread, TIMEOUT);
|
||||||
|
CloseHandle(pipeThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TextHook *man = ::hookman; man < ::hookman + MAX_HOOK; man++)
|
||||||
|
man->ClearHook();
|
||||||
|
//if (ith_has_section)
|
||||||
|
UnmapViewOfFile(::hookman);
|
||||||
|
|
||||||
|
CloseHandle(hSection);
|
||||||
|
CloseHandle(hMutex);
|
||||||
|
CloseHandle(hmMutex);
|
||||||
|
//} ITH_EXCEPT {}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//extern "C" {
|
||||||
|
DWORD NewHook(const HookParam &hp, LPCSTR lpname, DWORD flag)
|
||||||
|
{
|
||||||
|
std::string name = lpname;
|
||||||
|
int current = ::current_available - ::hookman;
|
||||||
|
if (current < MAX_HOOK) {
|
||||||
|
//flag &= 0xffff;
|
||||||
|
//if ((flag & HOOK_AUXILIARY) == 0)
|
||||||
|
flag |= HOOK_ADDITIONAL;
|
||||||
|
if (name[0] == '\0')
|
||||||
|
{
|
||||||
|
name = "UserHook" + std::to_string(user_hook_count++);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleOutput(("vnrcli:NewHook: try inserting hook: " + name).c_str());
|
||||||
|
|
||||||
|
// jichi 7/13/2014: This function would raise when too many hooks added
|
||||||
|
::hookman[current].InitHook(hp, name.c_str(), flag & 0xffff);
|
||||||
|
|
||||||
|
if (::hookman[current].InsertHook() == 0) {
|
||||||
|
ConsoleOutput(("vnrcli:NewHook: inserted hook: " + name).c_str());
|
||||||
|
NotifyHookInsert(hp, name.c_str());
|
||||||
|
} else
|
||||||
|
ConsoleOutput("vnrcli:NewHook:WARNING: failed to insert hook");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DWORD RemoveHook(DWORD addr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_HOOK; i++)
|
||||||
|
if (::hookman[i].Address ()== addr) {
|
||||||
|
::hookman[i].ClearHook();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
27
vnrhook64/src/main.h
Normal file
27
vnrhook64/src/main.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// main.h
|
||||||
|
// 8/23/2013 jichi
|
||||||
|
// Branch: ITH/IHF_DLL.h, rev 66
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include "include/const.h"
|
||||||
|
#include "include/types.h"
|
||||||
|
|
||||||
|
void ConsoleOutput(LPCSTR text); // jichi 12/25/2013: Used to return length of sent text
|
||||||
|
void NotifyHookInsert(HookParam hp, LPCSTR name);
|
||||||
|
void NotifyHookRemove(DWORD addr);
|
||||||
|
DWORD NewHook(const HookParam &hp, LPCSTR name, DWORD flag = HOOK_ENGINE);
|
||||||
|
DWORD RemoveHook(DWORD addr);
|
||||||
|
DWORD SwitchTrigger(DWORD on);
|
||||||
|
DWORD GetFunctionAddr(const char *name, DWORD *addr, DWORD *base, DWORD *size, LPWSTR *base_name);
|
||||||
|
|
||||||
|
// 10/14/2014 jichi: disable GDI hooks
|
||||||
|
void EnableGDIHooks();
|
||||||
|
void EnableGDIPlusHooks();
|
||||||
|
void DisableGDIHooks();
|
||||||
|
void DisableGDIPlusHooks();
|
||||||
|
bool GDIHooksEnabled();
|
||||||
|
bool GDIPlusHooksEnabled();
|
||||||
|
|
||||||
|
// EOF
|
127
vnrhook64/src/pipe.cc
Normal file
127
vnrhook64/src/pipe.cc
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// 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 "main.h"
|
||||||
|
#include "include/defs.h"
|
||||||
|
#include "hijack/texthook.h"
|
||||||
|
|
||||||
|
HANDLE hookPipe;
|
||||||
|
extern HMODULE currentModule;
|
||||||
|
|
||||||
|
DWORD WINAPI PipeManager(LPVOID unused)
|
||||||
|
{
|
||||||
|
enum { STANDARD_WAIT = 50 };
|
||||||
|
while (::running)
|
||||||
|
{
|
||||||
|
DWORD count;
|
||||||
|
BYTE buffer[PIPE_BUFFER_SIZE];
|
||||||
|
HANDLE hostPipe = ::hookPipe = INVALID_HANDLE_VALUE,
|
||||||
|
pipeAcquisitionMutex = CreateMutexW(nullptr, TRUE, ITH_GRANTPIPE_MUTEX);
|
||||||
|
|
||||||
|
while (::hookPipe == INVALID_HANDLE_VALUE || hostPipe == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
Sleep(STANDARD_WAIT);
|
||||||
|
if (::hookPipe == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
::hookPipe = CreateFileW(ITH_TEXT_PIPE, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
}
|
||||||
|
if (hostPipe == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
hostPipe = CreateFileW(ITH_COMMAND_PIPE, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*(DWORD*)buffer = GetCurrentProcessId();
|
||||||
|
WriteFile(::hookPipe, buffer, sizeof(DWORD), &count, nullptr);
|
||||||
|
|
||||||
|
ReleaseMutex(pipeAcquisitionMutex);
|
||||||
|
CloseHandle(pipeAcquisitionMutex);
|
||||||
|
|
||||||
|
ConsoleOutput("vnrcli:WaitForPipe: pipe connected");
|
||||||
|
ConsoleOutput("only read codes are supported on x64: engine disabled");
|
||||||
|
|
||||||
|
while (::running)
|
||||||
|
{
|
||||||
|
if (!ReadFile(hostPipe, buffer, PIPE_BUFFER_SIZE / 2, &count, nullptr)) // Artikash 5/21/2018: why / 2? wchar_t?
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DWORD command = *(DWORD*)buffer;
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case HOST_COMMAND_NEW_HOOK:
|
||||||
|
buffer[count] = 0;
|
||||||
|
NewHook(*(HookParam *)(buffer + sizeof(DWORD)), // Hook parameter
|
||||||
|
(LPSTR)(buffer + 4 + sizeof(HookParam)), // Hook name
|
||||||
|
0
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case HOST_COMMAND_REMOVE_HOOK:
|
||||||
|
{
|
||||||
|
TextHook *in = hookman;
|
||||||
|
for (int i = 0; i < currentHook; in++)
|
||||||
|
{
|
||||||
|
if (in->Address()) i++;
|
||||||
|
if (in->Address() == *(DWORD *)(buffer + sizeof(DWORD))) // Hook address
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (in->Address())
|
||||||
|
{
|
||||||
|
in->ClearHook();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HOST_COMMAND_DETACH:
|
||||||
|
::running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(::hookPipe);
|
||||||
|
CloseHandle(hostPipe);
|
||||||
|
}
|
||||||
|
FreeLibraryAndExitThread(::currentModule, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleOutput(LPCSTR text)
|
||||||
|
{
|
||||||
|
BYTE buffer[PIPE_BUFFER_SIZE];
|
||||||
|
*(DWORD*)buffer = HOST_NOTIFICATION;
|
||||||
|
*(DWORD*)(buffer + sizeof(DWORD)) = HOST_NOTIFICATION_TEXT;
|
||||||
|
strcpy((char*)buffer + sizeof(DWORD) * 2, text);
|
||||||
|
DWORD unused;
|
||||||
|
WriteFile(::hookPipe, buffer, strlen(text) + sizeof(DWORD) * 2, &unused, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifyHookInsert(HookParam hp, LPCSTR name)
|
||||||
|
{
|
||||||
|
BYTE buffer[PIPE_BUFFER_SIZE];
|
||||||
|
*(DWORD*)buffer = HOST_NOTIFICATION;
|
||||||
|
*(DWORD*)(buffer + sizeof(DWORD)) = HOST_NOTIFICATION_NEWHOOK;
|
||||||
|
*(HookParam*)(buffer + sizeof(DWORD) * 2) = hp;
|
||||||
|
strcpy((char*)buffer + sizeof(DWORD) * 2 + sizeof(HookParam), name);
|
||||||
|
DWORD unused;
|
||||||
|
WriteFile(::hookPipe, buffer, strlen(name) + sizeof(DWORD) * 2 + sizeof(HookParam), &unused, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifyHookRemove(DWORD addr)
|
||||||
|
{
|
||||||
|
BYTE buffer[sizeof(DWORD) * 3];
|
||||||
|
*(DWORD*)buffer = HOST_NOTIFICATION;
|
||||||
|
*(DWORD*)(buffer + sizeof(DWORD)) = HOST_NOTIFICATION_RMVHOOK;
|
||||||
|
*(DWORD*)(buffer + sizeof(DWORD) * 2) = addr;
|
||||||
|
DWORD unused;
|
||||||
|
WriteFile(::hookPipe, buffer, sizeof(DWORD) * 3, &unused, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
Loading…
x
Reference in New Issue
Block a user