fix #231: add input block only on map drawing

This commit is contained in:
Callow 2022-07-13 11:41:40 +03:00
parent f74a95fc5c
commit 770ea91296
3 changed files with 157 additions and 13 deletions

View File

@ -1,15 +1,153 @@
#include <pch-il2cpp.h>
enum THREADINFOCLASS { ThreadHideFromDebugger = 0x11 };
typedef NTSTATUS(WINAPI* NtQueryInformationThread_t)(HANDLE, THREADINFOCLASS, PVOID, ULONG, LPVOID);
typedef NTSTATUS(WINAPI* NtSetInformationThread_t)(HANDLE, THREADINFOCLASS, PVOID, ULONG);
typedef void(WINAPI* DbgUiRemoteBreakin_t)();
NtQueryInformationThread_t fnNtQueryInformationThread = nullptr;
NtSetInformationThread_t fnNtSetInformationThread = nullptr;
DbgUiRemoteBreakin_t fnDbgUiRemoteBreakin = nullptr;
static void RunVEH();
static void FindAPI();
static bool Patch_NtSetInformationThread();
static bool Patch_DbgUiRemoteBreakin();
static long WINAPI DebugHandler(PEXCEPTION_POINTERS exception);
static void WINAPI DbgUiRemoteBreakin_Hook();
static NTSTATUS WINAPI NtSetInformationThread_Hook(HANDLE handle, THREADINFOCLASS infoClass, PVOID pValue, ULONG pSize);
void DebuggerBypassPre()
{
#ifdef _DEBUG
LOG_INFO("You have no implementation for anti-debugger bypass.\n\tSo if you try to attach VS debugger to process - game will crash.");
#endif
// Sry, implementation is private for now
if (!Patch_NtSetInformationThread())
LOG_ERROR("Failed to patch NtSetInformationThread, so main thread will be hidden from debugger. ^(");
}
void DebuggerBypassPost()
{
// Sry, implementation is privite for now
if (!Patch_DbgUiRemoteBreakin())
LOG_ERROR("Failed to patch DbgUiRemoteBreakin, so when debugger will try to attach, game crash. ^(");
RunVEH();
}
static void RunVEH()
{
AddVectoredExceptionHandler(1, DebugHandler);
}
static bool Patch_NtSetInformationThread()
{
if (fnNtSetInformationThread == nullptr && (FindAPI(), fnNtSetInformationThread == nullptr))
return false;
HookManager::install(fnNtSetInformationThread, NtSetInformationThread_Hook);
LOG_DEBUG("NtSetInformationThread api hooked. Origin at 0x%p", HookManager::getOrigin(NtSetInformationThread_Hook));
return true;
}
static bool Patch_DbgUiRemoteBreakin()
{
if (fnDbgUiRemoteBreakin == nullptr && (FindAPI(), fnDbgUiRemoteBreakin == nullptr))
return false;
HookManager::install(fnDbgUiRemoteBreakin, DbgUiRemoteBreakin_Hook);
LOG_DEBUG("DbgUiRemoteBreakin api hooked. Origin at 0x%p", HookManager::getOrigin(DbgUiRemoteBreakin_Hook));
return true;
}
static void FindAPI()
{
HMODULE hNTDLL = GetModuleHandle("ntdll.dll");
if (hNTDLL == NULL)
{
LOG_LAST_ERROR("Failed to get the 'ntdll.dll' handle");
return;
}
if (fnDbgUiRemoteBreakin == nullptr)
{
fnDbgUiRemoteBreakin = reinterpret_cast<DbgUiRemoteBreakin_t>(GetProcAddress(hNTDLL, "DbgUiRemoteBreakin"));
if (fnDbgUiRemoteBreakin == nullptr)
LOG_LAST_ERROR("GetProcAddress(ntdll::DbgUiRemoteBreakin) failed");
}
if (fnNtQueryInformationThread == nullptr)
{
fnNtQueryInformationThread = reinterpret_cast<NtQueryInformationThread_t>(GetProcAddress(hNTDLL, "NtQueryInformationThread"));
if (fnNtQueryInformationThread == nullptr)
LOG_LAST_ERROR("GetProcAddress(ntdll::NtQueryInformationThread) failed");
}
if (fnNtSetInformationThread == nullptr)
{
fnNtSetInformationThread = reinterpret_cast<NtSetInformationThread_t>(GetProcAddress(hNTDLL, "NtSetInformationThread"));
if (fnNtSetInformationThread == nullptr)
LOG_LAST_ERROR("GetProcAddress(ntdll::NtSetInformationThread) failed");
}
}
// Modified version of https://guidedhacking.com/threads/how-to-find-hidden-threads-threadhidefromdebugger-antidebug-trick.14281/
static bool IsThreadHidden(DWORD threadID)
{
if (fnNtQueryInformationThread == nullptr &&
(FindAPI(), fnNtQueryInformationThread == nullptr)) // Yeah, seems like a shit ^)
return false;
HANDLE hThread = OpenThread(
THREAD_QUERY_INFORMATION,
false,
threadID);
if (hThread == NULL) {
std::cout << " - Error :" << util::GetLastErrorAsString();
return false;
}
unsigned char lHideThread = 0;
ULONG lRet = 0;
NTSTATUS errorCode = fnNtQueryInformationThread(hThread, (THREADINFOCLASS)0x11, &lHideThread, sizeof(lHideThread), &lRet);
WaitForSingleObject(hThread, INFINITE);
return static_cast<bool>(lHideThread);
}
static long WINAPI DebugHandler(PEXCEPTION_POINTERS exception) {
PEXCEPTION_RECORD record = exception->ExceptionRecord;
PCONTEXT context = exception->ContextRecord;
if (record->ExceptionCode == EXCEPTION_SINGLE_STEP) {
SuspendThread(GetCurrentThread());
return EXCEPTION_CONTINUE_EXECUTION;
}
else if (record->ExceptionCode == EXCEPTION_BREAKPOINT)
{
CONTEXT ctx = {};
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
DWORD threadID = GetThreadId(GetCurrentThread());
LOG_WARNING("Breakpoint exception! Thread: %d; Hidden: %s", threadID, IsThreadHidden(threadID) ? "true" : "false");
return EXCEPTION_CONTINUE_EXECUTION;
}
else if (context->Rip == 0x8887777)
{
SuspendThread(GetCurrentThread());
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
static void WINAPI DbgUiRemoteBreakin_Hook()
{
return;
}
static NTSTATUS WINAPI NtSetInformationThread_Hook(HANDLE handle, THREADINFOCLASS infoClass, PVOID pValue, ULONG pSize)
{
if (infoClass == ThreadHideFromDebugger)
{
return 1;
}
return CALL_ORIGIN(NtSetInformationThread_Hook, handle, infoClass, pValue, pSize);
}

View File

@ -1379,12 +1379,6 @@ namespace cheat::feature
void InteractiveMap::DrawExternal()
{
// If any InputText is focused, the game will not respond any keyboard input.
auto ctx = ImGui::GetCurrentContext();
if (ctx->IO.WantCaptureKeyboard && !renderer::IsInputLocked())
renderer::SetInputLock(this, true);
else if (!ctx->IO.WantCaptureKeyboard && renderer::IsInputLocked())
renderer::SetInputLock(this, false);
if (IsMiniMapActive() && f_Enabled)
DrawMinimapPoints();
@ -1393,13 +1387,25 @@ namespace cheat::feature
bool mapActive = IsMapActive();
if (mapActive != _lastMapActive)
{
MapToggled(mapActive);
if (!mapActive)
renderer::SetInputLock(this, false);
}
_lastMapActive = mapActive;
if (!mapActive)
return;
// If any InputText is focused, the game will not respond any keyboard input.
auto ctx = ImGui::GetCurrentContext();
if (ctx->IO.WantCaptureKeyboard && !renderer::IsInputLocked())
renderer::SetInputLock(this, true);
else if (!ctx->IO.WantCaptureKeyboard && renderer::IsInputLocked())
renderer::SetInputLock(this, false);
auto mapManager = GET_SINGLETON(MoleMole_MapManager);
if (mapManager == nullptr)
return;

View File

@ -43,7 +43,7 @@ void Run(HMODULE* phModule)
#ifdef _DEBUG
LOG_DEBUG("Waiting 10sec for loading game library.");
Sleep(10000);
Sleep(15000);
#else
LOG_DEBUG("Waiting 15sec for game initialize.");
Sleep(15000);