reorganize, everything
This commit is contained in:
parent
98649ffbcc
commit
446ff71464
@ -2,7 +2,6 @@
|
||||
#include "ui_mainwindow.h"
|
||||
#include "extensions.h"
|
||||
#include "misc.h"
|
||||
#include "../vnrhook/include/const.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QInputDialog>
|
||||
#include <QFileDialog>
|
||||
@ -78,9 +77,9 @@ void MainWindow::AddThread(TextThread* thread)
|
||||
{
|
||||
ttCombo->addItem(
|
||||
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)
|
||||
@ -116,7 +115,7 @@ void MainWindow::ThreadOutput(TextThread* thread, QString output)
|
||||
|
||||
QString MainWindow::TextThreadString(TextThread* thread)
|
||||
{
|
||||
ThreadParameter tp = thread->GetThreadParameter();
|
||||
ThreadParam tp = thread->GetThreadParam();
|
||||
return QString("%1:%2:%3:%4: ").arg(
|
||||
QString::number(tp.pid),
|
||||
QString::number(tp.hook, 16),
|
||||
@ -125,7 +124,7 @@ QString MainWindow::TextThreadString(TextThread* thread)
|
||||
).toUpper();
|
||||
}
|
||||
|
||||
ThreadParameter MainWindow::ParseTextThreadString(QString textThreadString)
|
||||
ThreadParam MainWindow::ParseTextThreadString(QString textThreadString)
|
||||
{
|
||||
QStringList threadParam = textThreadString.split(":");
|
||||
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)) },
|
||||
{ "text number", 0 },
|
||||
{ "process id", thread->GetThreadParameter().pid },
|
||||
{ "hook address", (int)thread->GetThreadParameter().hook },
|
||||
{ "hook address (upper 32 bits)", (int)(thread->GetThreadParameter().hook >> 32) }
|
||||
{ "process id", thread->GetThreadParam().pid },
|
||||
{ "hook address", (int)thread->GetThreadParam().hook },
|
||||
{ "hook address (upper 32 bits)", (int)(thread->GetThreadParam().hook >> 32) }
|
||||
};
|
||||
}
|
||||
|
||||
@ -161,7 +160,7 @@ QVector<HookParam> MainWindow::GetAllHooks(DWORD processId)
|
||||
QVector<HookParam> hooks;
|
||||
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))
|
||||
{
|
||||
addresses.insert(tp.hook);
|
||||
|
@ -44,7 +44,7 @@ private slots:
|
||||
|
||||
private:
|
||||
QString TextThreadString(TextThread* thread);
|
||||
ThreadParameter ParseTextThreadString(QString textThreadString);
|
||||
ThreadParam ParseTextThreadString(QString textThreadString);
|
||||
DWORD GetSelectedProcessId();
|
||||
void ReloadExtensions();
|
||||
std::unordered_map<std::string, int> GetInfoForExtensions(TextThread* thread);
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "misc.h"
|
||||
#include "../vnrhook/include/const.h"
|
||||
#include "const.h"
|
||||
#include <QRegExp>
|
||||
#include <Psapi.h>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define MISC_H
|
||||
|
||||
#include "qtcommon.h"
|
||||
#include "../host/host.h"
|
||||
#include "pipe.h"
|
||||
|
||||
QString GetFullModuleName(DWORD processId, HMODULE module = NULL);
|
||||
QString GetModuleName(DWORD processId, HMODULE module = NULL);
|
||||
|
@ -1,8 +1,4 @@
|
||||
set(vnrhost_src
|
||||
host.h
|
||||
pipe.h
|
||||
textthread.h
|
||||
winmutex.h
|
||||
host.cc
|
||||
pipe.cc
|
||||
textthread.cc
|
||||
|
67
host/host.cc
67
host/host.cc
@ -4,21 +4,33 @@
|
||||
|
||||
#include "host.h"
|
||||
#include "pipe.h"
|
||||
#include "winmutex.h"
|
||||
#include "../vnrhook/include/const.h"
|
||||
#include "../vnrhook/include/defs.h"
|
||||
#include "../vnrhook/include/types.h"
|
||||
#include "const.h"
|
||||
#include "defs.h"
|
||||
#include "../vnrhook/hijack/texthook.h"
|
||||
|
||||
|
||||
struct ThreadParameterHasher
|
||||
struct ProcessRecord
|
||||
{
|
||||
size_t operator()(const ThreadParameter& tp) const
|
||||
{
|
||||
return std::hash<__int64>()(tp.pid << 6) + std::hash<__int64>()(tp.hook) + std::hash<__int64>()(tp.retn) + std::hash<__int64>()(tp.spl);
|
||||
}
|
||||
HANDLE processHandle;
|
||||
HANDLE sectionMutex;
|
||||
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::recursive_mutex hostMutex;
|
||||
@ -28,7 +40,7 @@ ProcessEventCallback OnAttach, OnDetach;
|
||||
|
||||
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
|
||||
|
||||
@ -38,7 +50,7 @@ namespace Host
|
||||
{
|
||||
OnAttach = onAttach; OnDetach = onDetach; OnCreate = onCreate; OnRemove = onRemove;
|
||||
OnCreate(textThreadsByParams[CONSOLE] = new TextThread(CONSOLE, USING_UNICODE));
|
||||
CreateNewPipe();
|
||||
CreatePipe();
|
||||
}
|
||||
|
||||
DLLEXPORT void Close()
|
||||
@ -102,25 +114,20 @@ namespace Host
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name)
|
||||
{
|
||||
BYTE buffer[PIPE_BUFFER_SIZE] = {};
|
||||
*(DWORD*)buffer = HOST_COMMAND_NEW_HOOK;
|
||||
*(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);
|
||||
auto info = InsertHookCmd(hp, name);
|
||||
return WriteFile(processRecordsByIds[pid].hostPipe, &info, sizeof(info), DUMMY, nullptr);
|
||||
}
|
||||
|
||||
DLLEXPORT bool RemoveHook(DWORD pid, DWORD addr)
|
||||
{
|
||||
BYTE buffer[sizeof(DWORD) * 2] = {};
|
||||
*(DWORD*)buffer = HOST_COMMAND_REMOVE_HOOK;
|
||||
*(DWORD*)(buffer + sizeof(DWORD)) = addr;
|
||||
return WriteFile(processRecordsByIds[pid].hostPipe, buffer, sizeof(DWORD) * 2, DUMMY, nullptr);
|
||||
auto info = RemoveHookCmd(addr);
|
||||
return WriteFile(processRecordsByIds[pid].hostPipe, &info, sizeof(info), DUMMY, nullptr);
|
||||
}
|
||||
|
||||
DLLEXPORT HookParam GetHookParam(DWORD pid, DWORD addr)
|
||||
@ -130,14 +137,14 @@ namespace Host
|
||||
ProcessRecord pr = processRecordsByIds[pid];
|
||||
if (pr.sectionMap == nullptr) return ret;
|
||||
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)
|
||||
if ((DWORD)hooks[i].Address() == addr)
|
||||
ret = hooks[i].hp;
|
||||
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)
|
||||
{
|
||||
@ -147,7 +154,7 @@ namespace Host
|
||||
ProcessRecord pr = processRecordsByIds[pid];
|
||||
if (pr.sectionMap == nullptr) return L"";
|
||||
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)
|
||||
if ((DWORD)hooks[i].Address() == addr)
|
||||
{
|
||||
@ -158,7 +165,7 @@ namespace Host
|
||||
return std::wstring(A2W(buffer.c_str()));
|
||||
}
|
||||
|
||||
DLLEXPORT TextThread* GetThread(ThreadParameter tp)
|
||||
DLLEXPORT TextThread* GetThread(ThreadParam tp)
|
||||
{
|
||||
HOST_LOCK;
|
||||
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;
|
||||
HOST_LOCK;
|
||||
@ -181,10 +188,10 @@ void DispatchText(ThreadParameter tp, const BYTE* text, int len)
|
||||
it->AddText(text, len);
|
||||
}
|
||||
|
||||
void RemoveThreads(bool(*RemoveIf)(ThreadParameter, ThreadParameter), ThreadParameter cmp)
|
||||
void RemoveThreads(bool(*RemoveIf)(ThreadParam, ThreadParam), ThreadParam cmp)
|
||||
{
|
||||
HOST_LOCK;
|
||||
std::vector<ThreadParameter> removedThreads;
|
||||
std::vector<ThreadParam> removedThreads;
|
||||
for (auto i : textThreadsByParams)
|
||||
if (RemoveIf(i.first, cmp))
|
||||
{
|
||||
|
18
host/host.h
18
host/host.h
@ -6,19 +6,9 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "textthread.h"
|
||||
#include "../vnrhook/include/types.h"
|
||||
|
||||
#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(TextThread*)> ThreadEventCallback;
|
||||
|
||||
@ -32,15 +22,15 @@ namespace Host
|
||||
DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name = "");
|
||||
DLLEXPORT bool RemoveHook(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 TextThread* GetThread(ThreadParameter tp);
|
||||
DLLEXPORT TextThread* GetThread(ThreadParam tp);
|
||||
DLLEXPORT void AddConsoleOutput(std::wstring text);
|
||||
}
|
||||
|
||||
void DispatchText(ThreadParameter tp, const BYTE *text, int len);
|
||||
void RemoveThreads(bool(*RemoveIf)(ThreadParameter, ThreadParameter), ThreadParameter cmp);
|
||||
void DispatchText(ThreadParam tp, const BYTE *text, int len);
|
||||
void RemoveThreads(bool(*RemoveIf)(ThreadParam, ThreadParam), ThreadParam cmp);
|
||||
void RegisterProcess(DWORD pid, HANDLE hostPipe);
|
||||
void UnregisterProcess(DWORD pid);
|
||||
|
||||
|
49
host/pipe.cc
49
host/pipe.cc
@ -4,10 +4,10 @@
|
||||
|
||||
#include "pipe.h"
|
||||
#include "host.h"
|
||||
#include "../vnrhook/include/defs.h"
|
||||
#include "../vnrhook/include/const.h"
|
||||
#include "defs.h"
|
||||
#include "const.h"
|
||||
|
||||
void CreateNewPipe()
|
||||
void CreatePipe()
|
||||
{
|
||||
std::thread([]()
|
||||
{
|
||||
@ -17,7 +17,7 @@ void CreateNewPipe()
|
||||
|
||||
// jichi 9/27/2013: why recursion?
|
||||
// Artikash 5/20/2018: Easy way to create a new pipe for another process
|
||||
CreateNewPipe();
|
||||
CreatePipe();
|
||||
|
||||
BYTE buffer[PIPE_BUFFER_SIZE + 1] = {};
|
||||
DWORD bytesRead, processId;
|
||||
@ -25,34 +25,29 @@ void CreateNewPipe()
|
||||
RegisterProcess(processId, hostPipe);
|
||||
|
||||
while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
|
||||
switch (*(int*)buffer)
|
||||
{
|
||||
buffer[bytesRead] = 0;
|
||||
buffer[bytesRead + 1] = 0;
|
||||
|
||||
if (*(DWORD*)buffer == HOST_NOTIFICATION)
|
||||
switch (*(DWORD*)(buffer + sizeof(DWORD))) // Artikash 7/17/2018: Notification type
|
||||
{
|
||||
case HOST_NOTIFICATION_NEWHOOK: // Artikash 7/18/2018: Useless for now, but could be used to implement smth later
|
||||
break;
|
||||
//case HOST_NOTIFICATION_NEWHOOK: // Artikash 7/18/2018: Useless for now, but could be used to implement smth later
|
||||
//break;
|
||||
case HOST_NOTIFICATION_RMVHOOK:
|
||||
RemoveThreads([](auto one, auto two) { return one.pid == two.pid && one.hook == two.hook; },
|
||||
{ processId, *(DWORD*)(buffer + sizeof(DWORD) * 2) }); // Address
|
||||
{
|
||||
auto info = *(HookRemovedNotif*)buffer;
|
||||
RemoveThreads([](auto one, auto two) { return one.pid == two.pid && one.hook == two.hook; }, { processId, info.address });
|
||||
}
|
||||
break;
|
||||
case HOST_NOTIFICATION_TEXT:
|
||||
USES_CONVERSION;
|
||||
Host::AddConsoleOutput(A2W((LPCSTR)(buffer + sizeof(DWORD) * 2))); // Text
|
||||
break;
|
||||
}
|
||||
else DispatchText(
|
||||
{
|
||||
processId,
|
||||
*(DWORD*)buffer, // Hook address
|
||||
*(DWORD*)(buffer + sizeof(DWORD)), // Return address
|
||||
*(DWORD*)(buffer + sizeof(DWORD) * 2) // Split
|
||||
},
|
||||
buffer + HEADER_SIZE, // Data
|
||||
bytesRead - HEADER_SIZE // Data size
|
||||
);
|
||||
auto info = *(ConsoleOutputNotif*)buffer;
|
||||
USES_CONVERSION;
|
||||
Host::AddConsoleOutput(A2W(info.message));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
ThreadParam tp = *(ThreadParam*)buffer;
|
||||
DispatchText(tp, buffer + sizeof(tp), bytesRead - sizeof(tp));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DisconnectNamedPipe(hookPipe);
|
||||
|
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
|
||||
// 8/24/2013 jichi
|
||||
// Branch IHF/TextThread.cpp, rev 133
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (disable:4100) // C4100: unreference formal parameter
|
||||
#endif // _MSC_VER
|
||||
|
||||
#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
|
||||
|
||||
TextThread::TextThread(ThreadParameter tp, DWORD status) :
|
||||
TextThread::TextThread(ThreadParam tp, DWORD status) :
|
||||
deletionEvent(CreateEventW(nullptr, FALSE, FALSE, NULL)),
|
||||
flushThread([&]() { while (WaitForSingleObject(deletionEvent, 100), Flush()); }),
|
||||
timestamp(GetTickCount()),
|
||||
|
@ -5,34 +5,18 @@
|
||||
// Branch: ITH/TextThread.h, rev 120
|
||||
|
||||
#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
|
||||
{
|
||||
typedef std::function<std::wstring(TextThread*, std::wstring)> ThreadOutputCallback;
|
||||
public:
|
||||
TextThread(ThreadParameter tp, DWORD status);
|
||||
TextThread(ThreadParam tp, DWORD status);
|
||||
virtual ~TextThread();
|
||||
|
||||
virtual std::wstring GetStore();
|
||||
ThreadParameter GetThreadParameter() { return tp; }
|
||||
ThreadParam GetThreadParam() { return tp; }
|
||||
|
||||
void RegisterOutputCallBack(ThreadOutputCallback cb) { Output = cb; }
|
||||
|
||||
@ -50,7 +34,7 @@ private:
|
||||
|
||||
DWORD timestamp;
|
||||
ThreadOutputCallback Output;
|
||||
ThreadParameter tp;
|
||||
ThreadParam tp;
|
||||
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
|
||||
// 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"
|
||||
|
||||
// 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")
|
||||
set(vnrhook_src
|
||||
include/const.h
|
||||
include/defs.h
|
||||
include/types.h
|
||||
src/main.cc
|
||||
src/main.h
|
||||
src/pipe.cc
|
||||
src/util/ithsys/ithsys.cc
|
||||
src/hijack/texthook.cc
|
||||
main.cc
|
||||
pipe.cc
|
||||
util/ithsys/ithsys.cc
|
||||
hijack/texthook.cc
|
||||
)
|
||||
else()
|
||||
set(vnrhook_src
|
||||
include/const.h
|
||||
include/defs.h
|
||||
include/types.h
|
||||
src/except.h
|
||||
src/main.cc
|
||||
src/main.h
|
||||
src/pipe.cc
|
||||
src/engine/engine.cc
|
||||
src/engine/engine.h
|
||||
src/engine/hookdefs.h
|
||||
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
|
||||
main.cc
|
||||
pipe.cc
|
||||
engine/engine.cc
|
||||
engine/match.cc
|
||||
engine/pchooks.cc
|
||||
hijack/texthook.cc
|
||||
util/util.cc
|
||||
util/ithsys/ithsys.cc
|
||||
util/disasm/disasm.cc
|
||||
util/memdbg/memsearch.cc
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories(src/util)
|
||||
include_directories(util)
|
||||
|
||||
add_library(vnrhook SHARED ${vnrhook_src})
|
||||
|
||||
|
@ -7,21 +7,21 @@
|
||||
# pragma warning (disable:4819)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include "src/engine/engine.h"
|
||||
#include "engine/engine.h"
|
||||
#include "ntdll/ntdll.h"
|
||||
#include "src/engine/match.h"
|
||||
#include "src/engine/hookdefs.h"
|
||||
#include "src/util/util.h"
|
||||
#include "src/main.h"
|
||||
#include "src/engine/mono/funcinfo.h"
|
||||
#include "src/engine/ppsspp/funcinfo.h"
|
||||
#include "src/except.h"
|
||||
#include "engine/match.h"
|
||||
#include "util/util.h"
|
||||
#include "main.h"
|
||||
#include "engine/mono/funcinfo.h"
|
||||
#include "engine/ppsspp/funcinfo.h"
|
||||
#include "except.h"
|
||||
#include "ithsys/ithsys.h"
|
||||
#include "memdbg/memsearch.h"
|
||||
#include "disasm/disasm.h"
|
||||
#include "cpputil/cppcstring.h"
|
||||
#include "mono/monoobject.h"
|
||||
#include "growl.h"
|
||||
#include "const.h"
|
||||
//#include <boost/foreach.hpp>
|
||||
#include <cstdio>
|
||||
#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)
|
||||
|
||||
#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
|
||||
|
@ -7,13 +7,13 @@
|
||||
//# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include "src/engine/match.h"
|
||||
#include "src/engine/engine.h"
|
||||
#include "src/engine/pchooks.h"
|
||||
#include "src/util/growl.h"
|
||||
#include "src/util/util.h"
|
||||
#include "src/main.h"
|
||||
#include "src/except.h"
|
||||
#include "engine/match.h"
|
||||
#include "engine/engine.h"
|
||||
#include "engine/pchooks.h"
|
||||
#include "util/growl.h"
|
||||
#include "util/util.h"
|
||||
#include "main.h"
|
||||
#include "except.h"
|
||||
#include "ithsys/ithsys.h"
|
||||
|
||||
//#define ConsoleOutput(...) (void)0 // jichi 8/18/2013: I don't need ConsoleOutput
|
@ -1,8 +1,8 @@
|
||||
// pchooks.cc
|
||||
// 8/1/2014 jichi
|
||||
|
||||
#include "src/engine/pchooks.h"
|
||||
#include "src/main.h"
|
||||
#include "engine/pchooks.h"
|
||||
#include "main.h"
|
||||
//#include <gdiplus.h>
|
||||
|
||||
#define DEBUG "vnrcli"
|
@ -9,11 +9,11 @@
|
||||
//# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include "src/hijack/texthook.h"
|
||||
#include "src/engine/match.h"
|
||||
#include "src/except.h"
|
||||
#include "src/main.h"
|
||||
#include "include/const.h"
|
||||
#include "hijack/texthook.h"
|
||||
#include "engine/match.h"
|
||||
#include "except.h"
|
||||
#include "main.h"
|
||||
#include "const.h"
|
||||
#include "ithsys/ithsys.h"
|
||||
#include "disasm/disasm.h"
|
||||
//#include "winseh/winseh.h"
|
||||
@ -293,9 +293,8 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn)
|
||||
}
|
||||
dwCount = GetLength(dwDataBase, dwDataIn);
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if (hp.length_offset == 1) {
|
||||
@ -304,27 +303,27 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn)
|
||||
dwDataIn = _byteswap_ushort(dwDataIn & 0xffff);
|
||||
if (dwCount == 1)
|
||||
dwDataIn &= 0xff;
|
||||
*(WORD *)(pbData + HEADER_SIZE) = dwDataIn & 0xffff;
|
||||
*(WORD *)(pbData + sizeof(ThreadParam)) = dwDataIn & 0xffff;
|
||||
}
|
||||
else
|
||||
::memcpy(pbData + HEADER_SIZE, (void *)dwDataIn, dwCount);
|
||||
::memcpy(pbData + sizeof(ThreadParam), (void *)dwDataIn, dwCount);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
*(DWORD *)pbData = dwAddr;
|
||||
if (dwType & (NO_CONTEXT|FIXING_SPLIT))
|
||||
dwRetn = 0;
|
||||
|
||||
*(ThreadParam*)pbData = { GetCurrentProcessId(), dwAddr, dwRetn, dwSplit };
|
||||
*((DWORD *)pbData + 1) = dwRetn;
|
||||
*((DWORD *)pbData + 2) = dwSplit;
|
||||
if (dwCount) {
|
||||
DWORD unused;
|
||||
|
||||
//CliLockPipe();
|
||||
WriteFile(::hookPipe, pbData, dwCount + HEADER_SIZE, &unused, nullptr);
|
||||
WriteFile(::hookPipe, pbData, dwCount + sizeof(ThreadParam), &unused, nullptr);
|
||||
//CliUnlockPipe();
|
||||
}
|
||||
return 0;
|
||||
@ -454,7 +453,7 @@ DWORD WINAPI ReaderThread(LPVOID threadParam)
|
||||
while (true)
|
||||
{
|
||||
Sleep(500);
|
||||
if (memcmp(buffer + HEADER_SIZE, currentAddress, dataLen) == 0)
|
||||
if (memcmp(buffer + sizeof(ThreadParam), currentAddress, dataLen) == 0)
|
||||
{
|
||||
changeCount = 0;
|
||||
continue;
|
||||
@ -471,12 +470,10 @@ DWORD WINAPI ReaderThread(LPVOID threadParam)
|
||||
else
|
||||
dataLen = strlen(currentAddress);
|
||||
|
||||
*(DWORD*)buffer = hook->hp.address;
|
||||
*(DWORD*)(buffer + 4) = 0;
|
||||
*(DWORD*)(buffer + 8) = 0;
|
||||
memcpy(buffer + HEADER_SIZE, currentAddress, dataLen);
|
||||
*(ThreadParam*)buffer = { GetCurrentProcessId(), hook->hp.address, 0, 0 };
|
||||
memcpy(buffer + sizeof(ThreadParam), currentAddress, dataLen);
|
||||
DWORD unused;
|
||||
WriteFile(::hookPipe, buffer, dataLen + HEADER_SIZE, &unused, nullptr);
|
||||
WriteFile(::hookPipe, buffer, dataLen + sizeof(ThreadParam), &unused, nullptr);
|
||||
}
|
||||
hook->ClearHook();
|
||||
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
|
||||
// Branch: ITH/IHF_DLL.h, rev 66
|
||||
|
||||
#include "include/const.h"
|
||||
#include "include/types.h"
|
||||
#include "common.h"
|
||||
#include "pipe.h"
|
||||
|
||||
void ConsoleOutput(LPCSTR text); // jichi 12/25/2013: Used to return length of sent text
|
||||
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
|
||||
// See: http://ja.wikipedia.org/wiki/プロジェクト:美少女ゲーム系/ゲームエンジン
|
||||
|
||||
#include "src/util/util.h"
|
||||
#include "util/util.h"
|
||||
#include "ithsys/ithsys.h"
|
||||
|
||||
namespace { // unnamed
|
Loading…
Reference in New Issue
Block a user