mirror of
https://github.com/Artikash/Textractor.git
synced 2024-12-23 17:04:12 +08:00
reorganize, everything
This commit is contained in:
parent
98649ffbcc
commit
446ff71464
@ -2,7 +2,6 @@
|
|||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
#include "extensions.h"
|
#include "extensions.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "../vnrhook/include/const.h"
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
@ -78,9 +77,9 @@ void MainWindow::AddThread(TextThread* thread)
|
|||||||
{
|
{
|
||||||
ttCombo->addItem(
|
ttCombo->addItem(
|
||||||
TextThreadString(thread) +
|
TextThreadString(thread) +
|
||||||
QString::fromStdWString(Host::GetHookName(thread->GetThreadParameter().pid, thread->GetThreadParameter().hook)) +
|
QString::fromStdWString(Host::GetHookName(thread->GetThreadParam().pid, thread->GetThreadParam().hook)) +
|
||||||
" (" +
|
" (" +
|
||||||
GenerateCode(Host::GetHookParam(thread->GetThreadParameter()), thread->GetThreadParameter().pid) +
|
GenerateCode(Host::GetHookParam(thread->GetThreadParam()), thread->GetThreadParam().pid) +
|
||||||
")"
|
")"
|
||||||
);
|
);
|
||||||
thread->RegisterOutputCallBack([&](TextThread* thread, std::wstring output)
|
thread->RegisterOutputCallBack([&](TextThread* thread, std::wstring output)
|
||||||
@ -116,7 +115,7 @@ void MainWindow::ThreadOutput(TextThread* thread, QString output)
|
|||||||
|
|
||||||
QString MainWindow::TextThreadString(TextThread* thread)
|
QString MainWindow::TextThreadString(TextThread* thread)
|
||||||
{
|
{
|
||||||
ThreadParameter tp = thread->GetThreadParameter();
|
ThreadParam tp = thread->GetThreadParam();
|
||||||
return QString("%1:%2:%3:%4: ").arg(
|
return QString("%1:%2:%3:%4: ").arg(
|
||||||
QString::number(tp.pid),
|
QString::number(tp.pid),
|
||||||
QString::number(tp.hook, 16),
|
QString::number(tp.hook, 16),
|
||||||
@ -125,7 +124,7 @@ QString MainWindow::TextThreadString(TextThread* thread)
|
|||||||
).toUpper();
|
).toUpper();
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadParameter MainWindow::ParseTextThreadString(QString textThreadString)
|
ThreadParam MainWindow::ParseTextThreadString(QString textThreadString)
|
||||||
{
|
{
|
||||||
QStringList threadParam = textThreadString.split(":");
|
QStringList threadParam = textThreadString.split(":");
|
||||||
return { threadParam[0].toUInt(), threadParam[1].toULongLong(nullptr, 16), threadParam[2].toULongLong(nullptr, 16), threadParam[3].toULongLong(nullptr, 16) };
|
return { threadParam[0].toUInt(), threadParam[1].toULongLong(nullptr, 16), threadParam[2].toULongLong(nullptr, 16), threadParam[3].toULongLong(nullptr, 16) };
|
||||||
@ -149,9 +148,9 @@ std::unordered_map<std::string, int> MainWindow::GetInfoForExtensions(TextThread
|
|||||||
{
|
{
|
||||||
{ "current select", (int)ttCombo->currentText().startsWith(TextThreadString(thread)) },
|
{ "current select", (int)ttCombo->currentText().startsWith(TextThreadString(thread)) },
|
||||||
{ "text number", 0 },
|
{ "text number", 0 },
|
||||||
{ "process id", thread->GetThreadParameter().pid },
|
{ "process id", thread->GetThreadParam().pid },
|
||||||
{ "hook address", (int)thread->GetThreadParameter().hook },
|
{ "hook address", (int)thread->GetThreadParam().hook },
|
||||||
{ "hook address (upper 32 bits)", (int)(thread->GetThreadParameter().hook >> 32) }
|
{ "hook address (upper 32 bits)", (int)(thread->GetThreadParam().hook >> 32) }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +160,7 @@ QVector<HookParam> MainWindow::GetAllHooks(DWORD processId)
|
|||||||
QVector<HookParam> hooks;
|
QVector<HookParam> hooks;
|
||||||
for (int i = 0; i < ttCombo->count(); ++i)
|
for (int i = 0; i < ttCombo->count(); ++i)
|
||||||
{
|
{
|
||||||
ThreadParameter tp = ParseTextThreadString(ttCombo->itemText(i));
|
ThreadParam tp = ParseTextThreadString(ttCombo->itemText(i));
|
||||||
if (tp.pid == processId && !addresses.contains(tp.hook))
|
if (tp.pid == processId && !addresses.contains(tp.hook))
|
||||||
{
|
{
|
||||||
addresses.insert(tp.hook);
|
addresses.insert(tp.hook);
|
||||||
|
@ -44,7 +44,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QString TextThreadString(TextThread* thread);
|
QString TextThreadString(TextThread* thread);
|
||||||
ThreadParameter ParseTextThreadString(QString textThreadString);
|
ThreadParam ParseTextThreadString(QString textThreadString);
|
||||||
DWORD GetSelectedProcessId();
|
DWORD GetSelectedProcessId();
|
||||||
void ReloadExtensions();
|
void ReloadExtensions();
|
||||||
std::unordered_map<std::string, int> GetInfoForExtensions(TextThread* thread);
|
std::unordered_map<std::string, int> GetInfoForExtensions(TextThread* thread);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "../vnrhook/include/const.h"
|
#include "const.h"
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define MISC_H
|
#define MISC_H
|
||||||
|
|
||||||
#include "qtcommon.h"
|
#include "qtcommon.h"
|
||||||
#include "../host/host.h"
|
#include "pipe.h"
|
||||||
|
|
||||||
QString GetFullModuleName(DWORD processId, HMODULE module = NULL);
|
QString GetFullModuleName(DWORD processId, HMODULE module = NULL);
|
||||||
QString GetModuleName(DWORD processId, HMODULE module = NULL);
|
QString GetModuleName(DWORD processId, HMODULE module = NULL);
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
set(vnrhost_src
|
set(vnrhost_src
|
||||||
host.h
|
|
||||||
pipe.h
|
|
||||||
textthread.h
|
|
||||||
winmutex.h
|
|
||||||
host.cc
|
host.cc
|
||||||
pipe.cc
|
pipe.cc
|
||||||
textthread.cc
|
textthread.cc
|
||||||
|
67
host/host.cc
67
host/host.cc
@ -4,21 +4,33 @@
|
|||||||
|
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
#include "pipe.h"
|
#include "pipe.h"
|
||||||
#include "winmutex.h"
|
#include "const.h"
|
||||||
#include "../vnrhook/include/const.h"
|
#include "defs.h"
|
||||||
#include "../vnrhook/include/defs.h"
|
#include "../vnrhook/hijack/texthook.h"
|
||||||
#include "../vnrhook/include/types.h"
|
|
||||||
|
|
||||||
|
struct ProcessRecord
|
||||||
struct ThreadParameterHasher
|
|
||||||
{
|
{
|
||||||
size_t operator()(const ThreadParameter& tp) const
|
HANDLE processHandle;
|
||||||
{
|
HANDLE sectionMutex;
|
||||||
return std::hash<__int64>()(tp.pid << 6) + std::hash<__int64>()(tp.hook) + std::hash<__int64>()(tp.retn) + std::hash<__int64>()(tp.spl);
|
HANDLE section;
|
||||||
}
|
LPVOID sectionMap;
|
||||||
|
HANDLE hostPipe;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<ThreadParameter, TextThread*, ThreadParameterHasher> textThreadsByParams;
|
// Artikash 5/31/2018: required for unordered_map to work with struct key
|
||||||
|
template <> struct std::hash<ThreadParam> { size_t operator()(const ThreadParam& tp) const { return std::hash<__int64>()((tp.pid + tp.hook) ^ (tp.retn + tp.spl)); } };
|
||||||
|
bool operator==(const ThreadParam& one, const ThreadParam& two) { return memcmp(&one, &two, sizeof(ThreadParam)) == 0; }
|
||||||
|
|
||||||
|
// Artikash 7/20/2018: similar to std::lock guard but use Winapi objects for cross process comms
|
||||||
|
class MutexLocker
|
||||||
|
{
|
||||||
|
HANDLE mutex;
|
||||||
|
public:
|
||||||
|
MutexLocker(HANDLE mutex) : mutex(mutex) { WaitForSingleObject(mutex, 0); }
|
||||||
|
~MutexLocker() { if (mutex != INVALID_HANDLE_VALUE && mutex != nullptr) ReleaseMutex(mutex); }
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<ThreadParam, TextThread*> textThreadsByParams;
|
||||||
std::unordered_map<DWORD, ProcessRecord> processRecordsByIds;
|
std::unordered_map<DWORD, ProcessRecord> processRecordsByIds;
|
||||||
|
|
||||||
std::recursive_mutex hostMutex;
|
std::recursive_mutex hostMutex;
|
||||||
@ -28,7 +40,7 @@ ProcessEventCallback OnAttach, OnDetach;
|
|||||||
|
|
||||||
DWORD DUMMY[100];
|
DWORD DUMMY[100];
|
||||||
|
|
||||||
ThreadParameter CONSOLE{ 0, -1UL, -1UL, -1UL };
|
ThreadParam CONSOLE{ 0, -1ULL, -1ULL, -1ULL };
|
||||||
|
|
||||||
#define HOST_LOCK std::lock_guard<std::recursive_mutex> hostLocker(hostMutex) // Synchronized scope for accessing private data
|
#define HOST_LOCK std::lock_guard<std::recursive_mutex> hostLocker(hostMutex) // Synchronized scope for accessing private data
|
||||||
|
|
||||||
@ -38,7 +50,7 @@ namespace Host
|
|||||||
{
|
{
|
||||||
OnAttach = onAttach; OnDetach = onDetach; OnCreate = onCreate; OnRemove = onRemove;
|
OnAttach = onAttach; OnDetach = onDetach; OnCreate = onCreate; OnRemove = onRemove;
|
||||||
OnCreate(textThreadsByParams[CONSOLE] = new TextThread(CONSOLE, USING_UNICODE));
|
OnCreate(textThreadsByParams[CONSOLE] = new TextThread(CONSOLE, USING_UNICODE));
|
||||||
CreateNewPipe();
|
CreatePipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
DLLEXPORT void Close()
|
DLLEXPORT void Close()
|
||||||
@ -102,25 +114,20 @@ namespace Host
|
|||||||
|
|
||||||
DLLEXPORT bool DetachProcess(DWORD processId)
|
DLLEXPORT bool DetachProcess(DWORD processId)
|
||||||
{
|
{
|
||||||
DWORD command = HOST_COMMAND_DETACH;
|
int command = HOST_COMMAND_DETACH;
|
||||||
return WriteFile(processRecordsByIds[processId].hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
return WriteFile(processRecordsByIds[processId].hostPipe, &command, sizeof(command), DUMMY, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name)
|
DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name)
|
||||||
{
|
{
|
||||||
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
auto info = InsertHookCmd(hp, name);
|
||||||
*(DWORD*)buffer = HOST_COMMAND_NEW_HOOK;
|
return WriteFile(processRecordsByIds[pid].hostPipe, &info, sizeof(info), DUMMY, nullptr);
|
||||||
*(HookParam*)(buffer + sizeof(DWORD)) = hp;
|
|
||||||
if (name.size()) strcpy((char*)buffer + sizeof(DWORD) + sizeof(HookParam), name.c_str());
|
|
||||||
return WriteFile(processRecordsByIds[pid].hostPipe, buffer, sizeof(DWORD) + sizeof(HookParam) + name.size(), DUMMY, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DLLEXPORT bool RemoveHook(DWORD pid, DWORD addr)
|
DLLEXPORT bool RemoveHook(DWORD pid, DWORD addr)
|
||||||
{
|
{
|
||||||
BYTE buffer[sizeof(DWORD) * 2] = {};
|
auto info = RemoveHookCmd(addr);
|
||||||
*(DWORD*)buffer = HOST_COMMAND_REMOVE_HOOK;
|
return WriteFile(processRecordsByIds[pid].hostPipe, &info, sizeof(info), DUMMY, nullptr);
|
||||||
*(DWORD*)(buffer + sizeof(DWORD)) = addr;
|
|
||||||
return WriteFile(processRecordsByIds[pid].hostPipe, buffer, sizeof(DWORD) * 2, DUMMY, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DLLEXPORT HookParam GetHookParam(DWORD pid, DWORD addr)
|
DLLEXPORT HookParam GetHookParam(DWORD pid, DWORD addr)
|
||||||
@ -130,14 +137,14 @@ namespace Host
|
|||||||
ProcessRecord pr = processRecordsByIds[pid];
|
ProcessRecord pr = processRecordsByIds[pid];
|
||||||
if (pr.sectionMap == nullptr) return ret;
|
if (pr.sectionMap == nullptr) return ret;
|
||||||
MutexLocker locker(pr.sectionMutex);
|
MutexLocker locker(pr.sectionMutex);
|
||||||
const Hook* hooks = (const Hook*)pr.sectionMap;
|
const TextHook* hooks = (const TextHook*)pr.sectionMap;
|
||||||
for (int i = 0; i < MAX_HOOK; ++i)
|
for (int i = 0; i < MAX_HOOK; ++i)
|
||||||
if ((DWORD)hooks[i].Address() == addr)
|
if ((DWORD)hooks[i].Address() == addr)
|
||||||
ret = hooks[i].hp;
|
ret = hooks[i].hp;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DLLEXPORT HookParam GetHookParam(ThreadParameter tp) { return GetHookParam(tp.pid, tp.hook); }
|
DLLEXPORT HookParam GetHookParam(ThreadParam tp) { return GetHookParam(tp.pid, tp.hook); }
|
||||||
|
|
||||||
DLLEXPORT std::wstring GetHookName(DWORD pid, DWORD addr)
|
DLLEXPORT std::wstring GetHookName(DWORD pid, DWORD addr)
|
||||||
{
|
{
|
||||||
@ -147,7 +154,7 @@ namespace Host
|
|||||||
ProcessRecord pr = processRecordsByIds[pid];
|
ProcessRecord pr = processRecordsByIds[pid];
|
||||||
if (pr.sectionMap == nullptr) return L"";
|
if (pr.sectionMap == nullptr) return L"";
|
||||||
MutexLocker locker(pr.sectionMutex);
|
MutexLocker locker(pr.sectionMutex);
|
||||||
const Hook* hooks = (const Hook*)pr.sectionMap;
|
const TextHook* hooks = (const TextHook*)pr.sectionMap;
|
||||||
for (int i = 0; i < MAX_HOOK; ++i)
|
for (int i = 0; i < MAX_HOOK; ++i)
|
||||||
if ((DWORD)hooks[i].Address() == addr)
|
if ((DWORD)hooks[i].Address() == addr)
|
||||||
{
|
{
|
||||||
@ -158,7 +165,7 @@ namespace Host
|
|||||||
return std::wstring(A2W(buffer.c_str()));
|
return std::wstring(A2W(buffer.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
DLLEXPORT TextThread* GetThread(ThreadParameter tp)
|
DLLEXPORT TextThread* GetThread(ThreadParam tp)
|
||||||
{
|
{
|
||||||
HOST_LOCK;
|
HOST_LOCK;
|
||||||
return textThreadsByParams[tp];
|
return textThreadsByParams[tp];
|
||||||
@ -171,7 +178,7 @@ namespace Host
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DispatchText(ThreadParameter tp, const BYTE* text, int len)
|
void DispatchText(ThreadParam tp, const BYTE* text, int len)
|
||||||
{
|
{
|
||||||
if (!text || len <= 0) return;
|
if (!text || len <= 0) return;
|
||||||
HOST_LOCK;
|
HOST_LOCK;
|
||||||
@ -181,10 +188,10 @@ void DispatchText(ThreadParameter tp, const BYTE* text, int len)
|
|||||||
it->AddText(text, len);
|
it->AddText(text, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveThreads(bool(*RemoveIf)(ThreadParameter, ThreadParameter), ThreadParameter cmp)
|
void RemoveThreads(bool(*RemoveIf)(ThreadParam, ThreadParam), ThreadParam cmp)
|
||||||
{
|
{
|
||||||
HOST_LOCK;
|
HOST_LOCK;
|
||||||
std::vector<ThreadParameter> removedThreads;
|
std::vector<ThreadParam> removedThreads;
|
||||||
for (auto i : textThreadsByParams)
|
for (auto i : textThreadsByParams)
|
||||||
if (RemoveIf(i.first, cmp))
|
if (RemoveIf(i.first, cmp))
|
||||||
{
|
{
|
||||||
|
18
host/host.h
18
host/host.h
@ -6,19 +6,9 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "textthread.h"
|
#include "textthread.h"
|
||||||
#include "../vnrhook/include/types.h"
|
|
||||||
|
|
||||||
#define DLLEXPORT __declspec(dllexport)
|
#define DLLEXPORT __declspec(dllexport)
|
||||||
|
|
||||||
struct ProcessRecord
|
|
||||||
{
|
|
||||||
HANDLE processHandle;
|
|
||||||
HANDLE sectionMutex;
|
|
||||||
HANDLE section;
|
|
||||||
LPVOID sectionMap;
|
|
||||||
HANDLE hostPipe;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::function<void(DWORD)> ProcessEventCallback;
|
typedef std::function<void(DWORD)> ProcessEventCallback;
|
||||||
typedef std::function<void(TextThread*)> ThreadEventCallback;
|
typedef std::function<void(TextThread*)> ThreadEventCallback;
|
||||||
|
|
||||||
@ -32,15 +22,15 @@ namespace Host
|
|||||||
DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name = "");
|
DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name = "");
|
||||||
DLLEXPORT bool RemoveHook(DWORD pid, DWORD addr);
|
DLLEXPORT bool RemoveHook(DWORD pid, DWORD addr);
|
||||||
DLLEXPORT HookParam GetHookParam(DWORD pid, DWORD addr);
|
DLLEXPORT HookParam GetHookParam(DWORD pid, DWORD addr);
|
||||||
DLLEXPORT HookParam GetHookParam(ThreadParameter tp);
|
DLLEXPORT HookParam GetHookParam(ThreadParam tp);
|
||||||
DLLEXPORT std::wstring GetHookName(DWORD pid, DWORD addr);
|
DLLEXPORT std::wstring GetHookName(DWORD pid, DWORD addr);
|
||||||
|
|
||||||
DLLEXPORT TextThread* GetThread(ThreadParameter tp);
|
DLLEXPORT TextThread* GetThread(ThreadParam tp);
|
||||||
DLLEXPORT void AddConsoleOutput(std::wstring text);
|
DLLEXPORT void AddConsoleOutput(std::wstring text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DispatchText(ThreadParameter tp, const BYTE *text, int len);
|
void DispatchText(ThreadParam tp, const BYTE *text, int len);
|
||||||
void RemoveThreads(bool(*RemoveIf)(ThreadParameter, ThreadParameter), ThreadParameter cmp);
|
void RemoveThreads(bool(*RemoveIf)(ThreadParam, ThreadParam), ThreadParam cmp);
|
||||||
void RegisterProcess(DWORD pid, HANDLE hostPipe);
|
void RegisterProcess(DWORD pid, HANDLE hostPipe);
|
||||||
void UnregisterProcess(DWORD pid);
|
void UnregisterProcess(DWORD pid);
|
||||||
|
|
||||||
|
61
host/pipe.cc
61
host/pipe.cc
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
#include "pipe.h"
|
#include "pipe.h"
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
#include "../vnrhook/include/defs.h"
|
#include "defs.h"
|
||||||
#include "../vnrhook/include/const.h"
|
#include "const.h"
|
||||||
|
|
||||||
void CreateNewPipe()
|
void CreatePipe()
|
||||||
{
|
{
|
||||||
std::thread([]()
|
std::thread([]()
|
||||||
{
|
{
|
||||||
@ -17,7 +17,7 @@ void CreateNewPipe()
|
|||||||
|
|
||||||
// jichi 9/27/2013: why recursion?
|
// jichi 9/27/2013: why recursion?
|
||||||
// Artikash 5/20/2018: Easy way to create a new pipe for another process
|
// Artikash 5/20/2018: Easy way to create a new pipe for another process
|
||||||
CreateNewPipe();
|
CreatePipe();
|
||||||
|
|
||||||
BYTE buffer[PIPE_BUFFER_SIZE + 1] = {};
|
BYTE buffer[PIPE_BUFFER_SIZE + 1] = {};
|
||||||
DWORD bytesRead, processId;
|
DWORD bytesRead, processId;
|
||||||
@ -25,35 +25,30 @@ void CreateNewPipe()
|
|||||||
RegisterProcess(processId, hostPipe);
|
RegisterProcess(processId, hostPipe);
|
||||||
|
|
||||||
while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
|
while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
|
||||||
{
|
switch (*(int*)buffer)
|
||||||
buffer[bytesRead] = 0;
|
{
|
||||||
buffer[bytesRead + 1] = 0;
|
//case HOST_NOTIFICATION_NEWHOOK: // Artikash 7/18/2018: Useless for now, but could be used to implement smth later
|
||||||
|
//break;
|
||||||
if (*(DWORD*)buffer == HOST_NOTIFICATION)
|
case HOST_NOTIFICATION_RMVHOOK:
|
||||||
switch (*(DWORD*)(buffer + sizeof(DWORD))) // Artikash 7/17/2018: Notification type
|
{
|
||||||
{
|
auto info = *(HookRemovedNotif*)buffer;
|
||||||
case HOST_NOTIFICATION_NEWHOOK: // Artikash 7/18/2018: Useless for now, but could be used to implement smth later
|
RemoveThreads([](auto one, auto two) { return one.pid == two.pid && one.hook == two.hook; }, { processId, info.address });
|
||||||
break;
|
}
|
||||||
case HOST_NOTIFICATION_RMVHOOK:
|
break;
|
||||||
RemoveThreads([](auto one, auto two) { return one.pid == two.pid && one.hook == two.hook; },
|
case HOST_NOTIFICATION_TEXT:
|
||||||
{ processId, *(DWORD*)(buffer + sizeof(DWORD) * 2) }); // Address
|
{
|
||||||
break;
|
auto info = *(ConsoleOutputNotif*)buffer;
|
||||||
case HOST_NOTIFICATION_TEXT:
|
USES_CONVERSION;
|
||||||
USES_CONVERSION;
|
Host::AddConsoleOutput(A2W(info.message));
|
||||||
Host::AddConsoleOutput(A2W((LPCSTR)(buffer + sizeof(DWORD) * 2))); // Text
|
}
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
else DispatchText(
|
{
|
||||||
{
|
ThreadParam tp = *(ThreadParam*)buffer;
|
||||||
processId,
|
DispatchText(tp, buffer + sizeof(tp), bytesRead - sizeof(tp));
|
||||||
*(DWORD*)buffer, // Hook address
|
}
|
||||||
*(DWORD*)(buffer + sizeof(DWORD)), // Return address
|
break;
|
||||||
*(DWORD*)(buffer + sizeof(DWORD) * 2) // Split
|
}
|
||||||
},
|
|
||||||
buffer + HEADER_SIZE, // Data
|
|
||||||
bytesRead - HEADER_SIZE // Data size
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
DisconnectNamedPipe(hookPipe);
|
DisconnectNamedPipe(hookPipe);
|
||||||
DisconnectNamedPipe(hostPipe);
|
DisconnectNamedPipe(hostPipe);
|
||||||
|
10
host/pipe.h
10
host/pipe.h
@ -1,10 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// pipe.h
|
|
||||||
// 7/19/2018 Artikash
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
void CreateNewPipe();
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,16 +1,13 @@
|
|||||||
// textthread.cc
|
// textthread.cc
|
||||||
// 8/24/2013 jichi
|
// 8/24/2013 jichi
|
||||||
// Branch IHF/TextThread.cpp, rev 133
|
// Branch IHF/TextThread.cpp, rev 133
|
||||||
#ifdef _MSC_VER
|
|
||||||
# pragma warning (disable:4100) // C4100: unreference formal parameter
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
#include "textthread.h"
|
#include "textthread.h"
|
||||||
#include "../vnrhook/include/const.h"
|
#include "const.h"
|
||||||
|
|
||||||
#define TT_LOCK std::lock_guard<std::recursive_mutex> ttLocker(ttMutex) // Synchronized scope for accessing private data
|
#define TT_LOCK std::lock_guard<std::recursive_mutex> ttLocker(ttMutex) // Synchronized scope for accessing private data
|
||||||
|
|
||||||
TextThread::TextThread(ThreadParameter tp, DWORD status) :
|
TextThread::TextThread(ThreadParam tp, DWORD status) :
|
||||||
deletionEvent(CreateEventW(nullptr, FALSE, FALSE, NULL)),
|
deletionEvent(CreateEventW(nullptr, FALSE, FALSE, NULL)),
|
||||||
flushThread([&]() { while (WaitForSingleObject(deletionEvent, 100), Flush()); }),
|
flushThread([&]() { while (WaitForSingleObject(deletionEvent, 100), Flush()); }),
|
||||||
timestamp(GetTickCount()),
|
timestamp(GetTickCount()),
|
||||||
|
@ -5,34 +5,18 @@
|
|||||||
// Branch: ITH/TextThread.h, rev 120
|
// Branch: ITH/TextThread.h, rev 120
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "pipe.h"
|
||||||
|
|
||||||
struct ThreadParameter
|
|
||||||
{
|
|
||||||
DWORD pid; // jichi: 5/11/2014: The process ID
|
|
||||||
unsigned __int64 hook; // Artikash 6/6/2018: The insertion address of the hook
|
|
||||||
unsigned __int64 retn; // jichi 5/11/2014: The return address of the hook
|
|
||||||
unsigned __int64 spl; // jichi 5/11/2014: the processed split value of the hook paramete
|
|
||||||
|
|
||||||
// Artikash 5/31/2018: required for unordered_map to work with struct key
|
|
||||||
friend bool operator==(const ThreadParameter& one, const ThreadParameter& two)
|
|
||||||
{
|
|
||||||
return one.pid == two.pid && one.hook == two.hook && one.retn == two.retn && one.spl == two.spl;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TextThread;
|
|
||||||
typedef std::function<std::wstring(TextThread*, std::wstring)> ThreadOutputCallback;
|
|
||||||
|
|
||||||
//extern DWORD split_time,repeat_count,global_filter,cyclic_remove;
|
|
||||||
|
|
||||||
class TextThread
|
class TextThread
|
||||||
{
|
{
|
||||||
|
typedef std::function<std::wstring(TextThread*, std::wstring)> ThreadOutputCallback;
|
||||||
public:
|
public:
|
||||||
TextThread(ThreadParameter tp, DWORD status);
|
TextThread(ThreadParam tp, DWORD status);
|
||||||
virtual ~TextThread();
|
virtual ~TextThread();
|
||||||
|
|
||||||
virtual std::wstring GetStore();
|
virtual std::wstring GetStore();
|
||||||
ThreadParameter GetThreadParameter() { return tp; }
|
ThreadParam GetThreadParam() { return tp; }
|
||||||
|
|
||||||
void RegisterOutputCallBack(ThreadOutputCallback cb) { Output = cb; }
|
void RegisterOutputCallBack(ThreadOutputCallback cb) { Output = cb; }
|
||||||
|
|
||||||
@ -50,7 +34,7 @@ private:
|
|||||||
|
|
||||||
DWORD timestamp;
|
DWORD timestamp;
|
||||||
ThreadOutputCallback Output;
|
ThreadOutputCallback Output;
|
||||||
ThreadParameter tp;
|
ThreadParam tp;
|
||||||
DWORD status;
|
DWORD status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
// winmutex.h
|
|
||||||
// 12/11/2011 jichi
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
// Artikash 7/20/2018: similar to std::lock guard but use Winapi objects for cross process comms
|
|
||||||
|
|
||||||
class MutexLocker
|
|
||||||
{
|
|
||||||
HANDLE mutex;
|
|
||||||
public:
|
|
||||||
MutexLocker(HANDLE mutex) : mutex(mutex) { WaitForSingleObject(mutex, 0); }
|
|
||||||
~MutexLocker() { if (mutex != INVALID_HANDLE_VALUE && mutex != nullptr) ReleaseMutex(mutex); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// EOF
|
|
64
include/const.h
Normal file
64
include/const.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// vnrhook/const.h
|
||||||
|
// 8/23/2013 jichi
|
||||||
|
// Branch: ITH/common.h, rev 128
|
||||||
|
|
||||||
|
enum { MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 0x1000 };
|
||||||
|
|
||||||
|
// jichi 375/2014: Add offset of pusha/pushad
|
||||||
|
// http://faydoc.tripod.com/cpu/pushad.htm
|
||||||
|
// http://agth.wikia.com/wiki/Cheat_Engine_AGTH_Tutorial
|
||||||
|
//
|
||||||
|
// Warning: The offset in ITH has -4 offset comparing to pusha and AGTH
|
||||||
|
enum pusha_off
|
||||||
|
{
|
||||||
|
pusha_eax_off = -0x4,
|
||||||
|
pusha_ecx_off = -0x8,
|
||||||
|
pusha_edx_off = -0xc,
|
||||||
|
pusha_ebx_off = -0x10,
|
||||||
|
pusha_esp_off = -0x14,
|
||||||
|
pusha_ebp_off = -0x18,
|
||||||
|
pusha_esi_off = -0x1c,
|
||||||
|
pusha_edi_off = -0x20,
|
||||||
|
pusha_off = -0x24 // pushad offset
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HostCommandType
|
||||||
|
{
|
||||||
|
HOST_COMMAND = -1, // null type
|
||||||
|
HOST_COMMAND_NEW_HOOK = 0,
|
||||||
|
HOST_COMMAND_REMOVE_HOOK = 1,
|
||||||
|
HOST_COMMAND_MODIFY_HOOK = 2,
|
||||||
|
HOST_COMMAND_HIJACK_PROCESS = 3,
|
||||||
|
HOST_COMMAND_DETACH = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HostNotificationType
|
||||||
|
{
|
||||||
|
HOST_NOTIFICATION = -1, // null type
|
||||||
|
HOST_NOTIFICATION_TEXT = 0,
|
||||||
|
HOST_NOTIFICATION_NEWHOOK = 1,
|
||||||
|
HOST_NOTIFICATION_RMVHOOK = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HookParamType : unsigned long
|
||||||
|
{
|
||||||
|
USING_STRING = 0x1, // type(data) is char* or wchar_t* and has length
|
||||||
|
USING_UNICODE = 0x2, // type(data) is wchar_t or wchar_t*
|
||||||
|
BIG_ENDIAN = 0x4, // type(data) is char
|
||||||
|
DATA_INDIRECT = 0x8,
|
||||||
|
USING_SPLIT = 0x10, // aware of split time?
|
||||||
|
SPLIT_INDIRECT = 0x20,
|
||||||
|
MODULE_OFFSET = 0x40, // do hash module, and the address is relative to module
|
||||||
|
//FUNCTION_OFFSET = 0x80, // do hash function, and the address is relative to funccion
|
||||||
|
USING_UTF8 = 0x100,
|
||||||
|
NO_CONTEXT = 0x400,
|
||||||
|
HOOK_EMPTY = 0x800,
|
||||||
|
FIXING_SPLIT = 0x1000,
|
||||||
|
DIRECT_READ = 0x2000, // /R read code instead of classic /H hook code
|
||||||
|
HOOK_ENGINE = 0x4000,
|
||||||
|
HOOK_ADDITIONAL = 0x8000
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { FIXED_SPLIT_VALUE = 0x10001 }; // 6/1/2014: Fixed split value for hok parameter. Fuse all threads, and prevent floating
|
@ -3,16 +3,6 @@
|
|||||||
// vnrhook/defs.h
|
// vnrhook/defs.h
|
||||||
// 8/23/2013 jichi
|
// 8/23/2013 jichi
|
||||||
|
|
||||||
// DLL files
|
|
||||||
|
|
||||||
//#define ITH_SERVER_DLL L"vnrsrv.dll"
|
|
||||||
//#define ITH_CLIENT_DLL L"vnrcli.dll"
|
|
||||||
//#define ITH_CLIENT_XP_DLL L"vnrclixp.dll"
|
|
||||||
////#define ITH_CLIENT_UX_DLL L"vnrcliux.dll"
|
|
||||||
//#define ITH_ENGINE_DLL L"vnreng.dll"
|
|
||||||
//#define ITH_ENGINE_XP_DLL L"vnrengxp.dll"
|
|
||||||
//#define ITH_ENGINE_UX_DLL L"vnrengux.dll"
|
|
||||||
|
|
||||||
#define ITH_DLL L"vnrhook.dll"
|
#define ITH_DLL L"vnrhook.dll"
|
||||||
|
|
||||||
// Pipes
|
// Pipes
|
70
include/pipe.h
Normal file
70
include/pipe.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "const.h"
|
||||||
|
|
||||||
|
void CreatePipe();
|
||||||
|
|
||||||
|
// jichi 3/7/2014: Add guessed comment
|
||||||
|
struct HookParam
|
||||||
|
{
|
||||||
|
// jichi 8/24/2013: For special hooks.
|
||||||
|
typedef void(*text_fun_t)(DWORD esp, HookParam *hp, BYTE index, DWORD *data, DWORD *split, DWORD *len);
|
||||||
|
typedef bool(*filter_fun_t)(LPVOID str, DWORD *len, HookParam *hp, BYTE index); // jichi 10/24/2014: Add filter function. Return true if skip the text
|
||||||
|
typedef bool(*hook_fun_t)(DWORD esp, HookParam *hp); // jichi 10/24/2014: Add generic hook function, return false if stop execution.
|
||||||
|
|
||||||
|
unsigned __int64 address; // absolute or relative address
|
||||||
|
short offset, // offset of the data in the memory
|
||||||
|
index, // deref_offset1
|
||||||
|
split, // offset of the split character
|
||||||
|
split_index; // deref_offset2
|
||||||
|
DWORD module; // hash of the module
|
||||||
|
DWORD type; // flags
|
||||||
|
WORD length_offset; // index of the string length
|
||||||
|
DWORD user_value; // 7/20/2014: jichi additional parameters for PSP games
|
||||||
|
|
||||||
|
text_fun_t text_fun;
|
||||||
|
filter_fun_t filter_fun;
|
||||||
|
hook_fun_t hook_fun;
|
||||||
|
|
||||||
|
BYTE hook_len, // ?
|
||||||
|
recover_len; // ?
|
||||||
|
HANDLE readerHandle; // Artikash 8/4/2018: handle for reader thread
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThreadParam // From hook
|
||||||
|
{
|
||||||
|
DWORD pid; // jichi: 5/11/2014: The process ID
|
||||||
|
unsigned __int64 hook; // Artikash 6/6/2018: The insertion address of the hook
|
||||||
|
unsigned __int64 retn; // jichi 5/11/2014: The return address of the hook
|
||||||
|
unsigned __int64 spl; // jichi 5/11/2014: the processed split value of the hook paramete
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InsertHookCmd // From host
|
||||||
|
{
|
||||||
|
InsertHookCmd(HookParam hp, std::string name = "") : hp(hp) { strncpy(this->name, name.c_str(), 500); };
|
||||||
|
int command = HOST_COMMAND_NEW_HOOK;
|
||||||
|
HookParam hp;
|
||||||
|
char name[MESSAGE_SIZE] = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RemoveHookCmd // From host
|
||||||
|
{
|
||||||
|
RemoveHookCmd(unsigned __int64 address) : address(address) {};
|
||||||
|
int command = HOST_COMMAND_REMOVE_HOOK;
|
||||||
|
unsigned __int64 address;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConsoleOutputNotif // From hook
|
||||||
|
{
|
||||||
|
ConsoleOutputNotif(std::string message = "") { strncpy(this->message, message.c_str(), 500); };
|
||||||
|
int command = HOST_NOTIFICATION_TEXT;
|
||||||
|
char message[MESSAGE_SIZE] = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HookRemovedNotif // From hook
|
||||||
|
{
|
||||||
|
HookRemovedNotif(unsigned __int64 address) : address(address) {};
|
||||||
|
int command = HOST_NOTIFICATION_RMVHOOK;
|
||||||
|
unsigned __int64 address;
|
||||||
|
};
|
@ -2,50 +2,27 @@ include_directories(.)
|
|||||||
|
|
||||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||||
set(vnrhook_src
|
set(vnrhook_src
|
||||||
include/const.h
|
main.cc
|
||||||
include/defs.h
|
pipe.cc
|
||||||
include/types.h
|
util/ithsys/ithsys.cc
|
||||||
src/main.cc
|
hijack/texthook.cc
|
||||||
src/main.h
|
|
||||||
src/pipe.cc
|
|
||||||
src/util/ithsys/ithsys.cc
|
|
||||||
src/hijack/texthook.cc
|
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
set(vnrhook_src
|
set(vnrhook_src
|
||||||
include/const.h
|
main.cc
|
||||||
include/defs.h
|
pipe.cc
|
||||||
include/types.h
|
engine/engine.cc
|
||||||
src/except.h
|
engine/match.cc
|
||||||
src/main.cc
|
engine/pchooks.cc
|
||||||
src/main.h
|
hijack/texthook.cc
|
||||||
src/pipe.cc
|
util/util.cc
|
||||||
src/engine/engine.cc
|
util/ithsys/ithsys.cc
|
||||||
src/engine/engine.h
|
util/disasm/disasm.cc
|
||||||
src/engine/hookdefs.h
|
util/memdbg/memsearch.cc
|
||||||
src/engine/match.cc
|
|
||||||
src/engine/match.h
|
|
||||||
src/engine/pchooks.cc
|
|
||||||
src/engine/pchooks.h
|
|
||||||
src/engine/mono/funcinfo.h
|
|
||||||
src/engine/mono/types.h
|
|
||||||
src/engine/ppsspp/funcinfo.h
|
|
||||||
src/hijack/texthook.cc
|
|
||||||
src/hijack/texthook.h
|
|
||||||
src/util/growl.h
|
|
||||||
src/util/util.cc
|
|
||||||
src/util/util.h
|
|
||||||
src/util/ithsys/ithsys.cc
|
|
||||||
src/util/disasm/disasm.cc
|
|
||||||
src/util/memdbg/memdbg.h
|
|
||||||
src/util/memdbg/memsearch.cc
|
|
||||||
src/util/memdbg/memsearch.h
|
|
||||||
src/util/mono/monoobject.h
|
|
||||||
src/util/mono/monotype.h
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(src/util)
|
include_directories(util)
|
||||||
|
|
||||||
add_library(vnrhook SHARED ${vnrhook_src})
|
add_library(vnrhook SHARED ${vnrhook_src})
|
||||||
|
|
||||||
|
@ -7,21 +7,21 @@
|
|||||||
# pragma warning (disable:4819)
|
# pragma warning (disable:4819)
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
#include "src/engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "ntdll/ntdll.h"
|
#include "ntdll/ntdll.h"
|
||||||
#include "src/engine/match.h"
|
#include "engine/match.h"
|
||||||
#include "src/engine/hookdefs.h"
|
#include "util/util.h"
|
||||||
#include "src/util/util.h"
|
#include "main.h"
|
||||||
#include "src/main.h"
|
#include "engine/mono/funcinfo.h"
|
||||||
#include "src/engine/mono/funcinfo.h"
|
#include "engine/ppsspp/funcinfo.h"
|
||||||
#include "src/engine/ppsspp/funcinfo.h"
|
#include "except.h"
|
||||||
#include "src/except.h"
|
|
||||||
#include "ithsys/ithsys.h"
|
#include "ithsys/ithsys.h"
|
||||||
#include "memdbg/memsearch.h"
|
#include "memdbg/memsearch.h"
|
||||||
#include "disasm/disasm.h"
|
#include "disasm/disasm.h"
|
||||||
#include "cpputil/cppcstring.h"
|
#include "cpputil/cppcstring.h"
|
||||||
#include "mono/monoobject.h"
|
#include "mono/monoobject.h"
|
||||||
#include "growl.h"
|
#include "growl.h"
|
||||||
|
#include "const.h"
|
||||||
//#include <boost/foreach.hpp>
|
//#include <boost/foreach.hpp>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -38,50 +38,6 @@
|
|||||||
|
|
||||||
enum { VNR_TEXT_CAPACITY = 1500 }; // estimated max number of bytes allowed in VNR, slightly larger than VNR's text limit (1000)
|
enum { VNR_TEXT_CAPACITY = 1500 }; // estimated max number of bytes allowed in VNR, slightly larger than VNR's text limit (1000)
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
# include "src/util/growl.h"
|
|
||||||
//# include "uniquemap.h"
|
|
||||||
//# include "uniquemap.cc"
|
|
||||||
namespace { // unnamed debug functions
|
|
||||||
// jichi 12/17/2013: Copied from int TextHook::GetLength(DWORD base, DWORD in)
|
|
||||||
int GetHookDataLength(const HookParam &hp, DWORD base, DWORD in)
|
|
||||||
{
|
|
||||||
if (CC_UNLIKELY(!base))
|
|
||||||
return 0;
|
|
||||||
int len;
|
|
||||||
switch (hp.length_offset) {
|
|
||||||
default: // jichi 12/26/2013: I should not put this default branch to the end
|
|
||||||
len = *((int *)base + hp.length_offset);
|
|
||||||
if (len >= 0) {
|
|
||||||
if (hp.type & USING_UNICODE)
|
|
||||||
len <<= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (len != -1)
|
|
||||||
break;
|
|
||||||
//len == -1 then continue to case 0.
|
|
||||||
case 0:
|
|
||||||
if (hp.type & USING_UNICODE)
|
|
||||||
len = wcslen((LPCWSTR)in) << 1;
|
|
||||||
else
|
|
||||||
len = strlen((LPCSTR)in);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (hp.type & USING_UNICODE)
|
|
||||||
len = 2;
|
|
||||||
else {
|
|
||||||
if (hp.type & BIG_ENDIAN)
|
|
||||||
in >>= 8;
|
|
||||||
len = LeadByteTable[in&0xff]; //Slightly faster than IsDBCSLeadByte
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// jichi 12/25/2013: This function originally return -1 if failed
|
|
||||||
//return len;
|
|
||||||
return max(0, len);
|
|
||||||
}
|
|
||||||
} // unnamed
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
namespace { // unnamed helpers
|
namespace { // unnamed helpers
|
||||||
|
|
@ -7,13 +7,13 @@
|
|||||||
//# 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 "src/engine/match.h"
|
#include "engine/match.h"
|
||||||
#include "src/engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "src/engine/pchooks.h"
|
#include "engine/pchooks.h"
|
||||||
#include "src/util/growl.h"
|
#include "util/growl.h"
|
||||||
#include "src/util/util.h"
|
#include "util/util.h"
|
||||||
#include "src/main.h"
|
#include "main.h"
|
||||||
#include "src/except.h"
|
#include "except.h"
|
||||||
#include "ithsys/ithsys.h"
|
#include "ithsys/ithsys.h"
|
||||||
|
|
||||||
//#define ConsoleOutput(...) (void)0 // jichi 8/18/2013: I don't need ConsoleOutput
|
//#define ConsoleOutput(...) (void)0 // jichi 8/18/2013: I don't need ConsoleOutput
|
@ -1,8 +1,8 @@
|
|||||||
// pchooks.cc
|
// pchooks.cc
|
||||||
// 8/1/2014 jichi
|
// 8/1/2014 jichi
|
||||||
|
|
||||||
#include "src/engine/pchooks.h"
|
#include "engine/pchooks.h"
|
||||||
#include "src/main.h"
|
#include "main.h"
|
||||||
//#include <gdiplus.h>
|
//#include <gdiplus.h>
|
||||||
|
|
||||||
#define DEBUG "vnrcli"
|
#define DEBUG "vnrcli"
|
@ -9,11 +9,11 @@
|
|||||||
//# 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 "src/hijack/texthook.h"
|
#include "hijack/texthook.h"
|
||||||
#include "src/engine/match.h"
|
#include "engine/match.h"
|
||||||
#include "src/except.h"
|
#include "except.h"
|
||||||
#include "src/main.h"
|
#include "main.h"
|
||||||
#include "include/const.h"
|
#include "const.h"
|
||||||
#include "ithsys/ithsys.h"
|
#include "ithsys/ithsys.h"
|
||||||
#include "disasm/disasm.h"
|
#include "disasm/disasm.h"
|
||||||
//#include "winseh/winseh.h"
|
//#include "winseh/winseh.h"
|
||||||
@ -293,9 +293,8 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn)
|
|||||||
}
|
}
|
||||||
dwCount = GetLength(dwDataBase, dwDataIn);
|
dwCount = GetLength(dwDataBase, dwDataIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// jichi 12/25/2013: validate data size
|
// jichi 12/25/2013: validate data size
|
||||||
if (dwCount == 0 || dwCount > PIPE_BUFFER_SIZE - HEADER_SIZE)
|
if (dwCount == 0 || dwCount > PIPE_BUFFER_SIZE - sizeof(ThreadParam))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (hp.length_offset == 1) {
|
if (hp.length_offset == 1) {
|
||||||
@ -304,27 +303,27 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn)
|
|||||||
dwDataIn = _byteswap_ushort(dwDataIn & 0xffff);
|
dwDataIn = _byteswap_ushort(dwDataIn & 0xffff);
|
||||||
if (dwCount == 1)
|
if (dwCount == 1)
|
||||||
dwDataIn &= 0xff;
|
dwDataIn &= 0xff;
|
||||||
*(WORD *)(pbData + HEADER_SIZE) = dwDataIn & 0xffff;
|
*(WORD *)(pbData + sizeof(ThreadParam)) = dwDataIn & 0xffff;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
::memcpy(pbData + HEADER_SIZE, (void *)dwDataIn, dwCount);
|
::memcpy(pbData + sizeof(ThreadParam), (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 + HEADER_SIZE, &dwCount, &hp, 0) || dwCount <= 0) {
|
if (hp.filter_fun && !hp.filter_fun(pbData + sizeof(ThreadParam), &dwCount, &hp, 0) || dwCount <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*(DWORD *)pbData = dwAddr;
|
|
||||||
if (dwType & (NO_CONTEXT|FIXING_SPLIT))
|
if (dwType & (NO_CONTEXT|FIXING_SPLIT))
|
||||||
dwRetn = 0;
|
dwRetn = 0;
|
||||||
|
|
||||||
|
*(ThreadParam*)pbData = { GetCurrentProcessId(), dwAddr, dwRetn, dwSplit };
|
||||||
*((DWORD *)pbData + 1) = dwRetn;
|
*((DWORD *)pbData + 1) = dwRetn;
|
||||||
*((DWORD *)pbData + 2) = dwSplit;
|
*((DWORD *)pbData + 2) = dwSplit;
|
||||||
if (dwCount) {
|
if (dwCount) {
|
||||||
DWORD unused;
|
DWORD unused;
|
||||||
|
|
||||||
//CliLockPipe();
|
//CliLockPipe();
|
||||||
WriteFile(::hookPipe, pbData, dwCount + HEADER_SIZE, &unused, nullptr);
|
WriteFile(::hookPipe, pbData, dwCount + sizeof(ThreadParam), &unused, nullptr);
|
||||||
//CliUnlockPipe();
|
//CliUnlockPipe();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -454,7 +453,7 @@ DWORD WINAPI ReaderThread(LPVOID threadParam)
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Sleep(500);
|
Sleep(500);
|
||||||
if (memcmp(buffer + HEADER_SIZE, currentAddress, dataLen) == 0)
|
if (memcmp(buffer + sizeof(ThreadParam), currentAddress, dataLen) == 0)
|
||||||
{
|
{
|
||||||
changeCount = 0;
|
changeCount = 0;
|
||||||
continue;
|
continue;
|
||||||
@ -471,12 +470,10 @@ DWORD WINAPI ReaderThread(LPVOID threadParam)
|
|||||||
else
|
else
|
||||||
dataLen = strlen(currentAddress);
|
dataLen = strlen(currentAddress);
|
||||||
|
|
||||||
*(DWORD*)buffer = hook->hp.address;
|
*(ThreadParam*)buffer = { GetCurrentProcessId(), hook->hp.address, 0, 0 };
|
||||||
*(DWORD*)(buffer + 4) = 0;
|
memcpy(buffer + sizeof(ThreadParam), currentAddress, dataLen);
|
||||||
*(DWORD*)(buffer + 8) = 0;
|
|
||||||
memcpy(buffer + HEADER_SIZE, currentAddress, dataLen);
|
|
||||||
DWORD unused;
|
DWORD unused;
|
||||||
WriteFile(::hookPipe, buffer, dataLen + HEADER_SIZE, &unused, nullptr);
|
WriteFile(::hookPipe, buffer, dataLen + sizeof(ThreadParam), &unused, nullptr);
|
||||||
}
|
}
|
||||||
hook->ClearHook();
|
hook->ClearHook();
|
||||||
return 0;
|
return 0;
|
63
vnrhook/hijack/texthook.h
Normal file
63
vnrhook/hijack/texthook.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#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 "common.h"
|
||||||
|
#include "pipe.h"
|
||||||
|
|
||||||
|
extern int currentHook;
|
||||||
|
extern DWORD trigger;
|
||||||
|
|
||||||
|
// jichi 9/25/2013: This class will be used by NtMapViewOfSectionfor
|
||||||
|
// interprocedure communication, where constructor/destructor will NOT work.
|
||||||
|
class TextHook
|
||||||
|
{
|
||||||
|
int InsertHookCode();
|
||||||
|
int InsertReadCode();
|
||||||
|
int UnsafeInsertHookCode();
|
||||||
|
DWORD UnsafeSend(DWORD dwDataBase, DWORD dwRetn);
|
||||||
|
int RemoveHookCode();
|
||||||
|
int RemoveReadCode();
|
||||||
|
int SetHookName(LPCSTR name);
|
||||||
|
public:
|
||||||
|
LPSTR hook_name;
|
||||||
|
int name_length;
|
||||||
|
BYTE recover[0x68 - sizeof(HookParam)];
|
||||||
|
BYTE original[0x10];
|
||||||
|
HookParam hp;
|
||||||
|
|
||||||
|
unsigned __int64 Address() const { return hp.address; }
|
||||||
|
DWORD Type() const { return hp.type; }
|
||||||
|
WORD Length() const { return hp.hook_len; }
|
||||||
|
LPSTR Name() const { return hook_name; }
|
||||||
|
int NameLength() const { return name_length; }
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
// jichi 1/16/2015: Though called max hook, it means max number of text threads
|
||||||
|
enum { MAX_HOOK = 64 };
|
||||||
|
enum { HOOK_SECTION_SIZE = MAX_HOOK * sizeof(TextHook) * 2, HOOK_BUFFER_SIZE = MAX_HOOK * sizeof(TextHook) };
|
||||||
|
|
||||||
|
extern TextHook *hookman,
|
||||||
|
*current_available;
|
||||||
|
|
||||||
|
extern bool running,
|
||||||
|
live;
|
||||||
|
|
||||||
|
extern HANDLE hookPipe,
|
||||||
|
hmMutex;
|
||||||
|
|
||||||
|
DWORD WINAPI PipeManager(LPVOID unused);
|
||||||
|
|
||||||
|
enum : int { yes = 0, no = 1 };
|
||||||
|
|
||||||
|
// EOF
|
@ -1,89 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
// vnrhook/const.h
|
|
||||||
// 8/23/2013 jichi
|
|
||||||
// Branch: ITH/common.h, rev 128
|
|
||||||
|
|
||||||
// jichi 1/16/2015: Though called max hook, it means max number of text threads
|
|
||||||
enum { MAX_HOOK = 64 }; // must be larger than HOOK_FUN_COUNT
|
|
||||||
|
|
||||||
//enum { HOOK_SECTION_SIZE = 0x2000 }; // default ITH value
|
|
||||||
// jichi 1/16/2015: Change to a very large number to prevent crash
|
|
||||||
//enum { MAX_HOOK = 0x100 }; // must be larger than HookFunCount
|
|
||||||
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
|
|
||||||
// http://faydoc.tripod.com/cpu/pushad.htm
|
|
||||||
// http://agth.wikia.com/wiki/Cheat_Engine_AGTH_Tutorial
|
|
||||||
//
|
|
||||||
// Warning: The offset in ITH has -4 offset comparing to pusha and AGTH
|
|
||||||
enum pusha_off {
|
|
||||||
pusha_eax_off = -0x4
|
|
||||||
, pusha_ecx_off = -0x8
|
|
||||||
, pusha_edx_off = -0xc
|
|
||||||
, pusha_ebx_off = -0x10
|
|
||||||
, pusha_esp_off = -0x14
|
|
||||||
, pusha_ebp_off = -0x18
|
|
||||||
, pusha_esi_off = -0x1c
|
|
||||||
, pusha_edi_off = -0x20
|
|
||||||
, pusha_off = -0x24 // pushad offset
|
|
||||||
};
|
|
||||||
|
|
||||||
enum HostCommandType {
|
|
||||||
HOST_COMMAND = -1 // null type
|
|
||||||
, HOST_COMMAND_NEW_HOOK = 0
|
|
||||||
, HOST_COMMAND_REMOVE_HOOK = 1
|
|
||||||
, HOST_COMMAND_MODIFY_HOOK = 2
|
|
||||||
, HOST_COMMAND_HIJACK_PROCESS = 3
|
|
||||||
, HOST_COMMAND_DETACH = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
enum HostNotificationType {
|
|
||||||
HOST_NOTIFICATION = -1 // null type
|
|
||||||
, HOST_NOTIFICATION_TEXT = 0
|
|
||||||
, HOST_NOTIFICATION_NEWHOOK = 1
|
|
||||||
, HOST_NOTIFICATION_RMVHOOK = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
// jichi 9/8/2013: The meaning are guessed
|
|
||||||
// Values must be within DWORD
|
|
||||||
// Unused values are as follows:
|
|
||||||
// - 0x100
|
|
||||||
enum HookParamType : unsigned long {
|
|
||||||
USING_STRING = 0x1 // type(data) is char* or wchar_t* and has length
|
|
||||||
, USING_UNICODE = 0x2 // type(data) is wchar_t or wchar_t*
|
|
||||||
, BIG_ENDIAN = 0x4 // type(data) is char
|
|
||||||
, DATA_INDIRECT = 0x8
|
|
||||||
, USING_SPLIT = 0x10 // aware of split time?
|
|
||||||
, SPLIT_INDIRECT = 0x20
|
|
||||||
, MODULE_OFFSET = 0x40 // do hash module, and the address is relative to module
|
|
||||||
//, FUNCTION_OFFSET = 0x80 // do hash function, and the address is relative to funccion
|
|
||||||
, USING_UTF8 = 0x100
|
|
||||||
//, STRING_LAST_CHAR = 0x200
|
|
||||||
, NO_CONTEXT = 0x400
|
|
||||||
, HOOK_EMPTY = 0x800
|
|
||||||
, FIXING_SPLIT = 0x1000
|
|
||||||
, DIRECT_READ = 0x2000 // /R read code instead of classic /H hook code
|
|
||||||
//, HOOK_AUXILIARY = 0x2000 // jichi 12/13/2013: None of known hooks are auxiliary
|
|
||||||
//, RELATIVE_SPLIT = 0x2000 // Artikash 8/3/2018: does nothing
|
|
||||||
, HOOK_ENGINE = 0x4000
|
|
||||||
, HOOK_ADDITIONAL = 0x8000
|
|
||||||
};
|
|
||||||
|
|
||||||
// 6/1/2014: Fixed split value for hok parameter
|
|
||||||
// Fuse all threads, and prevent floating
|
|
||||||
enum { FIXED_SPLIT_VALUE = 0x10001 };
|
|
||||||
|
|
||||||
enum { PIPE_BUFFER_SIZE = 0x1000};
|
|
||||||
|
|
||||||
// jichi 12/25/2013: Header in each message sent to vnrsrv
|
|
||||||
// There are totally three elements
|
|
||||||
// - 0x0 dwAddr hook address
|
|
||||||
// - 0x4 dwRetn return address
|
|
||||||
// - 0x8 dwSplit split value
|
|
||||||
#define HEADER_SIZE sizeof(DWORD) * 3
|
|
||||||
|
|
||||||
#define TIMEOUT 5000 // 5 seconds
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,66 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// vnrhook/types.h
|
|
||||||
// 8/23/2013 jichi
|
|
||||||
// Branch: ITH/common.h, rev 128
|
|
||||||
|
|
||||||
#include <windows.h> // needed for windef types
|
|
||||||
|
|
||||||
/** jichi 3/7/2014: Add guessed comment
|
|
||||||
*
|
|
||||||
* DWORD addr absolute or relative address
|
|
||||||
* DWORD split esp offset of the split character
|
|
||||||
*
|
|
||||||
* http://faydoc.tripod.com/cpu/pushad.htm
|
|
||||||
* http://agth.wikia.com/wiki/Cheat_Engine_AGTH_Tutorial
|
|
||||||
* The order is the same as pushd
|
|
||||||
* EAX, ECX, EDX, EBX, ESP (original value), EBP, ESI, and EDI (if the current operand-size attribute is 32) and AX, CX, DX, BX, SP
|
|
||||||
* Negative values of 'data_offset' and 'sub_offset' refer to registers:-4 for EAX, -8 for ECX, -C for EDX, -10 for EBX, -14 for ESP, -18 for EBP, -1C for ESI, -20 for EDI
|
|
||||||
*/
|
|
||||||
struct HookParam {
|
|
||||||
// jichi 8/24/2013: For special hooks.
|
|
||||||
typedef void (*text_fun_t)(DWORD esp, HookParam *hp, BYTE index, DWORD *data, DWORD *split, DWORD *len);
|
|
||||||
|
|
||||||
// jichi 10/24/2014: Add filter function. Return true if skip the text
|
|
||||||
typedef bool (*filter_fun_t)(LPVOID str, DWORD *len, HookParam *hp, BYTE index);
|
|
||||||
|
|
||||||
// jichi 10/24/2014: Add generic hook function, return false if stop execution.
|
|
||||||
typedef bool (*hook_fun_t)(DWORD esp, HookParam *hp);
|
|
||||||
|
|
||||||
unsigned __int64 address; // absolute or relative address
|
|
||||||
short offset, // offset of the data in the memory
|
|
||||||
index,
|
|
||||||
split, // offset of the split character
|
|
||||||
split_index;
|
|
||||||
|
|
||||||
DWORD module; // hash of the module
|
|
||||||
text_fun_t text_fun;
|
|
||||||
filter_fun_t filter_fun;
|
|
||||||
hook_fun_t hook_fun;
|
|
||||||
DWORD type; // flags
|
|
||||||
WORD length_offset; // index of the string length
|
|
||||||
BYTE hook_len, // ?
|
|
||||||
recover_len; // ?
|
|
||||||
|
|
||||||
// 7/20/2014: jichi additional parameters for PSP games
|
|
||||||
DWORD user_value;
|
|
||||||
|
|
||||||
// Artikash 8/4/2018: handle for reader thread
|
|
||||||
HANDLE readerHandle;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Hook { // size: 0x80
|
|
||||||
HookParam hp;
|
|
||||||
LPSTR hook_name;
|
|
||||||
int name_length;
|
|
||||||
BYTE recover[0x68 - sizeof(HookParam)];
|
|
||||||
BYTE original[0x10];
|
|
||||||
|
|
||||||
unsigned __int64 Address() const { return hp.address; }
|
|
||||||
DWORD Type() const { return hp.type; }
|
|
||||||
WORD Length() const { return hp.hook_len; }
|
|
||||||
LPSTR Name() const { return hook_name; }
|
|
||||||
int NameLength() const { return name_length; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// EOF
|
|
128
vnrhook/main.cc
Normal file
128
vnrhook/main.cc
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
// 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 "defs.h"
|
||||||
|
#include "engine/engine.h"
|
||||||
|
#include "engine/match.h"
|
||||||
|
#include "hijack/texthook.h"
|
||||||
|
#include "util/growl.h"
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
|
||||||
|
// jichi 6/3/2014: memory range of the current module
|
||||||
|
DWORD processStartAddress,
|
||||||
|
processStopAddress;
|
||||||
|
|
||||||
|
WCHAR hm_section[0x100];
|
||||||
|
HANDLE hSection;
|
||||||
|
bool running;
|
||||||
|
int currentHook = 0,
|
||||||
|
user_hook_count = 0;
|
||||||
|
DWORD trigger = 0;
|
||||||
|
HANDLE
|
||||||
|
hFile,
|
||||||
|
hMutex,
|
||||||
|
hmMutex;
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID unused)
|
||||||
|
{
|
||||||
|
switch (fdwReason)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
{
|
||||||
|
::hmMutex = CreateMutexW(nullptr, FALSE, (ITH_HOOKMAN_MUTEX_ + std::to_wstring(GetCurrentProcessId())).c_str());
|
||||||
|
if (GetLastError() == ERROR_ALREADY_EXISTS) return FALSE;
|
||||||
|
DisableThreadLibraryCalls(hModule);
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
::hookman = (TextHook*)MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, HOOK_BUFFER_SIZE);
|
||||||
|
|
||||||
|
::processStartAddress = ::processStopAddress = (DWORD)GetModuleHandleW(nullptr);
|
||||||
|
|
||||||
|
MEMORY_BASIC_INFORMATION info;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
VirtualQuery((void*)::processStopAddress, &info, sizeof(info));
|
||||||
|
::processStopAddress = (DWORD)info.BaseAddress + info.RegionSize;
|
||||||
|
} while (info.Protect > PAGE_NOACCESS);
|
||||||
|
processStopAddress -= info.RegionSize;
|
||||||
|
|
||||||
|
::running = true;
|
||||||
|
::current_available = ::hookman;
|
||||||
|
|
||||||
|
CreatePipe();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
{
|
||||||
|
::running = false;
|
||||||
|
|
||||||
|
for (TextHook *man = ::hookman; man < ::hookman + MAX_HOOK; man++) man->ClearHook();
|
||||||
|
//if (ith_has_section)
|
||||||
|
UnmapViewOfFile(::hookman);
|
||||||
|
|
||||||
|
CloseHandle(::hookPipe);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD SwitchTrigger(DWORD t)
|
||||||
|
{
|
||||||
|
trigger = t;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
@ -4,8 +4,8 @@
|
|||||||
// 8/23/2013 jichi
|
// 8/23/2013 jichi
|
||||||
// Branch: ITH/IHF_DLL.h, rev 66
|
// Branch: ITH/IHF_DLL.h, rev 66
|
||||||
|
|
||||||
#include "include/const.h"
|
#include "common.h"
|
||||||
#include "include/types.h"
|
#include "pipe.h"
|
||||||
|
|
||||||
void ConsoleOutput(LPCSTR text); // jichi 12/25/2013: Used to return length of sent text
|
void ConsoleOutput(LPCSTR text); // jichi 12/25/2013: Used to return length of sent text
|
||||||
void NotifyHookInsert(HookParam hp, LPCSTR name);
|
void NotifyHookInsert(HookParam hp, LPCSTR name);
|
116
vnrhook/pipe.cc
Normal file
116
vnrhook/pipe.cc
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// 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()
|
||||||
|
{
|
||||||
|
std::thread([]()
|
||||||
|
{
|
||||||
|
enum { STANDARD_WAIT = 50 };
|
||||||
|
while (::running)
|
||||||
|
{
|
||||||
|
DWORD count = 0;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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_WRITE_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
DWORD mode = PIPE_READMODE_MESSAGE;
|
||||||
|
SetNamedPipeHandleState(hostPipe, &mode, NULL, NULL);
|
||||||
|
}
|
||||||
|
Sleep(STANDARD_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
*(DWORD*)buffer = GetCurrentProcessId();
|
||||||
|
WriteFile(::hookPipe, buffer, sizeof(DWORD), &count, nullptr);
|
||||||
|
|
||||||
|
ReleaseMutex(pipeAcquisitionMutex);
|
||||||
|
CloseHandle(pipeAcquisitionMutex);
|
||||||
|
|
||||||
|
ConsoleOutput("vnrcli:WaitForPipe: 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);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HOST_COMMAND_REMOVE_HOOK:
|
||||||
|
{
|
||||||
|
auto info = *(RemoveHookCmd*)buffer;
|
||||||
|
for (int i = 0; i < MAX_HOOK; ++i)
|
||||||
|
if (::hookman[i].Address() == info.address)
|
||||||
|
::hookman[i].ClearHook();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HOST_COMMAND_DETACH:
|
||||||
|
{
|
||||||
|
::running = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hostPipe);
|
||||||
|
}
|
||||||
|
FreeLibraryAndExitThread(GetModuleHandleW(ITH_DLL), 0);
|
||||||
|
}).detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleOutput(LPCSTR text)
|
||||||
|
{
|
||||||
|
auto info = ConsoleOutputNotif(text);
|
||||||
|
WriteFile(::hookPipe, &info, strlen(text) + sizeof(info), DUMMY, 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)
|
||||||
|
{
|
||||||
|
auto info = HookRemovedNotif(addr);
|
||||||
|
WriteFile(::hookPipe, &info, sizeof(info), DUMMY, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// engine/hookdefs.h
|
|
||||||
// 7/20/2014 jichi
|
|
||||||
|
|
||||||
// For HookParam user flags
|
|
||||||
enum HookParamFlag : unsigned long {
|
|
||||||
HPF_Null = 0 // never used
|
|
||||||
, HPF_IgnoreSameAddress = 1 // ignore the last same text address
|
|
||||||
};
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,78 +0,0 @@
|
|||||||
#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
|
|
@ -1,175 +0,0 @@
|
|||||||
// 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 "src/main.h"
|
|
||||||
#include "src/engine/engine.h"
|
|
||||||
#include "src/engine/match.h"
|
|
||||||
#include "src/hijack/texthook.h"
|
|
||||||
#include "src/util/growl.h"
|
|
||||||
#include "src/except.h"
|
|
||||||
#include "include/const.h"
|
|
||||||
#include "include/defs.h"
|
|
||||||
#include "ithsys/ithsys.h"
|
|
||||||
#include "util/util.h"
|
|
||||||
#include <cstdio> // for swprintf
|
|
||||||
//#include "ntinspect/ntinspect.h"
|
|
||||||
//#include "winseh/winseh.h"
|
|
||||||
//#include <boost/foreach.hpp>
|
|
||||||
//#include "md5.h"
|
|
||||||
//#include <ITH\AVL.h>
|
|
||||||
//#include <ITH\ntdll.h>
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
|
|
||||||
// jichi 6/3/2014: memory range of the current module
|
|
||||||
DWORD processStartAddress,
|
|
||||||
processStopAddress;
|
|
||||||
|
|
||||||
enum { HOOK_BUFFER_SIZE = MAX_HOOK * sizeof(TextHook) };
|
|
||||||
|
|
||||||
WCHAR hm_section[0x100];
|
|
||||||
HANDLE hSection;
|
|
||||||
bool running;
|
|
||||||
int currentHook = 0,
|
|
||||||
user_hook_count = 0;
|
|
||||||
DWORD trigger = 0;
|
|
||||||
HANDLE
|
|
||||||
hFile,
|
|
||||||
hMutex,
|
|
||||||
hmMutex;
|
|
||||||
HMODULE currentModule;
|
|
||||||
//DWORD current_process_id;
|
|
||||||
extern DWORD enter_count;
|
|
||||||
//extern LPWSTR current_dir;
|
|
||||||
extern DWORD engine_type;
|
|
||||||
|
|
||||||
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 = (TextHook*)MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, HOOK_BUFFER_SIZE);
|
|
||||||
|
|
||||||
::processStartAddress = ::processStopAddress = (DWORD)GetModuleHandleW(nullptr);
|
|
||||||
|
|
||||||
#ifndef _WIN64
|
|
||||||
MEMORY_BASIC_INFORMATION info;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
VirtualQuery((void*)::processStopAddress, &info, sizeof(info));
|
|
||||||
::processStopAddress = (DWORD)info.BaseAddress + info.RegionSize;
|
|
||||||
} while (info.Protect > PAGE_NOACCESS);
|
|
||||||
processStopAddress -= info.RegionSize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
{
|
|
||||||
wchar_t hm_mutex[0x100];
|
|
||||||
swprintf(hm_mutex, ITH_HOOKMAN_MUTEX_ L"%d", GetCurrentProcessId());
|
|
||||||
::hmMutex = CreateMutexW(nullptr, FALSE, hm_mutex);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD SwitchTrigger(DWORD t)
|
|
||||||
{
|
|
||||||
trigger = t;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,138 +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 "src/hijack/texthook.h"
|
|
||||||
#include "src/engine/match.h"
|
|
||||||
#include "src/util/util.h"
|
|
||||||
#include "src/main.h"
|
|
||||||
#include "include/defs.h"
|
|
||||||
#include "src/util/growl.h"
|
|
||||||
#include "ithsys/ithsys.h"
|
|
||||||
#include <cstdio> // for swprintf
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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_WRITE_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
||||||
DWORD mode = PIPE_READMODE_MESSAGE;
|
|
||||||
SetNamedPipeHandleState(hostPipe, &mode, NULL, NULL);
|
|
||||||
}
|
|
||||||
Sleep(STANDARD_WAIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
*(DWORD*)buffer = GetCurrentProcessId();
|
|
||||||
WriteFile(::hookPipe, buffer, sizeof(DWORD), &count, nullptr);
|
|
||||||
|
|
||||||
ReleaseMutex(pipeAcquisitionMutex);
|
|
||||||
CloseHandle(pipeAcquisitionMutex);
|
|
||||||
|
|
||||||
ConsoleOutput("vnrcli:WaitForPipe: pipe connected");
|
|
||||||
#ifdef _WIN64
|
|
||||||
ConsoleOutput("Hooks don't work on x64, only read codes work. Engine disabled.");
|
|
||||||
#else
|
|
||||||
Engine::Hijack();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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
|
|
@ -3,7 +3,7 @@
|
|||||||
// Branch: ITH_Engine/engine.cpp, revision 133
|
// Branch: ITH_Engine/engine.cpp, revision 133
|
||||||
// See: http://ja.wikipedia.org/wiki/プロジェクト:美少女ゲーム系/ゲームエンジン
|
// See: http://ja.wikipedia.org/wiki/プロジェクト:美少女ゲーム系/ゲームエンジン
|
||||||
|
|
||||||
#include "src/util/util.h"
|
#include "util/util.h"
|
||||||
#include "ithsys/ithsys.h"
|
#include "ithsys/ithsys.h"
|
||||||
|
|
||||||
namespace { // unnamed
|
namespace { // unnamed
|
Loading…
x
Reference in New Issue
Block a user