forked from Public-Mirror/Textractor
use raii for process records and mutexes. remove a lot of manual resource management
This commit is contained in:
parent
1915008d00
commit
c877d9cd31
@ -1,4 +1,5 @@
|
|||||||
#include "extensions.h"
|
#include "extensions.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
static std::optional<Extension> LoadExtension(QString extenName)
|
static std::optional<Extension> LoadExtension(QString extenName)
|
||||||
{
|
{
|
||||||
@ -13,13 +14,13 @@ static std::optional<Extension> LoadExtension(QString extenName)
|
|||||||
|
|
||||||
void Extension::Load(QString extenName)
|
void Extension::Load(QString extenName)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::shared_mutex> extenLock(extenMutex);
|
LOCK(extenMutex);
|
||||||
if (auto extension = LoadExtension(extenName)) extensions.push_back(extension.value());
|
if (auto extension = LoadExtension(extenName)) extensions.push_back(extension.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Extension::SendToBack(QString extenName)
|
void Extension::SendToBack(QString extenName)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::shared_mutex> extenLock(extenMutex);
|
LOCK(extenMutex);
|
||||||
Extension* extenIter = std::find_if(extensions.begin(), extensions.end(), [&](Extension extension) { return extension.name == extenName; });
|
Extension* extenIter = std::find_if(extensions.begin(), extensions.end(), [&](Extension extension) { return extension.name == extenName; });
|
||||||
Extension extension = *extenIter;
|
Extension extension = *extenIter;
|
||||||
extensions.erase(extenIter);
|
extensions.erase(extenIter);
|
||||||
@ -28,13 +29,14 @@ void Extension::SendToBack(QString extenName)
|
|||||||
|
|
||||||
void Extension::Unload(QString extenName)
|
void Extension::Unload(QString extenName)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::shared_mutex> extenLock(extenMutex);
|
LOCK(extenMutex);
|
||||||
extensions.erase(std::find_if(extensions.begin(), extensions.end(), [&](Extension extension) { return extension.name == extenName; }));
|
extensions.erase(std::find_if(extensions.begin(), extensions.end(), [&](Extension extension) { return extension.name == extenName; }));
|
||||||
FreeLibrary(GetModuleHandleW(extenName.toStdWString().c_str()));
|
FreeLibrary(GetModuleHandleW(extenName.toStdWString().c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QString> Extension::GetNames()
|
QVector<QString> Extension::GetNames()
|
||||||
{
|
{
|
||||||
|
std::shared_lock sharedLock(extenMutex);
|
||||||
QVector<QString> ret;
|
QVector<QString> ret;
|
||||||
for (auto extension : extensions) ret.push_back(extension.name);
|
for (auto extension : extensions) ret.push_back(extension.name);
|
||||||
return ret;
|
return ret;
|
||||||
@ -50,7 +52,7 @@ bool Extension::DispatchSentence(std::wstring& sentence, std::unordered_map<std:
|
|||||||
InfoForExtension* miscInfoTraverser = &miscInfoLinkedList;
|
InfoForExtension* miscInfoTraverser = &miscInfoLinkedList;
|
||||||
for (auto& i : miscInfo) miscInfoTraverser = miscInfoTraverser->next = new InfoForExtension{ i.first.c_str(), i.second, nullptr };
|
for (auto& i : miscInfo) miscInfoTraverser = miscInfoTraverser->next = new InfoForExtension{ i.first.c_str(), i.second, nullptr };
|
||||||
|
|
||||||
std::shared_lock<std::shared_mutex> extenLock(extenMutex);
|
std::shared_lock sharedLock(extenMutex);
|
||||||
for (auto extension : extensions)
|
for (auto extension : extensions)
|
||||||
{
|
{
|
||||||
wchar_t* nextBuffer = extension.callback(sentenceBuffer, &miscInfoLinkedList);
|
wchar_t* nextBuffer = extension.callback(sentenceBuffer, &miscInfoLinkedList);
|
||||||
|
108
GUI/host/host.cc
108
GUI/host/host.cc
@ -9,20 +9,45 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
struct ProcessRecord
|
class ProcessRecord
|
||||||
{
|
{
|
||||||
HANDLE processHandle;
|
public:
|
||||||
HANDLE sectionMutex;
|
ProcessRecord(DWORD processId, HANDLE hostPipe) :
|
||||||
|
hostPipe(hostPipe),
|
||||||
|
section(OpenFileMappingW(FILE_MAP_READ, FALSE, (ITH_SECTION_ + std::to_wstring(processId)).c_str())),
|
||||||
|
sectionMap(MapViewOfFile(section, FILE_MAP_READ, 0, 0, HOOK_SECTION_SIZE / 2)), // jichi 1/16/2015: Changed to half to hook section size
|
||||||
|
sectionMutex(ITH_HOOKMAN_MUTEX_ + std::to_wstring(processId))
|
||||||
|
{}
|
||||||
|
|
||||||
|
~ProcessRecord()
|
||||||
|
{
|
||||||
|
UnmapViewOfFile(sectionMap);
|
||||||
|
CloseHandle(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextHook GetHook(uint64_t addr)
|
||||||
|
{
|
||||||
|
if (sectionMap == nullptr) return {};
|
||||||
|
LOCK(sectionMutex);
|
||||||
|
auto hooks = (const TextHook*)sectionMap;
|
||||||
|
for (int i = 0; i < MAX_HOOK; ++i)
|
||||||
|
if (hooks[i].hp.insertion_address == addr) return hooks[i];
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE hostPipe;
|
||||||
|
|
||||||
|
private:
|
||||||
HANDLE section;
|
HANDLE section;
|
||||||
LPVOID sectionMap;
|
LPVOID sectionMap;
|
||||||
HANDLE hostPipe;
|
WinMutex sectionMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
ThreadEventCallback OnCreate, OnRemove;
|
ThreadEventCallback OnCreate, OnRemove;
|
||||||
ProcessEventCallback OnAttach, OnDetach;
|
ProcessEventCallback OnAttach, OnDetach;
|
||||||
|
|
||||||
std::unordered_map<ThreadParam, std::shared_ptr<TextThread>> textThreadsByParams;
|
std::unordered_map<ThreadParam, std::shared_ptr<TextThread>> textThreadsByParams;
|
||||||
std::unordered_map<DWORD, ProcessRecord> processRecordsByIds;
|
std::unordered_map<DWORD, std::unique_ptr<ProcessRecord>> processRecordsByIds;
|
||||||
|
|
||||||
std::recursive_mutex hostMutex;
|
std::recursive_mutex hostMutex;
|
||||||
|
|
||||||
@ -51,31 +76,19 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterProcess(DWORD pid, HANDLE hostPipe)
|
void RegisterProcess(DWORD processId, HANDLE hostPipe)
|
||||||
{
|
{
|
||||||
LOCK(hostMutex);
|
LOCK(hostMutex);
|
||||||
ProcessRecord record;
|
processRecordsByIds.insert({ processId, std::make_unique<ProcessRecord>(processId, hostPipe) });
|
||||||
record.hostPipe = hostPipe;
|
OnAttach(processId);
|
||||||
record.section = OpenFileMappingW(FILE_MAP_READ, FALSE, (ITH_SECTION_ + std::to_wstring(pid)).c_str());
|
|
||||||
record.sectionMap = MapViewOfFile(record.section, FILE_MAP_READ, 0, 0, HOOK_SECTION_SIZE / 2); // jichi 1/16/2015: Changed to half to hook section size
|
|
||||||
record.processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
|
||||||
record.sectionMutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, (ITH_HOOKMAN_MUTEX_ + std::to_wstring(pid)).c_str());
|
|
||||||
processRecordsByIds[pid] = record;
|
|
||||||
OnAttach(pid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnregisterProcess(DWORD pid)
|
void UnregisterProcess(DWORD processId)
|
||||||
{
|
{
|
||||||
|
OnDetach(processId);
|
||||||
LOCK(hostMutex);
|
LOCK(hostMutex);
|
||||||
ProcessRecord pr = processRecordsByIds[pid];
|
processRecordsByIds.erase(processId);
|
||||||
if (!pr.hostPipe) return;
|
RemoveThreads([&](ThreadParam tp) { return tp.pid == processId; });
|
||||||
CloseHandle(pr.sectionMutex);
|
|
||||||
UnmapViewOfFile(pr.sectionMap);
|
|
||||||
CloseHandle(pr.processHandle);
|
|
||||||
CloseHandle(pr.section);
|
|
||||||
processRecordsByIds[pid] = {};
|
|
||||||
RemoveThreads([&](ThreadParam tp) { return tp.pid == pid; });
|
|
||||||
OnDetach(pid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartPipe()
|
void StartPipe()
|
||||||
@ -149,7 +162,7 @@ namespace Host
|
|||||||
// Artikash 7/25/2018: This is only called when Textractor is closed, at which point Windows should free everything itself...right?
|
// Artikash 7/25/2018: This is only called when Textractor is closed, at which point Windows should free everything itself...right?
|
||||||
#ifdef _DEBUG // Check memory leaks
|
#ifdef _DEBUG // Check memory leaks
|
||||||
LOCK(hostMutex);
|
LOCK(hostMutex);
|
||||||
for (auto[pid, pr] : processRecordsByIds) UnregisterProcess(pid);
|
processRecordsByIds.clear();
|
||||||
textThreadsByParams.clear();
|
textThreadsByParams.clear();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -204,54 +217,37 @@ namespace Host
|
|||||||
|
|
||||||
void DetachProcess(DWORD processId)
|
void DetachProcess(DWORD processId)
|
||||||
{
|
{
|
||||||
|
LOCK(hostMutex);
|
||||||
auto command = HOST_COMMAND_DETACH;
|
auto command = HOST_COMMAND_DETACH;
|
||||||
WriteFile(processRecordsByIds[processId].hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
WriteFile(processRecordsByIds.at(processId)->hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertHook(DWORD pid, HookParam hp, std::string name)
|
void InsertHook(DWORD processId, HookParam hp, std::string name)
|
||||||
{
|
{
|
||||||
|
LOCK(hostMutex);
|
||||||
auto command = InsertHookCmd(hp, name);
|
auto command = InsertHookCmd(hp, name);
|
||||||
WriteFile(processRecordsByIds[pid].hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
WriteFile(processRecordsByIds.at(processId)->hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveHook(DWORD pid, uint64_t addr)
|
void RemoveHook(DWORD processId, uint64_t addr)
|
||||||
{
|
{
|
||||||
|
LOCK(hostMutex);
|
||||||
auto command = RemoveHookCmd(addr);
|
auto command = RemoveHookCmd(addr);
|
||||||
WriteFile(processRecordsByIds[pid].hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
WriteFile(processRecordsByIds.at(processId)->hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
HookParam GetHookParam(DWORD pid, uint64_t addr)
|
HookParam GetHookParam(DWORD processId, uint64_t addr)
|
||||||
{
|
{
|
||||||
|
if (processId == 0) return {};
|
||||||
LOCK(hostMutex);
|
LOCK(hostMutex);
|
||||||
HookParam ret = {};
|
return processRecordsByIds.at(processId)->GetHook(addr).hp;
|
||||||
ProcessRecord pr = processRecordsByIds[pid];
|
|
||||||
if (pr.sectionMap == nullptr) return ret;
|
|
||||||
WaitForSingleObject(pr.sectionMutex, 0);
|
|
||||||
const TextHook* hooks = (const TextHook*)pr.sectionMap;
|
|
||||||
for (int i = 0; i < MAX_HOOK; ++i)
|
|
||||||
if (hooks[i].hp.insertion_address == addr)
|
|
||||||
ret = hooks[i].hp;
|
|
||||||
ReleaseMutex(pr.sectionMutex);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring GetHookName(DWORD pid, uint64_t addr)
|
std::wstring GetHookName(DWORD processId, uint64_t addr)
|
||||||
{
|
{
|
||||||
if (pid == 0) return L"Console";
|
if (processId == 0) return L"Console";
|
||||||
LOCK(hostMutex);
|
LOCK(hostMutex);
|
||||||
std::string buffer = "";
|
return StringToWideString(processRecordsByIds.at(processId)->GetHook(addr).hookName, CP_UTF8);
|
||||||
ProcessRecord pr = processRecordsByIds[pid];
|
|
||||||
if (pr.sectionMap == nullptr) return L"";
|
|
||||||
WaitForSingleObject(pr.sectionMutex, 0);
|
|
||||||
const TextHook* hooks = (const TextHook*)pr.sectionMap;
|
|
||||||
for (int i = 0; i < MAX_HOOK; ++i)
|
|
||||||
if (hooks[i].hp.insertion_address == addr)
|
|
||||||
{
|
|
||||||
buffer.resize(hooks[i].name_length);
|
|
||||||
ReadProcessMemory(pr.processHandle, hooks[i].hook_name, buffer.data(), hooks[i].name_length, nullptr);
|
|
||||||
}
|
|
||||||
ReleaseMutex(pr.sectionMutex);
|
|
||||||
return StringToWideString(buffer, CP_UTF8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TextThread> GetThread(ThreadParam tp)
|
std::shared_ptr<TextThread> GetThread(ThreadParam tp)
|
||||||
|
@ -15,15 +15,15 @@ namespace Host
|
|||||||
void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onRemove, TextThread::OutputCallback output);
|
void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onRemove, TextThread::OutputCallback output);
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
bool InjectProcess(DWORD pid, DWORD timeout = 5000);
|
bool InjectProcess(DWORD processId, DWORD timeout = 5000);
|
||||||
void DetachProcess(DWORD pid);
|
void DetachProcess(DWORD processId);
|
||||||
|
|
||||||
void InsertHook(DWORD pid, HookParam hp, std::string name = "");
|
void InsertHook(DWORD processId, HookParam hp, std::string name = "");
|
||||||
void RemoveHook(DWORD pid, uint64_t addr);
|
void RemoveHook(DWORD processId, uint64_t addr);
|
||||||
|
|
||||||
HookParam GetHookParam(DWORD pid, uint64_t addr);
|
HookParam GetHookParam(DWORD processId, uint64_t addr);
|
||||||
inline HookParam GetHookParam(ThreadParam tp) { return GetHookParam(tp.pid, tp.hook); }
|
inline HookParam GetHookParam(ThreadParam tp) { return GetHookParam(tp.pid, tp.hook); }
|
||||||
std::wstring GetHookName(DWORD pid, uint64_t addr);
|
std::wstring GetHookName(DWORD processId, uint64_t addr);
|
||||||
inline std::wstring GetHookName(ThreadParam tp) { return GetHookName(tp.pid, tp.hook); }
|
inline std::wstring GetHookName(ThreadParam tp) { return GetHookName(tp.pid, tp.hook); }
|
||||||
|
|
||||||
std::shared_ptr<TextThread> GetThread(ThreadParam tp);
|
std::shared_ptr<TextThread> GetThread(ThreadParam tp);
|
||||||
|
@ -59,8 +59,9 @@ MainWindow::~MainWindow()
|
|||||||
settings.setValue("Flush_Delay", TextThread::flushDelay);
|
settings.setValue("Flush_Delay", TextThread::flushDelay);
|
||||||
settings.setValue("Max_Buffer_Size", TextThread::maxBufferSize);
|
settings.setValue("Max_Buffer_Size", TextThread::maxBufferSize);
|
||||||
settings.sync();
|
settings.sync();
|
||||||
Host::Close();
|
|
||||||
delete ui;
|
delete ui;
|
||||||
|
|
||||||
|
Host::Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::AddProcess(unsigned processId)
|
void MainWindow::AddProcess(unsigned processId)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// 8/23/2013 jichi
|
// 8/23/2013 jichi
|
||||||
// Branch: ITH/common.h, rev 128
|
// Branch: ITH/common.h, rev 128
|
||||||
|
|
||||||
enum { MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 0x1000, SHIFT_JIS = 932, MAX_THREAD_COUNT = 250, MAX_MODULE_SIZE = 120 };
|
enum { MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 2000, SHIFT_JIS = 932, MAX_THREAD_COUNT = 250, MAX_MODULE_SIZE = 120, HOOK_NAME_SIZE = 30 };
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -40,12 +40,22 @@ struct ThreadParam // From hook, used internally by host as well
|
|||||||
template <> struct std::hash<ThreadParam> { size_t operator()(const ThreadParam& tp) const { return std::hash<int64_t>()((tp.pid + tp.hook) ^ (tp.retn + tp.spl)); } };
|
template <> struct std::hash<ThreadParam> { size_t operator()(const ThreadParam& tp) const { return std::hash<int64_t>()((tp.pid + tp.hook) ^ (tp.retn + tp.spl)); } };
|
||||||
static bool operator==(const ThreadParam& one, const ThreadParam& two) { return one.pid == two.pid && one.hook == two.hook && one.retn == two.retn && one.spl == two.spl; }
|
static bool operator==(const ThreadParam& one, const ThreadParam& two) { return one.pid == two.pid && one.hook == two.hook && one.retn == two.retn && one.spl == two.spl; }
|
||||||
|
|
||||||
|
class WinMutex
|
||||||
|
{
|
||||||
|
HANDLE mutex;
|
||||||
|
public:
|
||||||
|
WinMutex(std::wstring name) : mutex(CreateMutexW(nullptr, false, name.c_str())) {}
|
||||||
|
~WinMutex() { ReleaseMutex(mutex); CloseHandle(mutex); }
|
||||||
|
void lock() { WaitForSingleObject(mutex, 0); }
|
||||||
|
void unlock() { ReleaseMutex(mutex); }
|
||||||
|
};
|
||||||
|
|
||||||
struct InsertHookCmd // From host
|
struct InsertHookCmd // From host
|
||||||
{
|
{
|
||||||
InsertHookCmd(HookParam hp, std::string name = "") : hp(hp) { strcpy_s<MESSAGE_SIZE>(this->name, name.c_str()); };
|
InsertHookCmd(HookParam hp, std::string name = "") : hp(hp) { strcpy_s<HOOK_NAME_SIZE>(this->name, name.c_str()); };
|
||||||
int command = HOST_COMMAND_NEW_HOOK;
|
int command = HOST_COMMAND_NEW_HOOK;
|
||||||
HookParam hp;
|
HookParam hp;
|
||||||
char name[MESSAGE_SIZE] = {};
|
char name[HOOK_NAME_SIZE] = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RemoveHookCmd // From host
|
struct RemoveHookCmd // From host
|
||||||
@ -69,4 +79,4 @@ struct HookRemovedNotif // From hook
|
|||||||
uint64_t address;
|
uint64_t address;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LOCK(mutex) std::lock_guard<std::recursive_mutex> lock(mutex)
|
#define LOCK(mutex) std::lock_guard lock(mutex)
|
||||||
|
@ -102,16 +102,14 @@ namespace { // unnamed
|
|||||||
|
|
||||||
bool TextHook::InsertHook()
|
bool TextHook::InsertHook()
|
||||||
{
|
{
|
||||||
bool ret = false;
|
|
||||||
//ConsoleOutput("vnrcli:InsertHook: enter");
|
//ConsoleOutput("vnrcli:InsertHook: enter");
|
||||||
WaitForSingleObject(hmMutex, 0);
|
LOCK(*sectionMutex);
|
||||||
if (hp.type & DIRECT_READ) ret = InsertReadCode();
|
if (hp.type & DIRECT_READ) return InsertReadCode();
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
else ret = InsertHookCode();
|
else return InsertHookCode();
|
||||||
#endif
|
#endif
|
||||||
ReleaseMutex(hmMutex);
|
|
||||||
//ConsoleOutput("vnrcli:InsertHook: leave");
|
//ConsoleOutput("vnrcli:InsertHook: leave");
|
||||||
return ret;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
@ -222,16 +220,8 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn)
|
|||||||
|
|
||||||
bool TextHook::InsertHookCode()
|
bool TextHook::InsertHookCode()
|
||||||
{
|
{
|
||||||
bool ret = false;
|
|
||||||
// jichi 9/17/2013: might raise 0xC0000005 AccessViolationException on win7
|
// jichi 9/17/2013: might raise 0xC0000005 AccessViolationException on win7
|
||||||
__try { ret = UnsafeInsertHookCode(); }
|
// Artikash 10/30/2018: No, I think that's impossible now that I moved to minhook
|
||||||
__except (1) {};
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool TextHook::UnsafeInsertHookCode()
|
|
||||||
{
|
|
||||||
if (hp.type & MODULE_OFFSET) // Map hook offset to real address
|
if (hp.type & MODULE_OFFSET) // Map hook offset to real address
|
||||||
if (hp.type & FUNCTION_OFFSET)
|
if (hp.type & FUNCTION_OFFSET)
|
||||||
if (FARPROC function = GetProcAddress(GetModuleHandleW(hp.module), hp.function)) hp.insertion_address += (uint64_t)function;
|
if (FARPROC function = GetProcAddress(GetModuleHandleW(hp.module), hp.function)) hp.insertion_address += (uint64_t)function;
|
||||||
@ -243,7 +233,7 @@ bool TextHook::UnsafeInsertHookCode()
|
|||||||
if (hp.codepage == 0) hp.codepage = SHIFT_JIS; // Use Shift-JIS unless custom encoding was specified
|
if (hp.codepage == 0) hp.codepage = SHIFT_JIS; // Use Shift-JIS unless custom encoding was specified
|
||||||
|
|
||||||
BYTE* original;
|
BYTE* 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, (void**)&original))
|
||||||
if (err == MH_ERROR_ALREADY_CREATED)
|
if (err == MH_ERROR_ALREADY_CREATED)
|
||||||
{
|
{
|
||||||
@ -334,14 +324,13 @@ bool TextHook::InsertReadCode()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHook::InitHook(const HookParam &h, LPCSTR name, WORD set_flag)
|
void TextHook::InitHook(const HookParam &h, LPCSTR name, DWORD set_flag)
|
||||||
{
|
{
|
||||||
WaitForSingleObject(hmMutex, 0);
|
LOCK(*sectionMutex);
|
||||||
hp = h;
|
hp = h;
|
||||||
hp.insertion_address = hp.address;
|
hp.insertion_address = hp.address;
|
||||||
hp.type |= set_flag;
|
hp.type |= set_flag;
|
||||||
if (name && name != hook_name) SetHookName(name);
|
strcpy_s<HOOK_NAME_SIZE>(hookName, name);
|
||||||
ReleaseMutex(hmMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHook::RemoveHookCode()
|
void TextHook::RemoveHookCode()
|
||||||
@ -358,22 +347,12 @@ void TextHook::RemoveReadCode()
|
|||||||
|
|
||||||
void TextHook::ClearHook()
|
void TextHook::ClearHook()
|
||||||
{
|
{
|
||||||
WaitForSingleObject(hmMutex, 0);
|
LOCK(*sectionMutex);
|
||||||
if (hook_name) ConsoleOutput(("Textractor: removing hook: " + std::string(hook_name)).c_str());
|
ConsoleOutput(("Textractor: removing hook: " + std::string(hookName)).c_str());
|
||||||
if (hp.type & DIRECT_READ) RemoveReadCode();
|
if (hp.type & DIRECT_READ) RemoveReadCode();
|
||||||
else RemoveHookCode();
|
else RemoveHookCode();
|
||||||
NotifyHookRemove(hp.insertion_address);
|
NotifyHookRemove(hp.insertion_address);
|
||||||
if (hook_name) delete[] hook_name;
|
|
||||||
memset(this, 0, sizeof(TextHook)); // jichi 11/30/2013: This is the original code of ITH
|
memset(this, 0, sizeof(TextHook)); // jichi 11/30/2013: This is the original code of ITH
|
||||||
ReleaseMutex(hmMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextHook::SetHookName(LPCSTR name)
|
|
||||||
{
|
|
||||||
name_length = strlen(name) + 1;
|
|
||||||
if (hook_name) delete[] hook_name;
|
|
||||||
hook_name = new char[name_length];
|
|
||||||
strcpy(hook_name, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextHook::GetLength(DWORD base, DWORD in)
|
int TextHook::GetLength(DWORD base, DWORD in)
|
||||||
|
@ -20,32 +20,28 @@ class TextHook
|
|||||||
{
|
{
|
||||||
bool InsertHookCode();
|
bool InsertHookCode();
|
||||||
bool InsertReadCode();
|
bool InsertReadCode();
|
||||||
bool UnsafeInsertHookCode();
|
|
||||||
DWORD UnsafeSend(DWORD dwDataBase, DWORD dwRetn);
|
DWORD UnsafeSend(DWORD dwDataBase, DWORD dwRetn);
|
||||||
|
int GetLength(DWORD base, DWORD in); // jichi 12/25/2013: Return 0 if failed
|
||||||
void RemoveHookCode();
|
void RemoveHookCode();
|
||||||
void RemoveReadCode();
|
void RemoveReadCode();
|
||||||
void SetHookName(LPCSTR name);
|
|
||||||
public:
|
public:
|
||||||
HookParam hp;
|
HookParam hp;
|
||||||
LPSTR hook_name;
|
char hookName[HOOK_NAME_SIZE];
|
||||||
int name_length;
|
|
||||||
BYTE trampoline[120];
|
BYTE trampoline[120];
|
||||||
HANDLE readerHandle;
|
HANDLE readerHandle;
|
||||||
|
|
||||||
bool InsertHook();
|
bool InsertHook();
|
||||||
void InitHook(const HookParam &hp, LPCSTR name = 0, WORD set_flag = 0);
|
void InitHook(const HookParam &hp, LPCSTR name, DWORD set_flag);
|
||||||
DWORD Send(DWORD dwDataBase, DWORD dwRetn);
|
DWORD Send(DWORD dwDataBase, DWORD dwRetn);
|
||||||
void ClearHook();
|
void ClearHook();
|
||||||
int GetLength(DWORD base, DWORD in); // jichi 12/25/2013: Return 0 if failed
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { MAX_HOOK = 300 };
|
enum { MAX_HOOK = 300 };
|
||||||
enum { HOOK_SECTION_SIZE = MAX_HOOK * sizeof(TextHook) * 2, HOOK_BUFFER_SIZE = MAX_HOOK * sizeof(TextHook) };
|
enum { HOOK_SECTION_SIZE = MAX_HOOK * sizeof(TextHook) * 2, HOOK_BUFFER_SIZE = MAX_HOOK * sizeof(TextHook) };
|
||||||
|
|
||||||
extern TextHook *hookman;
|
extern TextHook *hookman;
|
||||||
|
|
||||||
extern bool running;
|
extern bool running;
|
||||||
|
extern HANDLE hookPipe;
|
||||||
extern HANDLE hookPipe, hmMutex;
|
extern std::unique_ptr<WinMutex> sectionMutex;
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
@ -21,7 +21,7 @@ HANDLE hSection;
|
|||||||
bool running;
|
bool running;
|
||||||
int currentHook = 0, userhookCount = 0;
|
int currentHook = 0, userhookCount = 0;
|
||||||
DWORD trigger = 0;
|
DWORD trigger = 0;
|
||||||
HANDLE hmMutex;
|
std::unique_ptr<WinMutex> sectionMutex;
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
|
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
|
||||||
{
|
{
|
||||||
@ -29,7 +29,7 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
|
|||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
{
|
{
|
||||||
::hmMutex = CreateMutexW(nullptr, FALSE, (ITH_HOOKMAN_MUTEX_ + std::to_wstring(GetCurrentProcessId())).c_str());
|
sectionMutex = std::make_unique<WinMutex>(ITH_HOOKMAN_MUTEX_ + std::to_wstring(GetCurrentProcessId()));
|
||||||
if (GetLastError() == ERROR_ALREADY_EXISTS) return FALSE;
|
if (GetLastError() == ERROR_ALREADY_EXISTS) return FALSE;
|
||||||
DisableThreadLibraryCalls(hModule);
|
DisableThreadLibraryCalls(hModule);
|
||||||
|
|
||||||
@ -55,7 +55,6 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
|
|||||||
|
|
||||||
CloseHandle(::hookPipe);
|
CloseHandle(::hookPipe);
|
||||||
CloseHandle(hSection);
|
CloseHandle(hSection);
|
||||||
CloseHandle(hmMutex);
|
|
||||||
//} ITH_EXCEPT {}
|
//} ITH_EXCEPT {}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user