diff --git a/3rdparty/README.txt b/3rdparty/README.txt index 1dfcc110..85b1f948 100644 --- a/3rdparty/README.txt +++ b/3rdparty/README.txt @@ -1 +1 @@ -To build the IDA plugin, extract the contents of idasdk695.zip in the directory "idasdk" \ No newline at end of file +To build the IDA plugin, extract the contents of idasdk75.zip into any directory of your choice and export it to the "IDASDK" environment variable. \ No newline at end of file diff --git a/3rdparty/ntdll/ntdll.h b/3rdparty/ntdll/ntdll.h index a89b1106..0ae4a195 100644 --- a/3rdparty/ntdll/ntdll.h +++ b/3rdparty/ntdll/ntdll.h @@ -223,18 +223,20 @@ typedef struct _UNICODE_STRING typedef const UNICODE_STRING *PCUNICODE_STRING; #define DECLARE_UNICODE_STRING_SIZE(_var, _size) \ -WCHAR _var ## _buffer[_size]; \ -__pragma(warning(push)) \ -__pragma(warning(disable:4221)) __pragma(warning(disable:4204)) \ -UNICODE_STRING _var = { 0, (_size) * sizeof(WCHAR) , _var ## _buffer } \ -__pragma(warning(pop)) + WCHAR _var ## _buffer[_size]; \ + __pragma(warning(push)) \ + __pragma(warning(disable:4221)) \ + __pragma(warning(disable:4204)) \ + UNICODE_STRING _var = { 0, (_size) * sizeof(WCHAR) , _var ## _buffer } \ + __pragma(warning(pop)) #define DECLARE_STATIC_UNICODE_STRING_SIZE(_var, _size) \ -WCHAR _var ## _buffer[_size]; \ -__pragma(warning(push)) \ -__pragma(warning(disable:4221)) __pragma(warning(disable:4204)) \ -static UNICODE_STRING _var = { 0, (_size) * sizeof(WCHAR) , _var ## _buffer } \ -__pragma(warning(pop)) + WCHAR _var ## _buffer[_size]; \ + __pragma(warning(push)) \ + __pragma(warning(disable:4221)) \ + __pragma(warning(disable:4204)) \ + static UNICODE_STRING _var = { 0, (_size) * sizeof(WCHAR) , _var ## _buffer } \ + __pragma(warning(pop)) #if defined(__clang__) #define RTL_CONSTANT_STRING(s) \ diff --git a/Documentation/ScyllaHideDocumentation.tex b/Documentation/ScyllaHideDocumentation.tex index 65efc5d1..dd0b6013 100644 --- a/Documentation/ScyllaHideDocumentation.tex +++ b/Documentation/ScyllaHideDocumentation.tex @@ -60,7 +60,7 @@ \section{Description} \begin{itemize} \item OllyDbg v1 and v2 \url{http://www.ollydbg.de} \item x64dbg \url{http://x64dbg.com} or \url{https://github.com/x64dbg/x64dbg} -\item Hex-Rays IDA v6 \url{https://www.hex-rays.com/products/ida} +\item Hex-Rays IDA v7.5 \url{https://www.hex-rays.com/products/ida} \item TitanEngine v2 \url{https://bitbucket.org/mrexodia/titanengine-update} and \url{http://www.reversinglabs.com/open-source/titanengine.html} \end{itemize} @@ -85,14 +85,16 @@ \subsection{OllyDbg v1} \subsection{OllyDbg v2} Copy scylla\_hide.ini, HookLibraryx86.dll and ScyllaHideOlly2.dll to your specific plugins directory. -\subsection{IDA v6} +\subsection{IDA v7.5} \textbf{32-bit:} Copy scylla\_hide.ini, HookLibraryx86.dll and ScyllaHideIDA.plw to your IDA plugins directory. \textbf{64-bit:} -Copy scylla\_hide.ini, HookLibraryx64.dll, ScyllaHideIDASrvx64.exe and ScyllaHideIDA.p64 to your IDA plugins directory. +Copy HookLibraryx64.dll, ScyllaHideIDAServerx64.exe to your host machine where you intended to debug (normally a Virtual Machine). -Note: \\Start ScyllaHideIDASrvx64.exe to debug 64bit applications remotely. \\Start ScyllaHideIDASrvx86.exe to debug 32bit applications remotely. +Copy ScyllaHideIDAProPlugin64.dll and scylla\_hide.ini to your IDA plugins directory. + +Note: \\Start ScyllaHideIDAServerx64.exe to debug 64bit applications remotely. \\Start ScyllaHideIDASrvx86.exe to debug 32bit applications remotely. Command line: ScyllaHideIDASrvxXX.exe \\ For example: ScyllaHideIDASrvxXX.exe 1345 diff --git a/HookLibrary/DllMain.cpp b/HookLibrary/DllMain.cpp index abc35639..3193c75e 100644 --- a/HookLibrary/DllMain.cpp +++ b/HookLibrary/DllMain.cpp @@ -2,8 +2,9 @@ #pragma comment(linker, "/ENTRY:DllMain") +//---------------------------------------------------------------------------------- BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { LdrDisableThreadCalloutsForDll(hinstDLL); return TRUE; -} \ No newline at end of file +} diff --git a/HookLibrary/Export.def b/HookLibrary/Export.def index c9b1879e..78bf020d 100644 --- a/HookLibrary/Export.def +++ b/HookLibrary/Export.def @@ -1,33 +1,33 @@ LIBRARY EXPORTS -HookDllData -HookedGetLocalTime -HookedGetSystemTime -HookedGetTickCount -HookedGetTickCount64 -HookedKiUserExceptionDispatcher -HookedNativeCallInternal -HookedNtClose -HookedNtContinue -HookedNtCreateThread -HookedNtCreateThreadEx -HookedNtDuplicateObject -HookedNtGetContextThread -HookedNtQueryInformationProcess -HookedNtQueryObject -HookedNtQueryPerformanceCounter -HookedNtQuerySystemInformation -HookedNtQuerySystemTime -HookedNtSetContextThread -HookedNtSetDebugFilterState -HookedNtSetInformationProcess -HookedNtSetInformationThread -HookedNtUserBlockInput -HookedNtUserBuildHwndList -HookedNtUserBuildHwndList_Eight -HookedNtUserFindWindowEx -HookedNtUserGetForegroundWindow -HookedNtUserQueryWindow -HookedNtYieldExecution -HookedOutputDebugStringA -HookedNtResumeThread \ No newline at end of file + HookDllData + HookedGetLocalTime + HookedGetSystemTime + HookedGetTickCount + HookedGetTickCount64 + HookedKiUserExceptionDispatcher + HookedNativeCallInternal + HookedNtClose + HookedNtContinue + HookedNtCreateThread + HookedNtCreateThreadEx + HookedNtDuplicateObject + HookedNtGetContextThread + HookedNtQueryInformationProcess + HookedNtQueryObject + HookedNtQueryPerformanceCounter + HookedNtQuerySystemInformation + HookedNtQuerySystemTime + HookedNtSetContextThread + HookedNtSetDebugFilterState + HookedNtSetInformationProcess + HookedNtSetInformationThread + HookedNtUserBlockInput + HookedNtUserBuildHwndList + HookedNtUserBuildHwndList_Eight + HookedNtUserFindWindowEx + HookedNtUserGetForegroundWindow + HookedNtUserQueryWindow + HookedNtYieldExecution + HookedOutputDebugStringA + HookedNtResumeThread \ No newline at end of file diff --git a/HookLibrary/HookHelper.cpp b/HookLibrary/HookHelper.cpp index 309971d2..feb903cd 100644 --- a/HookLibrary/HookHelper.cpp +++ b/HookLibrary/HookHelper.cpp @@ -5,115 +5,197 @@ #include "HookedFunctions.h" #include "HookMain.h" -const WCHAR * BadProcessnameList[] = -{ - L"ollydbg.exe", - L"ida.exe", - L"ida64.exe", - L"idag.exe", - L"idag64.exe", - L"idaw.exe", - L"idaw64.exe", - L"idaq.exe", - L"idaq64.exe", - L"idau.exe", - L"idau64.exe", - L"scylla.exe", - L"scylla_x64.exe", - L"scylla_x86.exe", - L"protection_id.exe", - L"x64dbg.exe", - L"x32dbg.exe", - L"windbg.exe", - L"reshacker.exe", - L"ImportREC.exe", - L"IMMUNITYDEBUGGER.EXE", - L"devenv.exe" +//---------------------------------------------------------------------------------- +const wchar_t *BadProcessnameList[] = +{ + // Olly + L"ollydbg.exe", + // IDA + L"ida.exe", L"ida64.exe", L"idag.exe", L"idag64.exe", + L"idaw.exe", L"idaw64.exe", L"idaq.exe", L"idaq64.exe", + L"idau.exe", L"idau64.exe", L"win64_remote64.exe", + // Scylla + L"scylla.exe", L"scylla_x64.exe", L"scylla_x86.exe", + // Protection ID + L"protection_id.exe", + // x64dbg + L"x64dbg.exe", L"x32dbg.exe", + // Windbg + L"windbg.exe", "cdb.exe" + // Res hacker + L"reshacker.exe", + // Imprec + L"ImportREC.exe", + // Immunity + L"IMMUNITYDEBUGGER.EXE", + // Visual Studio + L"devenv.exe", + nullptr }; -const WCHAR * BadWindowTextList[] = +//---------------------------------------------------------------------------------- +const wchar_t *BadWindowTextList[] = { L"OLLYDBG", - L"ida", - L"disassembly", - L"scylla", - L"Debug", - L"[CPU", - L"Immunity", - L"WinDbg", - L"x32dbg", - L"x64dbg", - L"Import reconstructor" + L"ida", + L"disassembly", + L"scylla", + L"Debug", + L"[CPU", + L"Immunity", + L"WinDbg", + L"x32dbg", + L"x64dbg", + L"Import reconstructor", + nullptr }; -const WCHAR * BadWindowClassList[] = +//---------------------------------------------------------------------------------- +const wchar_t *BadWindowClassList[] = { - L"OLLYDBG", - L"Zeta Debugger", - L"Rock Debugger", - L"ObsidianGUI", - L"ID", //Immunity Debugger - L"WinDbgFrameClass", //WinDBG - L"idawindow", - L"tnavbox", - L"idaview", - L"tgrzoom" + L"OLLYDBG", + L"Zeta Debugger", + L"Rock Debugger", + L"ObsidianGUI", + L"ID", //Immunity Debugger + L"WinDbgFrameClass", //WinDBG + L"idawindow", + L"tnavbox", + L"idaview", + L"tgrzoom", + nullptr }; +//---------------------------------------------------------------------------------- extern "C" void InstrumentationCallbackAsm(); extern HOOK_DLL_DATA HookDllData; + extern SAVE_DEBUG_REGISTERS ArrayDebugRegister[100]; +static DWORD dwExplorerPid = 0; + static USHORT DebugObjectTypeIndex = 0; static USHORT ProcessTypeIndex = 0; static USHORT ThreadTypeIndex = 0; -bool IsProcessNameBad(PUNICODE_STRING processName) +static BYTE memory[sizeof(IMAGE_NT_HEADERS) + 0x100] = { 0 }; + +WCHAR MalwareFile[MAX_PATH] = { 0 }; +const WCHAR MalwareFilename[] = L"Unpacked.exe"; + +//---------------------------------------------------------------------------------- +static LUID ConvertLongToLuid(LONG value) { - if (processName == nullptr || processName->Length == 0 || processName->Buffer == nullptr) - return false; + LUID luid; + LARGE_INTEGER largeInt; + largeInt.QuadPart = value; + luid.LowPart = largeInt.LowPart; + luid.HighPart = largeInt.HighPart; + return luid; +} - UNICODE_STRING badProcessName; - for (int i = 0; i < _countof(BadProcessnameList); i++) - { - RtlInitUnicodeString(&badProcessName, const_cast(BadProcessnameList[i])); - if (RtlEqualUnicodeString(processName, &badProcessName, TRUE)) - return true; - } - return false; +//---------------------------------------------------------------------------------- +bool RtlUnicodeStringContains(PUNICODE_STRING Str, PUNICODE_STRING SubStr, BOOLEAN CaseInsensitive) +{ + if (Str == nullptr || SubStr == nullptr || Str->Length < SubStr->Length) + return false; + + const USHORT numCharsDiff = (Str->Length - SubStr->Length) / sizeof(WCHAR); + UNICODE_STRING slice = *Str; + slice.Length = SubStr->Length; + + for (USHORT i = 0; i <= numCharsDiff; ++i, ++slice.Buffer, slice.MaximumLength -= sizeof(WCHAR)) + { + if (RtlEqualUnicodeString(&slice, SubStr, CaseInsensitive)) + return true; + } + return false; } -bool IsWindowClassNameBad(PUNICODE_STRING className) +//---------------------------------------------------------------------------------- +static bool IsUnicodeStringInTable(PUNICODE_STRING uStr, const wchar_t* Table[]) { - if (className == nullptr || className->Length == 0 || className->Buffer == nullptr) - return false; + if (uStr == nullptr || uStr->Length == 0 || uStr->Buffer == nullptr) + return false; + + UNICODE_STRING uValue; + for (size_t i = 0; ; ++i) + { + auto wStr = const_cast(Table[i]); + if (wStr == nullptr) + break; + + RtlInitUnicodeString(&uValue, wStr); + if (RtlUnicodeStringContains(uStr, &uValue, TRUE)) + return true; + } + return false; +} - UNICODE_STRING badWindowClassName; - for (int i = 0; i < _countof(BadWindowClassList); i++) - { - RtlInitUnicodeString(&badWindowClassName, const_cast(BadWindowClassList[i])); - if (RtlUnicodeStringContains(className, &badWindowClassName, TRUE)) - return true; - } - return false; +//---------------------------------------------------------------------------------- +void ThreadDebugContextRemoveEntry(const int index) +{ + ArrayDebugRegister[index].dwThreadId = 0; } -bool IsWindowNameBad(PUNICODE_STRING windowName) +//---------------------------------------------------------------------------------- +void ThreadDebugContextSaveContext(const int index, const PCONTEXT ThreadContext) { - if (windowName == nullptr || windowName->Length == 0 || windowName->Buffer == nullptr) - return false; + ArrayDebugRegister[index].dwThreadId = HandleToULong(NtCurrentTeb()->ClientId.UniqueThread); + ArrayDebugRegister[index].Dr0 = ThreadContext->Dr0; + ArrayDebugRegister[index].Dr1 = ThreadContext->Dr1; + ArrayDebugRegister[index].Dr2 = ThreadContext->Dr2; + ArrayDebugRegister[index].Dr3 = ThreadContext->Dr3; + ArrayDebugRegister[index].Dr6 = ThreadContext->Dr6; + ArrayDebugRegister[index].Dr7 = ThreadContext->Dr7; +} - UNICODE_STRING badWindowName; - for (int i = 0; i < _countof(BadWindowTextList); i++) - { - RtlInitUnicodeString(&badWindowName, const_cast(BadWindowTextList[i])); - if (RtlUnicodeStringContains(windowName, &badWindowName, TRUE)) - return true; - } - return false; +//---------------------------------------------------------------------------------- +int ThreadDebugContextFindExistingSlotIndex() +{ + auto CurrentThreadId = HandleToULong(NtCurrentTeb()->ClientId.UniqueThread); + for (size_t i = 0; i < _countof(ArrayDebugRegister); i++) + { + if (ArrayDebugRegister[i].dwThreadId != 0) + { + if (ArrayDebugRegister[i].dwThreadId == CurrentThreadId) + return int(i); + } + } + return -1; +} + +//---------------------------------------------------------------------------------- +int ThreadDebugContextFindFreeSlotIndex() +{ + for (size_t i = 0; i < _countof(ArrayDebugRegister); i++) + { + if (ArrayDebugRegister[i].dwThreadId == 0) + return int(i); + } + return -1; +} + +//---------------------------------------------------------------------------------- +bool IsProcessNameBad(PUNICODE_STRING processName) +{ + return IsUnicodeStringInTable(processName, BadProcessnameList); +} + +//---------------------------------------------------------------------------------- +bool IsWindowClassNameBad(PUNICODE_STRING className) +{ + return IsUnicodeStringInTable(className, BadWindowClassList); +} + +//---------------------------------------------------------------------------------- +bool IsWindowNameBad(PUNICODE_STRING windowName) +{ + return IsUnicodeStringInTable(windowName, BadWindowTextList); } +//---------------------------------------------------------------------------------- bool IsWindowBad(HWND hWnd) { if (HookDllData.EnableProtectProcessId) @@ -121,6 +203,7 @@ bool IsWindowBad(HWND hWnd) const ULONG Pid = HookDllData.dNtUserQueryWindow != nullptr ? HandleToULong(HookDllData.dNtUserQueryWindow(hWnd, WindowProcess)) : HandleToULong(HookDllData.NtUserQueryWindow(hWnd, WindowProcess)); + if (Pid == HookDllData.dwProtectedProcessId) return true; } @@ -138,6 +221,7 @@ bool IsWindowBad(HWND hWnd) return IsWindowNameBad(&WindowText); } +//---------------------------------------------------------------------------------- static void GetBadObjectTypes() { // If NtQSI is not hooked, this function is N/A @@ -160,36 +244,43 @@ static void GetBadObjectTypes() PSYSTEM_HANDLE_INFORMATION_EX HandleInfo = &Dummy; ULONG Size; NTSTATUS Status; - if ((Status = HookDllData.dNtQuerySystemInformation(SystemExtendedHandleInformation, - HandleInfo, - sizeof(Dummy), - &Size)) != STATUS_INFO_LENGTH_MISMATCH) - goto exit; - - HandleInfo = (PSYSTEM_HANDLE_INFORMATION_EX)RtlAllocateHeap(RtlProcessHeap(), 0, 2 * Size); - Status = HookDllData.dNtQuerySystemInformation(SystemExtendedHandleInformation, - HandleInfo, - 2 * Size, - nullptr); - if (!NT_SUCCESS(Status)) - goto exit; - - // Enumerate all handles - for (ULONG i = 0; i < HandleInfo->NumberOfHandles; ++i) - { - SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Entry = HandleInfo->Handles[i]; - if (Entry.UniqueProcessId != (ULONG_PTR)NtCurrentTeb()->ClientId.UniqueProcess) - continue; // Not our process - - if (Entry.HandleValue == (ULONG_PTR)DebugObjectHandle) - DebugObjectTypeIndex = Entry.ObjectTypeIndex; - else if (Entry.HandleValue == (ULONG_PTR)ProcessHandle) - ProcessTypeIndex = Entry.ObjectTypeIndex; - else if (Entry.HandleValue == (ULONG_PTR)ThreadHandle) - ThreadTypeIndex = Entry.ObjectTypeIndex; - } -exit: + do + { + Status = HookDllData.dNtQuerySystemInformation( + SystemExtendedHandleInformation, + HandleInfo, + sizeof(Dummy), + &Size); + + if (Status != STATUS_INFO_LENGTH_MISMATCH) + break; + + HandleInfo = (PSYSTEM_HANDLE_INFORMATION_EX)RtlAllocateHeap(RtlProcessHeap(), 0, 2 * Size); + Status = HookDllData.dNtQuerySystemInformation(SystemExtendedHandleInformation, + HandleInfo, + 2 * Size, + nullptr); + if (!NT_SUCCESS(Status)) + break; + + // Enumerate all handles + for (ULONG i = 0; i < HandleInfo->NumberOfHandles; ++i) + { + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Entry = HandleInfo->Handles[i]; + if (Entry.UniqueProcessId != (ULONG_PTR)NtCurrentTeb()->ClientId.UniqueProcess) + continue; // Not our process + + if (Entry.HandleValue == (ULONG_PTR)DebugObjectHandle) + DebugObjectTypeIndex = Entry.ObjectTypeIndex; + else if (Entry.HandleValue == (ULONG_PTR)ProcessHandle) + ProcessTypeIndex = Entry.ObjectTypeIndex; + else if (Entry.HandleValue == (ULONG_PTR)ThreadHandle) + ThreadTypeIndex = Entry.ObjectTypeIndex; + } + } while (false); + + // Cleanup if (DebugObjectHandle != nullptr) NtClose(DebugObjectHandle); if (ProcessHandle != nullptr) @@ -200,24 +291,22 @@ static void GetBadObjectTypes() RtlFreeHeap(RtlProcessHeap(), 0, HandleInfo); } +//---------------------------------------------------------------------------------- bool IsObjectTypeBad(USHORT objectTypeIndex) { GetBadObjectTypes(); - return objectTypeIndex == DebugObjectTypeIndex || - objectTypeIndex == ProcessTypeIndex || - objectTypeIndex == ThreadTypeIndex; + return objectTypeIndex == DebugObjectTypeIndex + || objectTypeIndex == ProcessTypeIndex + || objectTypeIndex == ThreadTypeIndex; } -static LUID ConvertLongToLuid(LONG value) +bool IsThreadInProcess(HANDLE ThreadHandle) { - LUID luid; - LARGE_INTEGER largeInt; - largeInt.QuadPart = value; - luid.LowPart = largeInt.LowPart; - luid.HighPart = largeInt.HighPart; - return luid; + return ThreadHandle == NtCurrentThread + || HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess) == GetProcessIdByThreadHandle(ThreadHandle); } +//---------------------------------------------------------------------------------- bool HasDebugPrivileges(HANDLE hProcess) { HANDLE hToken; @@ -240,23 +329,24 @@ bool HasDebugPrivileges(HANDLE hProcess) return hasDebugPrivileges == TRUE; } +//---------------------------------------------------------------------------------- bool IsWow64Process(HANDLE ProcessHandle) { PPEB WoW64Peb = nullptr; - const NTSTATUS Status = NtQueryInformationProcess(ProcessHandle, - ProcessWow64Information, - &WoW64Peb, - sizeof(WoW64Peb), - nullptr); + const NTSTATUS Status = NtQueryInformationProcess( + ProcessHandle, + ProcessWow64Information, + &WoW64Peb, + sizeof(WoW64Peb), + nullptr); return NT_SUCCESS(Status) && WoW64Peb != nullptr; } -NTSTATUS -InstallInstrumentationCallbackHook( +//---------------------------------------------------------------------------------- +NTSTATUS InstallInstrumentationCallbackHook( _In_ HANDLE ProcessHandle, - _In_ BOOLEAN Remove - ) + _In_ BOOLEAN Remove) { const PVOID Callback = Remove ? nullptr : (PVOID)InstrumentationCallbackAsm; NTSTATUS Status = STATUS_NOT_SUPPORTED; @@ -310,6 +400,7 @@ InstallInstrumentationCallbackHook( (PVOID)&Callback, sizeof(Callback)); + // Restore debug privilege RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, SeDebugWasEnabled, FALSE, &SeDebugWasEnabled); } #endif @@ -317,65 +408,57 @@ InstallInstrumentationCallbackHook( return Status; } -void * GetPEBRemote(HANDLE hProcess) +//---------------------------------------------------------------------------------- +void *GetPEBRemote(HANDLE hProcess) { PROCESS_BASIC_INFORMATION pbi; if (HookDllData.dNtQueryInformationProcess) { if (HookDllData.dNtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), 0) >= 0) - { return pbi.PebBaseAddress; - } } else { //maybe not hooked if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), 0) >= 0) - { return pbi.PebBaseAddress; - } } return 0; } - +//---------------------------------------------------------------------------------- DWORD GetProcessIdByProcessHandle(HANDLE hProcess) { PROCESS_BASIC_INFORMATION pbi; - if (HookDllData.dNtQueryInformationProcess) + if (HookDllData.dNtQueryInformationProcess != nullptr) { if (HookDllData.dNtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), 0) >= 0) - { return HandleToULong(pbi.UniqueProcessId); - } } else { - //maybe not hooked if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), 0) >= 0) - { return HandleToULong(pbi.UniqueProcessId); - } } return 0; } +//---------------------------------------------------------------------------------- DWORD GetProcessIdByThreadHandle(HANDLE hThread) { THREAD_BASIC_INFORMATION tbi; if (NT_SUCCESS(NtQueryInformationThread(hThread, ThreadBasicInformation, &tbi, sizeof(THREAD_BASIC_INFORMATION), 0))) - { return HandleToULong(tbi.ClientId.UniqueProcess); - } return 0; } +//---------------------------------------------------------------------------------- void TerminateProcessByProcessId(DWORD dwProcess) { if (dwProcess == 0) @@ -392,39 +475,43 @@ void TerminateProcessByProcessId(DWORD dwProcess) } } -static DWORD dwExplorerPid = 0; - +//---------------------------------------------------------------------------------- DWORD GetExplorerProcessId() { if (dwExplorerPid == 0) { UNICODE_STRING explorerName = RTL_CONSTANT_STRING(L"explorer.exe"); - dwExplorerPid = GetProcessIdByName(&explorerName); + dwExplorerPid = NtGetProcessIdByName(&explorerName); } return dwExplorerPid; } -DWORD GetProcessIdByName(PUNICODE_STRING processName) +//---------------------------------------------------------------------------------- +DWORD NtGetProcessIdByName(PUNICODE_STRING processName) { ULONG size; if (NtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) return 0; + const PSYSTEM_PROCESS_INFORMATION systemProcessInfo = static_cast(RtlAllocateHeap(RtlProcessHeap(), 0, 2 * size)); + NTSTATUS status; if (HookDllData.dNtQuerySystemInformation != nullptr) { - status = HookDllData.dNtQuerySystemInformation(SystemProcessInformation, - systemProcessInfo, - 2 * size, - nullptr); + status = HookDllData.dNtQuerySystemInformation( + SystemProcessInformation, + systemProcessInfo, + 2 * size, + nullptr); } else { - status = NtQuerySystemInformation(SystemProcessInformation, - systemProcessInfo, - 2 * size, - nullptr); + status = NtQuerySystemInformation( + SystemProcessInformation, + systemProcessInfo, + 2 * size, + nullptr); } if (!NT_SUCCESS(status)) return 0; @@ -448,68 +535,7 @@ DWORD GetProcessIdByName(PUNICODE_STRING processName) return pid; } -bool RtlUnicodeStringContains(PUNICODE_STRING Str, PUNICODE_STRING SubStr, BOOLEAN CaseInsensitive) -{ - if (Str == nullptr || SubStr == nullptr || Str->Length < SubStr->Length) - return false; - - const USHORT numCharsDiff = (Str->Length - SubStr->Length) / sizeof(WCHAR); - UNICODE_STRING slice = *Str; - slice.Length = SubStr->Length; - - for (USHORT i = 0; i <= numCharsDiff; ++i, ++slice.Buffer, slice.MaximumLength -= sizeof(WCHAR)) - { - if (RtlEqualUnicodeString(&slice, SubStr, CaseInsensitive)) - return true; - } - return false; -} - -void ThreadDebugContextRemoveEntry(const int index) -{ - ArrayDebugRegister[index].dwThreadId = 0; -} - -void ThreadDebugContextSaveContext(const int index, const PCONTEXT ThreadContext) -{ - ArrayDebugRegister[index].dwThreadId = HandleToULong(NtCurrentTeb()->ClientId.UniqueThread); - ArrayDebugRegister[index].Dr0 = ThreadContext->Dr0; - ArrayDebugRegister[index].Dr1 = ThreadContext->Dr1; - ArrayDebugRegister[index].Dr2 = ThreadContext->Dr2; - ArrayDebugRegister[index].Dr3 = ThreadContext->Dr3; - ArrayDebugRegister[index].Dr6 = ThreadContext->Dr6; - ArrayDebugRegister[index].Dr7 = ThreadContext->Dr7; -} - -int ThreadDebugContextFindExistingSlotIndex() -{ - for (int i = 0; i < _countof(ArrayDebugRegister); i++) - { - if (ArrayDebugRegister[i].dwThreadId != 0) - { - if (ArrayDebugRegister[i].dwThreadId == HandleToULong(NtCurrentTeb()->ClientId.UniqueThread)) - { - return i; - } - } - } - - return -1; -} - -int ThreadDebugContextFindFreeSlotIndex() -{ - for (int i = 0; i < _countof(ArrayDebugRegister); i++) - { - if (ArrayDebugRegister[i].dwThreadId == 0) - { - return i; - } - } - - return -1; -} - +//---------------------------------------------------------------------------------- // GetSystemTime and GetLocalTime are reimplemented here because the KernelBase functions use // RIP-relative addressing which breaks hooking. https://github.com/x64dbg/ScyllaHide/issues/31 void NTAPI RealGetSystemTime(PSYSTEMTIME lpSystemTime) @@ -527,6 +553,7 @@ void NTAPI RealGetSystemTime(PSYSTEMTIME lpSystemTime) lpSystemTime->wDayOfWeek = TimeFields.Weekday; } +//---------------------------------------------------------------------------------- void NTAPI RealGetLocalTime(LPSYSTEMTIME lpSystemTime) { TIME_FIELDS TimeFields; @@ -546,6 +573,7 @@ void NTAPI RealGetLocalTime(LPSYSTEMTIME lpSystemTime) lpSystemTime->wDayOfWeek = TimeFields.Weekday; } +//---------------------------------------------------------------------------------- void IncreaseSystemTime(LPSYSTEMTIME lpTime) { lpTime->wMilliseconds++; @@ -581,9 +609,7 @@ void IncreaseSystemTime(LPSYSTEMTIME lpTime) } } - -BYTE memory[sizeof(IMAGE_NT_HEADERS) + 0x100] = {0}; - +//---------------------------------------------------------------------------------- void DumpMalware(DWORD dwProcessId) { OBJECT_ATTRIBUTES attributes = { sizeof(OBJECT_ATTRIBUTES) }; @@ -625,9 +651,6 @@ void DumpMalware(DWORD dwProcessId) NtClose(hProcess); } -WCHAR MalwareFile[MAX_PATH] = {0}; -const WCHAR MalwareFilename[] = L"Unpacked.exe"; - bool WriteMalwareToDisk(LPCVOID buffer, DWORD bufferSize, DWORD_PTR imagebase) { if (MalwareFile[0] == 0) @@ -652,7 +675,12 @@ bool WriteMalwareToDisk(LPCVOID buffer, DWORD bufferSize, DWORD_PTR imagebase) return WriteMemoryToFile(MalwareFile, buffer,bufferSize, imagebase); } -bool WriteMemoryToFile(const WCHAR * filename, LPCVOID buffer, DWORD bufferSize, DWORD_PTR imagebase) +//---------------------------------------------------------------------------------- +bool WriteMemoryToFile( + const WCHAR * filename, + LPCVOID buffer, + DWORD bufferSize, + DWORD_PTR imagebase) { PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer; PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDos + pDos->e_lfanew); @@ -661,33 +689,42 @@ bool WriteMemoryToFile(const WCHAR * filename, LPCVOID buffer, DWORD bufferSize, UNICODE_STRING NtPath; if (!RtlDosPathNameToNtPathName_U(filename, &NtPath, nullptr, nullptr)) return false; + OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; InitializeObjectAttributes(&objectAttributes, &NtPath, OBJ_CASE_INSENSITIVE, nullptr, nullptr); HANDLE hFile; - NTSTATUS status = NtCreateFile(&hFile, - FILE_GENERIC_WRITE, - &objectAttributes, - &ioStatusBlock, - nullptr, - FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ, - FILE_OVERWRITE_IF, - FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, - nullptr, - 0); + NTSTATUS status = NtCreateFile( + &hFile, + FILE_GENERIC_WRITE, + &objectAttributes, + &ioStatusBlock, + nullptr, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + FILE_OVERWRITE_IF, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + nullptr, + 0); if (!NT_SUCCESS(status)) return false; status = NtWriteFile(hFile, nullptr, nullptr, nullptr, &ioStatusBlock, (PVOID)buffer, pNt->OptionalHeader.SizeOfHeaders, nullptr, nullptr); - for (WORD i = 0; i < pNt->FileHeader.NumberOfSections; i++) + for (WORD i = 0; i < pNt->FileHeader.NumberOfSections; i++, ++pSection) { - status = NtWriteFile(hFile, nullptr, nullptr, nullptr, &ioStatusBlock, (BYTE *)buffer + pSection->VirtualAddress, - pSection->SizeOfRawData, nullptr, nullptr); - pSection++; + status = NtWriteFile( + hFile, + nullptr, + nullptr, + nullptr, + &ioStatusBlock, + (BYTE *)buffer + pSection->VirtualAddress, + pSection->SizeOfRawData, + nullptr, + nullptr); } NtClose(hFile); diff --git a/HookLibrary/HookHelper.h b/HookLibrary/HookHelper.h index 65e4a816..a8f7e9fe 100644 --- a/HookLibrary/HookHelper.h +++ b/HookLibrary/HookHelper.h @@ -19,14 +19,16 @@ FORCEINLINE ULONG NTAPI RtlGetTickCount() bool HasDebugPrivileges(HANDLE hProcess); bool IsWow64Process(HANDLE ProcessHandle); -NTSTATUS InstallInstrumentationCallbackHook(HANDLE ProcessHandle, BOOLEAN Remove); +NTSTATUS InstallInstrumentationCallbackHook(_In_ HANDLE ProcessHandle, _In_ BOOLEAN Remove); DWORD GetExplorerProcessId(); -DWORD GetProcessIdByName(PUNICODE_STRING processName); +DWORD NtGetProcessIdByName(PUNICODE_STRING processName); bool IsProcessNameBad(PUNICODE_STRING processName); DWORD GetProcessIdByProcessHandle(HANDLE hProcess); DWORD GetProcessIdByThreadHandle(HANDLE hThread); +bool IsThreadInProcess(HANDLE ThreadHandle); + bool RtlUnicodeStringContains(PUNICODE_STRING Str, PUNICODE_STRING SubStr, BOOLEAN CaseInsensitive); bool IsWindowNameBad(PUNICODE_STRING windowName); diff --git a/HookLibrary/HookLibrary.vcxproj b/HookLibrary/HookLibrary.vcxproj index 383a276c..bd7abb4c 100644 --- a/HookLibrary/HookLibrary.vcxproj +++ b/HookLibrary/HookLibrary.vcxproj @@ -1,193 +1,193 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - 16.0 - {C36C2313-72A8-4583-B7D8-28E193D5287F} - Win32Proj - HookLibrary - 10.0 - - - - DynamicLibrary - true - v142 - Unicode - false - false - - - DynamicLibrary - true - v142 - Unicode - false - false - - - DynamicLibrary - false - v142 - true - Unicode - false - false - - - DynamicLibrary - false - v142 - true - Unicode - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - $(TargetName)x86 - - - false - $(TargetName)x64 - - - false - false - $(TargetName)x86 - - - false - false - $(TargetName)x64 - - - - WIN32;_DEBUG;_WINDOWS;_USRDLL;HOOKLIBRARY_EXPORTS;%(PreprocessorDefinitions) - true - true - - - Windows - Export.def - - - - - _DEBUG;_WINDOWS;_USRDLL;HOOKLIBRARY_EXPORTS;%(PreprocessorDefinitions) - Default - true - true - - - Windows - Export.def - - - - - WIN32;NDEBUG;_WINDOWS;_USRDLL;HOOKLIBRARY_EXPORTS;%(PreprocessorDefinitions) - false - false - - true - true - - - Windows - Export.def - false - - - - - NDEBUG;_WINDOWS;_USRDLL;HOOKLIBRARY_EXPORTS;%(PreprocessorDefinitions) - false - false - - true - true - - - Windows - Export.def - false - - - - - - - - - - - - - - - - - - - true - true - - - true - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + 16.0 + {C36C2313-72A8-4583-B7D8-28E193D5287F} + Win32Proj + HookLibrary + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + false + false + + + DynamicLibrary + true + v142 + Unicode + false + false + + + DynamicLibrary + false + v142 + true + Unicode + false + false + + + DynamicLibrary + false + v142 + true + Unicode + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + $(TargetName)x86 + + + false + $(TargetName)x64 + + + false + false + $(TargetName)x86 + + + false + false + $(TargetName)x64 + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;HOOKLIBRARY_EXPORTS;%(PreprocessorDefinitions) + true + true + + + Windows + Export.def + + + + + _DEBUG;_WINDOWS;_USRDLL;HOOKLIBRARY_EXPORTS;%(PreprocessorDefinitions) + Default + true + true + + + Windows + Export.def + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;HOOKLIBRARY_EXPORTS;%(PreprocessorDefinitions) + false + false + + true + true + + + Windows + Export.def + false + + + + + NDEBUG;_WINDOWS;_USRDLL;HOOKLIBRARY_EXPORTS;%(PreprocessorDefinitions) + false + false + + true + true + + + Windows + Export.def + false + + + + + + + + + + + + + + + + + + + true + true + + + true + true + + + + + + \ No newline at end of file diff --git a/HookLibrary/HookLibrary.vcxproj.filters b/HookLibrary/HookLibrary.vcxproj.filters index f418a48a..ea8b3139 100644 --- a/HookLibrary/HookLibrary.vcxproj.filters +++ b/HookLibrary/HookLibrary.vcxproj.filters @@ -1,55 +1,55 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/HookLibrary/HookMain.h b/HookLibrary/HookMain.h index fee4031e..5ce5e825 100644 --- a/HookLibrary/HookMain.h +++ b/HookLibrary/HookMain.h @@ -4,28 +4,30 @@ typedef BOOL(WINAPI * t_DllMain)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); -typedef void (WINAPI * t_GetSystemTime)(LPSYSTEMTIME lpSystemTime); //Kernel32.dll / kernelbase -typedef void (WINAPI * t_GetLocalTime)(LPSYSTEMTIME lpSystemTime); //Kernel32.dll / kernelbase -typedef DWORD(WINAPI * t_timeGetTime)(void); //Winmm.dll -> sometimes GetTickCount -typedef DWORD(WINAPI * t_GetTickCount)(void); //Kernel32.dll / kernelbase -typedef ULONGLONG(WINAPI * t_GetTickCount64)(void); -typedef BOOL(WINAPI * t_QueryPerformanceCounter)(LARGE_INTEGER *lpPerformanceCount); //Kernel32.dll -> ntdll.RtlQueryPerformanceCounter -> NO NATIVE CALL -typedef BOOL(WINAPI * t_QueryPerformanceFrequency)(LARGE_INTEGER *lpFrequency); //kernel32.dll -> ntdll.RtlQueryPerformanceFrequency -> ntdll.ZwQueryPerformanceCounter - -typedef DWORD(WINAPI * t_OutputDebugStringA)(LPCSTR lpOutputString); //Kernel32.dll -typedef DWORD(WINAPI * t_OutputDebugStringW)(LPCWSTR lpOutputString); //Kernel32.dll +typedef void (WINAPI *t_GetSystemTime)(LPSYSTEMTIME lpSystemTime); // Kernel32.dll / kernelbase +typedef void (WINAPI *t_GetLocalTime)(LPSYSTEMTIME lpSystemTime); // Kernel32.dll / kernelbase +typedef DWORD (WINAPI *t_timeGetTime)(void); // Winmm.dll -> sometimes GetTickCount +typedef DWORD (WINAPI *t_GetTickCount)(void); // Kernel32.dll / kernelbase +typedef ULONGLONG (WINAPI *t_GetTickCount64)(void); +typedef BOOL (WINAPI *t_QueryPerformanceCounter)(LARGE_INTEGER *lpPerformanceCount); // Kernel32.dll -> ntdll.RtlQueryPerformanceCounter -> NO NATIVE CALL +typedef BOOL (WINAPI *t_QueryPerformanceFrequency)(LARGE_INTEGER *lpFrequency); // kernel32.dll -> ntdll.RtlQueryPerformanceFrequency -> ntdll.ZwQueryPerformanceCounter + +typedef DWORD (WINAPI *t_OutputDebugStringA)(LPCSTR lpOutputString); // Kernel32.dll +typedef DWORD (WINAPI *t_OutputDebugStringW)(LPCWSTR lpOutputString); // Kernel32.dll //WIN 7 X64: OutputDebugStringW -> OutputDebugStringA #define MAX_NATIVE_HOOKS 32 #pragma pack(push, 1) -typedef struct _HOOK_NATIVE_CALL32 { +struct HOOK_NATIVE_CALL32 +{ DWORD eaxValue; DWORD ecxValue; PVOID hookedFunction; -} HOOK_NATIVE_CALL32; +}; -typedef struct _HOOK_DLL_DATA { +struct HOOK_DLL_DATA +{ HMODULE hDllImage; BOOLEAN EnablePebBeingDebugged; @@ -47,13 +49,13 @@ typedef struct _HOOK_DLL_DATA { BOOLEAN EnablePreventThreadCreation; BOOLEAN EnableNtCreateThreadExHook; - //Protect and Hide Hardware Breakpoints + // Protect and Hide Hardware Breakpoints BOOLEAN EnableNtGetContextThreadHook; BOOLEAN EnableNtSetContextThreadHook; BOOLEAN EnableNtContinueHook; BOOLEAN EnableKiUserExceptionDispatcherHook; - //Native user32.dll/win32u.dll functions + // Native user32.dll/win32u.dll functions ULONG_PTR NtUserBlockInputVA; ULONG_PTR NtUserQueryWindowVA; ULONG_PTR NtUserGetForegroundWindowVA; @@ -77,10 +79,10 @@ typedef struct _HOOK_DLL_DATA { BOOLEAN EnableNtQuerySystemTimeHook; BOOLEAN EnableNtQueryPerformanceCounterHook; - //special + // Special BOOLEAN EnableMalwareRunPeUnpacker; //t_NtWriteVirtualMemory dNtWriteVirtualMemory; - //DWORD NtWriteVirtualMemoryBackupSize; + // DWORD NtWriteVirtualMemoryBackupSize; t_NtResumeThread dNtResumeThread; DWORD NtResumeThreadBackupSize; @@ -166,11 +168,10 @@ typedef struct _HOOK_DLL_DATA { HOOK_NATIVE_CALL32 HookNative[MAX_NATIVE_HOOKS]; PVOID NativeCallContinue; #endif -} HOOK_DLL_DATA; +}; #pragma pack(pop) #define HOOK_ERROR_SUCCESS 0 #define HOOK_ERROR_RESOLVE_IMPORT 1 #define HOOK_ERROR_DLLMAIN 2 #define HOOK_ERROR_PEHEADER 3 - diff --git a/HookLibrary/HookedFunctions.cpp b/HookLibrary/HookedFunctions.cpp index 2c1827b3..4cfcebf9 100644 --- a/HookLibrary/HookedFunctions.cpp +++ b/HookLibrary/HookedFunctions.cpp @@ -8,6 +8,11 @@ HOOK_DLL_DATA HookDllData = { 0 }; #include "HookHelper.h" #include "Tls.h" +#ifndef STATUS_INVALID_PARAMETER + #define STATUS_INVALID_PARAMETER ((DWORD )0xC000000DL) +#endif + +//---------------------------------------------------------------------------------- void FakeCurrentParentProcessId(PSYSTEM_PROCESS_INFORMATION pInfo); void FakeCurrentOtherOperationCount(PSYSTEM_PROCESS_INFORMATION pInfo); void FilterHandleInfo(PSYSTEM_HANDLE_INFORMATION pHandleInfo, PULONG pReturnLengthAdjust); @@ -15,9 +20,9 @@ void FilterHandleInfoEx(PSYSTEM_HANDLE_INFORMATION_EX pHandleInfoEx, PULONG pRet void FilterProcess(PSYSTEM_PROCESS_INFORMATION pInfo); void FilterObjects(POBJECT_TYPES_INFORMATION pObjectTypes); void FilterObject(POBJECT_TYPE_INFORMATION pObject, bool zeroTotal); -void FilterHwndList(HWND * phwndFirst, PUINT pcHwndNeeded); +void FilterHwndList(HWND * phwndFirst, PULONG pcHwndNeeded); -SAVE_DEBUG_REGISTERS ArrayDebugRegister[100] = { 0 }; //Max 100 threads +SAVE_DEBUG_REGISTERS ArrayDebugRegister[100] = { 0 }; // Max 100 threads // https://forum.tuts4you.com/topic/40011-debugme-vmprotect-312-build-886-anti-debug-method-improved/#comment-192824 // https://github.com/x64dbg/ScyllaHide/issues/47 @@ -31,30 +36,38 @@ SAVE_DEBUG_REGISTERS ArrayDebugRegister[100] = { 0 }; //Max 100 threads if(ReturnLength != nullptr) \ (*ReturnLength) = TempReturnLength -NTSTATUS NTAPI HookedNtSetInformationThread(HANDLE ThreadHandle, THREADINFOCLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength) + +//---------------------------------------------------------------------------------- +NTSTATUS NTAPI HookedNtSetInformationThread( + HANDLE ThreadHandle, + THREADINFOCLASS ThreadInformationClass, + PVOID ThreadInformation, + ULONG ThreadInformationLength) { if (ThreadInformationClass == ThreadHideFromDebugger && ThreadInformationLength == 0) // NB: ThreadInformation is not checked, this is deliberate { - if (ThreadHandle == NtCurrentThread || - HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess) == GetProcessIdByThreadHandle(ThreadHandle)) //thread inside this process? - { + if (IsThreadInProcess(ThreadHandle)) return STATUS_SUCCESS; - } } return HookDllData.dNtSetInformationThread(ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength); } -NTSTATUS NTAPI HookedNtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength) +//---------------------------------------------------------------------------------- +NTSTATUS NTAPI HookedNtQuerySystemInformation( + SYSTEM_INFORMATION_CLASS SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength) { - if (SystemInformationClass == SystemKernelDebuggerInformation || - SystemInformationClass == SystemProcessInformation || - SystemInformationClass == SystemSessionProcessInformation || - SystemInformationClass == SystemHandleInformation || - SystemInformationClass == SystemExtendedHandleInformation || - SystemInformationClass == SystemExtendedProcessInformation || // Vista+ - SystemInformationClass == SystemCodeIntegrityInformation || // Vista+ + if (SystemInformationClass == SystemKernelDebuggerInformation || + SystemInformationClass == SystemProcessInformation || + SystemInformationClass == SystemSessionProcessInformation || + SystemInformationClass == SystemHandleInformation || + SystemInformationClass == SystemExtendedHandleInformation || + SystemInformationClass == SystemExtendedProcessInformation || // Vista+ + SystemInformationClass == SystemCodeIntegrityInformation || // Vista+ SystemInformationClass == SystemKernelDebuggerInformationEx || // 8.1+ - SystemInformationClass == SystemKernelDebuggerFlags || // 10+ + SystemInformationClass == SystemKernelDebuggerFlags || // 10+ SystemInformationClass == SystemCodeIntegrityUnlockInformation) // 10+ { NTSTATUS ntStat = HookDllData.dNtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); @@ -153,30 +166,24 @@ static ULONG ValueProcessBreakOnTermination = FALSE; static ULONG ValueProcessDebugFlags = PROCESS_DEBUG_INHERIT; // actual value is no inherit static bool IsProcessHandleTracingEnabled = false; -#ifndef STATUS_INVALID_PARAMETER -#define STATUS_INVALID_PARAMETER ((DWORD )0xC000000DL) -#endif - +//---------------------------------------------------------------------------------- // Instrumentation callback static LONG volatile InstrumentationCallbackHookInstalled = 0; static ULONG NumManualSyscalls = 0; -extern "C" -ULONG_PTR -NTAPI -InstrumentationCallback( +extern "C" ULONG_PTR NTAPI InstrumentationCallback( _In_ ULONG_PTR ReturnAddress, // ECX/R10 - _Inout_ ULONG_PTR ReturnVal // EAX/RAX - ) + _Inout_ ULONG_PTR ReturnVal) // EAX/RAX { if (InterlockedOr(TlsGetInstrumentationCallbackDisabled(), 0x1) == 0x1) return ReturnVal; // Do not recurse const PVOID ImageBase = NtCurrentPeb()->ImageBaseAddress; const PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader(ImageBase); - if (NtHeaders != nullptr && ReturnAddress >= (ULONG_PTR)ImageBase && - ReturnAddress < (ULONG_PTR)ImageBase + NtHeaders->OptionalHeader.SizeOfImage) + if ( NtHeaders != nullptr + && ReturnAddress >= (ULONG_PTR)ImageBase + && ReturnAddress < (ULONG_PTR)ImageBase + NtHeaders->OptionalHeader.SizeOfImage) { // Syscall return address within the exe file ReturnVal = (ULONG_PTR)(ULONG)STATUS_PORT_NOT_SET; @@ -184,9 +191,7 @@ InstrumentationCallback( // Uninstall ourselves after we have completed the sequence { NtQIP, NtQIP }. More NtSITs will follow but we can't do anything about them NumManualSyscalls++; if (NumManualSyscalls >= 2) - { InstallInstrumentationCallbackHook(NtCurrentProcess, TRUE); - } } InterlockedAnd(TlsGetInstrumentationCallbackDisabled(), 0); @@ -194,7 +199,13 @@ InstrumentationCallback( return ReturnVal; } -NTSTATUS NTAPI HookedNtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength) +//---------------------------------------------------------------------------------- +NTSTATUS NTAPI HookedNtQueryInformationProcess( + HANDLE ProcessHandle, + PROCESSINFOCLASS ProcessInformationClass, + PVOID ProcessInformation, + ULONG ProcessInformationLength, + PULONG ReturnLength) { if (NumManualSyscalls == 0 && InterlockedOr(&InstrumentationCallbackHookInstalled, 0x1) == 0) @@ -210,11 +221,12 @@ NTSTATUS NTAPI HookedNtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFO { // Verify (1) that the handle has PROCESS_QUERY_INFORMATION access, and (2) that writing // to ProcessInformation and/or ReturnLength does not cause any access or alignment violations - Status = HookDllData.dNtQueryInformationProcess(ProcessHandle, - ProcessDebugPort, // Note: not ProcessDebugObjectHandle - ProcessInformation, - sizeof(HANDLE), - ReturnLength); + Status = HookDllData.dNtQueryInformationProcess( + ProcessHandle, + ProcessDebugPort, // Note: not ProcessDebugObjectHandle + ProcessInformation, + sizeof(HANDLE), + ReturnLength); if (!NT_SUCCESS(Status)) return Status; @@ -229,13 +241,13 @@ NTSTATUS NTAPI HookedNtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFO return STATUS_PORT_NOT_SET; } - if ((ProcessInformationClass == ProcessDebugFlags || - ProcessInformationClass == ProcessDebugPort || - ProcessInformationClass == ProcessBasicInformation || - ProcessInformationClass == ProcessBreakOnTermination || - ProcessInformationClass == ProcessHandleTracing || - ProcessInformationClass == ProcessIoCounters) && - (ProcessHandle == NtCurrentProcess || HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess) == GetProcessIdByProcessHandle(ProcessHandle))) + if (( ProcessInformationClass == ProcessDebugFlags + || ProcessInformationClass == ProcessDebugPort + || ProcessInformationClass == ProcessBasicInformation + || ProcessInformationClass == ProcessBreakOnTermination + || ProcessInformationClass == ProcessHandleTracing + || ProcessInformationClass == ProcessIoCounters) + && (ProcessHandle == NtCurrentProcess || HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess) == GetProcessIdByProcessHandle(ProcessHandle))) { Status = HookDllData.dNtQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength); @@ -295,28 +307,27 @@ NTSTATUS NTAPI HookedNtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFO return HookDllData.dNtQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength); } -NTSTATUS NTAPI HookedNtSetInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength) +//---------------------------------------------------------------------------------- +NTSTATUS NTAPI HookedNtSetInformationProcess( + HANDLE ProcessHandle, + PROCESSINFOCLASS ProcessInformationClass, + PVOID ProcessInformation, + ULONG ProcessInformationLength) { if (ProcessHandle == NtCurrentProcess || HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess) == GetProcessIdByProcessHandle(ProcessHandle)) { if (ProcessInformationClass == ProcessBreakOnTermination) { if (ProcessInformationLength != sizeof(ULONG)) - { return STATUS_INFO_LENGTH_MISMATCH; - } // NtSetInformationProcess will happily dereference this pointer if (ProcessInformation == NULL) - { return STATUS_ACCESS_VIOLATION; - } // A process must have debug privileges enabled to set the ProcessBreakOnTermination flag if (!HasDebugPrivileges(NtCurrentProcess)) - { return STATUS_PRIVILEGE_NOT_HELD; - } ValueProcessBreakOnTermination = *((ULONG *)ProcessInformation); return STATUS_SUCCESS; @@ -326,30 +337,21 @@ NTSTATUS NTAPI HookedNtSetInformationProcess(HANDLE ProcessHandle, PROCESSINFOCL if (ProcessInformationClass == ProcessDebugFlags) { if (ProcessInformationLength != sizeof(ULONG)) - { return STATUS_INFO_LENGTH_MISMATCH; - } if (ProcessInformation == NULL) - { return STATUS_ACCESS_VIOLATION; - } ULONG Flags = *(ULONG*)ProcessInformation; if ((Flags & ~PROCESS_DEBUG_INHERIT) != 0) - { return STATUS_INVALID_PARAMETER; - } if ((Flags & PROCESS_DEBUG_INHERIT) != 0) - { ValueProcessDebugFlags &= ~PROCESS_NO_DEBUG_INHERIT; - } else - { ValueProcessDebugFlags |= PROCESS_NO_DEBUG_INHERIT; - } - return STATUS_SUCCESS; + + return STATUS_SUCCESS; } //PROCESS_HANDLE_TRACING_ENABLE -> ULONG, PROCESS_HANDLE_TRACING_ENABLE_EX -> ULONG,ULONG @@ -359,21 +361,15 @@ NTSTATUS NTAPI HookedNtSetInformationProcess(HANDLE ProcessHandle, PROCESSINFOCL if (enable) { if (ProcessInformationLength != sizeof(ULONG) && ProcessInformationLength != (sizeof(ULONG) * 2)) - { return STATUS_INFO_LENGTH_MISMATCH; - } // NtSetInformationProcess will happily dereference this pointer if (ProcessInformation == NULL) - { return STATUS_ACCESS_VIOLATION; - } PPROCESS_HANDLE_TRACING_ENABLE_EX phtEx = (PPROCESS_HANDLE_TRACING_ENABLE_EX)ProcessInformation; if (phtEx->Flags != 0) - { return STATUS_INVALID_PARAMETER; - } } IsProcessHandleTracingEnabled = enable; @@ -383,7 +379,13 @@ NTSTATUS NTAPI HookedNtSetInformationProcess(HANDLE ProcessHandle, PROCESSINFOCL return HookDllData.dNtSetInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength); } -NTSTATUS NTAPI HookedNtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength) +//---------------------------------------------------------------------------------- +NTSTATUS NTAPI HookedNtQueryObject( + HANDLE Handle, + OBJECT_INFORMATION_CLASS ObjectInformationClass, + PVOID ObjectInformation, + ULONG ObjectInformationLength, + PULONG ReturnLength) { NTSTATUS ntStat = HookDllData.dNtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength); @@ -412,30 +414,29 @@ NTSTATUS NTAPI HookedNtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS Objec return ntStat; } +//---------------------------------------------------------------------------------- NTSTATUS NTAPI HookedNtYieldExecution() { HookDllData.dNtYieldExecution(); - return STATUS_ACCESS_DENIED; //better than STATUS_SUCCESS or STATUS_NO_YIELD_PERFORMED + // Better than STATUS_SUCCESS or STATUS_NO_YIELD_PERFORMED + return STATUS_ACCESS_DENIED; } +//---------------------------------------------------------------------------------- NTSTATUS NTAPI HookedNtGetContextThread(HANDLE ThreadHandle, PCONTEXT ThreadContext) { DWORD ContextBackup = 0; BOOLEAN DebugRegistersRequested = FALSE; - if (ThreadHandle == NtCurrentThread || - HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess) == GetProcessIdByThreadHandle(ThreadHandle)) //thread inside this process? + if (IsThreadInProcess(ThreadHandle) && ThreadContext != nullptr) { - if (ThreadContext) - { - ContextBackup = ThreadContext->ContextFlags; - ThreadContext->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS; - DebugRegistersRequested = ThreadContext->ContextFlags != ContextBackup; - } + ContextBackup = ThreadContext->ContextFlags; + ThreadContext->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS; + DebugRegistersRequested = ThreadContext->ContextFlags != ContextBackup; } NTSTATUS ntStat = HookDllData.dNtGetContextThread(ThreadHandle, ThreadContext); - if (ContextBackup) + if (ContextBackup != 0) { ThreadContext->ContextFlags = ContextBackup; if (DebugRegistersRequested) @@ -457,38 +458,34 @@ NTSTATUS NTAPI HookedNtGetContextThread(HANDLE ThreadHandle, PCONTEXT ThreadCont return ntStat; } +//---------------------------------------------------------------------------------- NTSTATUS NTAPI HookedNtSetContextThread(HANDLE ThreadHandle, PCONTEXT ThreadContext) { DWORD ContextBackup = 0; - if (ThreadHandle == NtCurrentThread || - HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess) == GetProcessIdByThreadHandle(ThreadHandle)) //thread inside this process? + if (IsThreadInProcess(ThreadHandle) && ThreadContext != nullptr) { - if (ThreadContext) - { - ContextBackup = ThreadContext->ContextFlags; - ThreadContext->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS; - } + ContextBackup = ThreadContext->ContextFlags; + ThreadContext->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS; } NTSTATUS ntStat = HookDllData.dNtSetContextThread(ThreadHandle, ThreadContext); if (ContextBackup) - { ThreadContext->ContextFlags = ContextBackup; - } return ntStat; } -void NTAPI HandleKiUserExceptionDispatcher(PEXCEPTION_RECORD pExcptRec, PCONTEXT ContextFrame) +//---------------------------------------------------------------------------------- +void NTAPI HandleKiUserExceptionDispatcher( + PEXCEPTION_RECORD pExcptRec, + PCONTEXT ContextFrame) { - if (ContextFrame && (ContextFrame->ContextFlags & CONTEXT_DEBUG_REGISTERS)) + if (ContextFrame != nullptr && (ContextFrame->ContextFlags & CONTEXT_DEBUG_REGISTERS)) { int slotIndex = ThreadDebugContextFindFreeSlotIndex(); if (slotIndex != -1) - { ThreadDebugContextSaveContext(slotIndex, ContextFrame); - } ContextFrame->Dr0 = 0; ContextFrame->Dr1 = 0; @@ -498,15 +495,17 @@ void NTAPI HandleKiUserExceptionDispatcher(PEXCEPTION_RECORD pExcptRec, PCONTEXT ContextFrame->Dr7 = 0; } } + +//---------------------------------------------------------------------------------- #ifdef _WIN64 void NTAPI HookedKiUserExceptionDispatcher() { - // inline assembly is not supported in x86_64 with CL. a more elegant + // Inline assembly is not supported in x86_64 with CL. a more elegant // way to do this would be to modify the project to include an .asm // source file that defines 'HookedKiUserExceptionDispatcher' for both // 32 and 64 bit. // the + 8 in the line below is because we arrive at this function via - // a CALL instruction which causes the stack to shift. This CALL in + // a CALL instruction which causes the stack to shift. This CALL in // the trampoline is necessary because HandleKiUserExceptionDispatcher // will end in a RET instruction, and the CALL preserves the stack. PCONTEXT ContextFrame = (PCONTEXT)(((UINT_PTR)_AddressOfReturnAddress()) + 8); @@ -532,12 +531,14 @@ VOID NAKED NTAPI HookedKiUserExceptionDispatcher()// (PEXCEPTION_RECORD pExcptRe } #endif -static DWORD_PTR KiUserExceptionDispatcherAddress = 0; - -NTSTATUS NTAPI HookedNtContinue(PCONTEXT ThreadContext, BOOLEAN RaiseAlert) //restore DRx Registers +//---------------------------------------------------------------------------------- +// Restore DRx Registers +NTSTATUS NTAPI HookedNtContinue(PCONTEXT ThreadContext, BOOLEAN RaiseAlert) { + static DWORD_PTR KiUserExceptionDispatcherAddress = 0; + DWORD_PTR retAddress = (DWORD_PTR)_ReturnAddress(); - if (!KiUserExceptionDispatcherAddress) + if (KiUserExceptionDispatcherAddress == 0) { UNICODE_STRING NtdllName = RTL_CONSTANT_STRING(L"ntdll.dll"); PVOID Ntdll; @@ -548,8 +549,9 @@ NTSTATUS NTAPI HookedNtContinue(PCONTEXT ThreadContext, BOOLEAN RaiseAlert) //re } } - if (ThreadContext != nullptr && - retAddress >= KiUserExceptionDispatcherAddress && retAddress < (KiUserExceptionDispatcherAddress + 0x100)) + if ( ThreadContext != nullptr + && retAddress >= KiUserExceptionDispatcherAddress + && retAddress < (KiUserExceptionDispatcherAddress + 0x100)) { int index = ThreadDebugContextFindExistingSlotIndex(); if (index != -1) @@ -567,6 +569,7 @@ NTSTATUS NTAPI HookedNtContinue(PCONTEXT ThreadContext, BOOLEAN RaiseAlert) //re return HookDllData.dNtContinue(ThreadContext, RaiseAlert); } +//---------------------------------------------------------------------------------- #ifndef _WIN64 PVOID NTAPI HandleNativeCallInternal(DWORD eaxValue, DWORD ecxValue) { @@ -577,14 +580,10 @@ PVOID NTAPI HandleNativeCallInternal(DWORD eaxValue, DWORD ecxValue) if (HookDllData.HookNative[i].ecxValue) { if (HookDllData.HookNative[i].ecxValue == ecxValue) - { return HookDllData.HookNative[i].hookedFunction; - } } else - { return HookDllData.HookNative[i].hookedFunction; - } } } @@ -592,6 +591,7 @@ PVOID NTAPI HandleNativeCallInternal(DWORD eaxValue, DWORD ecxValue) } #endif +//---------------------------------------------------------------------------------- void NAKED NTAPI HookedNativeCallInternal() { #ifndef _WIN64 @@ -616,6 +616,7 @@ void NAKED NTAPI HookedNativeCallInternal() #endif } +//---------------------------------------------------------------------------------- NTSTATUS NTAPI HookedNtClose(HANDLE Handle) { OBJECT_HANDLE_FLAG_INFORMATION flags; @@ -839,6 +840,7 @@ BOOL NTAPI HookedNtUserBlockInput(BOOL fBlockIt) return FALSE; } +//---------------------------------------------------------------------------------- //GetLastError() function might not change if a debugger is present (it has never been the case that it is always set to zero). DWORD WINAPI HookedOutputDebugStringA(LPCSTR lpOutputString) //Worst anti-debug ever { @@ -885,6 +887,7 @@ NTSTATUS NTAPI HookedNtSetDebugFilterState(ULONG ComponentId, ULONG Level, BOOLE return HasDebugPrivileges(NtCurrentProcess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED; } +//---------------------------------------------------------------------------------- void FilterHwndList(HWND * phwndFirst, PULONG pcHwndNeeded) { for (UINT i = 0; i < *pcHwndNeeded; i++) @@ -961,34 +964,43 @@ HWND NTAPI HookedNtUserGetForegroundWindow() NTSTATUS NTAPI HookedNtCreateThread(PHANDLE ThreadHandle,ACCESS_MASK DesiredAccess,POBJECT_ATTRIBUTES ObjectAttributes,HANDLE ProcessHandle,PCLIENT_ID ClientId,PCONTEXT ThreadContext,PINITIAL_TEB InitialTeb,BOOLEAN CreateSuspended) { if (ProcessHandle == NtCurrentProcess) - { return STATUS_INSUFFICIENT_RESOURCES;//STATUS_INVALID_PARAMETER STATUS_INVALID_HANDLE STATUS_INSUFFICIENT_RESOURCES - } + return HookDllData.dNtCreateThread(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle, ClientId,ThreadContext, InitialTeb,CreateSuspended); } +//---------------------------------------------------------------------------------- //WIN 7: CreateThread -> CreateRemoteThreadEx -> NtCreateThreadEx -NTSTATUS NTAPI HookedNtCreateThreadEx(PHANDLE ThreadHandle,ACCESS_MASK DesiredAccess,POBJECT_ATTRIBUTES ObjectAttributes,HANDLE ProcessHandle,PUSER_THREAD_START_ROUTINE StartRoutine,PVOID Argument,ULONG CreateFlags,ULONG_PTR ZeroBits,SIZE_T StackSize,SIZE_T MaximumStackSize,PPS_ATTRIBUTE_LIST AttributeList) +NTSTATUS NTAPI HookedNtCreateThreadEx( + PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PUSER_THREAD_START_ROUTINE StartRoutine, + PVOID Argument, + ULONG CreateFlags, + ULONG_PTR ZeroBits, + SIZE_T StackSize, + SIZE_T MaximumStackSize, + PPS_ATTRIBUTE_LIST AttributeList) { - if (HookDllData.EnableNtCreateThreadExHook == TRUE) //prevent hide from debugger + // Prevent hide from debugger + if (HookDllData.EnableNtCreateThreadExHook == TRUE) { if (CreateFlags & THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER) - { CreateFlags ^= THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER; - } } if (HookDllData.EnablePreventThreadCreation == TRUE) { if (ProcessHandle == NtCurrentProcess) - { - return STATUS_INSUFFICIENT_RESOURCES;//STATUS_INVALID_PARAMETER STATUS_INVALID_HANDLE STATUS_INSUFFICIENT_RESOURCES - } + return STATUS_INSUFFICIENT_RESOURCES; // STATUS_INVALID_PARAMETER STATUS_INVALID_HANDLE STATUS_INSUFFICIENT_RESOURCES } return HookDllData.dNtCreateThreadEx(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle, StartRoutine, Argument, CreateFlags, ZeroBits, StackSize, MaximumStackSize,AttributeList); } +//---------------------------------------------------------------------------------- void FilterHandleInfo(PSYSTEM_HANDLE_INFORMATION pHandleInfo, PULONG pReturnLengthAdjust) { *pReturnLengthAdjust = 0; @@ -1011,6 +1023,7 @@ void FilterHandleInfo(PSYSTEM_HANDLE_INFORMATION pHandleInfo, PULONG pReturnLeng } } +//---------------------------------------------------------------------------------- void FilterHandleInfoEx(PSYSTEM_HANDLE_INFORMATION_EX pHandleInfoEx, PULONG pReturnLengthAdjust) { *pReturnLengthAdjust = 0; @@ -1033,6 +1046,7 @@ void FilterHandleInfoEx(PSYSTEM_HANDLE_INFORMATION_EX pHandleInfoEx, PULONG pRet } } +//---------------------------------------------------------------------------------- void FilterObjects(POBJECT_TYPES_INFORMATION pObjectTypes) { POBJECT_TYPE_INFORMATION pObject = pObjectTypes->TypeInformation; @@ -1044,6 +1058,7 @@ void FilterObjects(POBJECT_TYPES_INFORMATION pObjectTypes) } } +//---------------------------------------------------------------------------------- void FilterObject(POBJECT_TYPE_INFORMATION pObject, bool zeroTotal) { UNICODE_STRING debugObjectName = RTL_CONSTANT_STRING(L"DebugObject"); @@ -1055,6 +1070,7 @@ void FilterObject(POBJECT_TYPE_INFORMATION pObject, bool zeroTotal) } } +//---------------------------------------------------------------------------------- void FakeCurrentParentProcessId(PSYSTEM_PROCESS_INFORMATION pInfo) { while (true) @@ -1072,6 +1088,7 @@ void FakeCurrentParentProcessId(PSYSTEM_PROCESS_INFORMATION pInfo) } } +//---------------------------------------------------------------------------------- void FakeCurrentOtherOperationCount(PSYSTEM_PROCESS_INFORMATION pInfo) { while (true) @@ -1091,25 +1108,23 @@ void FakeCurrentOtherOperationCount(PSYSTEM_PROCESS_INFORMATION pInfo) } } +//---------------------------------------------------------------------------------- void FilterProcess(PSYSTEM_PROCESS_INFORMATION pInfo) { PSYSTEM_PROCESS_INFORMATION pPrev = pInfo; while (TRUE) { - if (IsProcessNameBad(&pInfo->ImageName) || ((HookDllData.EnableProtectProcessId == TRUE) && (HandleToULong(pInfo->UniqueProcessId) == HookDllData.dwProtectedProcessId))) + if ( IsProcessNameBad(&pInfo->ImageName) + || ((HookDllData.EnableProtectProcessId == TRUE) && (HandleToULong(pInfo->UniqueProcessId) == HookDllData.dwProtectedProcessId))) { if (pInfo->ImageName.Buffer) ZeroMemory(pInfo->ImageName.Buffer, pInfo->ImageName.Length); if (pInfo->NextEntryOffset == 0) //last element - { pPrev->NextEntryOffset = 0; - } else - { pPrev->NextEntryOffset += pInfo->NextEntryOffset; - } } else { @@ -1117,20 +1132,17 @@ void FilterProcess(PSYSTEM_PROCESS_INFORMATION pInfo) } if (pInfo->NextEntryOffset == 0) - { break; - } else - { pInfo = (PSYSTEM_PROCESS_INFORMATION)((DWORD_PTR)pInfo + pInfo->NextEntryOffset); - } } } +//---------------------------------------------------------------------------------- NTSTATUS NTAPI HookedNtResumeThread(HANDLE ThreadHandle, PULONG PreviousSuspendCount) { DWORD dwProcessId = GetProcessIdByThreadHandle(ThreadHandle); - if (dwProcessId != HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess)) //malware starts the thread of another process + if (dwProcessId != HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess)) // Malware starts the thread of another process { DumpMalware(dwProcessId); TerminateProcessByProcessId(dwProcessId); //terminate it @@ -1138,8 +1150,6 @@ NTSTATUS NTAPI HookedNtResumeThread(HANDLE ThreadHandle, PULONG PreviousSuspendC DbgBreakPoint(); return STATUS_SUCCESS; } - else - { - return HookDllData.dNtResumeThread(ThreadHandle, PreviousSuspendCount); - } + + return HookDllData.dNtResumeThread(ThreadHandle, PreviousSuspendCount); } diff --git a/HookLibrary/InstrumentationCallbackX64.asm b/HookLibrary/InstrumentationCallbackX64.asm index d55abb11..68af5624 100644 --- a/HookLibrary/InstrumentationCallbackX64.asm +++ b/HookLibrary/InstrumentationCallbackX64.asm @@ -4,7 +4,6 @@ extern InstrumentationCallback:near .code InstrumentationCallbackAsm proc - cmp eax, 0 ; STATUS_SUCCESS jne ReturnToCaller diff --git a/InjectorCLI/ApplyHooking.cpp b/InjectorCLI/ApplyHooking.cpp index 285d7268..a8387f76 100644 --- a/InjectorCLI/ApplyHooking.cpp +++ b/InjectorCLI/ApplyHooking.cpp @@ -7,22 +7,42 @@ #include "RemoteHook.h" #define STR(x) #x -#define HOOK(name) { \ - hdd->d##name = (t_##name)DetourCreateRemote(hProcess, "" STR(name) "", (void*)_##name, Hooked##name, true, &hdd->name##BackupSize); \ - if (hdd->d##name == nullptr) { return false; } } -#define HOOK_NATIVE(name) { \ - hdd->d##name = (t_##name)DetourCreateRemoteNative(hProcess, "" STR(name) "", (void*)_##name, Hooked##name, true, &hdd->name##BackupSize); \ - if (hdd->d##name == nullptr) { return false; } } -#define HOOK_NATIVE_NOTRAMP(name) DetourCreateRemoteNative(hProcess, "" STR(name) "", (void*)_##name, Hooked##name, false, &hdd->name##BackupSize) -#define FREE_HOOK(name) FreeMemory(hProcess, (void*)hdd->d##name); hdd->d##name = 0 -#define RESTORE_JMP(name) RestoreJumper(hProcess, (void*)_##name, (void*)hdd->d##name, hdd->name##BackupSize) + +#define HOOK(name) \ + if ((void*)_##name != nullptr) \ + { \ + hdd->d##name = (t_##name)DetourCreateRemote(hProcess, "" STR(name) "", (void*)_##name, Hooked##name, true, &hdd->name##BackupSize); \ + if (hdd->d##name == nullptr) \ + { \ + return false; \ + } \ + } + +#define HOOK_NATIVE(name) \ + if ((void*)_##name != nullptr) \ + { \ + hdd->d##name = (t_##name)DetourCreateRemoteNative(hProcess, "" STR(name) "", (void*)_##name, Hooked##name, true, &hdd->name##BackupSize); \ + if (hdd->d##name == nullptr) \ + { \ + return false; \ + } \ + } + +#define HOOK_NATIVE_NOTRAMP(name) \ + DetourCreateRemoteNative(hProcess, "" STR(name) "", (void*)_##name, Hooked##name, false, &hdd->name##BackupSize) + +#define FREE_HOOK(name) \ + FreeMemory(hProcess, (void*)hdd->d##name); hdd->d##name = 0 + +#define RESTORE_JMP(name) \ + RestoreJumper(hProcess, (void*)_##name, (void*)hdd->d##name, hdd->name##BackupSize) extern scl::Logger g_log; -void * HookedNativeCallInternal = 0; -void * NativeCallContinue = 0; +void *HookedNativeCallInternal = 0; +void *NativeCallContinue = 0; int countNativeHooks = 0; -HOOK_NATIVE_CALL32 * HookNative = 0; +HOOK_NATIVE_CALL32 *HookNative = 0; bool onceNativeCallContinue = false; bool fatalFindSyscallIndexFailure = false; bool fatalAlreadyHookedFailure = false; @@ -34,43 +54,48 @@ extern DWORD KiFastSystemCallAddress; extern DWORD KiFastSystemCallWow64Address; #endif -HMODULE hKernel = 0; -HMODULE hKernelbase = 0; -HMODULE hNtdll = 0; -HMODULE hUser = 0; - -t_KiUserExceptionDispatcher _KiUserExceptionDispatcher = 0; -t_OutputDebugStringA _OutputDebugStringA = 0; -t_GetTickCount _GetTickCount = 0; -t_GetTickCount64 _GetTickCount64 = 0; -t_GetLocalTime _GetLocalTime = 0; -t_GetSystemTime _GetSystemTime = 0; - -t_NtUserBlockInput _NtUserBlockInput = 0; -t_NtUserBuildHwndList _NtUserBuildHwndList = 0; -t_NtUserFindWindowEx _NtUserFindWindowEx = 0; -t_NtUserQueryWindow _NtUserQueryWindow = 0; -t_NtUserGetForegroundWindow _NtUserGetForegroundWindow = 0; - -t_NtSetInformationThread _NtSetInformationThread = 0; -t_NtQuerySystemInformation _NtQuerySystemInformation = 0; -t_NtQueryInformationProcess _NtQueryInformationProcess = 0; -t_NtSetInformationProcess _NtSetInformationProcess = 0; -t_NtQueryObject _NtQueryObject = 0; -t_NtYieldExecution _NtYieldExecution = 0; -t_NtGetContextThread _NtGetContextThread = 0; -t_NtSetContextThread _NtSetContextThread = 0; -t_NtContinue _NtContinue = 0; -t_NtClose _NtClose = 0; -t_NtDuplicateObject _NtDuplicateObject = 0; -t_NtSetDebugFilterState _NtSetDebugFilterState = 0; -t_NtCreateThread _NtCreateThread = 0; -t_NtCreateThreadEx _NtCreateThreadEx = 0; -t_NtQuerySystemTime _NtQuerySystemTime = 0; -t_NtQueryPerformanceCounter _NtQueryPerformanceCounter = 0; -t_NtResumeThread _NtResumeThread = 0; - -bool ApplyNtdllHook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWORD_PTR imageBase) +HMODULE hKernel = NULL; +HMODULE hKernelbase = NULL; +HMODULE hNtdll = NULL; +HMODULE hUser = NULL; + +t_KiUserExceptionDispatcher _KiUserExceptionDispatcher = 0; +t_OutputDebugStringA _OutputDebugStringA = 0; +t_GetTickCount _GetTickCount = 0; +t_GetTickCount64 _GetTickCount64 = 0; +t_GetLocalTime _GetLocalTime = 0; +t_GetSystemTime _GetSystemTime = 0; + +t_NtUserBlockInput _NtUserBlockInput = 0; +t_NtUserBuildHwndList _NtUserBuildHwndList = 0; +t_NtUserFindWindowEx _NtUserFindWindowEx = 0; +t_NtUserQueryWindow _NtUserQueryWindow = 0; +t_NtUserGetForegroundWindow _NtUserGetForegroundWindow = 0; + +t_NtSetInformationThread _NtSetInformationThread = 0; +t_NtQuerySystemInformation _NtQuerySystemInformation = 0; +t_NtQueryInformationProcess _NtQueryInformationProcess = 0; +t_NtSetInformationProcess _NtSetInformationProcess = 0; +t_NtQueryObject _NtQueryObject = 0; +t_NtYieldExecution _NtYieldExecution = 0; +t_NtGetContextThread _NtGetContextThread = 0; +t_NtSetContextThread _NtSetContextThread = 0; +t_NtContinue _NtContinue = 0; +t_NtClose _NtClose = 0; +t_NtDuplicateObject _NtDuplicateObject = 0; +t_NtSetDebugFilterState _NtSetDebugFilterState = 0; +t_NtCreateThread _NtCreateThread = 0; +t_NtCreateThreadEx _NtCreateThreadEx = 0; +t_NtQuerySystemTime _NtQuerySystemTime = 0; +t_NtQueryPerformanceCounter _NtQueryPerformanceCounter = 0; +t_NtResumeThread _NtResumeThread = 0; + +//---------------------------------------------------------------------------------- +bool ApplyNtdllHook( + HOOK_DLL_DATA *hdd, + HANDLE hProcess, + BYTE *dllMemory, + DWORD_PTR imageBase) { hNtdll = GetModuleHandleW(L"ntdll.dll"); @@ -80,45 +105,45 @@ bool ApplyNtdllHook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWOR HookNative = hdd->HookNative; #endif - void * HookedNtSetInformationThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtSetInformationThread") + imageBase); - void * HookedNtQuerySystemInformation = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQuerySystemInformation") + imageBase); - void * HookedNtQueryInformationProcess = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQueryInformationProcess") + imageBase); - void * HookedNtSetInformationProcess = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtSetInformationProcess") + imageBase); - void * HookedNtQueryObject = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQueryObject") + imageBase); - void * HookedNtYieldExecution = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtYieldExecution") + imageBase); - void * HookedNtGetContextThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtGetContextThread") + imageBase); - void * HookedNtSetContextThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtSetContextThread") + imageBase); - void * HookedKiUserExceptionDispatcher = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedKiUserExceptionDispatcher") + imageBase); - void * HookedNtContinue = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtContinue") + imageBase); - void * HookedNtClose = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtClose") + imageBase); - void * HookedNtDuplicateObject = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtDuplicateObject") + imageBase); - void * HookedNtSetDebugFilterState = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtSetDebugFilterState") + imageBase); - void * HookedNtCreateThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtCreateThread") + imageBase); - void * HookedNtCreateThreadEx = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtCreateThreadEx") + imageBase); - void * HookedNtQuerySystemTime = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQuerySystemTime") + imageBase); - void * HookedNtQueryPerformanceCounter = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQueryPerformanceCounter") + imageBase); - void * HookedNtResumeThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtResumeThread") + imageBase); - - HookedNativeCallInternal = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNativeCallInternal") + imageBase); - - _NtSetInformationThread = (t_NtSetInformationThread)GetProcAddress(hNtdll, "NtSetInformationThread"); - _NtQuerySystemInformation = (t_NtQuerySystemInformation)GetProcAddress(hNtdll, "NtQuerySystemInformation"); - _NtQueryInformationProcess = (t_NtQueryInformationProcess)GetProcAddress(hNtdll, "NtQueryInformationProcess"); - _NtSetInformationProcess = (t_NtSetInformationProcess)GetProcAddress(hNtdll, "NtSetInformationProcess"); - _NtQueryObject = (t_NtQueryObject)GetProcAddress(hNtdll, "NtQueryObject"); - _NtYieldExecution = (t_NtYieldExecution)GetProcAddress(hNtdll, "NtYieldExecution"); - _NtGetContextThread = (t_NtGetContextThread)GetProcAddress(hNtdll, "NtGetContextThread"); - _NtSetContextThread = (t_NtSetContextThread)GetProcAddress(hNtdll, "NtSetContextThread"); - _KiUserExceptionDispatcher = (t_KiUserExceptionDispatcher)GetProcAddress(hNtdll, "KiUserExceptionDispatcher"); - _NtContinue = (t_NtContinue)GetProcAddress(hNtdll, "NtContinue"); - _NtClose = (t_NtClose)GetProcAddress(hNtdll, "NtClose"); - _NtDuplicateObject = (t_NtDuplicateObject)GetProcAddress(hNtdll, "NtDuplicateObject"); - _NtSetDebugFilterState = (t_NtSetDebugFilterState)GetProcAddress(hNtdll, "NtSetDebugFilterState"); - _NtCreateThread = (t_NtCreateThread)GetProcAddress(hNtdll, "NtCreateThread"); - _NtCreateThreadEx = (t_NtCreateThreadEx)GetProcAddress(hNtdll, "NtCreateThreadEx"); - _NtQuerySystemTime = (t_NtQuerySystemTime)GetProcAddress(hNtdll, "NtQuerySystemTime"); - _NtQueryPerformanceCounter = (t_NtQueryPerformanceCounter)GetProcAddress(hNtdll, "NtQueryPerformanceCounter"); - _NtResumeThread = (t_NtResumeThread)GetProcAddress(hNtdll, "NtResumeThread"); + auto HookedNtSetInformationThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtSetInformationThread") + imageBase); + auto HookedNtQuerySystemInformation = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQuerySystemInformation") + imageBase); + auto HookedNtQueryInformationProcess = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQueryInformationProcess") + imageBase); + auto HookedNtSetInformationProcess = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtSetInformationProcess") + imageBase); + auto HookedNtQueryObject = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQueryObject") + imageBase); + auto HookedNtYieldExecution = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtYieldExecution") + imageBase); + auto HookedNtGetContextThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtGetContextThread") + imageBase); + auto HookedNtSetContextThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtSetContextThread") + imageBase); + auto HookedKiUserExceptionDispatcher = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedKiUserExceptionDispatcher") + imageBase); + auto HookedNtContinue = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtContinue") + imageBase); + auto HookedNtClose = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtClose") + imageBase); + auto HookedNtDuplicateObject = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtDuplicateObject") + imageBase); + auto HookedNtSetDebugFilterState = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtSetDebugFilterState") + imageBase); + auto HookedNtCreateThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtCreateThread") + imageBase); + auto HookedNtCreateThreadEx = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtCreateThreadEx") + imageBase); + auto HookedNtQuerySystemTime = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQuerySystemTime") + imageBase); + auto HookedNtQueryPerformanceCounter = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtQueryPerformanceCounter") + imageBase); + auto HookedNtResumeThread = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtResumeThread") + imageBase); + + HookedNativeCallInternal = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNativeCallInternal") + imageBase); + + _NtSetInformationThread = (t_NtSetInformationThread)GetProcAddress(hNtdll, "NtSetInformationThread"); + _NtQuerySystemInformation = (t_NtQuerySystemInformation)GetProcAddress(hNtdll, "NtQuerySystemInformation"); + _NtQueryInformationProcess = (t_NtQueryInformationProcess)GetProcAddress(hNtdll, "NtQueryInformationProcess"); + _NtSetInformationProcess = (t_NtSetInformationProcess)GetProcAddress(hNtdll, "NtSetInformationProcess"); + _NtQueryObject = (t_NtQueryObject)GetProcAddress(hNtdll, "NtQueryObject"); + _NtYieldExecution = (t_NtYieldExecution)GetProcAddress(hNtdll, "NtYieldExecution"); + _NtGetContextThread = (t_NtGetContextThread)GetProcAddress(hNtdll, "NtGetContextThread"); + _NtSetContextThread = (t_NtSetContextThread)GetProcAddress(hNtdll, "NtSetContextThread"); + _KiUserExceptionDispatcher = (t_KiUserExceptionDispatcher)GetProcAddress(hNtdll, "KiUserExceptionDispatcher"); + _NtContinue = (t_NtContinue)GetProcAddress(hNtdll, "NtContinue"); + _NtClose = (t_NtClose)GetProcAddress(hNtdll, "NtClose"); + _NtDuplicateObject = (t_NtDuplicateObject)GetProcAddress(hNtdll, "NtDuplicateObject"); + _NtSetDebugFilterState = (t_NtSetDebugFilterState)GetProcAddress(hNtdll, "NtSetDebugFilterState"); + _NtCreateThread = (t_NtCreateThread)GetProcAddress(hNtdll, "NtCreateThread"); + _NtCreateThreadEx = (t_NtCreateThreadEx)GetProcAddress(hNtdll, "NtCreateThreadEx"); + _NtQuerySystemTime = (t_NtQuerySystemTime)GetProcAddress(hNtdll, "NtQuerySystemTime"); + _NtQueryPerformanceCounter = (t_NtQueryPerformanceCounter)GetProcAddress(hNtdll, "NtQueryPerformanceCounter"); + _NtResumeThread = (t_NtResumeThread)GetProcAddress(hNtdll, "NtResumeThread"); g_log.LogDebug(L"ApplyNtdllHook -> _NtSetInformationThread %p _NtQuerySystemInformation %p _NtQueryInformationProcess %p _NtSetInformationProcess %p _NtQueryObject %p", _NtSetInformationThread, @@ -324,35 +349,40 @@ bool ApplyNtdllHook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWOR return true; } -bool ApplyKernel32Hook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWORD_PTR imageBase) +//---------------------------------------------------------------------------------- +bool ApplyKernel32Hook( + HOOK_DLL_DATA *hdd, + HANDLE hProcess, + BYTE *dllMemory, + DWORD_PTR imageBase) { hKernel = GetModuleHandleW(L"kernel32.dll"); hKernelbase = GetModuleHandleW(L"kernelbase.dll"); - if (GetModuleBaseRemote(hProcess, L"kernel32.dll") == nullptr || - (hKernelbase != nullptr && GetModuleBaseRemote(hProcess, L"kernelbase.dll") == nullptr)) + if ( GetModuleBaseRemote(hProcess, L"kernel32.dll") == nullptr + || (hKernelbase != nullptr && GetModuleBaseRemote(hProcess, L"kernelbase.dll") == nullptr)) { hdd->isKernel32Hooked = FALSE; return true; } - void * HookedOutputDebugStringA = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedOutputDebugStringA") + imageBase); - void * HookedGetTickCount = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedGetTickCount") + imageBase); - void * HookedGetTickCount64 = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedGetTickCount64") + imageBase); - void * HookedGetLocalTime = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedGetLocalTime") + imageBase); - void * HookedGetSystemTime = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedGetSystemTime") + imageBase); + auto HookedOutputDebugStringA = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedOutputDebugStringA") + imageBase); + auto HookedGetTickCount = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedGetTickCount") + imageBase); + auto HookedGetTickCount64 = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedGetTickCount64") + imageBase); + auto HookedGetLocalTime = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedGetLocalTime") + imageBase); + auto HookedGetSystemTime = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedGetSystemTime") + imageBase); HMODULE hCurrent = hKernel; - if (hKernelbase) + if (hKernelbase == NULL) { hCurrent = hKernelbase; g_log.LogDebug(L"ApplyKernel32Hook -> Using Kernelbase %p instead of kernel32 %p", hKernelbase, hKernel); } - _GetTickCount = (t_GetTickCount)GetProcAddress(hCurrent, "GetTickCount"); + _GetTickCount = (t_GetTickCount)GetProcAddress(hCurrent, "GetTickCount"); _GetTickCount64 = (t_GetTickCount64)GetProcAddress(hCurrent, "GetTickCount64"); - _GetLocalTime = (t_GetLocalTime)GetProcAddress(hCurrent, "GetLocalTime"); - _GetSystemTime = (t_GetSystemTime)GetProcAddress(hCurrent, "GetSystemTime"); + _GetLocalTime = (t_GetLocalTime)GetProcAddress(hCurrent, "GetLocalTime"); + _GetSystemTime = (t_GetSystemTime)GetProcAddress(hCurrent, "GetSystemTime"); _OutputDebugStringA = (t_OutputDebugStringA)GetProcAddress(hCurrent, "OutputDebugStringA"); @@ -368,32 +398,42 @@ bool ApplyKernel32Hook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, D g_log.LogDebug(L"ApplyKernel32Hook -> Hooking GetTickCount"); HOOK(GetTickCount); } + if (hdd->EnableGetTickCount64Hook == TRUE && _GetTickCount64 != 0) { g_log.LogDebug(L"ApplyKernel32Hook -> Hooking GetTickCount64"); HOOK(GetTickCount64); } + if (hdd->EnableGetLocalTimeHook == TRUE) { g_log.LogDebug(L"ApplyKernel32Hook -> Hooking GetLocalTime"); HOOK(GetLocalTime); } + if (hdd->EnableGetSystemTimeHook == TRUE) { g_log.LogDebug(L"ApplyKernel32Hook -> Hooking GetSystemTime"); HOOK(GetSystemTime); } + if (hdd->EnableOutputDebugStringHook == TRUE) { g_log.LogDebug(L"ApplyKernel32Hook -> Hooking OutputDebugStringA"); HOOK(OutputDebugStringA); } + hdd->isKernel32Hooked = TRUE; return true; } -bool ApplyUserHook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWORD_PTR imageBase) +//---------------------------------------------------------------------------------- +bool ApplyUserHook( + HOOK_DLL_DATA *hdd, + HANDLE hProcess, + BYTE *dllMemory, + DWORD_PTR imageBase) { if (GetModuleBaseRemote(hProcess, L"user32.dll") == nullptr && GetModuleBaseRemote(hProcess, L"win32u.dll") == nullptr) @@ -402,12 +442,12 @@ bool ApplyUserHook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWORD return true; } - void * HookedNtUserBlockInput = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserBlockInput") + imageBase); - void * HookedNtUserFindWindowEx = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserFindWindowEx") + imageBase); - void * HookedNtUserBuildHwndList = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserBuildHwndList") + imageBase); - void * HookedNtUserBuildHwndList_Eight = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserBuildHwndList_Eight") + imageBase); - void * HookedNtUserQueryWindow = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserQueryWindow") + imageBase); - void * HookedNtUserGetForegroundWindow = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserGetForegroundWindow") + imageBase); + auto HookedNtUserBlockInput = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserBlockInput") + imageBase); + auto HookedNtUserFindWindowEx = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserFindWindowEx") + imageBase); + auto HookedNtUserBuildHwndList = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserBuildHwndList") + imageBase); + auto HookedNtUserBuildHwndList_Eight = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserBuildHwndList_Eight") + imageBase); + auto HookedNtUserQueryWindow = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserQueryWindow") + imageBase); + auto HookedNtUserGetForegroundWindow = (void *)(GetDllFunctionAddressRVA(dllMemory, "HookedNtUserGetForegroundWindow") + imageBase); g_log.LogDebug(L"ApplyUserHook -> HookedNtUserBlockInput %p HookedNtUserFindWindowEx %p HookedNtUserBuildHwndList %p HookedNtUserBuildHwndList_Eight %p HookedNtUserQueryWindow %p HookedNtUserGetForegroundWindow %p", HookedNtUserBlockInput, @@ -417,16 +457,16 @@ bool ApplyUserHook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWORD HookedNtUserQueryWindow, HookedNtUserGetForegroundWindow); - _NtUserBlockInput = (t_NtUserBlockInput)hdd->NtUserBlockInputVA; - _NtUserFindWindowEx = (t_NtUserFindWindowEx)hdd->NtUserFindWindowExVA; - _NtUserBuildHwndList = (t_NtUserBuildHwndList)hdd->NtUserBuildHwndListVA; - _NtUserQueryWindow = (t_NtUserQueryWindow)hdd->NtUserQueryWindowVA; - _NtUserGetForegroundWindow = (t_NtUserGetForegroundWindow)hdd->NtUserGetForegroundWindowVA; + _NtUserBlockInput = (t_NtUserBlockInput)hdd->NtUserBlockInputVA; + _NtUserFindWindowEx = (t_NtUserFindWindowEx)hdd->NtUserFindWindowExVA; + _NtUserBuildHwndList = (t_NtUserBuildHwndList)hdd->NtUserBuildHwndListVA; + _NtUserQueryWindow = (t_NtUserQueryWindow)hdd->NtUserQueryWindowVA; + _NtUserGetForegroundWindow = (t_NtUserGetForegroundWindow)hdd->NtUserGetForegroundWindowVA; - hdd->NtUserQueryWindow = _NtUserQueryWindow; - hdd->NtUserGetClassName = (t_NtUserGetClassName)hdd->NtUserGetClassNameVA; - hdd->NtUserInternalGetWindowText = (t_NtUserInternalGetWindowText)hdd->NtUserInternalGetWindowTextVA; - hdd->NtUserGetThreadState = (t_NtUserGetThreadState)hdd->NtUserGetThreadStateVA; + hdd->NtUserQueryWindow = _NtUserQueryWindow; + hdd->NtUserGetClassName = (t_NtUserGetClassName)hdd->NtUserGetClassNameVA; + hdd->NtUserInternalGetWindowText = (t_NtUserInternalGetWindowText)hdd->NtUserInternalGetWindowTextVA; + hdd->NtUserGetThreadState = (t_NtUserGetThreadState)hdd->NtUserGetThreadStateVA; g_log.LogDebug(L"ApplyUserHook -> _NtUserBlockInput %p _NtUserFindWindowEx %p _NtUserBuildHwndList %p _NtUserQueryWindow %p _NtUserGetForegroundWindow %p", _NtUserBlockInput, @@ -440,26 +480,35 @@ bool ApplyUserHook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWORD g_log.LogDebug(L"ApplyUserHook -> Hooking NtUserBlockInput"); HOOK_NATIVE(NtUserBlockInput); } + if (hdd->EnableNtUserFindWindowExHook) { g_log.LogDebug(L"ApplyUserHook -> Hooking NtUserFindWindowEx"); HOOK_NATIVE(NtUserFindWindowEx); } - if (hdd->EnableNtUserBuildHwndListHook) + + if (hdd->EnableNtUserBuildHwndListHook && _NtUserBuildHwndList != nullptr) { g_log.LogDebug(L"ApplyUserHook -> Hooking NtUserBuildHwndList"); //HOOK_NATIVE(NtUserBuildHwndList); // Not possible here because Windows >= 8 uses a different function export - hdd->dNtUserBuildHwndList = (t_NtUserBuildHwndList)DetourCreateRemoteNative(hProcess, "NtUserBuildHwndList", (PVOID)_NtUserBuildHwndList, - (scl::GetWindowsVersion() <= scl::OS_WIN_7 ? HookedNtUserBuildHwndList : HookedNtUserBuildHwndList_Eight), - true, &hdd->NtUserBuildHwndListBackupSize); + hdd->dNtUserBuildHwndList = (t_NtUserBuildHwndList)DetourCreateRemoteNative( + hProcess, + "NtUserBuildHwndList", + (PVOID)_NtUserBuildHwndList, + (scl::GetWindowsVersion() <= scl::OS_WIN_7 ? HookedNtUserBuildHwndList : HookedNtUserBuildHwndList_Eight), + true, + &hdd->NtUserBuildHwndListBackupSize); + if (hdd->dNtUserBuildHwndList == nullptr) return false; } + if (hdd->EnableNtUserQueryWindowHook) { g_log.LogDebug(L"ApplyUserHook -> Hooking NtUserQueryWindow"); HOOK_NATIVE(NtUserQueryWindow); } + if (hdd->EnableNtUserGetForegroundWindowHook) { g_log.LogDebug(L"ApplyUserHook -> Hooking NtUserGetForegroundWindow"); @@ -471,10 +520,12 @@ bool ApplyUserHook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWORD return true; } +//---------------------------------------------------------------------------------- void ApplyPEBPatch(HANDLE hProcess, DWORD flags) { auto peb = scl::GetPeb(hProcess); - if (!peb) { + if (!peb) + { g_log.LogError(L"Failed to read PEB from remote process"); } else @@ -484,7 +535,8 @@ void ApplyPEBPatch(HANDLE hProcess, DWORD flags) if (flags & PEB_PATCH_NtGlobalFlag) peb->NtGlobalFlag &= ~0x70; - if (flags & PEB_PATCH_ProcessParameters) { + if (flags & PEB_PATCH_ProcessParameters) + { if (!scl::PebPatchProcessParameters(peb.get(), hProcess)) g_log.LogError(L"Failed to patch PEB!ProcessParameters"); } @@ -496,13 +548,10 @@ void ApplyPEBPatch(HANDLE hProcess, DWORD flags) } if (flags & PEB_PATCH_OsBuildNumber) - { peb->OSBuildNumber++; - } if (!scl::SetPeb(hProcess, peb.get())) g_log.LogError(L"Failed to write PEB to remote process"); - } #ifndef _WIN64 @@ -510,7 +559,8 @@ void ApplyPEBPatch(HANDLE hProcess, DWORD flags) return; auto peb64 = scl::Wow64GetPeb64(hProcess); - if (!peb64) { + if (!peb64) + { g_log.LogError(L"Failed to read PEB64 from remote process"); } else @@ -520,7 +570,8 @@ void ApplyPEBPatch(HANDLE hProcess, DWORD flags) if (flags & PEB_PATCH_NtGlobalFlag) peb64->NtGlobalFlag &= ~0x70; - if (flags & PEB_PATCH_ProcessParameters) { + if (flags & PEB_PATCH_ProcessParameters) + { if (!scl::Wow64Peb64PatchProcessParameters(peb64.get(), hProcess)) g_log.LogError(L"Failed to patch PEB64!ProcessParameters"); } @@ -531,10 +582,8 @@ void ApplyPEBPatch(HANDLE hProcess, DWORD flags) g_log.LogError(L"Failed to patch flags in PEB64!ProcessHeaps"); } - if (flags & PEB_PATCH_OsBuildNumber) - { + if ((flags & PEB_PATCH_OsBuildNumber) != 0) peb64->OSBuildNumber++; - } if (!scl::Wow64SetPeb64(hProcess, peb64.get())) g_log.LogError(L"Failed to write PEB64 to remote process"); @@ -542,6 +591,7 @@ void ApplyPEBPatch(HANDLE hProcess, DWORD flags) #endif } +//---------------------------------------------------------------------------------- void ApplyNtdllVersionPatch(HANDLE hProcess) { // This will get the 32 bit ntdll if we are on Wow64, which is fine. @@ -570,6 +620,7 @@ void ApplyNtdllVersionPatch(HANDLE hProcess) g_log.LogError(L"Failed to obtain size of VS_VERSION_INFO resource in ntdll.dll: %08X", Status); return; } + if (Address == nullptr || Size == 0) { g_log.LogError(L"VS_VERSION_INFO resource in ntdll.dll has size zero"); @@ -613,47 +664,45 @@ void ApplyNtdllVersionPatch(HANDLE hProcess) } } -void RestoreMemory(HANDLE hProcess, DWORD_PTR address, void * buffer, int bufferSize) +//---------------------------------------------------------------------------------- +void RestoreMemory(HANDLE hProcess, DWORD_PTR address, void *buffer, int bufferSize) { DWORD protect = 0; - if (address && buffer && bufferSize) + if (address != 0 && buffer != nullptr && bufferSize != 0) { if (VirtualProtectEx(hProcess, (void *)address, bufferSize, PAGE_EXECUTE_READWRITE, &protect)) { WriteProcessMemory(hProcess, (void *)address, buffer, bufferSize, 0); - VirtualProtectEx(hProcess, (void *)address, bufferSize, protect, &protect); } } - } -void RestoreJumper(HANDLE hProcess, void* address, void * backupAddress, DWORD backupSize) +//---------------------------------------------------------------------------------- +void RestoreJumper(HANDLE hProcess, void *address, void *backupAddress, DWORD backupSize) { - if (address && backupAddress && backupSize) + if (address != nullptr && backupAddress != nullptr && backupSize != 0) { - void * backup = malloc(backupSize); - if (backup) + void *backup = malloc(backupSize); + if (backup != nullptr) { if (ReadProcessMemory(hProcess, backupAddress, backup, backupSize, 0)) - { RestoreMemory(hProcess, (DWORD_PTR)address, backup, backupSize); - } free(backup); } } } -void FreeMemory(HANDLE hProcess, void * buffer) +//---------------------------------------------------------------------------------- +void FreeMemory(HANDLE hProcess, void *buffer) { - if (hProcess && buffer) - { + if (hProcess != NULL && buffer != nullptr) VirtualFreeEx(hProcess, buffer, 0, MEM_RELEASE); - } } -void RestoreNtdllHooks(HOOK_DLL_DATA * hdd, HANDLE hProcess) +//---------------------------------------------------------------------------------- +void RestoreNtdllHooks(HOOK_DLL_DATA *hdd, HANDLE hProcess) { #ifndef _WIN64 if (scl::IsWow64Process(hProcess)) @@ -713,15 +762,14 @@ void RestoreNtdllHooks(HOOK_DLL_DATA * hdd, HANDLE hProcess) FREE_HOOK(NtQuerySystemInformation); FREE_HOOK(NtSetInformationThread); - RESTORE_JMP(KiUserExceptionDispatcher); FREE_HOOK(KiUserExceptionDispatcher); - hdd->isNtdllHooked = FALSE; } -void RestoreKernel32Hooks(HOOK_DLL_DATA * hdd, HANDLE hProcess) +//---------------------------------------------------------------------------------- +void RestoreKernel32Hooks(HOOK_DLL_DATA *hdd, HANDLE hProcess) { RESTORE_JMP(OutputDebugStringA); RESTORE_JMP(GetTickCount); @@ -737,8 +785,9 @@ void RestoreKernel32Hooks(HOOK_DLL_DATA * hdd, HANDLE hProcess) hdd->isKernel32Hooked = FALSE; } - -void RestoreUserHooks(HOOK_DLL_DATA * hdd, HANDLE hProcess) + +//---------------------------------------------------------------------------------- +void RestoreUserHooks(HOOK_DLL_DATA *hdd, HANDLE hProcess) { #ifndef _WIN64 if (!scl::IsWow64Process(hProcess) && KiFastSystemCallAddress == 0) @@ -766,44 +815,40 @@ void RestoreUserHooks(HOOK_DLL_DATA * hdd, HANDLE hProcess) hdd->isUserDllHooked = FALSE; } -void RestoreHooks(HOOK_DLL_DATA * hdd, HANDLE hProcess) +//---------------------------------------------------------------------------------- +void RestoreHooks(HOOK_DLL_DATA *hdd, HANDLE hProcess) { if (hdd->isNtdllHooked) - { RestoreNtdllHooks(hdd, hProcess); - } if (hdd->isKernel32Hooked) - { RestoreKernel32Hooks(hdd, hProcess); - } if (hdd->isUserDllHooked) - { RestoreUserHooks(hdd, hProcess); - } FreeMemory(hProcess, hdd->hDllImage); hdd->hDllImage = 0; } -bool ApplyHook(HOOK_DLL_DATA * hdd, HANDLE hProcess, BYTE * dllMemory, DWORD_PTR imageBase) +//---------------------------------------------------------------------------------- +bool ApplyHook( + HOOK_DLL_DATA *hdd, + HANDLE hProcess, + BYTE *dllMemory, + DWORD_PTR imageBase) { bool success = true; hdd->hDllImage = (HMODULE)imageBase; if (!hdd->isNtdllHooked) - { success = success && ApplyNtdllHook(hdd, hProcess, dllMemory, imageBase); - } + if (!hdd->isKernel32Hooked) - { success = success && ApplyKernel32Hook(hdd, hProcess, dllMemory, imageBase); - } + if (!hdd->isUserDllHooked) - { success = success && ApplyUserHook(hdd, hProcess, dllMemory, imageBase); - } #ifndef _WIN64 hdd->NativeCallContinue = NativeCallContinue; diff --git a/InjectorCLI/CliMain.cpp b/InjectorCLI/CliMain.cpp index 4dbaf259..f611371e 100644 --- a/InjectorCLI/CliMain.cpp +++ b/InjectorCLI/CliMain.cpp @@ -19,9 +19,7 @@ std::wstring g_scyllaHideIniPath; HOOK_DLL_DATA g_hdd; - -void ChangeBadWindowText(); -void ReadSettings(); +static void ReadSettings(); DWORD GetProcessIdByName(const WCHAR * processName); bool startInjection(DWORD targetPid, const WCHAR * dllPath); bool SetDebugPrivileges(); @@ -43,82 +41,11 @@ static void LogCallback(const wchar_t *msg) _putws(msg); } -int wmain(int argc, wchar_t* argv[]) -{ - DWORD targetPid = 0; - WCHAR * dllPath = 0; - - auto wstrPath = scl::GetModuleFileNameW(); - wstrPath.resize(wstrPath.find_last_of(L'\\') + 1); - - g_scyllaHideIniPath = wstrPath + scl::Settings::kFileName; - - auto log_file = wstrPath + scl::Logger::kFileName; - g_log.SetLogFile(log_file.c_str()); - g_log.SetLogCb(scl::Logger::Info, LogCallback); - g_log.SetLogCb(scl::Logger::Error, LogCallback); - - ReadNtApiInformation(&g_hdd); - SetDebugPrivileges(); - //ChangeBadWindowText(); - g_settings.Load(g_scyllaHideIniPath.c_str()); - ReadSettings(); - - bool waitOnExit = true; - - if (argc >= 3) - { - wchar_t* pid; - - if (ArgStartsWith(argv[1], L"pid:", pid)) - { - auto radix = 10; - if(wcsstr(pid, L"0x") == pid) - radix = 16, pid += 2; - if(!convertNumber(pid, targetPid, radix)) - targetPid = 0; - } - else - targetPid = GetProcessIdByName(argv[1]); - - dllPath = argv[2]; - - if (argc >= 4) - waitOnExit = !(ArgStartsWith(argv[3], L"nowait")); - } - else - { - -#ifdef _WIN64 - targetPid = GetProcessIdByName(L"scylla_x64.exe");//scylla_x64 - dllPath = PREFIX_PATH L"\\Release\\HookLibraryx64.dll"; -#else - targetPid = GetProcessIdByName(L"ThemidaTest.exe");//GetProcessIdByName(L"ThemidaTest.exe");//GetProcessIdByName(L"VMProtect.vmp.exe");//GetProcessIdByName(L"scylla_x86.exe"); - dllPath = PREFIX_PATH L"\\Release\\HookLibraryx86.dll"; -#endif - } - - int result = 0; - - if (targetPid && dllPath) - { - wprintf(L"\nPID\t: %d 0x%X\nDLL Path: %s\n\n", targetPid, targetPid, dllPath); - if (!startInjection(targetPid, dllPath)) - result = 1; // failure - } - else - { - wprintf(L"Usage: %s [nowait]\n", argv[0]); - wprintf(L"Usage: %s pid: [nowait]", argv[0]); - } - - if (waitOnExit) - getchar(); - - return 0; -} - -static bool StartHooking(HANDLE hProcess, BYTE * dllMemory, DWORD_PTR imageBase) +//---------------------------------------------------------------------------------- +static bool StartHooking( + HANDLE hProcess, + BYTE *dllMemory, + DWORD_PTR imageBase) { g_hdd.dwProtectedProcessId = 0; g_hdd.EnableProtectProcessId = FALSE; @@ -145,16 +72,15 @@ static bool StartHooking(HANDLE hProcess, BYTE * dllMemory, DWORD_PTR imageBase) return ApplyHook(&g_hdd, hProcess, dllMemory, imageBase); } -bool startInjectionProcess(HANDLE hProcess, BYTE * dllMemory) +//---------------------------------------------------------------------------------- +bool startInjectionProcess(HANDLE hProcess, BYTE *dllMemory) { PROCESS_SUSPEND_INFO suspendInfo; if (!SafeSuspendProcess(hProcess, &suspendInfo)) return false; if (g_settings.opts().removeDebugPrivileges) - { RemoveDebugPrivileges(hProcess); - } const bool injectDll = g_settings.hook_dll_needed(); bool success = false; @@ -192,41 +118,43 @@ bool startInjectionProcess(HANDLE hProcess, BYTE * dllMemory) return success; } -bool startInjection(DWORD targetPid, const WCHAR * dllPath) +//---------------------------------------------------------------------------------- +bool startInjection(DWORD targetPid, const WCHAR *dllPath) { bool result = false; - HANDLE hProcess = OpenProcess( PROCESS_SUSPEND_RESUME | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, - 0, targetPid); - if (hProcess) + HANDLE hProcess = OpenProcess( + PROCESS_SUSPEND_RESUME | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, + 0, + targetPid); + + if (hProcess == NULL) { - BYTE * dllMemory = ReadFileToMemory(dllPath); - if (dllMemory) - { - result = startInjectionProcess(hProcess, dllMemory); - if (g_settings.opts().killAntiAttach) - { - if (!ApplyAntiAntiAttach(targetPid)) - { - wprintf(L"Anti-Anti-Attach failed\n"); - } - } - free(dllMemory); - } - else + wprintf(L"Cannot open process handle %d\n", targetPid); + return result; + } + + BYTE *dllMemory = ReadFileToMemory(dllPath); + if (dllMemory != nullptr) + { + result = startInjectionProcess(hProcess, dllMemory); + if (g_settings.opts().killAntiAttach) { - wprintf(L"Cannot read file to memory %s\n", dllPath); + if (!ApplyAntiAntiAttach(targetPid)) + wprintf(L"Anti-Anti-Attach failed\n"); } - CloseHandle(hProcess); + free(dllMemory); } else { - wprintf(L"Cannot open process handle %d\n", targetPid); + wprintf(L"Cannot read file to memory %s\n", dllPath); } + CloseHandle(hProcess); return result; } +//---------------------------------------------------------------------------------- bool SetDebugPrivileges() { TOKEN_PRIVILEGES Debug_Privileges; @@ -249,14 +177,13 @@ bool SetDebugPrivileges() return retVal; } -DWORD GetProcessIdByName(const WCHAR * processName) +//---------------------------------------------------------------------------------- +DWORD GetProcessIdByName(const WCHAR *processName) { HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) - { return 0; - } PROCESSENTRY32 pe32; pe32.dwSize = sizeof(PROCESSENTRY32); @@ -272,7 +199,7 @@ DWORD GetProcessIdByName(const WCHAR * processName) do { - if (!_wcsicmp(pe32.szExeFile, processName)) + if (_wcsicmp(pe32.szExeFile, processName) == 0) { pid = pe32.th32ProcessID; break; @@ -283,61 +210,68 @@ DWORD GetProcessIdByName(const WCHAR * processName) return pid; } -void ReadSettings() +//---------------------------------------------------------------------------------- +static void ReadSettings() { - g_hdd.EnableGetLocalTimeHook = g_settings.opts().hookGetLocalTime; - g_hdd.EnableGetSystemTimeHook = g_settings.opts().hookGetSystemTime; - g_hdd.EnableGetTickCount64Hook = g_settings.opts().hookGetTickCount64; - g_hdd.EnableGetTickCountHook = g_settings.opts().hookGetTickCount; - g_hdd.EnableKiUserExceptionDispatcherHook = g_settings.opts().hookKiUserExceptionDispatcher; - g_hdd.EnableNtCloseHook = g_settings.opts().hookNtClose; - g_hdd.EnableNtContinueHook = g_settings.opts().hookNtContinue; - g_hdd.EnableNtCreateThreadExHook = g_settings.opts().hookNtCreateThreadEx; - g_hdd.EnableNtGetContextThreadHook = g_settings.opts().hookNtGetContextThread; - g_hdd.EnableNtQueryInformationProcessHook = g_settings.opts().hookNtQueryInformationProcess; - g_hdd.EnableNtQueryObjectHook = g_settings.opts().hookNtQueryObject; - g_hdd.EnableNtQueryPerformanceCounterHook = g_settings.opts().hookNtQueryPerformanceCounter; - g_hdd.EnableNtQuerySystemInformationHook = g_settings.opts().hookNtQuerySystemInformation; - g_hdd.EnableNtQuerySystemTimeHook = g_settings.opts().hookNtQuerySystemTime; - g_hdd.EnableNtSetContextThreadHook = g_settings.opts().hookNtSetContextThread; - g_hdd.EnableNtSetDebugFilterStateHook = g_settings.opts().hookNtSetDebugFilterState; - g_hdd.EnableNtSetInformationThreadHook = g_settings.opts().hookNtSetInformationThread; - g_hdd.EnableNtUserBlockInputHook = g_settings.opts().hookNtUserBlockInput; - g_hdd.EnableNtUserBuildHwndListHook = g_settings.opts().hookNtUserBuildHwndList; - g_hdd.EnableNtUserFindWindowExHook = g_settings.opts().hookNtUserFindWindowEx; - g_hdd.EnableNtUserQueryWindowHook = g_settings.opts().hookNtUserQueryWindow; - g_hdd.EnableNtUserGetForegroundWindowHook = g_settings.opts().hookNtUserGetForegroundWindow; - g_hdd.EnableNtYieldExecutionHook = g_settings.opts().hookNtYieldExecution; - g_hdd.EnableOutputDebugStringHook = g_settings.opts().hookOutputDebugStringA; - g_hdd.EnablePebBeingDebugged = g_settings.opts().fixPebBeingDebugged; - g_hdd.EnablePebHeapFlags = g_settings.opts().fixPebHeapFlags; - g_hdd.EnablePebNtGlobalFlag = g_settings.opts().fixPebNtGlobalFlag; - g_hdd.EnablePebStartupInfo = g_settings.opts().fixPebStartupInfo; - g_hdd.EnablePebOsBuildNumber = g_settings.opts().fixPebOsBuildNumber; - g_hdd.EnablePreventThreadCreation = g_settings.opts().preventThreadCreation; - g_hdd.EnableProtectProcessId = g_settings.opts().protectProcessId; + g_hdd.EnableGetLocalTimeHook = g_settings.opts().hookGetLocalTime; + g_hdd.EnableGetSystemTimeHook = g_settings.opts().hookGetSystemTime; + g_hdd.EnableGetTickCount64Hook = g_settings.opts().hookGetTickCount64; + g_hdd.EnableGetTickCountHook = g_settings.opts().hookGetTickCount; + g_hdd.EnableKiUserExceptionDispatcherHook = g_settings.opts().hookKiUserExceptionDispatcher; + g_hdd.EnableNtCloseHook = g_settings.opts().hookNtClose; + g_hdd.EnableNtContinueHook = g_settings.opts().hookNtContinue; + g_hdd.EnableNtCreateThreadExHook = g_settings.opts().hookNtCreateThreadEx; + g_hdd.EnableNtGetContextThreadHook = g_settings.opts().hookNtGetContextThread; + g_hdd.EnableNtQueryInformationProcessHook = g_settings.opts().hookNtQueryInformationProcess; + g_hdd.EnableNtQueryObjectHook = g_settings.opts().hookNtQueryObject; + g_hdd.EnableNtQueryPerformanceCounterHook = g_settings.opts().hookNtQueryPerformanceCounter; + g_hdd.EnableNtQuerySystemInformationHook = g_settings.opts().hookNtQuerySystemInformation; + g_hdd.EnableNtQuerySystemTimeHook = g_settings.opts().hookNtQuerySystemTime; + g_hdd.EnableNtSetContextThreadHook = g_settings.opts().hookNtSetContextThread; + g_hdd.EnableNtSetDebugFilterStateHook = g_settings.opts().hookNtSetDebugFilterState; + g_hdd.EnableNtSetInformationThreadHook = g_settings.opts().hookNtSetInformationThread; + g_hdd.EnableNtUserBlockInputHook = g_settings.opts().hookNtUserBlockInput; + g_hdd.EnableNtUserBuildHwndListHook = g_settings.opts().hookNtUserBuildHwndList; + g_hdd.EnableNtUserFindWindowExHook = g_settings.opts().hookNtUserFindWindowEx; + g_hdd.EnableNtUserQueryWindowHook = g_settings.opts().hookNtUserQueryWindow; + g_hdd.EnableNtUserGetForegroundWindowHook = g_settings.opts().hookNtUserGetForegroundWindow; + g_hdd.EnableNtYieldExecutionHook = g_settings.opts().hookNtYieldExecution; + g_hdd.EnableOutputDebugStringHook = g_settings.opts().hookOutputDebugStringA; + g_hdd.EnablePebBeingDebugged = g_settings.opts().fixPebBeingDebugged; + g_hdd.EnablePebHeapFlags = g_settings.opts().fixPebHeapFlags; + g_hdd.EnablePebNtGlobalFlag = g_settings.opts().fixPebNtGlobalFlag; + g_hdd.EnablePebStartupInfo = g_settings.opts().fixPebStartupInfo; + g_hdd.EnablePebOsBuildNumber = g_settings.opts().fixPebOsBuildNumber; + g_hdd.EnablePreventThreadCreation = g_settings.opts().preventThreadCreation; + g_hdd.EnableProtectProcessId = g_settings.opts().protectProcessId; } -bool convertNumber(const wchar_t* str, unsigned long & result, int radix) +//---------------------------------------------------------------------------------- +bool convertNumber( + const wchar_t *str, + unsigned long &result, + int radix) { errno = 0; wchar_t* end; result = wcstoul(str, &end, radix); - if(!result && end == str) + if (result == 0 && end == str) return false; - if(result == ULLONG_MAX && errno) + if (result == ULLONG_MAX && errno) return false; - if(*end) + if (*end != L'\0') return false; return true; } +//---------------------------------------------------------------------------------- bool ArgStartsWith(wchar_t* arg, const wchar_t* with) { return _wcsnicmp(arg, with, wcslen(with)) == 0; } -bool ArgStartsWith(wchar_t* arg, const wchar_t* text, wchar_t* ¶m) +//---------------------------------------------------------------------------------- +bool ArgStartsWith(wchar_t *arg, const wchar_t *text, wchar_t* ¶m) { auto len = wcslen(text); @@ -350,3 +284,86 @@ bool ArgStartsWith(wchar_t* arg, const wchar_t* text, wchar_t* ¶m) param = nullptr; return false; } + +//---------------------------------------------------------------------------------- +int wmain(int argc, wchar_t* argv[]) +{ + DWORD targetPid = 0; + WCHAR *dllPath = 0; + + auto wstrPath = scl::GetModuleFileNameW(); + wstrPath.resize(wstrPath.find_last_of(L'\\') + 1); + + g_scyllaHideIniPath = wstrPath + scl::Settings::kFileName; + + auto log_file = wstrPath + scl::Logger::kFileName; + g_log.SetLogFile(log_file.c_str()); + g_log.SetLogCb(scl::Logger::Info, LogCallback); + g_log.SetLogCb(scl::Logger::Error, LogCallback); + + ReadNtApiInformation(&g_hdd); + SetDebugPrivileges(); + + g_settings.Load(g_scyllaHideIniPath.c_str()); + ReadSettings(); + + bool waitOnExit = true; + + if (argc >= 3) + { + wchar_t *pid; + + if (ArgStartsWith(argv[1], L"pid:", pid)) + { + auto radix = 10; + if (wcsstr(pid, L"0x") == pid) + radix = 16, pid += 2; + if (!convertNumber(pid, targetPid, radix)) + targetPid = 0; + } + else + { + targetPid = GetProcessIdByName(argv[1]); + } + + dllPath = argv[2]; + + if (argc >= 4) + waitOnExit = !(ArgStartsWith(argv[3], L"nowait")); + } + else + { +#ifdef _WIN64 + targetPid = GetProcessIdByName(L"scylla_x64.exe");//scylla_x64 + dllPath = PREFIX_PATH L"\\Release\\HookLibraryx64.dll"; +#else + targetPid = GetProcessIdByName(L"ThemidaTest.exe");//GetProcessIdByName(L"ThemidaTest.exe");//GetProcessIdByName(L"VMProtect.vmp.exe");//GetProcessIdByName(L"scylla_x86.exe"); + dllPath = PREFIX_PATH L"\\Release\\HookLibraryx86.dll"; +#endif + } + + int result = 0; + + if (targetPid != 0 && dllPath != nullptr) + { + wprintf(L"\nPID\t: %d 0x%X\nDLL Path: %s\n\n", targetPid, targetPid, dllPath); + if (!startInjection(targetPid, dllPath)) + result = 1; // failure + } + else + { + wchar_t *processName = wcsrchr(argv[0], '\\'); + if (processName == nullptr) + processName = argv[0]; + else + ++processName; + + wprintf(L"Usage: %s [nowait]\n", processName); + wprintf(L"Usage: %s pid: [nowait]", processName); + } + + if (waitOnExit) + getchar(); + + return 0; +} diff --git a/InjectorCLI/DynamicMapping.cpp b/InjectorCLI/DynamicMapping.cpp index 66fc99a0..6ef6a80b 100644 --- a/InjectorCLI/DynamicMapping.cpp +++ b/InjectorCLI/DynamicMapping.cpp @@ -4,50 +4,57 @@ #pragma comment(lib, "psapi.lib") -LPVOID MapModuleToProcess(HANDLE hProcess, BYTE * dllMemory, bool wipeHeaders) +//---------------------------------------------------------------------------------- +LPVOID MapModuleToProcess( + HANDLE hProcess, + BYTE *dllMemory, + bool wipeHeaders) { - PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)dllMemory; - PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew); + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)dllMemory; + PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew); PIMAGE_SECTION_HEADER pSecHeader = IMAGE_FIRST_SECTION(pNtHeader); if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE || pNtHeader->Signature != IMAGE_NT_SIGNATURE) - { return nullptr; - } - IMAGE_DATA_DIRECTORY relocDir = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; - bool relocatable = (pNtHeader->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) != 0; - bool hasRelocDir = pNtHeader->OptionalHeader.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_BASERELOC && relocDir.VirtualAddress > 0 && relocDir.Size > 0; - if (!hasRelocDir && (pNtHeader->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)) // A relocation dir is optional, but it must not have been stripped - { + IMAGE_DATA_DIRECTORY relocDir = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + bool relocatable = (pNtHeader->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) != 0; + bool hasRelocDir = pNtHeader->OptionalHeader.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_BASERELOC && relocDir.VirtualAddress > 0 && relocDir.Size > 0; + + // A relocation directory is optional, but it must not have been stripped + if (!hasRelocDir && (pNtHeader->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)) return nullptr; - } - ULONG_PTR headersBase = pNtHeader->OptionalHeader.ImageBase; - LPVOID preferredBase = relocatable ? nullptr : (LPVOID)headersBase; - LPVOID imageRemote = VirtualAllocEx(hProcess, preferredBase, pNtHeader->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); - LPVOID imageLocal = VirtualAlloc(nullptr, pNtHeader->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + ULONG_PTR headersBase = pNtHeader->OptionalHeader.ImageBase; + LPVOID preferredBase = relocatable ? nullptr : (LPVOID)headersBase; - if (!imageLocal || !imageRemote) - { + LPVOID imageRemote = VirtualAllocEx(hProcess, preferredBase, pNtHeader->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + LPVOID imageLocal = VirtualAlloc(nullptr, pNtHeader->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + + if (imageLocal == nullptr || imageRemote == nullptr) return nullptr; - } // Update the headers to the relocated image base if (relocatable && (ULONG_PTR)imageRemote != pNtHeader->OptionalHeader.ImageBase) pNtHeader->OptionalHeader.ImageBase = (ULONG_PTR)imageRemote; - memcpy((LPVOID)imageLocal, (LPVOID)pDosHeader, pNtHeader->OptionalHeader.SizeOfHeaders); + memcpy(imageLocal, pDosHeader, pNtHeader->OptionalHeader.SizeOfHeaders); SIZE_T imageSize = pNtHeader->OptionalHeader.SizeOfImage; - for (WORD i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++) + for (WORD i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++, ++pSecHeader) { - if (hasRelocDir && i == pNtHeader->FileHeader.NumberOfSections - 1 && - pSecHeader->VirtualAddress == relocDir.VirtualAddress && (pSecHeader->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) - imageSize = pSecHeader->VirtualAddress; // Limit the maximum VA to copy to the process to exclude .reloc if it is the last section + // Limit the maximum VA to copy to the process to exclude .reloc if it is the last section + if ( hasRelocDir + && i == pNtHeader->FileHeader.NumberOfSections - 1 + && pSecHeader->VirtualAddress == relocDir.VirtualAddress && (pSecHeader->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) + { + imageSize = pSecHeader->VirtualAddress; + } - memcpy((LPVOID)((DWORD_PTR)imageLocal + pSecHeader->VirtualAddress), (LPVOID)((DWORD_PTR)pDosHeader + pSecHeader->PointerToRawData), pSecHeader->SizeOfRawData); - pSecHeader++; + memcpy( + LPVOID((DWORD_PTR)imageLocal + pSecHeader->VirtualAddress), + LPVOID((DWORD_PTR)pDosHeader + pSecHeader->PointerToRawData), + pSecHeader->SizeOfRawData); } if (hasRelocDir) @@ -59,11 +66,19 @@ LPVOID MapModuleToProcess(HANDLE hProcess, BYTE * dllMemory, bool wipeHeaders) dwDelta); } - ResolveImports((PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)imageLocal + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress), (DWORD_PTR)imageLocal); + // Imports resolution + ResolveImports( + PIMAGE_IMPORT_DESCRIPTOR((DWORD_PTR)imageLocal + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress), + (DWORD_PTR)imageLocal); + // SIZE_T skipBytes = wipeHeaders ? pNtHeader->OptionalHeader.SizeOfHeaders : 0; - if (WriteProcessMemory(hProcess, (PVOID)((ULONG_PTR)imageRemote + skipBytes), (PVOID)((ULONG_PTR)imageLocal + skipBytes), - imageSize - skipBytes, nullptr)) + if (WriteProcessMemory( + hProcess, + (PVOID)((ULONG_PTR)imageRemote + skipBytes), + (PVOID)((ULONG_PTR)imageLocal + skipBytes), + imageSize - skipBytes, + nullptr)) { VirtualFree(imageLocal, 0, MEM_RELEASE); } @@ -76,6 +91,7 @@ LPVOID MapModuleToProcess(HANDLE hProcess, BYTE * dllMemory, bool wipeHeaders) return imageRemote; } +//---------------------------------------------------------------------------------- bool ResolveImports(PIMAGE_IMPORT_DESCRIPTOR pImport, DWORD_PTR module) { PIMAGE_THUNK_DATA thunkRef; @@ -83,30 +99,24 @@ bool ResolveImports(PIMAGE_IMPORT_DESCRIPTOR pImport, DWORD_PTR module) while (pImport->FirstThunk) { - char * moduleName = (char *)(module + pImport->Name); + char *moduleName = (char *)(module + pImport->Name); HMODULE hModule = GetModuleHandleA(moduleName); - if (!hModule) + if (hModule == nullptr) { hModule = LoadLibraryA(moduleName); if (!hModule) - { return false; - } } funcRef = (PIMAGE_THUNK_DATA)(module + pImport->FirstThunk); if (pImport->OriginalFirstThunk) - { thunkRef = (PIMAGE_THUNK_DATA)(module + pImport->OriginalFirstThunk); - } else - { thunkRef = (PIMAGE_THUNK_DATA)(module + pImport->FirstThunk); - } - while (thunkRef->u1.Function) + for (; thunkRef->u1.Function != 0; ++thunkRef, ++funcRef) { if (IMAGE_SNAP_BY_ORDINAL(thunkRef->u1.Function)) { @@ -118,14 +128,11 @@ bool ResolveImports(PIMAGE_IMPORT_DESCRIPTOR pImport, DWORD_PTR module) funcRef->u1.Function = (DWORD_PTR)GetProcAddress(hModule, (LPCSTR)thunkData->Name); } - if (!funcRef->u1.Function) + if (funcRef->u1.Function == 0) { MessageBoxA(0, "Function not resolved", moduleName, 0); return false; } - - thunkRef++; - funcRef++; } pImport++; @@ -134,33 +141,30 @@ bool ResolveImports(PIMAGE_IMPORT_DESCRIPTOR pImport, DWORD_PTR module) return true; } -void DoBaseRelocation(PIMAGE_BASE_RELOCATION relocation, DWORD_PTR memory, DWORD_PTR dwDelta) +//---------------------------------------------------------------------------------- +void DoBaseRelocation( + PIMAGE_BASE_RELOCATION relocation, + DWORD_PTR memory, + DWORD_PTR dwDelta) { - DWORD_PTR * patchAddress; + DWORD_PTR *patchAddress; WORD type, offset; while (relocation->VirtualAddress) { - PBYTE dest = (PBYTE)(memory + relocation->VirtualAddress); - DWORD count = (relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); - WORD * relocInfo = (WORD *)((DWORD_PTR)relocation + sizeof(IMAGE_BASE_RELOCATION)); + PBYTE dest = (PBYTE)(memory + relocation->VirtualAddress); + DWORD count = (relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); + WORD *relocInfo = (WORD *)((DWORD_PTR)relocation + sizeof(IMAGE_BASE_RELOCATION)); for (DWORD i = 0; i < count; i++) { type = relocInfo[i] >> 12; offset = relocInfo[i] & 0xfff; - switch (type) + if (type == IMAGE_REL_BASED_HIGHLOW || type == IMAGE_REL_BASED_DIR64) { - case IMAGE_REL_BASED_ABSOLUTE: - break; - case IMAGE_REL_BASED_HIGHLOW: - case IMAGE_REL_BASED_DIR64: patchAddress = (DWORD_PTR *)(dest + offset); *patchAddress += dwDelta; - break; - default: - break; } } @@ -168,11 +172,12 @@ void DoBaseRelocation(PIMAGE_BASE_RELOCATION relocation, DWORD_PTR memory, DWORD } } +//---------------------------------------------------------------------------------- DWORD RVAToOffset(PIMAGE_NT_HEADERS pNtHdr, DWORD dwRVA) { PIMAGE_SECTION_HEADER pSectionHdr = IMAGE_FIRST_SECTION(pNtHdr); - for (WORD i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++) + for (WORD i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, ++pSectionHdr) { if (pSectionHdr->VirtualAddress <= dwRVA) { @@ -183,71 +188,73 @@ DWORD RVAToOffset(PIMAGE_NT_HEADERS pNtHdr, DWORD dwRVA) return (dwRVA); } - } - pSectionHdr++; } - return (0); + return 0; } -DWORD GetDllFunctionAddressRVA(BYTE * dllMemory, LPCSTR apiName) + +//---------------------------------------------------------------------------------- +DWORD GetDllFunctionAddressRVA(BYTE *dllMemory, LPCSTR apiName) { PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)dllMemory; - PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew); - PIMAGE_EXPORT_DIRECTORY pExportDir; + PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew); - DWORD exportDirRVA = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; - DWORD exportDirOffset = RVAToOffset(pNtHeader, exportDirRVA); + DWORD exportDirRVA = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + DWORD exportDirOffset = RVAToOffset(pNtHeader, exportDirRVA); - pExportDir = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)dllMemory + exportDirOffset); + auto pExportDir = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)dllMemory + exportDirOffset); - DWORD * addressOfFunctionsArray = (DWORD *)((DWORD)pExportDir->AddressOfFunctions - exportDirRVA + (DWORD_PTR)pExportDir); - DWORD * addressOfNamesArray = (DWORD *)((DWORD)pExportDir->AddressOfNames - exportDirRVA + (DWORD_PTR)pExportDir); - WORD * addressOfNameOrdinalsArray = (WORD *)((DWORD)pExportDir->AddressOfNameOrdinals - exportDirRVA + (DWORD_PTR)pExportDir); + auto addressOfFunctionsArray = (DWORD *)((DWORD)pExportDir->AddressOfFunctions - exportDirRVA + (DWORD_PTR)pExportDir); + auto addressOfNamesArray = (DWORD *)((DWORD)pExportDir->AddressOfNames - exportDirRVA + (DWORD_PTR)pExportDir); + auto addressOfNameOrdinalsArray = (WORD *)((DWORD)pExportDir->AddressOfNameOrdinals - exportDirRVA + (DWORD_PTR)pExportDir); for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) { char * functionName = (char*)(addressOfNamesArray[i] - exportDirRVA + (DWORD_PTR)pExportDir); - if (!_stricmp(functionName, apiName)) - { return addressOfFunctionsArray[addressOfNameOrdinalsArray[i]]; - } } return 0; } +//---------------------------------------------------------------------------------- HMODULE GetModuleBaseRemote(HANDLE hProcess, const wchar_t* szDLLName) { DWORD cbNeeded = 0; wchar_t szModuleName[MAX_PATH] = { 0 }; - if (EnumProcessModules(hProcess, 0, 0, &cbNeeded)) + if (!EnumProcessModules(hProcess, 0, 0, &cbNeeded)) + return NULL; + + HMODULE *hMods = (HMODULE*)malloc(cbNeeded*sizeof(HMODULE)); + HMODULE hMod = NULL; + + do { - HMODULE* hMods = (HMODULE*)malloc(cbNeeded*sizeof(HMODULE)); - if (EnumProcessModules(hProcess, hMods, cbNeeded, &cbNeeded)) + if (!EnumProcessModules(hProcess, hMods, cbNeeded, &cbNeeded)) + break; + + for (unsigned int i = 0; i < cbNeeded / sizeof(HMODULE); i++) { - for (unsigned int i = 0; i < cbNeeded / sizeof(HMODULE); i++) + szModuleName[0] = 0; + if (GetModuleFileNameExW(hProcess, hMods[i], szModuleName, _countof(szModuleName))) { - szModuleName[0] = 0; - if (GetModuleFileNameExW(hProcess, hMods[i], szModuleName, _countof(szModuleName))) + wchar_t* dllName = wcsrchr(szModuleName, L'\\'); + if (dllName != nullptr) { - wchar_t* dllName = wcsrchr(szModuleName, L'\\'); - if (dllName) + dllName++; + if (_wcsicmp(dllName, szDLLName) == 0) { - dllName++; - if (!_wcsicmp(dllName, szDLLName)) - { - HMODULE module = hMods[i]; - free(hMods); - return module; - } + hMod = hMods[i]; + break; } } } } - free(hMods); - } - return 0; + } while (false); + + free(hMods); + return hMod; } diff --git a/InjectorCLI/DynamicMapping.h b/InjectorCLI/DynamicMapping.h index 7288a434..f6a83f58 100644 --- a/InjectorCLI/DynamicMapping.h +++ b/InjectorCLI/DynamicMapping.h @@ -2,6 +2,7 @@ #include +//---------------------------------------------------------------------------------- typedef struct _SameTebFlags { union @@ -27,9 +28,29 @@ typedef struct _SameTebFlags #define TEB_OFFSET_SAME_TEB_FLAGS 0xFCA #endif -LPVOID MapModuleToProcess(HANDLE hProcess, BYTE * dllMemory, bool wipeHeaders); -void DoBaseRelocation(PIMAGE_BASE_RELOCATION relocation, DWORD_PTR memory, DWORD_PTR dwDelta); -DWORD GetDllFunctionAddressRVA(BYTE * dllMemory, LPCSTR apiName); -DWORD RVAToOffset(PIMAGE_NT_HEADERS pNtHdr, DWORD dwRVA); -HMODULE GetModuleBaseRemote(HANDLE hProcess, const wchar_t* szDLLName); -bool ResolveImports(PIMAGE_IMPORT_DESCRIPTOR pImport, DWORD_PTR module); +//---------------------------------------------------------------------------------- +LPVOID MapModuleToProcess( + HANDLE hProcess, + BYTE *dllMemory, + bool wipeHeaders); + +void DoBaseRelocation( + PIMAGE_BASE_RELOCATION relocation, + DWORD_PTR memory, + DWORD_PTR dwDelta); + +DWORD GetDllFunctionAddressRVA( + BYTE *dllMemory, + LPCSTR apiName); + +DWORD RVAToOffset( + PIMAGE_NT_HEADERS pNtHdr, + DWORD dwRVA); + +HMODULE GetModuleBaseRemote( + HANDLE hProcess, + const wchar_t *szDLLName); + +bool ResolveImports( + PIMAGE_IMPORT_DESCRIPTOR pImport, + DWORD_PTR module); diff --git a/InjectorCLI/InjectorCLI.vcxproj b/InjectorCLI/InjectorCLI.vcxproj index 1c92ca19..2757290f 100644 --- a/InjectorCLI/InjectorCLI.vcxproj +++ b/InjectorCLI/InjectorCLI.vcxproj @@ -153,6 +153,11 @@ + + + {e468da07-48ea-40eb-a845-fa69c39d3396} + + diff --git a/InjectorCLI/RemoteHook.cpp b/InjectorCLI/RemoteHook.cpp index 1627a965..53a35504 100644 --- a/InjectorCLI/RemoteHook.cpp +++ b/InjectorCLI/RemoteHook.cpp @@ -11,13 +11,13 @@ // GDT selector numbers on AMD64 #define KGDT64_R3_CMCODE (2 * 16) // user mode 32-bit code -#define KGDT64_R3_CODE (3 * 16) // user mode 64-bit code +#define KGDT64_R3_CODE (3 * 16) // user mode 64-bit code #define RPL_MASK 3 -#if !defined(_WIN64) -_DecodeType DecodingType = Decode32Bits; -#else +#if defined(_WIN64) _DecodeType DecodingType = Decode64Bits; +#else +_DecodeType DecodingType = Decode32Bits; #endif #ifdef _WIN64 @@ -29,8 +29,8 @@ const int detourLenWow64FarJmp = 1 + sizeof(DWORD) + sizeof(USHORT); // EA far j extern scl::Settings g_settings; -extern void * HookedNativeCallInternal; -extern void * NativeCallContinue; +extern void *HookedNativeCallInternal; +extern void *NativeCallContinue; extern HOOK_NATIVE_CALL32 * HookNative; extern int countNativeHooks; extern bool onceNativeCallContinue; @@ -40,7 +40,8 @@ extern bool fatalAlreadyHookedFailure; BYTE originalBytes[60] = { 0 }; BYTE changedBytes[60] = { 0 }; -void WriteJumper(unsigned char * lpbFrom, unsigned char * lpbTo) +//---------------------------------------------------------------------------------- +void WriteJumper(unsigned char *lpbFrom, unsigned char *lpbTo) { #ifdef _WIN64 lpbFrom[0] = 0xFF; @@ -53,7 +54,12 @@ void WriteJumper(unsigned char * lpbFrom, unsigned char * lpbTo) #endif } -void WriteJumper(unsigned char * lpbFrom, unsigned char * lpbTo, unsigned char * buf, bool prefixNop) +//---------------------------------------------------------------------------------- +void WriteJumper( + unsigned char *lpbFrom, + unsigned char *lpbTo, + unsigned char *buf, + bool prefixNop) { #ifdef _WIN64 UNREFERENCED_PARAMETER(lpbFrom); @@ -74,6 +80,7 @@ void WriteJumper(unsigned char * lpbFrom, unsigned char * lpbTo, unsigned char * #endif } +//---------------------------------------------------------------------------------- #ifndef _WIN64 void WriteWow64Jumper(unsigned char * lpbTo, unsigned char * buf) { @@ -84,17 +91,20 @@ void WriteWow64Jumper(unsigned char * lpbTo, unsigned char * buf) } #endif -void ClearSyscallBreakpoint(const char* funcName, unsigned char* funcBytes) +//---------------------------------------------------------------------------------- +void ClearSyscallBreakpoint(const char *funcName, unsigned char *funcBytes) { // Do nothing if this is not a syscall stub - if ((funcName == nullptr || funcName[0] == '\0') || - (funcName[0] != 'N' || funcName[1] != 't') && - (funcName[0] != 'Z' || funcName[1] != 'w')) + if ( (funcName == nullptr || funcName[0] == '\0') + || (funcName[0] != 'N' || funcName[1] != 't') + && (funcName[0] != 'Z' || funcName[1] != 'w')) + { return; + } - if (funcBytes[0] == 0xCC || // int 3 - (funcBytes[0] == 0xCD && funcBytes[1] == 0x03) || // long int 3 - (funcBytes[0] == 0xF0 && funcBytes[1] == 0x0B)) // UD2 + if ( funcBytes[0] == 0xCC // int 3 + || (funcBytes[0] == 0xCD && funcBytes[1] == 0x03) // long int 3 + || (funcBytes[0] == 0xF0 && funcBytes[1] == 0x0B)) // UD2 { #ifdef _WIN64 // x64 stubs always start with 'mov r10, rcx' @@ -110,6 +120,7 @@ void ClearSyscallBreakpoint(const char* funcName, unsigned char* funcBytes) } } +//---------------------------------------------------------------------------------- #ifndef _WIN64 DWORD GetEcxSysCallIndex32(const BYTE * data, int dataSize) @@ -130,9 +141,7 @@ DWORD GetEcxSysCallIndex32(const BYTE * data, int dataSize) if (decomposerResult[0].opcode == I_MOV && decomposerResult[1].opcode == I_MOV) { if (decomposerResult[1].ops[0].index == R_ECX) - { return decomposerResult[1].imm.dword; - } } } } @@ -140,6 +149,7 @@ DWORD GetEcxSysCallIndex32(const BYTE * data, int dataSize) return 0; } +//---------------------------------------------------------------------------------- DWORD GetSysCallIndex32(const BYTE * data) { unsigned int DecodedInstructionsCount = 0; @@ -156,13 +166,9 @@ DWORD GetSysCallIndex32(const BYTE * data) if (decomposerResult[0].flags != FLAG_NOT_DECODABLE) { if (decomposerResult[0].opcode == I_MOV) - { return decomposerResult[0].imm.dword; - } else - { MessageBoxA(nullptr, "GetSysCallIndex32: Opcode is not I_MOV", "Distorm ERROR", MB_ICONERROR); - } } else { @@ -177,7 +183,8 @@ DWORD GetSysCallIndex32(const BYTE * data) return (DWORD)-1; // Don't return 0 here, it is a valid syscall index } -DWORD GetCallDestination(HANDLE hProcess, const BYTE * data, int dataSize) +//---------------------------------------------------------------------------------- +DWORD GetCallDestination(HANDLE hProcess, const BYTE *data, int dataSize) { unsigned int DecodedInstructionsCount = 0; _CodeInfo decomposerCi = { 0 }; @@ -229,9 +236,10 @@ DWORD GetCallDestination(HANDLE hProcess, const BYTE * data, int dataSize) } } - return NULL; + return 0; } +//---------------------------------------------------------------------------------- DWORD GetFunctionSizeRETN(BYTE * data, int dataSize) { unsigned int DecodedInstructionsCount = 0; @@ -250,9 +258,7 @@ DWORD GetFunctionSizeRETN(BYTE * data, int dataSize) if (decomposerResult[i].flags != FLAG_NOT_DECODABLE) { if (decomposerResult[i].opcode == I_RET) - { return (DWORD)(((DWORD_PTR)decomposerResult[i].addr + (DWORD_PTR)decomposerResult[i].size) - (DWORD_PTR)data); - } } } @@ -261,6 +267,7 @@ DWORD GetFunctionSizeRETN(BYTE * data, int dataSize) return 0; } +//---------------------------------------------------------------------------------- DWORD GetCallOffset(const BYTE * data, int dataSize, DWORD * callSize) { unsigned int DecodedInstructionsCount = 0; @@ -291,6 +298,7 @@ DWORD GetCallOffset(const BYTE * data, int dataSize, DWORD * callSize) return 0; } +//---------------------------------------------------------------------------------- ULONG_PTR FindPattern(ULONG_PTR base, ULONG size, const UCHAR* pattern, ULONG patternSize) { for (PUCHAR Address = (PUCHAR)base; Address < (PUCHAR)(base + size - patternSize); ++Address) @@ -308,10 +316,11 @@ ULONG_PTR FindPattern(ULONG_PTR base, ULONG size, const UCHAR* pattern, ULONG pa return 0; } +//---------------------------------------------------------------------------------- BYTE KiFastSystemCallWow64Backup[7] = { 0 }; DWORD KiFastSystemCallWow64Address = 0; // In wow64cpu.dll, named X86SwitchTo64BitMode prior to Windows 8 -void * DetourCreateRemoteWow64(void * hProcess, bool createTramp) +void *DetourCreateRemoteWow64(void * hProcess, bool createTramp) { PBYTE trampoline = nullptr; DWORD protect; @@ -474,6 +483,7 @@ void * DetourCreateRemoteWow64(void * hProcess, bool createTramp) return trampoline; } +//---------------------------------------------------------------------------------- //7C91E4F0 ntdll.KiFastSystemCall EB F9 JMP 7C91E4EB BYTE KiFastSystemCallJmpPatch[] = { 0xE9, 0x00, 0x00, 0x00, 0x00, 0xEB, 0xF9 }; @@ -481,7 +491,7 @@ BYTE KiFastSystemCallBackup[20] = { 0 }; DWORD KiFastSystemCallAddress = 0; DWORD KiFastSystemCallBackupSize = 0; -void * DetourCreateRemoteX86(void * hProcess, bool createTramp) +void *DetourCreateRemoteX86(void * hProcess, bool createTramp) { PBYTE trampoline = 0; DWORD protect; @@ -548,7 +558,14 @@ void * DetourCreateRemoteX86(void * hProcess, bool createTramp) return trampoline; } -void * DetourCreateRemote32(void * hProcess, const char* funcName, void * lpFuncOrig, void * lpFuncDetour, bool createTramp, unsigned long * backupSize) +//---------------------------------------------------------------------------------- +void *DetourCreateRemote32( + void *hProcess, + const char *funcName, + void *lpFuncOrig, + void *lpFuncDetour, + bool createTramp, + unsigned long *backupSize) { if (!scl::IsWow64Process(hProcess)) { @@ -617,7 +634,14 @@ void * DetourCreateRemote32(void * hProcess, const char* funcName, void * lpFunc #endif -void * DetourCreateRemote(void * hProcess, const char* funcName, void * lpFuncOrig, void * lpFuncDetour, bool createTramp, DWORD * backupSize) +//---------------------------------------------------------------------------------- +void *DetourCreateRemote( + void *hProcess, + const char *funcName, + void *lpFuncOrig, + void *lpFuncDetour, + bool createTramp, + DWORD *backupSize) { BYTE originalBytes[50] = { 0 }; BYTE tempSpace[1000] = { 0 }; @@ -640,8 +664,9 @@ void * DetourCreateRemote(void * hProcess, const char* funcName, void * lpFuncOr // Note that this check will give a false negative in the case that a function is hooked *and* has a breakpoint set on it (now cleared). // We can clear the breakpoint or detect the hook, not both. (If the hook is ours, this is actually a hack because we should be properly unhooking) #ifdef _WIN64 - const bool isHooked = (originalBytes[0] == 0xFF && originalBytes[1] == 0x25) || - (originalBytes[0] == 0x90 && originalBytes[1] == 0xFF && originalBytes[2] == 0x25); + const bool isHooked = + (originalBytes[0] == 0xFF && originalBytes[1] == 0x25) + || (originalBytes[0] == 0x90 && originalBytes[1] == 0xFF && originalBytes[2] == 0x25); #else const bool isHooked = originalBytes[0] == 0xE9; #endif @@ -661,8 +686,9 @@ void * DetourCreateRemote(void * hProcess, const char* funcName, void * lpFuncOr { *backupSize = detourLen; + // TODO: ;! trampoline pool. No need to allocate a page per trampoline trampoline = (PBYTE)VirtualAllocEx(hProcess, 0, detourLen + minDetourLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (!trampoline) + if (trampoline == nullptr) return 0; WriteProcessMemory(hProcess, trampoline, originalBytes, detourLen, 0); @@ -698,7 +724,8 @@ void * DetourCreateRemote(void * hProcess, const char* funcName, void * lpFuncOr } } -void * DetourCreate(void * lpFuncOrig, void * lpFuncDetour, bool createTramp) +//---------------------------------------------------------------------------------- +void *DetourCreate(void *lpFuncOrig, void *lpFuncDetour, bool createTramp) { PBYTE trampoline = 0; DWORD protect; @@ -742,7 +769,8 @@ void * DetourCreate(void * lpFuncOrig, void * lpFuncDetour, bool createTramp) } } -int GetDetourLen(const void * lpStart, const int minSize) +//---------------------------------------------------------------------------------- +int GetDetourLen(const void *lpStart, const int minSize) { int totalLen = 0; unsigned char * lpDataPos = (unsigned char *)lpStart; @@ -750,7 +778,7 @@ int GetDetourLen(const void * lpStart, const int minSize) while (totalLen < minSize) { int len = (int)LengthDisassemble((void *)lpDataPos); - if (len < 1) //len < 1 will cause infinite loops + if (len < 1) // len < 1 will cause infinite loops len = 1; lpDataPos += len; totalLen += len; @@ -759,6 +787,7 @@ int GetDetourLen(const void * lpStart, const int minSize) return totalLen; } +//---------------------------------------------------------------------------------- int LengthDisassemble(LPVOID DisassmAddress) { unsigned int DecodedInstructionsCount = 0; @@ -773,9 +802,7 @@ int LengthDisassemble(LPVOID DisassmAddress) if (distorm_decompose(&decomposerCi, decomposerResult, _countof(decomposerResult), &DecodedInstructionsCount) != DECRES_INPUTERR) { if (decomposerResult[0].flags != FLAG_NOT_DECODABLE) - { return decomposerResult[0].size; - } } return -1; //this is dangerous diff --git a/PluginGeneric/AttachDialog.cpp b/PluginGeneric/AttachDialog.cpp index f364d42f..9078104e 100644 --- a/PluginGeneric/AttachDialog.cpp +++ b/PluginGeneric/AttachDialog.cpp @@ -3,64 +3,67 @@ #include #ifdef OLLY1 -#include "..\ScyllaHideOlly1Plugin\resource.h" + #include "..\ScyllaHideOlly1Plugin\resource.h" #elif OLLY2 -#include "..\ScyllaHideOlly2Plugin\resource.h" -#include + #include "..\ScyllaHideOlly2Plugin\resource.h" + #include #elif __IDP__ -#include "..\ScyllaHideIDAProPlugin\resource.h" -#include + #include "..\ScyllaHideIDAProPlugin\resource.h" + #pragma warning(push) + #pragma warning(disable: 4244 4267) + #include + #pragma warning(pop) #elif X64DBG -#include "..\ScyllaHideX64DBGPlugin\resource.h" + #include "..\ScyllaHideX64DBGPlugin\resource.h" #endif #define BULLSEYE_CENTER_X_OFFSET 15 #define BULLSEYE_CENTER_Y_OFFSET 18 -typedef void(__cdecl * t_AttachProcess)(DWORD dwPID); +typedef void (__cdecl *t_AttachProcess)(DWORD dwPID); t_AttachProcess _AttachProcess = 0; -extern HINSTANCE hinst; #ifdef OLLY1 -extern HWND hwmain; // Handle of main OllyDbg window + extern HWND hwmain; // Handle of main OllyDbg window #elif OLLY2 -HWND hwmain = hwollymain; + HWND hwmain = hwollymain; #elif __IDP__ -HWND hwmain = (HWND)callui(ui_get_hwnd).vptr; + HWND hwmain = NULL; #elif X64DBG -extern HWND hwndDlg; -HWND hwmain; + extern HWND hwndDlg; + HWND hwmain; #endif + +extern HINSTANCE hinst; + HBITMAP hBitmapFinderToolFilled = NULL; HBITMAP hBitmapFinderToolEmpty = NULL; HCURSOR hCursorPrevious = NULL; HCURSOR hCursorSearchWindow = NULL; -BOOL bStartSearchWindow = FALSE; -HWND hwndFoundWindow = NULL; +BOOL bStartSearchWindow = FALSE; +HWND hwndFoundWindow = NULL; wchar_t title[256]; wchar_t pidTextHex[9]; wchar_t pidTextDec[11]; -DWORD pid = NULL; - -//toggles the finder image +DWORD pid = 0; + +//---------------------------------------------------------------------------------- +// Toggles the finder image void SetFinderToolImage(HWND hwnd, BOOL bSet) { HBITMAP hBmpToSet = NULL; if (bSet) - { hBmpToSet = hBitmapFinderToolFilled; - } else - { hBmpToSet = hBitmapFinderToolEmpty; - } SendDlgItemMessage(hwnd, IDC_ICON_FINDER, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmpToSet); } - -//centers cursor in bullseye. adds to the illusion that the bullseye can be dragged out + +//---------------------------------------------------------------------------------- +// Centers cursor in bullseye. adds to the illusion that the bullseye can be dragged out void MoveCursorPositionToBullsEye(HWND hwnd) { HWND hwndToolFinder = NULL; @@ -69,7 +72,7 @@ void MoveCursorPositionToBullsEye(HWND hwnd) hwndToolFinder = GetDlgItem(hwnd, IDC_ICON_FINDER); - if (hwndToolFinder) + if (hwndToolFinder != NULL) { GetWindowRect(hwndToolFinder, &rect); screenpoint.x = rect.left + BULLSEYE_CENTER_X_OFFSET; @@ -77,51 +80,39 @@ void MoveCursorPositionToBullsEye(HWND hwnd) SetCursorPos(screenpoint.x, screenpoint.y); } } - -//does some sanity checks on a possible found window + +//---------------------------------------------------------------------------------- +// Do sanity checks on a possible found window BOOL CheckWindowValidity(HWND hwnd, HWND hwndToCheck) { HWND hwndTemp = NULL; - if (hwndToCheck == NULL) - { + if (hwndToCheck == NULL || IsWindow(hwndToCheck) == FALSE) return FALSE; - } - if (IsWindow(hwndToCheck) == FALSE) - { - return FALSE; - } //same window as previous? if (hwndToCheck == hwndFoundWindow) - { return FALSE; - } //debugger window is not a valid one if (hwndToCheck == hwmain) - { return FALSE; - } // It also must not be the "Search Window" dialog box itself. if (hwndToCheck == hwnd) - { return FALSE; - } // It also must not be one of the dialog box's children... hwndTemp = GetParent(hwndToCheck); if ((hwndTemp == hwnd) || (hwndTemp == hwmain)) - { return FALSE; - } hwndFoundWindow = hwndToCheck; return TRUE; } - + +//---------------------------------------------------------------------------------- void DisplayExe(HWND hwnd, DWORD dwPid) { WCHAR filepath[MAX_PATH] = { 0 }; @@ -132,189 +123,181 @@ void DisplayExe(HWND hwnd, DWORD dwPid) CloseHandle(hProc); if (wcslen(filepath) > 0) - { SetDlgItemTextW(hwnd, IDC_EXEPATH, wcsrchr(filepath, L'\\') + 1); - } else - { SetDlgItemTextW(hwnd, IDC_EXEPATH, L"UNKNOWN"); - } } else { SetDlgItemTextW(hwnd, IDC_EXEPATH, L"UNKNOWN"); } } - -//attach dialog proc -INT_PTR CALLBACK AttachProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) + +//---------------------------------------------------------------------------------- +// Attach dialog proc +INT_PTR CALLBACK AttachProc( + HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam) { wchar_t buf[20] = { 0 }; switch (message) { - case WM_INITDIALOG: - { -#ifdef X64DBG - hwmain = hwndDlg; -#endif - - hBitmapFinderToolFilled = LoadBitmap(hinst, MAKEINTRESOURCE(IDB_FINDERFILLED)); - hBitmapFinderToolEmpty = LoadBitmap(hinst, MAKEINTRESOURCE(IDB_FINDEREMPTY)); - hCursorSearchWindow = LoadCursor(hinst, MAKEINTRESOURCE(IDC_CURSOR_SEARCH_WINDOW)); - - break; - } - case WM_CLOSE: - { - EndDialog(hWnd, NULL); - } - break; + case WM_INITDIALOG: + { + #ifdef X64DBG + hwmain = hwndDlg; + #endif - case WM_COMMAND: - { - switch (LOWORD(wParam)) { - case IDOK: { //attach - if (pid != NULL) { - EndDialog(hWnd, NULL); + hBitmapFinderToolFilled = LoadBitmap(hinst, MAKEINTRESOURCE(IDB_FINDERFILLED)); + hBitmapFinderToolEmpty = LoadBitmap(hinst, MAKEINTRESOURCE(IDB_FINDEREMPTY)); + hCursorSearchWindow = LoadCursor(hinst, MAKEINTRESOURCE(IDC_CURSOR_SEARCH_WINDOW)); - if (_AttachProcess != 0) - { - _AttachProcess(pid); - } - else - { - MessageBoxW(0, L"Developer!!! You forgot something _AttachProcess!!!!!", L"ERROR", 0); - } - } break; } - case IDCANCEL: { + case WM_CLOSE: EndDialog(hWnd, NULL); break; - } - case IDC_PIDHEX: { - if (0 < GetDlgItemTextW(hWnd, IDC_PIDHEX, buf, _countof(buf))) { - if (wcscmp(buf, pidTextHex) != 0) { - wcscpy(pidTextHex, buf); - swscanf(pidTextHex, L"%X", &pid); - wsprintfW(pidTextDec, L"%d", pid); - SetDlgItemTextW(hWnd, IDC_PIDDEC, pidTextDec); - DisplayExe(hWnd, pid); - SetDlgItemTextW(hWnd, IDC_TITLE, L""); - } - } - break; - } - case IDC_PIDDEC: + + case WM_COMMAND: { + switch (LOWORD(wParam)) + { + // Attach + case IDOK: + { + if (pid != NULL) + { + EndDialog(hWnd, NULL); + + if (_AttachProcess != nullptr) + _AttachProcess(pid); + else + MessageBoxW(0, L"Developer!!! You forgot something _AttachProcess!!!!!", L"ERROR", 0); + } + break; + } + case IDCANCEL: + { + EndDialog(hWnd, NULL); + break; + } + case IDC_PIDHEX: + { + if (0 < GetDlgItemTextW(hWnd, IDC_PIDHEX, buf, _countof(buf))) + { + if (wcscmp(buf, pidTextHex) != 0) + { + wcscpy(pidTextHex, buf); + swscanf_s(pidTextHex, L"%X", &pid); + wsprintfW(pidTextDec, L"%d", pid); + SetDlgItemTextW(hWnd, IDC_PIDDEC, pidTextDec); + DisplayExe(hWnd, pid); + SetDlgItemTextW(hWnd, IDC_TITLE, L""); + } + } + break; + } + case IDC_PIDDEC: + { - if (0 < GetDlgItemTextW(hWnd, IDC_PIDDEC, buf, _countof(buf))) { - if (wcscmp(buf, pidTextDec) != 0) { - wcscpy(pidTextDec, buf); - swscanf(pidTextDec, L"%d", &pid); - wsprintfW(pidTextHex, L"%X", pid); - SetDlgItemTextW(hWnd, IDC_PIDHEX, pidTextHex); - DisplayExe(hWnd, pid); - SetDlgItemTextW(hWnd, IDC_TITLE, L""); + if (0 < GetDlgItemTextW(hWnd, IDC_PIDDEC, buf, _countof(buf))) + { + if (wcscmp(buf, pidTextDec) != 0) + { + wcscpy_s(pidTextDec, buf); + swscanf_s(pidTextDec, L"%d", &pid); + wsprintfW(pidTextHex, L"%X", pid); + SetDlgItemTextW(hWnd, IDC_PIDHEX, pidTextHex); + DisplayExe(hWnd, pid); + SetDlgItemTextW(hWnd, IDC_TITLE, L""); + } + } + break; } - } - break; - } - case IDC_ICON_FINDER: { - bStartSearchWindow = TRUE; + case IDC_ICON_FINDER: + { + bStartSearchWindow = TRUE; - SetFinderToolImage(hWnd, FALSE); + SetFinderToolImage(hWnd, FALSE); - MoveCursorPositionToBullsEye(hWnd); + MoveCursorPositionToBullsEye(hWnd); - // Set the screen cursor to the BullsEye cursor. - if (hCursorSearchWindow) - { - hCursorPrevious = SetCursor(hCursorSearchWindow); - } - else - { - hCursorPrevious = NULL; - } + // Set the screen cursor to the BullsEye cursor. + if (hCursorSearchWindow) + hCursorPrevious = SetCursor(hCursorSearchWindow); + else + hCursorPrevious = NULL; - //redirect all mouse events to this AttachProc - SetCapture(hWnd); + //redirect all mouse events to this AttachProc + SetCapture(hWnd); - ShowWindow(hwmain, SW_HIDE); - break; - } + ShowWindow(hwmain, SW_HIDE); + break; + } + } + break; } - break; - } - - case WM_MOUSEMOVE: - { - if (bStartSearchWindow) + case WM_MOUSEMOVE: { - POINT screenpoint; - HWND hwndCurrentWindow = NULL; + if (bStartSearchWindow) + { + POINT screenpoint; + HWND hwndCurrentWindow = NULL; - GetCursorPos(&screenpoint); + GetCursorPos(&screenpoint); - hwndCurrentWindow = WindowFromPoint(screenpoint); + hwndCurrentWindow = WindowFromPoint(screenpoint); - if (CheckWindowValidity(hWnd, hwndCurrentWindow)) - { - //get some info about the window - GetWindowThreadProcessId(hwndFoundWindow, &pid); + if (CheckWindowValidity(hWnd, hwndCurrentWindow)) + { + //get some info about the window + GetWindowThreadProcessId(hwndFoundWindow, &pid); - DisplayExe(hWnd, pid); + DisplayExe(hWnd, pid); - if (GetWindowTextW(hwndCurrentWindow, title, _countof(title)) > 0) - { - SetDlgItemTextW(hWnd, IDC_TITLE, title); - } - else - { - SetDlgItemTextW(hWnd, IDC_TITLE, L""); - } + if (GetWindowTextW(hwndCurrentWindow, title, _countof(title)) > 0) + SetDlgItemTextW(hWnd, IDC_TITLE, title); + else + SetDlgItemTextW(hWnd, IDC_TITLE, L""); - wsprintfW(pidTextHex, L"%X", pid); - wsprintfW(pidTextDec, L"%d", pid); - SetDlgItemTextW(hWnd, IDC_PIDHEX, pidTextHex); - SetDlgItemTextW(hWnd, IDC_PIDDEC, pidTextDec); + wsprintfW(pidTextHex, L"%X", pid); + wsprintfW(pidTextDec, L"%d", pid); + SetDlgItemTextW(hWnd, IDC_PIDHEX, pidTextHex); + SetDlgItemTextW(hWnd, IDC_PIDDEC, pidTextDec); + } } - } - break; - } + break; + } - case WM_LBUTTONUP: - { - if (bStartSearchWindow) + case WM_LBUTTONUP: { - // restore cursor - if (hCursorPrevious) + if (bStartSearchWindow) { - SetCursor(hCursorPrevious); - } + // Restore cursor + if (hCursorPrevious) + SetCursor(hCursorPrevious); - SetFinderToolImage(hWnd, TRUE); + SetFinderToolImage(hWnd, TRUE); - // release the mouse capture. - ReleaseCapture(); + // Release the mouse capture. + ReleaseCapture(); - ShowWindow(hwmain, SW_SHOWNORMAL); + ShowWindow(hwmain, SW_SHOWNORMAL); - bStartSearchWindow = FALSE; + bStartSearchWindow = FALSE; + } + break; } - break; - } - - default: - { - return FALSE; - } + default: + return FALSE; } return 0; diff --git a/PluginGeneric/Injector.cpp b/PluginGeneric/Injector.cpp index 9ac306c2..ae89f0f0 100644 --- a/PluginGeneric/Injector.cpp +++ b/PluginGeneric/Injector.cpp @@ -7,7 +7,7 @@ #include #include -#include "..\InjectorCLI\\ApplyHooking.h" +#include "..\InjectorCLI\ApplyHooking.h" extern scl::Settings g_settings; extern scl::Logger g_log; @@ -18,14 +18,15 @@ typedef void(__cdecl * t_SetDebuggerBreakpoint)(DWORD_PTR address); t_SetDebuggerBreakpoint _SetDebuggerBreakpoint = 0; //anti-attach vars -DWORD ExitThread_addr; -BYTE* DbgUiIssueRemoteBreakin_addr; -DWORD jmpback; -DWORD DbgUiRemoteBreakin_addr; -BYTE* RemoteBreakinPatch; -BYTE OllyRemoteBreakInReplacement[8]; -HANDLE hDebuggee; - +DWORD ExitThread_addr; +BYTE *DbgUiIssueRemoteBreakin_addr; +DWORD jmpback; +DWORD DbgUiRemoteBreakin_addr; +BYTE *RemoteBreakinPatch; +BYTE OllyRemoteBreakInReplacement[8]; +HANDLE hDebuggee; + +//---------------------------------------------------------------------------------- void ReadNtApiInformation(HOOK_DLL_DATA *hdd) { scl::User32Loader user32Loader; @@ -43,14 +44,14 @@ void ReadNtApiInformation(HOOK_DLL_DATA *hdd) return; } - hdd->NtUserBlockInputVA = user32Loader.GetUserSyscallVa("NtUserBlockInput"); - hdd->NtUserQueryWindowVA = user32Loader.GetUserSyscallVa("NtUserQueryWindow"); - hdd->NtUserGetForegroundWindowVA = user32Loader.GetUserSyscallVa("NtUserGetForegroundWindow"); - hdd->NtUserBuildHwndListVA = user32Loader.GetUserSyscallVa("NtUserBuildHwndList"); - hdd->NtUserFindWindowExVA = user32Loader.GetUserSyscallVa("NtUserFindWindowEx"); - hdd->NtUserGetClassNameVA = user32Loader.GetUserSyscallVa("NtUserGetClassName"); - hdd->NtUserInternalGetWindowTextVA = user32Loader.GetUserSyscallVa("NtUserInternalGetWindowText"); - hdd->NtUserGetThreadStateVA = user32Loader.GetUserSyscallVa("NtUserGetThreadState"); + hdd->NtUserBlockInputVA = user32Loader.GetUserSyscallVa("NtUserBlockInput"); + hdd->NtUserQueryWindowVA = user32Loader.GetUserSyscallVa("NtUserQueryWindow"); + hdd->NtUserGetForegroundWindowVA = user32Loader.GetUserSyscallVa("NtUserGetForegroundWindow"); + hdd->NtUserBuildHwndListVA = user32Loader.GetUserSyscallVa("NtUserBuildHwndList"); + hdd->NtUserFindWindowExVA = user32Loader.GetUserSyscallVa("NtUserFindWindowEx"); + hdd->NtUserGetClassNameVA = user32Loader.GetUserSyscallVa("NtUserGetClassName"); + hdd->NtUserInternalGetWindowTextVA = user32Loader.GetUserSyscallVa("NtUserInternalGetWindowText"); + hdd->NtUserGetThreadStateVA = user32Loader.GetUserSyscallVa("NtUserGetThreadState"); g_log.LogInfo(L"Loaded VA for NtUserBlockInput = 0x%p", hdd->NtUserBlockInputVA); g_log.LogInfo(L"Loaded VA for NtUserQueryWindow = 0x%p", hdd->NtUserQueryWindowVA); @@ -61,7 +62,8 @@ void ReadNtApiInformation(HOOK_DLL_DATA *hdd) g_log.LogInfo(L"Loaded VA for NtUserInternalGetWindowText = 0x%p", hdd->NtUserInternalGetWindowTextVA); g_log.LogInfo(L"Loaded VA for NtUserGetThreadState = 0x%p", hdd->NtUserGetThreadStateVA); } - + +//---------------------------------------------------------------------------------- #ifndef _WIN64 void __declspec(naked) handleAntiAttach() { @@ -85,14 +87,16 @@ void __declspec(naked) handleAntiAttach() ULONG oldProtect; VirtualProtectEx(hDebuggee, RemoteBreakinPatch, sizeof(OllyRemoteBreakInReplacement), PAGE_EXECUTE_READ, &oldProtect); - _asm { + _asm + { popad mov eax, jmpback jmp eax } } #endif - + +//---------------------------------------------------------------------------------- void InstallAntiAttachHook() { #ifndef _WIN64 @@ -122,10 +126,14 @@ void InstallAntiAttachHook() *p = 0xC3; //retn #endif } - + +//---------------------------------------------------------------------------------- bool StartFixBeingDebugged(DWORD targetPid, bool setToNull) { - scl::Handle hProcess(OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, 0, targetPid)); + scl::Handle hProcess(OpenProcess( + PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, + 0, + targetPid)); if (!hProcess.get()) return false; @@ -150,20 +158,29 @@ bool StartFixBeingDebugged(DWORD targetPid, bool setToNull) return true; } - + +//---------------------------------------------------------------------------------- static bool GetProcessInfo(HANDLE hProcess, PPROCESS_SUSPEND_INFO processInfo) { PROCESS_BASIC_INFORMATION basicInfo = { 0 }; - NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &basicInfo, sizeof(basicInfo), nullptr); + NTSTATUS status = NtQueryInformationProcess( + hProcess, + ProcessBasicInformation, + &basicInfo, + sizeof(basicInfo), + nullptr); if (!NT_SUCCESS(status)) - return false; + return false; + ULONG size; status = NtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &size); if (status != STATUS_INFO_LENGTH_MISMATCH) - return false; + return false; + const PSYSTEM_PROCESS_INFORMATION systemProcessInfo = (PSYSTEM_PROCESS_INFORMATION)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, 2 * size); if (systemProcessInfo == nullptr) - return false; + return false; + status = NtQuerySystemInformation(SystemProcessInformation, systemProcessInfo, 2 * size, nullptr); if (!NT_SUCCESS(status)) { @@ -181,7 +198,8 @@ static bool GetProcessInfo(HANDLE hProcess, PPROCESS_SUSPEND_INFO processInfo) { numThreads = entry->NumberOfThreads; break; - } + } + if (entry->NextEntryOffset == 0) break; entry = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)entry + entry->NextEntryOffset); @@ -201,17 +219,18 @@ static bool GetProcessInfo(HANDLE hProcess, PPROCESS_SUSPEND_INFO processInfo) // Fill thread IDs processInfo->ThreadSuspendInfo = (PTHREAD_SUSPEND_INFO)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, numThreads * sizeof(THREAD_SUSPEND_INFO)); for (ULONG i = 0; i < numThreads; ++i) - { processInfo->ThreadSuspendInfo[i].ThreadId = entry->Threads[i].ClientId.UniqueThread; - } RtlFreeHeap(RtlProcessHeap(), 0, systemProcessInfo); return true; } - + +//---------------------------------------------------------------------------------- // NtSuspendProcess does not return STATUS_SUSPEND_COUNT_EXCEEDED (or any other error) when one or more thread(s) in the process is/are at the suspend limit. // This replacement suspends all threads in a process, storing the individual thread suspend statuses. True is returned iff all threads are suspended. -bool SafeSuspendProcess(HANDLE hProcess, PPROCESS_SUSPEND_INFO suspendInfo) +bool SafeSuspendProcess( + HANDLE hProcess, + PPROCESS_SUSPEND_INFO suspendInfo) { // Get process info if (!GetProcessInfo(hProcess, suspendInfo)) @@ -224,7 +243,12 @@ bool SafeSuspendProcess(HANDLE hProcess, PPROCESS_SUSPEND_INFO suspendInfo) CLIENT_ID clientId = { suspendInfo->ProcessId, suspendInfo->ThreadSuspendInfo[i].ThreadId }; // Open the thread by thread ID - NTSTATUS status = NtOpenThread(&threadSuspendInfo->ThreadHandle, THREAD_SUSPEND_RESUME, &objectAttributes, &clientId); + NTSTATUS status = NtOpenThread( + &threadSuspendInfo->ThreadHandle, + THREAD_SUSPEND_RESUME, + &objectAttributes, + &clientId); + if (!NT_SUCCESS(status)) { RtlFreeHeap(RtlProcessHeap(), 0, suspendInfo->ThreadSuspendInfo); @@ -242,7 +266,8 @@ bool SafeSuspendProcess(HANDLE hProcess, PPROCESS_SUSPEND_INFO suspendInfo) return true; } - + +//---------------------------------------------------------------------------------- // Replacement for NtResumeProcess, to be used with info obtained from a prior call to SafeSuspendProcess bool SafeResumeProcess(PPROCESS_SUSPEND_INFO suspendInfo) { @@ -260,8 +285,13 @@ bool SafeResumeProcess(PPROCESS_SUSPEND_INFO suspendInfo) RtlFreeHeap(RtlProcessHeap(), 0, suspendInfo->ThreadSuspendInfo); return success; } - -bool StartHooking(HANDLE hProcess, HOOK_DLL_DATA *hdd, BYTE * dllMemory, DWORD_PTR imageBase) + +//---------------------------------------------------------------------------------- +bool StartHooking( + HANDLE hProcess, + HOOK_DLL_DATA *hdd, + BYTE *dllMemory, + DWORD_PTR imageBase) { hdd->dwProtectedProcessId = GetCurrentProcessId(); hdd->EnableProtectProcessId = TRUE; @@ -287,8 +317,13 @@ bool StartHooking(HANDLE hProcess, HOOK_DLL_DATA *hdd, BYTE * dllMemory, DWORD_P return ApplyHook(hdd, hProcess, dllMemory, imageBase); } - -void startInjectionProcess(HANDLE hProcess, HOOK_DLL_DATA *hdd, BYTE * dllMemory, bool newProcess) + +//---------------------------------------------------------------------------------- +void startInjectionProcess( + HANDLE hProcess, + HOOK_DLL_DATA *hdd, + BYTE *dllMemory, + bool newProcess) { PROCESS_SUSPEND_INFO suspendInfo; if (!SafeSuspendProcess(hProcess, &suspendInfo)) @@ -302,32 +337,26 @@ void startInjectionProcess(HANDLE hProcess, HOOK_DLL_DATA *hdd, BYTE * dllMemory { //g_log.Log(L"Apply hooks again"); if (injectDll && StartHooking(hProcess, hdd, dllMemory, (DWORD_PTR)remoteImageBase)) - { WriteProcessMemory(hProcess, (LPVOID)((DWORD_PTR)hookDllDataAddressRva + (DWORD_PTR)remoteImageBase), hdd, sizeof(HOOK_DLL_DATA), 0); - } else if (!injectDll) - { StartHooking(hProcess, hdd, nullptr, 0); - } } else { if (g_settings.opts().removeDebugPrivileges) - { RemoveDebugPrivileges(hProcess); - } RestoreHooks(hdd, hProcess); if (injectDll) { remoteImageBase = MapModuleToProcess(hProcess, dllMemory, true); - if (remoteImageBase) + if (remoteImageBase != nullptr) { FillHookDllData(hProcess, hdd); - if (StartHooking(hProcess, hdd, dllMemory, (DWORD_PTR)remoteImageBase) && - WriteProcessMemory(hProcess, (LPVOID)((DWORD_PTR)hookDllDataAddressRva + (DWORD_PTR)remoteImageBase), hdd, sizeof(HOOK_DLL_DATA), 0)) + if ( StartHooking(hProcess, hdd, dllMemory, (DWORD_PTR)remoteImageBase) + && WriteProcessMemory(hProcess, (LPVOID)((DWORD_PTR)hookDllDataAddressRva + (DWORD_PTR)remoteImageBase), hdd, sizeof(HOOK_DLL_DATA), 0)) { g_log.LogInfo(L"Hook injection successful, image base %p", remoteImageBase); } @@ -350,15 +379,23 @@ void startInjectionProcess(HANDLE hProcess, HOOK_DLL_DATA *hdd, BYTE * dllMemory SafeResumeProcess(&suspendInfo); } - -void startInjection(DWORD targetPid, HOOK_DLL_DATA *hdd, const WCHAR * dllPath, bool newProcess) + +//---------------------------------------------------------------------------------- +void startInjection( + DWORD targetPid, + HOOK_DLL_DATA *hdd, + const WCHAR *dllPath, + bool newProcess) { - HANDLE hProcess = OpenProcess( PROCESS_SUSPEND_RESUME | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, - 0, targetPid); - if (hProcess) + HANDLE hProcess = OpenProcess( + PROCESS_SUSPEND_RESUME | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, + 0, + targetPid); + + if (hProcess != NULL) { - BYTE * dllMemory = ReadFileToMemory(dllPath); - if (dllMemory) + BYTE *dllMemory = ReadFileToMemory(dllPath); + if (dllMemory != nullptr) { startInjectionProcess(hProcess, hdd, dllMemory, newProcess); free(dllMemory); @@ -375,11 +412,17 @@ void startInjection(DWORD targetPid, HOOK_DLL_DATA *hdd, const WCHAR * dllPath, g_log.LogError(L"Cannot open process handle %d", targetPid); } } - -NTSTATUS CreateAndWaitForThread(HANDLE hProcess, LPTHREAD_START_ROUTINE threadStart, PVOID parameter, PHANDLE threadHandle, BOOLEAN suppressDllMains) + +//---------------------------------------------------------------------------------- +NTSTATUS CreateAndWaitForThread( + HANDLE hProcess, + LPTHREAD_START_ROUTINE threadStart, + PVOID parameter, + PHANDLE threadHandle, + BOOLEAN suppressDllMains) { NTSTATUS status = STATUS_UNSUCCESSFUL; - const t_NtCreateThreadEx fpNtCreateThreadEx = (t_NtCreateThreadEx)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx"); + const auto fpNtCreateThreadEx = (t_NtCreateThreadEx)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx"); if (fpNtCreateThreadEx == nullptr) { // We are on XP/2003 - use CreateRemoteThread @@ -415,7 +458,8 @@ NTSTATUS CreateAndWaitForThread(HANDLE hProcess, LPTHREAD_START_ROUTINE threadSt } return status; } - + +//---------------------------------------------------------------------------------- LPVOID NormalDllInjection(HANDLE hProcess, const WCHAR * dllPath) { SIZE_T memorySize = (wcslen(dllPath) + 1) * sizeof(WCHAR); @@ -438,9 +482,7 @@ LPVOID NormalDllInjection(HANDLE hProcess, const WCHAR * dllPath) GetExitCodeThread(hThread, (LPDWORD)&hModule); if (!hModule) - { g_log.LogError(L"DLL INJECTION: Failed load library!"); - } CloseHandle(hThread); } @@ -458,62 +500,75 @@ LPVOID NormalDllInjection(HANDLE hProcess, const WCHAR * dllPath) return hModule; } - + +//---------------------------------------------------------------------------------- DWORD GetAddressOfEntryPoint(BYTE * dllMemory) { PIMAGE_NT_HEADERS ntHeaders = RtlImageNtHeader(dllMemory); return HEADER_FIELD(ntHeaders, AddressOfEntryPoint); } - -LPVOID StealthDllInjection(HANDLE hProcess, const WCHAR * dllPath, BYTE * dllMemory) + +//---------------------------------------------------------------------------------- +LPVOID StealthDllInjection( + HANDLE hProcess, + const WCHAR *dllPath, + BYTE *dllMemory) { - LPVOID remoteImageBaseOfInjectedDll = 0; - - if (dllMemory) + LPVOID remoteImageBaseOfInjectedDll = nullptr; + do { + if (dllMemory == nullptr) + break; + remoteImageBaseOfInjectedDll = MapModuleToProcess(hProcess, dllMemory, false); - if (remoteImageBaseOfInjectedDll) - { + if (remoteImageBaseOfInjectedDll == nullptr) + break; - DWORD_PTR entryPoint = (DWORD_PTR)GetAddressOfEntryPoint(dllMemory); + DWORD_PTR entryPoint = (DWORD_PTR)GetAddressOfEntryPoint(dllMemory); - if (entryPoint) - { - DWORD_PTR dllMain = entryPoint + (DWORD_PTR)remoteImageBaseOfInjectedDll; + if (entryPoint == 0) + break; - g_log.LogInfo(L"DLL INJECTION: Starting thread at RVA %p VA %p!", entryPoint, dllMain); + DWORD_PTR dllMain = entryPoint + (DWORD_PTR)remoteImageBaseOfInjectedDll; - HANDLE hThread; - NTSTATUS status = CreateAndWaitForThread(hProcess, (LPTHREAD_START_ROUTINE)dllMain, remoteImageBaseOfInjectedDll, &hThread, TRUE); - if (NT_SUCCESS(status)) - { - CloseHandle(hThread); - } - else - { - g_log.LogError(L"DLL INJECTION: Failed to start thread: 0x%08X!", status); - } - } - } + g_log.LogInfo(L"DLL INJECTION: Starting thread at RVA %p VA %p!", entryPoint, dllMain); + + HANDLE hThread; + NTSTATUS status = CreateAndWaitForThread( + hProcess, + (LPTHREAD_START_ROUTINE)dllMain, + remoteImageBaseOfInjectedDll, + &hThread, + TRUE); + + if (NT_SUCCESS(status)) + CloseHandle(hThread); else - { - g_log.LogError(L"DLL INJECTION: Failed to map image of %s!", dllPath); - } - } + g_log.LogError(L"DLL INJECTION: Failed to start thread: 0x%08X!", status); + } while (false); + + + if (remoteImageBaseOfInjectedDll == nullptr) + g_log.LogError(L"DLL INJECTION: Failed to map image of %s!", dllPath); return remoteImageBaseOfInjectedDll; } - -void injectDll(DWORD targetPid, const WCHAR * dllPath) + +//---------------------------------------------------------------------------------- +void injectDll(DWORD targetPid, const WCHAR *dllPath) { - HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, 0, targetPid); + HANDLE hProcess = OpenProcess( + PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, + 0, + targetPid); + if (hProcess == nullptr) { g_log.LogError(L"DLL INJECTION: Cannot open process handle %d", targetPid); return; } - BYTE* dllMemory = ReadFileToMemory(dllPath); + BYTE *dllMemory = ReadFileToMemory(dllPath); if (dllMemory == nullptr) { g_log.LogError(L"DLL INJECTION: Failed to read file %s!", dllPath); @@ -531,11 +586,10 @@ void injectDll(DWORD targetPid, const WCHAR * dllPath) } bool processIsWow64 = scl::IsWow64Process(hProcess); - if ((scl::IsWindows64() && - ((processIsWow64 && ntHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) || - (!processIsWow64 && ntHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64))) - || - (!scl::IsWindows64() && ntHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)) + if ( ( scl::IsWindows64() + && ( (processIsWow64 && ntHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) + || (!processIsWow64 && ntHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) ) ) + || (!scl::IsWindows64() && ntHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)) { g_log.LogError(L"DLL INJECTION: DLL %s is of wrong bitness for process!", dllPath); free(dllMemory); @@ -596,78 +650,87 @@ void injectDll(DWORD targetPid, const WCHAR * dllPath) free(dllMemory); CloseHandle(hProcess); } - -BYTE * ReadFileToMemory(const WCHAR * targetFilePath) + +//---------------------------------------------------------------------------------- +BYTE *ReadFileToMemory(const WCHAR *targetFilePath) { HANDLE hFile; DWORD dwBytesRead; DWORD FileSize; - BYTE* FilePtr = 0; - - hFile = CreateFileW(targetFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); - if (hFile != INVALID_HANDLE_VALUE) - { - FileSize = GetFileSize(hFile, NULL); - if (FileSize > 0) + BYTE *FilePtr = nullptr; + + hFile = CreateFileW( + targetFilePath, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + 0); + if (hFile == INVALID_HANDLE_VALUE) + return nullptr; + + FileSize = GetFileSize(hFile, NULL); + if (FileSize > 0) + { + FilePtr = (BYTE *)calloc(FileSize + 1, 1); + if (FilePtr != nullptr) { - FilePtr = (BYTE*)calloc(FileSize + 1, 1); - if (FilePtr) + if (!ReadFile(hFile, (LPVOID)FilePtr, FileSize, &dwBytesRead, NULL)) { - if (!ReadFile(hFile, (LPVOID)FilePtr, FileSize, &dwBytesRead, NULL)) - { - free(FilePtr); - FilePtr = 0; - } - + free(FilePtr); + FilePtr = nullptr; } } - CloseHandle(hFile); } + CloseHandle(hFile); return FilePtr; } - + +//---------------------------------------------------------------------------------- void FillHookDllData(HANDLE hProcess, HOOK_DLL_DATA *hdd) { - hdd->EnablePebBeingDebugged = g_settings.opts().fixPebBeingDebugged; - hdd->EnablePebHeapFlags = g_settings.opts().fixPebHeapFlags; - hdd->EnablePebNtGlobalFlag = g_settings.opts().fixPebNtGlobalFlag; - hdd->EnablePebStartupInfo = g_settings.opts().fixPebStartupInfo; - hdd->EnablePebOsBuildNumber = g_settings.opts().fixPebOsBuildNumber; - hdd->EnableOutputDebugStringHook = g_settings.opts().hookOutputDebugStringA; - hdd->EnableNtSetInformationThreadHook = g_settings.opts().hookNtSetInformationThread; - hdd->EnableNtQueryInformationProcessHook = g_settings.opts().hookNtQueryInformationProcess; - hdd->EnableNtQuerySystemInformationHook = g_settings.opts().hookNtQuerySystemInformation; - hdd->EnableNtQueryObjectHook = g_settings.opts().hookNtQueryObject; - hdd->EnableNtYieldExecutionHook = g_settings.opts().hookNtYieldExecution; - hdd->EnableNtCloseHook = g_settings.opts().hookNtClose; - hdd->EnableNtCreateThreadExHook = g_settings.opts().hookNtCreateThreadEx; - hdd->EnablePreventThreadCreation = g_settings.opts().preventThreadCreation; - hdd->EnableNtUserBlockInputHook = g_settings.opts().hookNtUserBlockInput; - hdd->EnableNtUserFindWindowExHook = g_settings.opts().hookNtUserFindWindowEx; - hdd->EnableNtUserBuildHwndListHook = g_settings.opts().hookNtUserBuildHwndList; - hdd->EnableNtUserQueryWindowHook = g_settings.opts().hookNtUserQueryWindow; - hdd->EnableNtUserGetForegroundWindowHook = g_settings.opts().hookNtUserGetForegroundWindow; - hdd->EnableNtSetDebugFilterStateHook = g_settings.opts().hookNtSetDebugFilterState; - hdd->EnableGetTickCountHook = g_settings.opts().hookGetTickCount; - hdd->EnableGetTickCount64Hook = g_settings.opts().hookGetTickCount64; - hdd->EnableGetLocalTimeHook = g_settings.opts().hookGetLocalTime; - hdd->EnableGetSystemTimeHook = g_settings.opts().hookGetSystemTime; - hdd->EnableNtQuerySystemTimeHook = g_settings.opts().hookNtQuerySystemTime; - hdd->EnableNtQueryPerformanceCounterHook = g_settings.opts().hookNtQueryPerformanceCounter; - hdd->EnableNtSetInformationProcessHook = g_settings.opts().hookNtSetInformationProcess; - - hdd->EnableNtGetContextThreadHook = g_settings.opts().hookNtGetContextThread; - hdd->EnableNtSetContextThreadHook = g_settings.opts().hookNtSetContextThread; - hdd->EnableNtContinueHook = g_settings.opts().hookNtContinue | g_settings.opts().killAntiAttach; - hdd->EnableKiUserExceptionDispatcherHook = g_settings.opts().hookKiUserExceptionDispatcher; - hdd->EnableMalwareRunPeUnpacker = g_settings.opts().malwareRunpeUnpacker; - - hdd->isKernel32Hooked = FALSE; - hdd->isNtdllHooked = FALSE; - hdd->isUserDllHooked = FALSE; + hdd->EnablePebBeingDebugged = g_settings.opts().fixPebBeingDebugged; + hdd->EnablePebHeapFlags = g_settings.opts().fixPebHeapFlags; + hdd->EnablePebNtGlobalFlag = g_settings.opts().fixPebNtGlobalFlag; + hdd->EnablePebStartupInfo = g_settings.opts().fixPebStartupInfo; + hdd->EnablePebOsBuildNumber = g_settings.opts().fixPebOsBuildNumber; + hdd->EnableOutputDebugStringHook = g_settings.opts().hookOutputDebugStringA; + hdd->EnableNtSetInformationThreadHook = g_settings.opts().hookNtSetInformationThread; + hdd->EnableNtQueryInformationProcessHook = g_settings.opts().hookNtQueryInformationProcess; + hdd->EnableNtQuerySystemInformationHook = g_settings.opts().hookNtQuerySystemInformation; + hdd->EnableNtQueryObjectHook = g_settings.opts().hookNtQueryObject; + hdd->EnableNtYieldExecutionHook = g_settings.opts().hookNtYieldExecution; + hdd->EnableNtCloseHook = g_settings.opts().hookNtClose; + hdd->EnableNtCreateThreadExHook = g_settings.opts().hookNtCreateThreadEx; + hdd->EnablePreventThreadCreation = g_settings.opts().preventThreadCreation; + hdd->EnableNtUserBlockInputHook = g_settings.opts().hookNtUserBlockInput; + hdd->EnableNtUserFindWindowExHook = g_settings.opts().hookNtUserFindWindowEx; + hdd->EnableNtUserBuildHwndListHook = g_settings.opts().hookNtUserBuildHwndList; + hdd->EnableNtUserQueryWindowHook = g_settings.opts().hookNtUserQueryWindow; + hdd->EnableNtUserGetForegroundWindowHook = g_settings.opts().hookNtUserGetForegroundWindow; + hdd->EnableNtSetDebugFilterStateHook = g_settings.opts().hookNtSetDebugFilterState; + hdd->EnableGetTickCountHook = g_settings.opts().hookGetTickCount; + hdd->EnableGetTickCount64Hook = g_settings.opts().hookGetTickCount64; + hdd->EnableGetLocalTimeHook = g_settings.opts().hookGetLocalTime; + hdd->EnableGetSystemTimeHook = g_settings.opts().hookGetSystemTime; + hdd->EnableNtQuerySystemTimeHook = g_settings.opts().hookNtQuerySystemTime; + hdd->EnableNtQueryPerformanceCounterHook = g_settings.opts().hookNtQueryPerformanceCounter; + hdd->EnableNtSetInformationProcessHook = g_settings.opts().hookNtSetInformationProcess; + + hdd->EnableNtGetContextThreadHook = g_settings.opts().hookNtGetContextThread; + hdd->EnableNtSetContextThreadHook = g_settings.opts().hookNtSetContextThread; + hdd->EnableNtContinueHook = g_settings.opts().hookNtContinue | g_settings.opts().killAntiAttach; + hdd->EnableKiUserExceptionDispatcherHook = g_settings.opts().hookKiUserExceptionDispatcher; + hdd->EnableMalwareRunPeUnpacker = g_settings.opts().malwareRunpeUnpacker; + + hdd->isKernel32Hooked = FALSE; + hdd->isNtdllHooked = FALSE; + hdd->isUserDllHooked = FALSE; } - + +//---------------------------------------------------------------------------------- bool RemoveDebugPrivileges(HANDLE hProcess) { TOKEN_PRIVILEGES Debug_Privileges; @@ -688,67 +751,61 @@ bool RemoveDebugPrivileges(HANDLE hProcess) return false; } - -#define DbgBreakPoint_FUNC_SIZE 2 + +//---------------------------------------------------------------------------------- +#define DbgBreakPoint_FUNC_SIZE 2 #ifdef _WIN64 -#define DbgUiRemoteBreakin_FUNC_SIZE 0x42 -#define NtContinue_FUNC_SIZE 11 + #define DbgUiRemoteBreakin_FUNC_SIZE 0x42 + #define NtContinue_FUNC_SIZE 11 #else -#define DbgUiRemoteBreakin_FUNC_SIZE 0x54 -#define NtContinue_FUNC_SIZE 0x18 + #define DbgUiRemoteBreakin_FUNC_SIZE 0x54 + #define NtContinue_FUNC_SIZE 0x18 #endif - -typedef struct _PATCH_FUNC { - PCHAR funcName; - PVOID funcAddr; - SIZE_T funcSize; -} PATCH_FUNC; - - -PATCH_FUNC patchFunctions[] = { - { - "DbgBreakPoint", 0, DbgBreakPoint_FUNC_SIZE - }, - { - "DbgUiRemoteBreakin", 0, DbgUiRemoteBreakin_FUNC_SIZE - }, - { - "NtContinue", 0, NtContinue_FUNC_SIZE - } -}; - + +//---------------------------------------------------------------------------------- bool ApplyAntiAntiAttach(DWORD targetPid) { bool result = false; - HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, 0, targetPid); + HANDLE hProcess = OpenProcess( + PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, + 0, + targetPid); - if (!hProcess) + if (hProcess == NULL) return result; - HMODULE hMod = GetModuleHandleW(L"ntdll.dll"); - - for (ULONG i = 0; i < _countof(patchFunctions); i++) - { - patchFunctions[i].funcAddr = (PVOID)GetProcAddress(hMod, patchFunctions[i].funcName); - } - - for (ULONG i = 0; i < _countof(patchFunctions); i++) - { + HMODULE hMod = GetModuleHandleW(L"ntdll.dll"); + + struct PATCH_FUNC + { + PCHAR funcName; + SIZE_T funcSize; + } static const patchFunctions[] = + { + { "DbgBreakPoint", DbgBreakPoint_FUNC_SIZE }, + { "DbgUiRemoteBreakin", DbgUiRemoteBreakin_FUNC_SIZE }, + { "NtContinue", NtContinue_FUNC_SIZE } + }; + + ULONG i; + for (i = 0; i < _countof(patchFunctions); ++i) + { + auto funcAddr = (PVOID)GetProcAddress(hMod, patchFunctions[i].funcName); + if (funcAddr == nullptr) + break; + ULONG oldProtection; - if (VirtualProtectEx(hProcess, patchFunctions[i].funcAddr, patchFunctions[i].funcSize, PAGE_EXECUTE_READWRITE, &oldProtection) && - WriteProcessMemory(hProcess, patchFunctions[i].funcAddr, patchFunctions[i].funcAddr, patchFunctions[i].funcSize, nullptr)) - { - VirtualProtectEx(hProcess, patchFunctions[i].funcAddr, patchFunctions[i].funcSize, oldProtection, &oldProtection); - result = true; - } - else - { - result = false; + if (!VirtualProtectEx(hProcess, funcAddr, patchFunctions[i].funcSize, PAGE_EXECUTE_READWRITE, &oldProtection)) + break; + + bool ok = WriteProcessMemory(hProcess, funcAddr, funcAddr, patchFunctions[i].funcSize, nullptr) != FALSE; + + VirtualProtectEx(hProcess, funcAddr, patchFunctions[i].funcSize, oldProtection, &oldProtection); + if (!ok) break; - } } CloseHandle(hProcess); - return result; + return i == _countof(patchFunctions); } diff --git a/PluginGeneric/Injector.h b/PluginGeneric/Injector.h index 19d2738e..2468ce5b 100644 --- a/PluginGeneric/Injector.h +++ b/PluginGeneric/Injector.h @@ -7,18 +7,21 @@ #define HEADER_FIELD(NtHeaders, Field) (IMAGE64(NtHeaders) \ ? ((PIMAGE_NT_HEADERS64)(NtHeaders))->OptionalHeader.Field \ - : ((PIMAGE_NT_HEADERS32)(NtHeaders))->OptionalHeader.Field) + : ((PIMAGE_NT_HEADERS32)(NtHeaders))->OptionalHeader.Field) + #define THUNK_VAL(NtHeaders, Ptr, Val) (IMAGE64(NtHeaders) \ ? ((PIMAGE_THUNK_DATA64)(Ptr))->Val \ : ((PIMAGE_THUNK_DATA32)(Ptr))->Val) - + +//---------------------------------------------------------------------------------- typedef struct _THREAD_SUSPEND_INFO { HANDLE ThreadId; HANDLE ThreadHandle; NTSTATUS SuspendStatus; } THREAD_SUSPEND_INFO, *PTHREAD_SUSPEND_INFO; - + +//---------------------------------------------------------------------------------- typedef struct _PROCESS_SUSPEND_INFO { HANDLE ProcessId; @@ -26,14 +29,15 @@ typedef struct _PROCESS_SUSPEND_INFO ULONG NumThreads; PTHREAD_SUSPEND_INFO ThreadSuspendInfo; // THREAD_SUSPEND_INFO[NumThreads] } PROCESS_SUSPEND_INFO, *PPROCESS_SUSPEND_INFO; - + +//---------------------------------------------------------------------------------- void ReadNtApiInformation(HOOK_DLL_DATA *hdd); void InstallAntiAttachHook(); void startInjectionProcess(HANDLE hProcess, HOOK_DLL_DATA *hdd, BYTE * dllMemory, bool newProcess); void startInjection(DWORD targetPid, HOOK_DLL_DATA *hdd, const WCHAR * dllPath, bool newProcess); void injectDll(DWORD targetPid, const WCHAR * dllPath); -BYTE * ReadFileToMemory(const WCHAR * targetFilePath); +BYTE *ReadFileToMemory(const WCHAR * targetFilePath); void FillHookDllData(HANDLE hProcess, HOOK_DLL_DATA * data); bool StartFixBeingDebugged(DWORD targetPid, bool setToNull); bool ApplyAntiAntiAttach(DWORD targetPid); diff --git a/PluginGeneric/OptionsDialog.cpp b/PluginGeneric/OptionsDialog.cpp index 98a33590..8fbcf817 100644 --- a/PluginGeneric/OptionsDialog.cpp +++ b/PluginGeneric/OptionsDialog.cpp @@ -6,35 +6,34 @@ #include #include #include - + #include "..\PluginGeneric\Injector.h" #ifdef OLLY1 -#pragma pack(push) -#include -#pragma pack(pop) -#include "..\ScyllaHideOlly1Plugin\resource.h" - + #pragma pack(push) + #include + #pragma pack(pop) + #include "..\ScyllaHideOlly1Plugin\resource.h" #elif defined(OLLY2) -#pragma pack(push) -#include -#pragma pack(pop) -#include "..\ScyllaHideOlly2Plugin\resource.h" - -#elif defined(__IDP__) -//#define BUILD_IDA_64BIT 1 -#include -#include -#include -#include "..\ScyllaHideIDAProPlugin\IdaServerClient.h" -#include "..\PluginGeneric\AttachDialog.h" -#include "..\ScyllaHideIDAProPlugin\resource.h" - + #pragma pack(push) + #include + #pragma pack(pop) + #include "..\ScyllaHideOlly2Plugin\resource.h" +#elif defined(__IDP__) + #pragma warning(push) + #pragma warning(disable: 4244 4267) + #include + #include + #include + #pragma warning(pop) + #include "..\ScyllaHideIDAProPlugin\IdaServerClient.h" + #include "..\PluginGeneric\AttachDialog.h" + #include "..\ScyllaHideIDAProPlugin\resource.h" #elif defined(X64DBG) -#include -#include "..\ScyllaHideX64DBGPlugin\resource.h" -#define IDC_EXCEPTION_ALL 123432 -#define IDC_SELECT_EXCEPTIONS 23949 + #include + #include "..\ScyllaHideX64DBGPlugin\resource.h" + #define IDC_EXCEPTION_ALL 123432 + #define IDC_SELECT_EXCEPTIONS 23949 #endif #define SCYLLA_MAX_TOOLTIP_WIDTH 500 @@ -55,8 +54,11 @@ wchar_t DllPathForInjection[MAX_PATH] = { 0 }; #endif void createExceptionWindow(HWND hwnd); - -static void UpdateOptionsExceptions(HWND hWnd, const scl::Settings *settings) + +//---------------------------------------------------------------------------------- +static void UpdateOptionsExceptions( + HWND hWnd, + const scl::Settings *settings) { auto opts = &settings->opts(); @@ -75,7 +77,8 @@ static void UpdateOptionsExceptions(HWND hWnd, const scl::Settings *settings) opts->handleExceptionRip; #elif defined(__IDP__) - auto check = opts->handleExceptionNoncontinuableException && + auto check = + opts->handleExceptionNoncontinuableException && opts->handleExceptionPrint && opts->handleExceptionAssertionFailure && opts->handleExceptionRip; @@ -86,8 +89,11 @@ static void UpdateOptionsExceptions(HWND hWnd, const scl::Settings *settings) CheckDlgButton(hWnd, IDC_EXCEPTION_ALL, check ? BST_CHECKED : BST_UNCHECKED); } - -static void UpdateOptions(HWND hWnd, const scl::Settings *settings) + +//---------------------------------------------------------------------------------- +static void UpdateOptions( + HWND hWnd, + const scl::Settings *settings) { auto opts = &settings->opts(); @@ -173,7 +179,7 @@ static void UpdateOptions(HWND hWnd, const scl::Settings *settings) CheckDlgButton(hWnd, IDC_AUTOSTARTSERVER, opts->idaAutoStartServer); SetDlgItemTextW(hWnd, IDC_SERVERPORT, opts->idaServerPort.c_str()); -#ifdef BUILD_IDA_64BIT +#ifdef __EA64__ EnableWindow(GetDlgItem(hWnd, IDC_AUTOSTARTSERVER), scl::IsWindows64()); #else EnableWindow(GetDlgItem(hWnd, IDC_AUTOSTARTSERVER), FALSE); @@ -183,86 +189,89 @@ static void UpdateOptions(HWND hWnd, const scl::Settings *settings) #endif UpdateOptionsExceptions(hWnd, settings); -} +} +//---------------------------------------------------------------------------------- void SaveOptions(HWND hWnd, scl::Settings *settings) { auto opts = &settings->opts(); - opts->fixPebBeingDebugged = (IsDlgButtonChecked(hWnd, IDC_PEBBEINGDEBUGGED) == BST_CHECKED); - opts->fixPebHeapFlags = (IsDlgButtonChecked(hWnd, IDC_PEBHEAPFLAGS) == BST_CHECKED); - opts->fixPebNtGlobalFlag = (IsDlgButtonChecked(hWnd, IDC_PEBNTGLOBALFLAG) == BST_CHECKED); - opts->fixPebStartupInfo = (IsDlgButtonChecked(hWnd, IDC_PEBSTARTUPINFO) == BST_CHECKED); - opts->fixPebOsBuildNumber = (IsDlgButtonChecked(hWnd, IDC_PEBOSBUILDNUMBER) == BST_CHECKED); - opts->hookNtSetInformationThread = (IsDlgButtonChecked(hWnd, IDC_NTSETINFORMATIONTHREAD) == BST_CHECKED); - opts->hookNtSetInformationProcess = (IsDlgButtonChecked(hWnd, IDC_NTSETINFORMATIONPROCESS) == BST_CHECKED); - opts->hookNtQuerySystemInformation = (IsDlgButtonChecked(hWnd, IDC_NTQUERYSYSTEMINFORMATION) == BST_CHECKED); - opts->hookNtQueryInformationProcess = (IsDlgButtonChecked(hWnd, IDC_NTQUERYINFORMATIONPROCESS) == BST_CHECKED); - opts->hookNtQueryObject = (IsDlgButtonChecked(hWnd, IDC_NTQUERYOBJECT) == BST_CHECKED); - opts->hookNtYieldExecution = (IsDlgButtonChecked(hWnd, IDC_NTYIELDEXECUTION) == BST_CHECKED); - opts->hookOutputDebugStringA = (IsDlgButtonChecked(hWnd, IDC_OUTPUTDEBUGSTRINGA) == BST_CHECKED); - opts->hookNtGetContextThread = (IsDlgButtonChecked(hWnd, IDC_NTGETCONTEXTTHREAD) == BST_CHECKED); - opts->hookNtSetContextThread = (IsDlgButtonChecked(hWnd, IDC_NTSETCONTEXTTHREAD) == BST_CHECKED); - opts->hookNtContinue = (IsDlgButtonChecked(hWnd, IDC_NTCONTINUE) == BST_CHECKED); - opts->hookKiUserExceptionDispatcher = (IsDlgButtonChecked(hWnd, IDC_KIUED) == BST_CHECKED); - opts->hookNtUserFindWindowEx = (IsDlgButtonChecked(hWnd, IDC_NTUSERFINDWINDOWEX) == BST_CHECKED); - opts->hookNtUserBlockInput = (IsDlgButtonChecked(hWnd, IDC_NTUSERBLOCKINPUT) == BST_CHECKED); - opts->hookNtUserBuildHwndList = (IsDlgButtonChecked(hWnd, IDC_NTUSERBUILDHWNDLIST) == BST_CHECKED); - opts->hookNtUserQueryWindow = (IsDlgButtonChecked(hWnd, IDC_NTUSERQUERYWINDOW) == BST_CHECKED); - opts->hookNtUserGetForegroundWindow = (IsDlgButtonChecked(hWnd, IDC_NTUSERGETFOREGROUNDWINDOW) == BST_CHECKED); - opts->hookNtSetDebugFilterState = (IsDlgButtonChecked(hWnd, IDC_NTSETDEBUGFILTERSTATE) == BST_CHECKED); - opts->hookNtClose = (IsDlgButtonChecked(hWnd, IDC_NTCLOSE) == BST_CHECKED); - opts->hookNtCreateThreadEx = (IsDlgButtonChecked(hWnd, IDC_NTCREATETHREADEX) == BST_CHECKED); - opts->preventThreadCreation = (IsDlgButtonChecked(hWnd, IDC_PREVENTTHREADCREATION) == BST_CHECKED); - opts->malwareRunpeUnpacker = (IsDlgButtonChecked(hWnd, IDC_RUNPE) == BST_CHECKED); - opts->removeDebugPrivileges = (IsDlgButtonChecked(hWnd, IDC_REMOVEDEBUGPRIV) == BST_CHECKED); - opts->dllStealth = (IsDlgButtonChecked(hWnd, IDC_DLLSTEALTH) == BST_CHECKED); - opts->dllNormal = (IsDlgButtonChecked(hWnd, IDC_DLLNORMAL) == BST_CHECKED); - opts->dllUnload = (IsDlgButtonChecked(hWnd, IDC_DLLUNLOAD) == BST_CHECKED); - opts->hookGetTickCount = (IsDlgButtonChecked(hWnd, IDC_GETTICKCOUNT) == BST_CHECKED); - opts->hookGetTickCount64 = (IsDlgButtonChecked(hWnd, IDC_GETTICKCOUNT64) == BST_CHECKED); - opts->hookGetLocalTime = (IsDlgButtonChecked(hWnd, IDC_GETLOCALTIME) == BST_CHECKED); - opts->hookGetSystemTime = (IsDlgButtonChecked(hWnd, IDC_GETSYSTEMTIME) == BST_CHECKED); - opts->hookNtQuerySystemTime = (IsDlgButtonChecked(hWnd, IDC_NTQUERYSYSTEMTIME) == BST_CHECKED); - opts->hookNtQueryPerformanceCounter = (IsDlgButtonChecked(hWnd, IDC_NTQUERYPERFCOUNTER) == BST_CHECKED); - opts->killAntiAttach = (IsDlgButtonChecked(hWnd, IDC_KILLANTIATTACH) == BST_CHECKED); + opts->fixPebBeingDebugged = (IsDlgButtonChecked(hWnd, IDC_PEBBEINGDEBUGGED) == BST_CHECKED); + opts->fixPebHeapFlags = (IsDlgButtonChecked(hWnd, IDC_PEBHEAPFLAGS) == BST_CHECKED); + opts->fixPebNtGlobalFlag = (IsDlgButtonChecked(hWnd, IDC_PEBNTGLOBALFLAG) == BST_CHECKED); + opts->fixPebStartupInfo = (IsDlgButtonChecked(hWnd, IDC_PEBSTARTUPINFO) == BST_CHECKED); + opts->fixPebOsBuildNumber = (IsDlgButtonChecked(hWnd, IDC_PEBOSBUILDNUMBER) == BST_CHECKED); + opts->hookNtSetInformationThread = (IsDlgButtonChecked(hWnd, IDC_NTSETINFORMATIONTHREAD) == BST_CHECKED); + opts->hookNtSetInformationProcess = (IsDlgButtonChecked(hWnd, IDC_NTSETINFORMATIONPROCESS) == BST_CHECKED); + opts->hookNtQuerySystemInformation = (IsDlgButtonChecked(hWnd, IDC_NTQUERYSYSTEMINFORMATION) == BST_CHECKED); + opts->hookNtQueryInformationProcess = (IsDlgButtonChecked(hWnd, IDC_NTQUERYINFORMATIONPROCESS) == BST_CHECKED); + opts->hookNtQueryObject = (IsDlgButtonChecked(hWnd, IDC_NTQUERYOBJECT) == BST_CHECKED); + opts->hookNtYieldExecution = (IsDlgButtonChecked(hWnd, IDC_NTYIELDEXECUTION) == BST_CHECKED); + opts->hookOutputDebugStringA = (IsDlgButtonChecked(hWnd, IDC_OUTPUTDEBUGSTRINGA) == BST_CHECKED); + opts->hookNtGetContextThread = (IsDlgButtonChecked(hWnd, IDC_NTGETCONTEXTTHREAD) == BST_CHECKED); + opts->hookNtSetContextThread = (IsDlgButtonChecked(hWnd, IDC_NTSETCONTEXTTHREAD) == BST_CHECKED); + opts->hookNtContinue = (IsDlgButtonChecked(hWnd, IDC_NTCONTINUE) == BST_CHECKED); + opts->hookKiUserExceptionDispatcher = (IsDlgButtonChecked(hWnd, IDC_KIUED) == BST_CHECKED); + opts->hookNtUserFindWindowEx = (IsDlgButtonChecked(hWnd, IDC_NTUSERFINDWINDOWEX) == BST_CHECKED); + opts->hookNtUserBlockInput = (IsDlgButtonChecked(hWnd, IDC_NTUSERBLOCKINPUT) == BST_CHECKED); + opts->hookNtUserBuildHwndList = (IsDlgButtonChecked(hWnd, IDC_NTUSERBUILDHWNDLIST) == BST_CHECKED); + opts->hookNtUserQueryWindow = (IsDlgButtonChecked(hWnd, IDC_NTUSERQUERYWINDOW) == BST_CHECKED); + opts->hookNtUserGetForegroundWindow = (IsDlgButtonChecked(hWnd, IDC_NTUSERGETFOREGROUNDWINDOW) == BST_CHECKED); + opts->hookNtSetDebugFilterState = (IsDlgButtonChecked(hWnd, IDC_NTSETDEBUGFILTERSTATE) == BST_CHECKED); + opts->hookNtClose = (IsDlgButtonChecked(hWnd, IDC_NTCLOSE) == BST_CHECKED); + opts->hookNtCreateThreadEx = (IsDlgButtonChecked(hWnd, IDC_NTCREATETHREADEX) == BST_CHECKED); + opts->preventThreadCreation = (IsDlgButtonChecked(hWnd, IDC_PREVENTTHREADCREATION) == BST_CHECKED); + opts->malwareRunpeUnpacker = (IsDlgButtonChecked(hWnd, IDC_RUNPE) == BST_CHECKED); + opts->removeDebugPrivileges = (IsDlgButtonChecked(hWnd, IDC_REMOVEDEBUGPRIV) == BST_CHECKED); + opts->dllStealth = (IsDlgButtonChecked(hWnd, IDC_DLLSTEALTH) == BST_CHECKED); + opts->dllNormal = (IsDlgButtonChecked(hWnd, IDC_DLLNORMAL) == BST_CHECKED); + opts->dllUnload = (IsDlgButtonChecked(hWnd, IDC_DLLUNLOAD) == BST_CHECKED); + opts->hookGetTickCount = (IsDlgButtonChecked(hWnd, IDC_GETTICKCOUNT) == BST_CHECKED); + opts->hookGetTickCount64 = (IsDlgButtonChecked(hWnd, IDC_GETTICKCOUNT64) == BST_CHECKED); + opts->hookGetLocalTime = (IsDlgButtonChecked(hWnd, IDC_GETLOCALTIME) == BST_CHECKED); + opts->hookGetSystemTime = (IsDlgButtonChecked(hWnd, IDC_GETSYSTEMTIME) == BST_CHECKED); + opts->hookNtQuerySystemTime = (IsDlgButtonChecked(hWnd, IDC_NTQUERYSYSTEMTIME) == BST_CHECKED); + opts->hookNtQueryPerformanceCounter = (IsDlgButtonChecked(hWnd, IDC_NTQUERYPERFCOUNTER) == BST_CHECKED); + opts->killAntiAttach = (IsDlgButtonChecked(hWnd, IDC_KILLANTIATTACH) == BST_CHECKED); #ifdef OLLY1 - opts->ollyRemoveEpBreak = (IsDlgButtonChecked(hWnd, IDC_DELEPBREAK) == BST_CHECKED); - opts->ollyFixBugs = (IsDlgButtonChecked(hWnd, IDC_FIXOLLY) == BST_CHECKED); - opts->ollyX64Fix = (IsDlgButtonChecked(hWnd, IDC_X64FIX) == BST_CHECKED); - opts->ollyBreakOnTls = (IsDlgButtonChecked(hWnd, IDC_BREAKTLS) == BST_CHECKED); - opts->ollySkipEpOutsideCode = (IsDlgButtonChecked(hWnd, IDC_SKIPEPOUTSIDE) == BST_CHECKED); - opts->ollyIgnoreBadPeImage = (IsDlgButtonChecked(hWnd, IDC_BADPEIMAGE) == BST_CHECKED); - opts->ollyAdvancedGoto = (IsDlgButtonChecked(hWnd, IDC_ADVANCEDGOTO) == BST_CHECKED); - opts->ollySkipCompressedDoAnalyze = (IsDlgButtonChecked(hWnd, IDC_COMPRESSEDANALYZE) == BST_CHECKED); - opts->ollySkipCompressedDoNothing = (IsDlgButtonChecked(hWnd, IDC_COMPRESSEDNOTHING) == BST_CHECKED); - opts->ollySkipLoadDllDoLoad = (IsDlgButtonChecked(hWnd, IDC_LOADDLLLOAD) == BST_CHECKED); - opts->ollySkipLoadDllDoNothing = (IsDlgButtonChecked(hWnd, IDC_LOADDLLNOTHING) == BST_CHECKED); - opts->ollyAdvancedInfobar = (IsDlgButtonChecked(hWnd, IDC_ADVANCEDINFOBAR) == BST_CHECKED); - - opts->ollyWindowTitle = scl::GetDlgItemTextW(hWnd, IDC_OLLYTITLE); + opts->ollyRemoveEpBreak = (IsDlgButtonChecked(hWnd, IDC_DELEPBREAK) == BST_CHECKED); + opts->ollyFixBugs = (IsDlgButtonChecked(hWnd, IDC_FIXOLLY) == BST_CHECKED); + opts->ollyX64Fix = (IsDlgButtonChecked(hWnd, IDC_X64FIX) == BST_CHECKED); + opts->ollyBreakOnTls = (IsDlgButtonChecked(hWnd, IDC_BREAKTLS) == BST_CHECKED); + opts->ollySkipEpOutsideCode = (IsDlgButtonChecked(hWnd, IDC_SKIPEPOUTSIDE) == BST_CHECKED); + opts->ollyIgnoreBadPeImage = (IsDlgButtonChecked(hWnd, IDC_BADPEIMAGE) == BST_CHECKED); + opts->ollyAdvancedGoto = (IsDlgButtonChecked(hWnd, IDC_ADVANCEDGOTO) == BST_CHECKED); + opts->ollySkipCompressedDoAnalyze = (IsDlgButtonChecked(hWnd, IDC_COMPRESSEDANALYZE) == BST_CHECKED); + opts->ollySkipCompressedDoNothing = (IsDlgButtonChecked(hWnd, IDC_COMPRESSEDNOTHING) == BST_CHECKED); + opts->ollySkipLoadDllDoLoad = (IsDlgButtonChecked(hWnd, IDC_LOADDLLLOAD) == BST_CHECKED); + opts->ollySkipLoadDllDoNothing = (IsDlgButtonChecked(hWnd, IDC_LOADDLLNOTHING) == BST_CHECKED); + opts->ollyAdvancedInfobar = (IsDlgButtonChecked(hWnd, IDC_ADVANCEDINFOBAR) == BST_CHECKED); + + opts->ollyWindowTitle = scl::GetDlgItemTextW(hWnd, IDC_OLLYTITLE); SetWindowTextW(hwmain, opts->ollyWindowTitle.c_str()); #elif defined(OLLY2) - opts->ollyWindowTitle = scl::GetDlgItemTextW(hWnd, IDC_OLLYTITLE); + opts->ollyWindowTitle = scl::GetDlgItemTextW(hWnd, IDC_OLLYTITLE); SetWindowTextW(hwollymain, opts->ollyWindowTitle.c_str()); #elif defined(__IDP__) - opts->idaAutoStartServer = (IsDlgButtonChecked(hWnd, IDC_AUTOSTARTSERVER) == BST_CHECKED); - opts->idaServerPort = scl::GetDlgItemTextW(hWnd, IDC_SERVERPORT); + opts->idaAutoStartServer = (IsDlgButtonChecked(hWnd, IDC_AUTOSTARTSERVER) == BST_CHECKED); + opts->idaServerPort = scl::GetDlgItemTextW(hWnd, IDC_SERVERPORT); #endif settings->Save(); } - + +//---------------------------------------------------------------------------------- HWND CreateTooltips(HWND hDlg) { static const struct { unsigned ctrl_id; const wchar_t *text; - } ctrl_tips[] = { + } ctrl_tips[] = + { { IDOK, L"Apply Settings and close the dialog" }, { IDC_PROFILES, L"Select profile" }, { IDC_SAVEPROFILE, L"Save profile" }, @@ -373,7 +382,7 @@ HWND CreateTooltips(HWND hDlg) { IDC_NTSETDEBUGFILTERSTATE, L"ScyllaHide returns always STATUS_ACCESS_DENIED.\r\n" - L"This anti-debugn measurement isn't used very often.\r\n" + L"This anti-debug measurement isn't used very often.\r\n" L"Probably you will never need this option in a real world target." }, { @@ -566,361 +575,366 @@ HWND CreateTooltips(HWND hDlg) return hToolTipWnd; } - -//options dialog proc -INT_PTR CALLBACK OptionsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) + +//---------------------------------------------------------------------------------- +// Options dialog procedure +INT_PTR CALLBACK OptionsDlgProc( + HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam) { switch (message) { - case WM_INITDIALOG: - { - // add current profile to options title - auto wstrTitle = scl::fmtw(L"[ScyllaHide Options] Profile: %s", g_settings.profile_name().c_str()); - SetWindowTextW(hDlg, wstrTitle.c_str()); - - // fill combobox with profiles - for (size_t i = 0; i < g_settings.profile_names().size(); i++) - { - SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_ADDSTRING, 0, (LPARAM)g_settings.profile_names()[i].c_str()); - if (g_settings.profile_name() == g_settings.profile_names()[i]) - SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_SETCURSEL, i, 0); - } - - UpdateOptions(hDlg, &g_settings); - -#ifdef OLLY1 - EnableWindow(GetDlgItem(hDlg, IDC_X64FIX), !scl::IsWindows64()); -#endif - - CreateTooltips(hDlg); - - break; - } - case WM_CLOSE: - { - EndDialog(hDlg, NULL); - } - break; - - case WM_COMMAND: - { - switch (LOWORD(wParam)) - { - case IDC_PROFILES: + case WM_INITDIALOG: { - if (HIWORD(wParam) != CBN_SELCHANGE) - break; - - auto profileIdx = (int)SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_GETCURSEL, 0, 0); - g_settings.SetProfile(g_settings.profile_names()[profileIdx].c_str()); - - // update options title + // add current profile to options title auto wstrTitle = scl::fmtw(L"[ScyllaHide Options] Profile: %s", g_settings.profile_name().c_str()); SetWindowTextW(hDlg, wstrTitle.c_str()); + // fill combobox with profiles + for (size_t i = 0; i < g_settings.profile_names().size(); i++) + { + SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_ADDSTRING, 0, (LPARAM)g_settings.profile_names()[i].c_str()); + if (g_settings.profile_name() == g_settings.profile_names()[i]) + SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_SETCURSEL, i, 0); + } + UpdateOptions(hDlg, &g_settings); + + #ifdef OLLY1 + EnableWindow(GetDlgItem(hDlg, IDC_X64FIX), !scl::IsWindows64()); + #endif + + CreateTooltips(hDlg); + +#ifdef __IDP__ + EnableWindow(GetDlgItem(hDlg, IDC_ATTACH), FALSE); +#endif break; } + case WM_CLOSE: + EndDialog(hDlg, NULL); + break; - case IDC_SAVEPROFILE: + case WM_COMMAND: { - if (HIWORD(wParam) != BN_CLICKED) - break; - - std::wstring wstrNewProfileName; - -#ifdef OLLY1 - std::string strNewProfileName; - strNewProfileName.resize(MAX_PATH); - if (_Gettext("New profile name?", &strNewProfileName[0], 0, 0, 0) <= 0) - break; - wstrNewProfileName = scl::wstr_conv().from_bytes(strNewProfileName.c_str()); - -#elif defined(OLLY2) - wstrNewProfileName.resize(MAX_PATH); - if (Getstring(hDlg, L"New profile name?", &wstrNewProfileName[0], wstrNewProfileName.size(), 0, 0, 0, 0, 0, 0) <= 0) - break; - wstrNewProfileName.resize(lstrlenW(wstrNewProfileName.c_str())); - -#elif defined(__IDP__) - auto szNewProfileName = askstr(0, "", "New profile name?"); - if (!szNewProfileName) - break; - wstrNewProfileName = scl::wstr_conv().from_bytes(szNewProfileName); - -#elif defined(X64DBG) - std::string strNewProfileName; - strNewProfileName.resize(GUI_MAX_LINE_SIZE); - if (!GuiGetLineWindow("New profile name?", &strNewProfileName[0])) - break; - wstrNewProfileName = scl::wstr_conv().from_bytes(strNewProfileName.c_str()); -#endif + switch (LOWORD(wParam)) + { + case IDC_PROFILES: + { + if (HIWORD(wParam) != CBN_SELCHANGE) + break; - if (!g_settings.AddProfile(wstrNewProfileName.c_str())) - break; - g_settings.SetProfile(wstrNewProfileName.c_str()); + auto profileIdx = (int)SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_GETCURSEL, 0, 0); + g_settings.SetProfile(g_settings.profile_names()[profileIdx].c_str()); - auto wstrTitle = scl::fmtw(L"[ScyllaHide Options] Profile: %s", g_settings.profile_name().c_str()); - SetWindowTextW(hDlg, wstrTitle.c_str()); + // update options title + auto wstrTitle = scl::fmtw(L"[ScyllaHide Options] Profile: %s", g_settings.profile_name().c_str()); + SetWindowTextW(hDlg, wstrTitle.c_str()); - SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_ADDSTRING, 0, (LPARAM)wstrNewProfileName.c_str()); - auto profileCount = (int)SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_GETCOUNT, 0, 0); - SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_SETCURSEL, profileCount - 1, 0); + UpdateOptions(hDlg, &g_settings); + break; + } - UpdateOptions(hDlg, &g_settings); - break; - } + case IDC_SAVEPROFILE: + { + if (HIWORD(wParam) != BN_CLICKED) + break; + + std::wstring wstrNewProfileName; + + #ifdef OLLY1 + std::string strNewProfileName; + strNewProfileName.resize(MAX_PATH); + if (_Gettext("New profile name?", &strNewProfileName[0], 0, 0, 0) <= 0) + break; + wstrNewProfileName = scl::wstr_conv().from_bytes(strNewProfileName.c_str()); + + #elif defined(OLLY2) + wstrNewProfileName.resize(MAX_PATH); + if (Getstring(hDlg, L"New profile name?", &wstrNewProfileName[0], wstrNewProfileName.size(), 0, 0, 0, 0, 0, 0) <= 0) + break; + wstrNewProfileName.resize(lstrlenW(wstrNewProfileName.c_str())); + + #elif defined(__IDP__) + qstring NewProfileName; + if (!ask_str(&NewProfileName, 0, "New profile name?")) + break; + wstrNewProfileName = scl::wstr_conv().from_bytes(NewProfileName.c_str()); + + #elif defined(X64DBG) + std::string strNewProfileName; + strNewProfileName.resize(GUI_MAX_LINE_SIZE); + if (!GuiGetLineWindow("New profile name?", &strNewProfileName[0])) + break; + wstrNewProfileName = scl::wstr_conv().from_bytes(strNewProfileName.c_str()); + #endif + + if (!g_settings.AddProfile(wstrNewProfileName.c_str())) + break; + g_settings.SetProfile(wstrNewProfileName.c_str()); + + auto wstrTitle = scl::fmtw(L"[ScyllaHide Options] Profile: %s", g_settings.profile_name().c_str()); + SetWindowTextW(hDlg, wstrTitle.c_str()); + + SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_ADDSTRING, 0, (LPARAM)wstrNewProfileName.c_str()); + auto profileCount = (int)SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_GETCOUNT, 0, 0); + SendDlgItemMessageW(hDlg, IDC_PROFILES, CB_SETCURSEL, profileCount - 1, 0); + + UpdateOptions(hDlg, &g_settings); + break; + } - case IDOK: - { - if (HIWORD(wParam) != BN_CLICKED) - break; + case IDOK: + { + if (HIWORD(wParam) != BN_CLICKED) + break; - SaveOptions(hDlg, &g_settings); + SaveOptions(hDlg, &g_settings); - if (ProcessId) - { + if (ProcessId != 0) + { #ifdef __IDP__ -#ifndef BUILD_IDA_64BIT - startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); -#endif + #ifndef __EA64__ + startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + #endif #else - startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); #endif - bHooked = true; - MessageBoxW(hDlg, L"Applied changes! Restarting target is NOT necessary!", L"[ScyllaHide Options]", MB_ICONINFORMATION); - } - else - { - MessageBoxW(hDlg, L"Please start the target to apply changes!", L"[ScyllaHide Options]", MB_ICONINFORMATION); - } - - EndDialog(hDlg, NULL); - break; - } - - case IDC_APPLY: - { - if (HIWORD(wParam) != BN_CLICKED) - break; - - SaveOptions(hDlg, &g_settings); - break; - } + bHooked = true; + MessageBoxW(hDlg, L"Applied changes! Restarting target is NOT necessary!", L"[ScyllaHide Options]", MB_ICONINFORMATION); + } + else + { + MessageBoxW(hDlg, L"Please start the target to apply changes!", L"[ScyllaHide Options]", MB_ICONINFORMATION); + } - case IDC_EXCEPTION_ALL: - { - if (HIWORD(wParam) != BN_CLICKED) - break; + EndDialog(hDlg, NULL); + break; + } - auto value = (IsDlgButtonChecked(hDlg, IDC_EXCEPTION_ALL) == BST_CHECKED); - g_settings.opts().handleExceptionPrint = value; - g_settings.opts().handleExceptionIllegalInstruction = value; - g_settings.opts().handleExceptionInvalidLockSequence = value; - g_settings.opts().handleExceptionNoncontinuableException = value; - g_settings.opts().handleExceptionRip = value; - g_settings.opts().handleExceptionAssertionFailure = value; - g_settings.opts().handleExceptionBreakpoint = value; - g_settings.opts().handleExceptionGuardPageViolation = value; - g_settings.opts().handleExceptionWx86Breakpoint = value; - break; - } + case IDC_APPLY: + { + if (HIWORD(wParam) != BN_CLICKED) + break; - case IDC_PROTECTDRX: - { - if (HIWORD(wParam) != BN_CLICKED) - break; + SaveOptions(hDlg, &g_settings); + break; + } - auto state = IsDlgButtonChecked(hDlg, IDC_PROTECTDRX); - CheckDlgButton(hDlg, IDC_NTGETCONTEXTTHREAD, state); - CheckDlgButton(hDlg, IDC_NTSETCONTEXTTHREAD, state); - CheckDlgButton(hDlg, IDC_NTCONTINUE, state); - CheckDlgButton(hDlg, IDC_KIUED, state); - break; - } + case IDC_EXCEPTION_ALL: + { + if (HIWORD(wParam) != BN_CLICKED) + break; + + auto value = (IsDlgButtonChecked(hDlg, IDC_EXCEPTION_ALL) == BST_CHECKED); + g_settings.opts().handleExceptionPrint = value; + g_settings.opts().handleExceptionIllegalInstruction = value; + g_settings.opts().handleExceptionInvalidLockSequence = value; + g_settings.opts().handleExceptionNoncontinuableException = value; + g_settings.opts().handleExceptionRip = value; + g_settings.opts().handleExceptionAssertionFailure = value; + g_settings.opts().handleExceptionBreakpoint = value; + g_settings.opts().handleExceptionGuardPageViolation = value; + g_settings.opts().handleExceptionWx86Breakpoint = value; + break; + } - case IDC_NTGETCONTEXTTHREAD: - case IDC_NTSETCONTEXTTHREAD: - case IDC_NTCONTINUE: - case IDC_KIUED: - { - if (HIWORD(wParam) != BN_CLICKED) - break; + case IDC_PROTECTDRX: + { + if (HIWORD(wParam) != BN_CLICKED) + break; + + auto state = IsDlgButtonChecked(hDlg, IDC_PROTECTDRX); + CheckDlgButton(hDlg, IDC_NTGETCONTEXTTHREAD, state); + CheckDlgButton(hDlg, IDC_NTSETCONTEXTTHREAD, state); + CheckDlgButton(hDlg, IDC_NTCONTINUE, state); + CheckDlgButton(hDlg, IDC_KIUED, state); + break; + } - auto checked = IsDlgButtonChecked(hDlg, IDC_NTGETCONTEXTTHREAD) - || IsDlgButtonChecked(hDlg, IDC_NTSETCONTEXTTHREAD) - || IsDlgButtonChecked(hDlg, IDC_NTCONTINUE) - || IsDlgButtonChecked(hDlg, IDC_KIUED); + case IDC_NTGETCONTEXTTHREAD: + case IDC_NTSETCONTEXTTHREAD: + case IDC_NTCONTINUE: + case IDC_KIUED: + { + if (HIWORD(wParam) != BN_CLICKED) + break; - CheckDlgButton(hDlg, IDC_PROTECTDRX, checked); - break; - } + auto checked = IsDlgButtonChecked(hDlg, IDC_NTGETCONTEXTTHREAD) + || IsDlgButtonChecked(hDlg, IDC_NTSETCONTEXTTHREAD) + || IsDlgButtonChecked(hDlg, IDC_NTCONTINUE) + || IsDlgButtonChecked(hDlg, IDC_KIUED); - case IDC_PEB: - { - if (HIWORD(wParam) != BN_CLICKED) - break; + CheckDlgButton(hDlg, IDC_PROTECTDRX, checked); + break; + } - auto state = IsDlgButtonChecked(hDlg, IDC_PEB); - CheckDlgButton(hDlg, IDC_PEBBEINGDEBUGGED, state); - CheckDlgButton(hDlg, IDC_PEBHEAPFLAGS, state); - CheckDlgButton(hDlg, IDC_PEBNTGLOBALFLAG, state); - CheckDlgButton(hDlg, IDC_PEBSTARTUPINFO, state); - CheckDlgButton(hDlg, IDC_PEBOSBUILDNUMBER, state); - break; - } + case IDC_PEB: + { + if (HIWORD(wParam) != BN_CLICKED) + break; + + auto state = IsDlgButtonChecked(hDlg, IDC_PEB); + CheckDlgButton(hDlg, IDC_PEBBEINGDEBUGGED, state); + CheckDlgButton(hDlg, IDC_PEBHEAPFLAGS, state); + CheckDlgButton(hDlg, IDC_PEBNTGLOBALFLAG, state); + CheckDlgButton(hDlg, IDC_PEBSTARTUPINFO, state); + CheckDlgButton(hDlg, IDC_PEBOSBUILDNUMBER, state); + break; + } - case IDC_PEBBEINGDEBUGGED: - case IDC_PEBHEAPFLAGS: - case IDC_PEBNTGLOBALFLAG: - case IDC_PEBSTARTUPINFO: - case IDC_PEBOSBUILDNUMBER: - { - if (HIWORD(wParam) != BN_CLICKED) - break; + case IDC_PEBBEINGDEBUGGED: + case IDC_PEBHEAPFLAGS: + case IDC_PEBNTGLOBALFLAG: + case IDC_PEBSTARTUPINFO: + case IDC_PEBOSBUILDNUMBER: + { + if (HIWORD(wParam) != BN_CLICKED) + break; - auto checked = IsDlgButtonChecked(hDlg, IDC_PEBBEINGDEBUGGED) - || IsDlgButtonChecked(hDlg, IDC_PEBHEAPFLAGS) - || IsDlgButtonChecked(hDlg, IDC_PEBNTGLOBALFLAG) - || IsDlgButtonChecked(hDlg, IDC_PEBSTARTUPINFO) - || IsDlgButtonChecked(hDlg, IDC_PEBOSBUILDNUMBER); + auto checked = IsDlgButtonChecked(hDlg, IDC_PEBBEINGDEBUGGED) + || IsDlgButtonChecked(hDlg, IDC_PEBHEAPFLAGS) + || IsDlgButtonChecked(hDlg, IDC_PEBNTGLOBALFLAG) + || IsDlgButtonChecked(hDlg, IDC_PEBSTARTUPINFO) + || IsDlgButtonChecked(hDlg, IDC_PEBOSBUILDNUMBER); - CheckDlgButton(hDlg, IDC_PEB, checked); - break; - } + CheckDlgButton(hDlg, IDC_PEB, checked); + break; + } -#ifdef OLLY1 - case IDC_COMPRESSED: - { - if (HIWORD(wParam) != BN_CLICKED) - break; + #ifdef OLLY1 + case IDC_COMPRESSED: + { + if (HIWORD(wParam) != BN_CLICKED) + break; - auto checked = (IsDlgButtonChecked(hDlg, IDC_COMPRESSED) == BST_CHECKED); + auto checked = (IsDlgButtonChecked(hDlg, IDC_COMPRESSED) == BST_CHECKED); - EnableWindow(GetDlgItem(hDlg, IDC_COMPRESSEDANALYZE), checked); - EnableWindow(GetDlgItem(hDlg, IDC_COMPRESSEDNOTHING), checked); + EnableWindow(GetDlgItem(hDlg, IDC_COMPRESSEDANALYZE), checked); + EnableWindow(GetDlgItem(hDlg, IDC_COMPRESSEDNOTHING), checked); - if (!checked) { - CheckDlgButton(hDlg, IDC_COMPRESSEDANALYZE, BST_UNCHECKED); - CheckDlgButton(hDlg, IDC_COMPRESSEDNOTHING, BST_UNCHECKED); - } - break; - } + if (!checked) { + CheckDlgButton(hDlg, IDC_COMPRESSEDANALYZE, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_COMPRESSEDNOTHING, BST_UNCHECKED); + } + break; + } - case IDC_LOADDLL: - { - if (HIWORD(wParam) != BN_CLICKED) - break; + case IDC_LOADDLL: + { + if (HIWORD(wParam) != BN_CLICKED) + break; - auto checked = (IsDlgButtonChecked(hDlg, IDC_LOADDLL) == BST_CHECKED); + auto checked = (IsDlgButtonChecked(hDlg, IDC_LOADDLL) == BST_CHECKED); - EnableWindow(GetDlgItem(hDlg, IDC_LOADDLLLOAD), checked); - EnableWindow(GetDlgItem(hDlg, IDC_LOADDLLNOTHING), checked); + EnableWindow(GetDlgItem(hDlg, IDC_LOADDLLLOAD), checked); + EnableWindow(GetDlgItem(hDlg, IDC_LOADDLLNOTHING), checked); - if (!checked) { - CheckDlgButton(hDlg, IDC_LOADDLLLOAD, BST_UNCHECKED); - CheckDlgButton(hDlg, IDC_LOADDLLNOTHING, BST_UNCHECKED); - } - break; - } -#endif + if (!checked) + { + CheckDlgButton(hDlg, IDC_LOADDLLLOAD, BST_UNCHECKED); + CheckDlgButton(hDlg, IDC_LOADDLLNOTHING, BST_UNCHECKED); + } + break; + } + #endif #ifdef __IDP__ - case IDC_DLLNORMAL: - case IDC_DLLSTEALTH: - case IDC_DLLUNLOAD: - { - if (HIWORD(wParam) != BN_CLICKED) - break; - - //DLL injection options need to be updated on-the-fly coz the injection button is ON the options window - g_settings.opts().dllStealth = (IsDlgButtonChecked(hDlg, IDC_DLLSTEALTH) == BST_CHECKED); - g_settings.opts().dllNormal = (IsDlgButtonChecked(hDlg, IDC_DLLNORMAL) == BST_CHECKED); - g_settings.opts().dllUnload = (IsDlgButtonChecked(hDlg, IDC_DLLUNLOAD) == BST_CHECKED); - break; - } + case IDC_DLLNORMAL: + case IDC_DLLSTEALTH: + case IDC_DLLUNLOAD: + { + if (HIWORD(wParam) != BN_CLICKED) + break; - case IDC_INJECTDLL: - { - if (HIWORD(wParam) != BN_CLICKED) + // DLL injection options need to be updated on-the-fly because the injection button is ON the options window + g_settings.opts().dllStealth = (IsDlgButtonChecked(hDlg, IDC_DLLSTEALTH) == BST_CHECKED); + g_settings.opts().dllNormal = (IsDlgButtonChecked(hDlg, IDC_DLLNORMAL) == BST_CHECKED); + g_settings.opts().dllUnload = (IsDlgButtonChecked(hDlg, IDC_DLLUNLOAD) == BST_CHECKED); break; + } - if (ProcessId) + case IDC_INJECTDLL: { - if (scl::GetFileDialogW(DllPathForInjection, _countof(DllPathForInjection))) + if (HIWORD(wParam) != BN_CLICKED) + break; + + if (ProcessId != 0) { - if (dbg->is_remote()) - { - SendInjectToServer(ProcessId); - } - else + if (scl::GetFileDialogW(DllPathForInjection, _countof(DllPathForInjection))) { -#ifndef BUILD_IDA_64BIT - injectDll(ProcessId, DllPathForInjection); -#endif - } + if (dbg->is_remote()) + { + SendInjectToServer(ProcessId); + } + else + { + #ifndef __EA64__ + injectDll(ProcessId, DllPathForInjection); + #endif + } + } } + break; } - break; - } - case IDC_ATTACH: - { - if (HIWORD(wParam) != BN_CLICKED) + case IDC_ATTACH: + { + if (HIWORD(wParam) != BN_CLICKED) + break; + + EndDialog(hDlg, NULL); + DialogBoxW(hinst, MAKEINTRESOURCE(IDD_ATTACH), GetForegroundWindow(), AttachProc); break; + } - EndDialog(hDlg, NULL); - DialogBoxW(hinst, MAKEINTRESOURCE(IDD_ATTACH), (HWND)callui(ui_get_hwnd).vptr, &AttachProc); - break; - } + case IDC_ABOUT: + { + if (HIWORD(wParam) != BN_CLICKED) + break; - case IDC_ABOUT: - { - if (HIWORD(wParam) != BN_CLICKED) + scl::ShowAboutBox(GetForegroundWindow()); break; - - scl::ShowAboutBox((HWND)callui(ui_get_hwnd).vptr); - break; - } + } #endif + case IDC_SELECT_EXCEPTIONS: + { + if (HIWORD(wParam) != BN_CLICKED) + break; - case IDC_SELECT_EXCEPTIONS: - { - if (HIWORD(wParam) != BN_CLICKED) + createExceptionWindow(hDlg); + UpdateOptionsExceptions(hDlg, &g_settings); break; + } - createExceptionWindow(hDlg); - UpdateOptionsExceptions(hDlg, &g_settings); - break; - } - - default: - break; + default: + break; } - } - break; + break; - default: - { - return FALSE; - } + default: + return FALSE; } - return 0; + return FALSE; } - -typedef struct _NAME_TOOLTIP { + +//---------------------------------------------------------------------------------- +struct NAME_TOOLTIP { const WCHAR * name; WCHAR * tooltip; ULONG_PTR windowId; -} NAME_TOOLTIP; +}; -enum { +enum +{ ID_EXCEPTION_PRINT = 200, ID_EXCEPTION_RIP, ID_EXCEPTION_Noncontinable, @@ -951,7 +965,8 @@ NAME_TOOLTIP exceptionNamesTooltip[] = { { L"Assertion Failure", L"STATUS_ASSERTION_FAILURE 0xC0000420", ID_EXCEPTION_AssertionFailure } #endif }; - + +//---------------------------------------------------------------------------------- #define HEIGHT_OF_EXCEPTION_CHECKBOX 16 #define EXCEPTION_WINDOW_BASE_HEIGHT 46 #define EXCEPTION_WINDOW_WIDTH 200 @@ -1002,9 +1017,12 @@ LRESULT CALLBACK ExceptionSettingsWndproc(HWND hwnd, UINT msg, WPARAM wparam, LP SendMessageW(hwndTT, TTM_ADDTOOL, 0, (LPARAM)&ti); } - if (g_settings.opts().handleExceptionPrint) CheckDlgButton(hwnd, ID_EXCEPTION_PRINT, BST_CHECKED); - if (g_settings.opts().handleExceptionIllegalInstruction) CheckDlgButton(hwnd, ID_EXCEPTION_Illegal, BST_CHECKED); - if (g_settings.opts().handleExceptionInvalidLockSequence) CheckDlgButton(hwnd, ID_EXCEPTION_InvalidLockSequence, BST_CHECKED); + if (g_settings.opts().handleExceptionPrint) + CheckDlgButton(hwnd, ID_EXCEPTION_PRINT, BST_CHECKED); + if (g_settings.opts().handleExceptionIllegalInstruction) + CheckDlgButton(hwnd, ID_EXCEPTION_Illegal, BST_CHECKED); + if (g_settings.opts().handleExceptionInvalidLockSequence) + CheckDlgButton(hwnd, ID_EXCEPTION_InvalidLockSequence, BST_CHECKED); if (g_settings.opts().handleExceptionNoncontinuableException) CheckDlgButton(hwnd, ID_EXCEPTION_Noncontinable, BST_CHECKED); if (g_settings.opts().handleExceptionAssertionFailure) CheckDlgButton(hwnd, ID_EXCEPTION_AssertionFailure, BST_CHECKED); if (g_settings.opts().handleExceptionBreakpoint) CheckDlgButton(hwnd, ID_EXCEPTION_Breakpoint, BST_CHECKED); @@ -1051,7 +1069,7 @@ LRESULT CALLBACK ExceptionSettingsWndproc(HWND hwnd, UINT msg, WPARAM wparam, LP return DefWindowProcW(hwnd, msg, wparam, lparam); } - +//---------------------------------------------------------------------------------- void createExceptionWindow(HWND hwnd) { WCHAR * classname = L"exception_window_config_scyllahide"; diff --git a/README.md b/README.md index 6cbfab74..dfe46f21 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ScyllaHide supports various debuggers through plugins: - OllyDbg [v1](http://www.ollydbg.de) and [v2](http://www.ollydbg.de/version2.html) - [x64dbg](https://x64dbg.com) -- [Hex-Rays IDA](https://www.hex-rays.com/products/ida/) v6 (not supported) +- [Hex-Rays IDA 7.5+](https://www.hex-rays.com/products/ida/) (x86 is not supported) - TitanEngine v2 ([original](http://www.reversinglabs.com/open-source/titanengine.html) and [updated](https://github.com/x64dbg/TitanEngine/) versions) PE x64 debugging is fully supported with plugins for x64dbg and IDA. diff --git a/Scylla/Logger.cpp b/Scylla/Logger.cpp index 86d50392..db6ca07e 100644 --- a/Scylla/Logger.cpp +++ b/Scylla/Logger.cpp @@ -5,19 +5,22 @@ #include "Util.h" const wchar_t scl::Logger::kFileName[] = L"scylla_hide.log"; - + +//---------------------------------------------------------------------------------- scl::Logger::Logger() { ZeroMemory(cb_a_, sizeof(cb_a_)); ZeroMemory(cb_w_, sizeof(cb_w_)); } - + +//---------------------------------------------------------------------------------- scl::Logger::~Logger() { if (file_.is_open()) file_.close(); } - + +//---------------------------------------------------------------------------------- bool scl::Logger::SetLogFile(const wchar_t *filepath) { if (file_.is_open()) @@ -27,7 +30,8 @@ bool scl::Logger::SetLogFile(const wchar_t *filepath) return file_.is_open(); } - + +//---------------------------------------------------------------------------------- void scl::Logger::LogDebug(const wchar_t *fmt, ...) { va_list ap; @@ -35,7 +39,8 @@ void scl::Logger::LogDebug(const wchar_t *fmt, ...) LogGeneric("DEBUG", cb_a_[Debug], cb_w_[Debug], fmt, ap); va_end(ap); } - + +//---------------------------------------------------------------------------------- void scl::Logger::LogInfo(const wchar_t *fmt, ...) { va_list ap; @@ -43,7 +48,8 @@ void scl::Logger::LogInfo(const wchar_t *fmt, ...) LogGeneric("INFO", cb_a_[Info], cb_w_[Info], fmt, ap); va_end(ap); } - + +//---------------------------------------------------------------------------------- void scl::Logger::LogError(const wchar_t *fmt, ...) { va_list ap; @@ -51,18 +57,24 @@ void scl::Logger::LogError(const wchar_t *fmt, ...) LogGeneric("ERROR", cb_a_[Error], cb_w_[Error], fmt, ap); va_end(ap); } - -void scl::Logger::LogGeneric(const char *prefix, LogCbA cb_a, LogCbW cb_w, const wchar_t *fmt, va_list ap) + +//---------------------------------------------------------------------------------- +void scl::Logger::LogGeneric( + const char *prefix, + LogCbA cb_a, + LogCbW cb_w, + const wchar_t *fmt, + va_list ap) { va_list vap; va_copy(vap, ap); auto strw = scl::vfmtw(fmt, ap); va_end(ap); - if (cb_w) + if (cb_w != nullptr) cb_w(strw.c_str()); - if (cb_a || file_.is_open()) + if (cb_a != nullptr || file_.is_open()) { auto stra = scl::wstr_conv().to_bytes(strw); diff --git a/Scylla/Logger.h b/Scylla/Logger.h index 324519ce..6c016872 100644 --- a/Scylla/Logger.h +++ b/Scylla/Logger.h @@ -3,21 +3,33 @@ #include #include -namespace scl { - +namespace scl +{ class Logger { public: - typedef void(*LogCbA)(const char *msg); - typedef void(*LogCbW)(const wchar_t *msg); - enum Severity { Debug = 0, Info, Error, MaxSeverity - }; + }; + + typedef void(*LogCbA)(const char* msg); + typedef void(*LogCbW)(const wchar_t* msg); + + private: + LogCbA cb_a_[MaxSeverity]; + LogCbW cb_w_[MaxSeverity]; + std::ofstream file_; + + protected: + void LogGeneric(const char* prefix, LogCbA cb_a, LogCbW cb_w, const wchar_t* fmt, va_list ap); + + public: + typedef void(*LogCbA)(const char *msg); + typedef void(*LogCbW)(const wchar_t *msg); static const wchar_t kFileName[]; @@ -39,14 +51,5 @@ namespace scl { void LogDebug(const wchar_t *fmt, ...); void LogInfo(const wchar_t *fmt, ...); void LogError(const wchar_t *fmt, ...); - - protected: - void LogGeneric(const char *prefix, LogCbA cb_a, LogCbW cb_w, const wchar_t *fmt, va_list ap); - - private: - LogCbA cb_a_[MaxSeverity]; - LogCbW cb_w_[MaxSeverity]; - std::ofstream file_; }; - } diff --git a/Scylla/NtApiShim.h b/Scylla/NtApiShim.h index 83cf0b32..371f3571 100644 --- a/Scylla/NtApiShim.h +++ b/Scylla/NtApiShim.h @@ -3,32 +3,47 @@ #include #ifndef FLG_HEAP_ENABLE_TAIL_CHECK -#define FLG_HEAP_ENABLE_TAIL_CHECK 0x10 + #define FLG_HEAP_ENABLE_TAIL_CHECK 0x10 #endif #ifndef FLG_HEAP_ENABLE_FREE_CHECK -#define FLG_HEAP_ENABLE_FREE_CHECK 0x20 + #define FLG_HEAP_ENABLE_FREE_CHECK 0x20 #endif #ifndef FLG_HEAP_VALIDATE_PARAMETERS -#define FLG_HEAP_VALIDATE_PARAMETERS 0x40 + #define FLG_HEAP_VALIDATE_PARAMETERS 0x40 #endif #ifndef HEAP_SKIP_VALIDATION_CHECKS -#define HEAP_SKIP_VALIDATION_CHECKS 0x10000000 + #define HEAP_SKIP_VALIDATION_CHECKS 0x10000000 #endif #ifndef HEAP_VALIDATE_PARAMETERS_ENABLED -#define HEAP_VALIDATE_PARAMETERS_ENABLED 0x40000000 + #define HEAP_VALIDATE_PARAMETERS_ENABLED 0x40000000 #endif #ifndef DBG_PRINTEXCEPTION_WIDE_C -#define DBG_PRINTEXCEPTION_WIDE_C ((DWORD)0x4001000A) + #define DBG_PRINTEXCEPTION_WIDE_C ((DWORD)0x4001000A) #endif -typedef NTSTATUS(WINAPI *t_NtWow64QueryInformationProcess64)(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); -typedef NTSTATUS(WINAPI *t_NtWow64ReadVirtualMemory64)(HANDLE ProcessHandle, PVOID64 BaseAddress, PVOID Buffer, ULONGLONG BufferSize, PULONGLONG NumberOfBytesRead); -typedef NTSTATUS(WINAPI *t_NtWow64WriteVirtualMemory64)(HANDLE ProcessHandle, PVOID64 BaseAddress, LPCVOID Buffer, ULONGLONG BufferSize, PULONGLONG NumberOfBytesWritten); +typedef NTSTATUS(WINAPI *t_NtWow64QueryInformationProcess64)( + HANDLE ProcessHandle, + PROCESSINFOCLASS ProcessInformationClass, + PVOID ProcessInformation, + ULONG ProcessInformationLength, + PULONG ReturnLength); +typedef NTSTATUS(WINAPI *t_NtWow64ReadVirtualMemory64)( + HANDLE ProcessHandle, + PVOID64 BaseAddress, + PVOID Buffer, + ULONGLONG BufferSize, + PULONGLONG NumberOfBytesRead); +typedef NTSTATUS(WINAPI *t_NtWow64WriteVirtualMemory64)( + HANDLE ProcessHandle, + PVOID64 BaseAddress, + LPCVOID Buffer, + ULONGLONG BufferSize, + PULONGLONG NumberOfBytesWritten); namespace scl @@ -66,7 +81,8 @@ namespace scl }; template - struct RTL_USER_PROCESS_PARAMETERS { + struct RTL_USER_PROCESS_PARAMETERS + { ULONG MaximumLength; ULONG Length; diff --git a/Scylla/Peb.cpp b/Scylla/Peb.cpp index f61789cd..9d49cf3c 100644 --- a/Scylla/Peb.cpp +++ b/Scylla/Peb.cpp @@ -2,7 +2,8 @@ #include #include #include "Util.h" - + +//---------------------------------------------------------------------------------- scl::PEB *scl::GetPebAddress(HANDLE hProcess) { ::PROCESS_BASIC_INFORMATION pbi = { 0 }; @@ -11,7 +12,8 @@ scl::PEB *scl::GetPebAddress(HANDLE hProcess) return NT_SUCCESS(status) ? (PEB *)pbi.PebBaseAddress : nullptr; } - + +//---------------------------------------------------------------------------------- /** * Get PEB64 address of WOW64 process. */ @@ -27,7 +29,8 @@ PVOID64 scl::GetPeb64Address(HANDLE hProcess) return nullptr; } - + +//---------------------------------------------------------------------------------- std::shared_ptr scl::GetPeb(HANDLE hProcess) { auto peb_addr = GetPebAddress(hProcess); @@ -40,7 +43,8 @@ std::shared_ptr scl::GetPeb(HANDLE hProcess) return peb; } - + +//---------------------------------------------------------------------------------- /** * @remark Use only real process handles. */ @@ -59,7 +63,8 @@ std::shared_ptr scl::Wow64GetPeb64(HANDLE hProcess) return nullptr; } - + +//---------------------------------------------------------------------------------- bool scl::SetPeb(HANDLE hProcess, const PEB *pPeb) { auto peb_addr = GetPebAddress(hProcess); @@ -68,7 +73,8 @@ bool scl::SetPeb(HANDLE hProcess, const PEB *pPeb) return WriteProcessMemory(hProcess, peb_addr, pPeb, sizeof(*pPeb), nullptr) == TRUE; } - + +//---------------------------------------------------------------------------------- /** * @remark Use only real process handles. */ @@ -84,7 +90,8 @@ bool scl::Wow64SetPeb64(HANDLE hProcess, const PEB64 *pPeb64) return false; } - + +//---------------------------------------------------------------------------------- PVOID64 scl::Wow64GetModuleHandle64(HANDLE hProcess, const wchar_t* moduleName) { const auto Peb64 = Wow64GetPeb64(hProcess); @@ -105,15 +112,15 @@ PVOID64 scl::Wow64GetModuleHandle64(HANDLE hProcess, const wchar_t* moduleName) if (!Wow64ReadProcessMemory64(hProcess, (PVOID64)Head.InLoadOrderLinks.Flink, &Head, sizeof(Head), nullptr)) break; - wchar_t* BaseDllName = (wchar_t*)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, Head.BaseDllName.MaximumLength); - if (BaseDllName == nullptr || - !Wow64ReadProcessMemory64(hProcess, (PVOID64)Head.BaseDllName.Buffer, BaseDllName, Head.BaseDllName.MaximumLength, nullptr)) + wchar_t *BaseDllName = (wchar_t*)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, Head.BaseDllName.MaximumLength); + if ( BaseDllName == nullptr + || !Wow64ReadProcessMemory64(hProcess, (PVOID64)Head.BaseDllName.Buffer, BaseDllName, Head.BaseDllName.MaximumLength, nullptr)) + { break; + } if (_wcsicmp(moduleName, BaseDllName) == 0) - { DllBase = (PVOID64)Head.DllBase; - } RtlFreeHeap(RtlProcessHeap(), 0, BaseDllName); @@ -121,7 +128,8 @@ PVOID64 scl::Wow64GetModuleHandle64(HANDLE hProcess, const wchar_t* moduleName) return DllBase; } - + +//---------------------------------------------------------------------------------- DWORD scl::GetHeapFlagsOffset(bool x64) { if (x64) @@ -138,8 +146,9 @@ DWORD scl::GetHeapFlagsOffset(bool x64) else return 0x0C; } -} +} +//---------------------------------------------------------------------------------- DWORD scl::GetHeapForceFlagsOffset(bool x64) { if (x64) diff --git a/Scylla/Peb.h b/Scylla/Peb.h index cf4ce6a7..e443bbba 100644 --- a/Scylla/Peb.h +++ b/Scylla/Peb.h @@ -9,8 +9,8 @@ // http://terminus.rewolf.pl/terminus/structures/ntdll/_PEB_combined.html // -namespace scl { - +namespace scl +{ #pragma pack(push, 1) template struct _LIST_ENTRY_T @@ -91,7 +91,7 @@ namespace scl { }; - template + template struct _PEB_T { union @@ -163,7 +163,7 @@ namespace scl { T ImageProcessAffinityMask; T ActiveProcessAffinityMask; }; - T GdiHandleBuffer[A]; + T GdiHandleBuffer[GDIBUFFERSIZE]; T PostProcessInitRoutine; T TlsExpansionBitmap; DWORD TlsExpansionBitmapBits[32]; @@ -209,4 +209,4 @@ namespace scl { DWORD GetHeapFlagsOffset(bool x64); DWORD GetHeapForceFlagsOffset(bool x64); - } +} diff --git a/Scylla/PebHider.cpp b/Scylla/PebHider.cpp index 5eb03abd..71f8feea 100644 --- a/Scylla/PebHider.cpp +++ b/Scylla/PebHider.cpp @@ -25,7 +25,8 @@ // The set of force flags to clear is the intersection of valid force flags and the debug flags #define HEAP_CLEARABLE_FORCE_FLAGS (HEAP_CLEARABLE_FLAGS & HEAP_VALID_FORCE_FLAGS) - + +//---------------------------------------------------------------------------------- bool scl::PebPatchProcessParameters(PEB* peb, HANDLE hProcess) { RTL_USER_PROCESS_PARAMETERS rupp; @@ -46,8 +47,9 @@ bool scl::PebPatchProcessParameters(PEB* peb, HANDLE hProcess) return (WriteProcessMemory(hProcess, (PVOID)peb->ProcessParameters, &rupp, sizeof(rupp), nullptr) == TRUE); } - -bool scl::Wow64Peb64PatchProcessParameters(PEB64* peb64, HANDLE hProcess) + +//---------------------------------------------------------------------------------- +bool scl::Wow64Peb64PatchProcessParameters(PEB64 *peb64, HANDLE hProcess) { #ifndef _WIN64 scl::RTL_USER_PROCESS_PARAMETERS rupp; @@ -93,7 +95,7 @@ bool scl::PebPatchHeapFlags(PEB* peb, HANDLE hProcess) if (ReadProcessMemory(hProcess, heaps[i], (PVOID)heap.data(), heap.size(), nullptr) == FALSE) return false; - auto flags = (DWORD *)(heap.data() + scl::GetHeapFlagsOffset(is_x64)); + auto flags = (DWORD *)(heap.data() + scl::GetHeapFlagsOffset(is_x64)); auto force_flags = (DWORD *)(heap.data() + scl::GetHeapForceFlagsOffset(is_x64)); *flags &= ~HEAP_CLEARABLE_FLAGS; @@ -106,8 +108,9 @@ bool scl::PebPatchHeapFlags(PEB* peb, HANDLE hProcess) return true; } - -bool scl::Wow64Peb64PatchHeapFlags(PEB64* peb, HANDLE hProcess) + +//---------------------------------------------------------------------------------- +bool scl::Wow64Peb64PatchHeapFlags(PEB64 *peb, HANDLE hProcess) { std::vector heaps; heaps.resize(peb->NumberOfHeaps); diff --git a/Scylla/Resource.h b/Scylla/Resource.h deleted file mode 100644 index 3b1b6e5d..00000000 --- a/Scylla/Resource.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include - -namespace scl -{ - class Handle - { - public: - explicit Handle(HANDLE handle) : handle_(handle) {} - ~Handle() - { - if (handle_ && (handle_ != INVALID_HANDLE_VALUE)) - CloseHandle(handle_); - } - - Handle(const Handle &other) = delete; - Handle &operator=(const Handle &other) = delete; - - HANDLE get() const { return handle_; } - - private: - HANDLE handle_; - }; -} diff --git a/Scylla/Scylla.vcxproj b/Scylla/Scylla.vcxproj index 4da574ce..7d91fa01 100644 --- a/Scylla/Scylla.vcxproj +++ b/Scylla/Scylla.vcxproj @@ -1,171 +1,170 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - 16.0 - {E468DA07-48EA-40EB-A845-FA69C39D3396} - Win32Proj - Scylla - 10.0 - - - - StaticLibrary - true - v142 - Unicode - false - false - - - StaticLibrary - true - v142 - Unicode - false - false - - - StaticLibrary - false - v142 - true - Unicode - false - false - - - StaticLibrary - false - v142 - true - Unicode - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - true - - - false - false - - - false - false - - - - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - - - true - - - - - _DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - - - true - - - - - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - - - true - - - - - NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - - - true - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + 16.0 + {E468DA07-48EA-40EB-A845-FA69C39D3396} + Win32Proj + Scylla + 10.0 + + + + StaticLibrary + true + v142 + Unicode + false + false + + + StaticLibrary + true + v142 + Unicode + false + false + + + StaticLibrary + false + v142 + true + Unicode + false + false + + + StaticLibrary + false + v142 + true + Unicode + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + false + + + false + false + + + + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + true + + + + + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + true + + + + + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + true + + + + + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + true + + + \ No newline at end of file diff --git a/Scylla/Scylla.vcxproj.filters b/Scylla/Scylla.vcxproj.filters index 02a91492..2320cecd 100644 --- a/Scylla/Scylla.vcxproj.filters +++ b/Scylla/Scylla.vcxproj.filters @@ -1,78 +1,75 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + \ No newline at end of file diff --git a/Scylla/User32Loader.cpp b/Scylla/User32Loader.cpp index e0cc56c7..301851f3 100644 --- a/Scylla/User32Loader.cpp +++ b/Scylla/User32Loader.cpp @@ -19,12 +19,14 @@ scl::User32Loader::~User32Loader() if (Win32kUserDll != nullptr) FreeLibrary((HMODULE)Win32kUserDll); } - + +//---------------------------------------------------------------------------------- // Finds the requested user32/win32u syscalls by name for later retrieval with GetUserSyscallVa bool scl::User32Loader::FindSyscalls(const std::vector& syscallNames) { if (Win32kUserDll == nullptr) // Failed to load user32.dll or win32u.dll - return false; + return false; + if (OsBuildNumber < 2600) // Unsupported or unknown OS return false; @@ -78,7 +80,8 @@ bool scl::User32Loader::FindSyscalls(const std::vector& syscallName return check; } - + +//---------------------------------------------------------------------------------- // Returns the win32k syscall number for a function name LONG scl::User32Loader::GetUserSyscallIndex(const std::string& functionName) const { @@ -86,7 +89,8 @@ LONG scl::User32Loader::GetUserSyscallIndex(const std::string& functionName) con { const PUCHAR syscallAddress = (PUCHAR)GetProcAddress((HMODULE)Win32kUserDll, functionName.c_str()); if (syscallAddress == nullptr) - return -1; + return -1; + for (PUCHAR address = syscallAddress; address < syscallAddress + 16; ++address) { if (address[0] == 0xB8 && address[1] != 0xD1) @@ -106,7 +110,8 @@ LONG scl::User32Loader::GetUserSyscallIndex(const std::string& functionName) con } return -1; } - + +//---------------------------------------------------------------------------------- // Scans user32.dll and returns the VA of the function that performs the syscall with the given index ULONG_PTR scl::User32Loader::FindSyscallByIndex(LONG win32kSyscallIndex) const { diff --git a/Scylla/User32Loader.h b/Scylla/User32Loader.h index 0fe3c651..abc8056b 100644 --- a/Scylla/User32Loader.h +++ b/Scylla/User32Loader.h @@ -9,7 +9,15 @@ namespace scl { class User32Loader { - public: + private: + const USHORT OsBuildNumber; + const bool NativeX86; + const PUCHAR Win32kUserDll; // win32u.dll if OsBuildNumber >= 14393, user32.dll otherwise + + std::map FunctionNamesAndVas; + + ULONG_PTR FindSyscallByIndex(LONG win32kSyscallIndex) const; + public: User32Loader(); ~User32Loader(); @@ -17,14 +25,5 @@ namespace scl ULONG_PTR GetUserSyscallVa(const std::string& functionName) const { return FunctionNamesAndVas.at(functionName); } LONG GetUserSyscallIndex(const std::string& functionName) const; - - private: - ULONG_PTR FindSyscallByIndex(LONG win32kSyscallIndex) const; - - const USHORT OsBuildNumber; - const bool NativeX86; - const PUCHAR Win32kUserDll; // win32u.dll if OsBuildNumber >= 14393, user32.dll otherwise - - std::map FunctionNamesAndVas; }; } diff --git a/Scylla/Util.cpp b/Scylla/Util.cpp index 7971af6e..31674614 100644 --- a/Scylla/Util.cpp +++ b/Scylla/Util.cpp @@ -1,7 +1,8 @@ #include "Util.h" #include #include "NtApiShim.h" - + +//---------------------------------------------------------------------------------- std::wstring scl::fmtw(const wchar_t *fmt, ...) { va_list ap; @@ -12,7 +13,8 @@ std::wstring scl::fmtw(const wchar_t *fmt, ...) return str; } - + +//---------------------------------------------------------------------------------- std::wstring scl::vfmtw(const wchar_t *fmt, va_list ap) { va_list vap; @@ -30,7 +32,8 @@ std::wstring scl::vfmtw(const wchar_t *fmt, va_list ap) return wstr; } - + +//---------------------------------------------------------------------------------- std::wstring scl::GetModuleFileNameW(HMODULE hModule) { std::wstring wstrFileName; @@ -43,7 +46,8 @@ std::wstring scl::GetModuleFileNameW(HMODULE hModule) wstrFileName.resize(copied); return wstrFileName; } - + +//---------------------------------------------------------------------------------- std::wstring scl::FormatMessageW(DWORD dwErrnum) { wchar_t *wszBuffer = nullptr; @@ -64,7 +68,8 @@ std::wstring scl::FormatMessageW(DWORD dwErrnum) return wstrError; } - + +//---------------------------------------------------------------------------------- std::wstring scl::GetWindowTextW(HWND hWnd) { std::wstring wstr; @@ -73,19 +78,22 @@ std::wstring scl::GetWindowTextW(HWND hWnd) ::GetWindowTextW(hWnd, &wstr[0], len); return wstr; } - + +//---------------------------------------------------------------------------------- std::wstring scl::GetDlgItemTextW(HWND hDlg, int nIDDlgItem) { return GetWindowTextW(::GetDlgItem(hDlg, nIDDlgItem)); } - + +//---------------------------------------------------------------------------------- bool scl::FileExistsW(const wchar_t *wszPath) { auto dwAttrib = ::GetFileAttributesW(wszPath); return (dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY); } - + +//---------------------------------------------------------------------------------- bool scl::GetFileDialogW(wchar_t *buffer, DWORD buffer_size) { OPENFILENAMEW sOpenFileName = { 0 }; @@ -104,31 +112,37 @@ bool scl::GetFileDialogW(wchar_t *buffer, DWORD buffer_size) return (TRUE == GetOpenFileNameW(&sOpenFileName)); } - +//---------------------------------------------------------------------------------- std::vector scl::IniLoadSectionNames(const wchar_t *file) { std::wstring buf; DWORD ret = 0; - while (((DWORD)buf.size() - ret) < 3) { + while (((DWORD)buf.size() - ret) < 3) + { buf.resize(buf.size() + MAX_PATH); ret = ::GetPrivateProfileSectionNamesW(&buf[0], (DWORD)buf.size(), file); } std::vector sections; auto data = buf.c_str(); - for (; data[0]; data += lstrlenW(data) + 1) { + for (; data[0]; data += lstrlenW(data) + 1) sections.push_back(data); - } return sections; } - -std::wstring scl::IniLoadString(const wchar_t *file, const wchar_t *section, const wchar_t *key, const wchar_t *default_value) + +//---------------------------------------------------------------------------------- +std::wstring scl::IniLoadString( + const wchar_t *file, + const wchar_t *section, + const wchar_t *key, + const wchar_t *default_value) { std::wstring buf; DWORD ret = 0; - while (((DWORD)buf.size() - ret) < 3) { + while (((DWORD)buf.size() - ret) < 3) + { buf.resize(buf.size() + MAX_PATH); ret = ::GetPrivateProfileStringW(section, key, default_value, &buf[0], (DWORD)buf.size(), file); } @@ -136,28 +150,46 @@ std::wstring scl::IniLoadString(const wchar_t *file, const wchar_t *section, con return buf; } - -bool scl::IniSaveString(const wchar_t *file, const wchar_t *section, const wchar_t *key, const wchar_t *value) + +//---------------------------------------------------------------------------------- +bool scl::IniSaveString( + const wchar_t *file, + const wchar_t *section, + const wchar_t *key, + const wchar_t *value) { return WritePrivateProfileStringW(section, key, value, file) == TRUE; } - + +//---------------------------------------------------------------------------------- std::wstring_convert> &scl::wstr_conv() { static std::wstring_convert> conv; return conv; } - -bool scl::Wow64QueryInformationProcess64(HANDLE hProcess, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength) + +//---------------------------------------------------------------------------------- +bool scl::Wow64QueryInformationProcess64( + HANDLE hProcess, + PROCESSINFOCLASS ProcessInformationClass, + PVOID ProcessInformation, + ULONG ProcessInformationLength, + PULONG ReturnLength) { auto _NtWow64QueryInformationProcess64 = (t_NtWow64QueryInformationProcess64)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtWow64QueryInformationProcess64"); - if (!_NtWow64QueryInformationProcess64) + if (_NtWow64QueryInformationProcess64 == nullptr) return false; return NT_SUCCESS(_NtWow64QueryInformationProcess64(hProcess, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength)); } - -bool scl::Wow64ReadProcessMemory64(HANDLE hProcess, PVOID64 address, PVOID buffer, ULONGLONG buffer_size, PULONGLONG bytes_read) + +//---------------------------------------------------------------------------------- +bool scl::Wow64ReadProcessMemory64( + HANDLE hProcess, + PVOID64 address, + PVOID buffer, + ULONGLONG buffer_size, + PULONGLONG bytes_read) { #ifndef _WIN64 auto _NtWow64ReadVirtualMemory64 = (t_NtWow64ReadVirtualMemory64)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtWow64ReadVirtualMemory64"); @@ -177,8 +209,14 @@ bool scl::Wow64ReadProcessMemory64(HANDLE hProcess, PVOID64 address, PVOID buffe return false; } - -bool scl::Wow64WriteProcessMemory64(HANDLE hProcess, PVOID64 address, LPCVOID buffer, ULONGLONG buffer_size, PULONGLONG bytes_written) + +//---------------------------------------------------------------------------------- +bool scl::Wow64WriteProcessMemory64( + HANDLE hProcess, + PVOID64 address, + LPCVOID buffer, + ULONGLONG buffer_size, + PULONGLONG bytes_written) { #ifndef _WIN64 auto _NtWow64WriteVirtualMemory64 = (t_NtWow64WriteVirtualMemory64)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtWow64WriteVirtualMemory64"); diff --git a/Scylla/Util.h b/Scylla/Util.h index a8386e91..29352ccd 100644 --- a/Scylla/Util.h +++ b/Scylla/Util.h @@ -6,7 +6,6 @@ #include #include #include -#include "Resource.h" #include "NtApiShim.h" namespace scl @@ -32,7 +31,11 @@ namespace scl bool IniSaveString(const wchar_t *file, const wchar_t *section, const wchar_t *key, const wchar_t *value); template - VALUE_TYPE IniLoadNum(const wchar_t *file, const wchar_t *section, const wchar_t *key, VALUE_TYPE default_value) + VALUE_TYPE IniLoadNum( + const wchar_t *file, + const wchar_t *section, + const wchar_t *key, + VALUE_TYPE default_value) { static_assert((BASE == 8) || (BASE == 10) || (BASE == 16), "invalid base"); @@ -56,7 +59,11 @@ namespace scl } template - bool IniSaveNum(const wchar_t *file, const wchar_t *section, const wchar_t *key, VALUE_TYPE value) + bool IniSaveNum( + const wchar_t *file, + const wchar_t *section, + const wchar_t *key, + VALUE_TYPE value) { static_assert((BASE == 8) || (BASE == 10) || (BASE == 16), "invalid base"); @@ -74,8 +81,40 @@ namespace scl std::wstring_convert> &wstr_conv(); - bool Wow64QueryInformationProcess64(HANDLE hProcess, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); + bool Wow64QueryInformationProcess64( + HANDLE hProcess, + PROCESSINFOCLASS ProcessInformationClass, + PVOID ProcessInformation, + ULONG ProcessInformationLength, + PULONG ReturnLength); + + bool Wow64ReadProcessMemory64( + HANDLE hProcess, + PVOID64 address, + PVOID buffer, + ULONGLONG buffer_size, + PULONGLONG bytes_read); - bool Wow64ReadProcessMemory64(HANDLE hProcess, PVOID64 address, PVOID buffer, ULONGLONG buffer_size, PULONGLONG bytes_read); bool Wow64WriteProcessMemory64(HANDLE hProcess, PVOID64 address, LPCVOID buffer, ULONGLONG buffer_size, PULONGLONG bytes_written); + + //---------------------------------------------------------------------------------- + // HANDLE wrapper class + class Handle + { + public: + explicit Handle(HANDLE handle) : handle_(handle) {} + ~Handle() + { + if (handle_ != NULL && (handle_ != INVALID_HANDLE_VALUE)) + CloseHandle(handle_); + } + + Handle(const Handle& other) = delete; + Handle& operator=(const Handle& other) = delete; + + HANDLE get() const { return handle_; } + + private: + HANDLE handle_; + }; }; diff --git a/Scylla/scylla.props b/Scylla/scylla.props index 12f5a420..140e02c5 100644 --- a/Scylla/scylla.props +++ b/Scylla/scylla.props @@ -12,7 +12,7 @@ Level3 NotUsing - $(SolutionDir);$(SolutionDir)3rdparty;$(SolutionDir)3rdparty\idasdk\include; + $(SolutionDir);$(SolutionDir)3rdparty;$(IDASDK)\include; WIN32_NO_STATUS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) Caret true @@ -26,7 +26,7 @@ /Gw /Zc:threadSafeInit- %(AdditionalOptions) - $(SolutionDir)3rdparty;$(SolutionDir)3rdparty\idasdk\lib;$(OutDir) + $(SolutionDir)3rdparty;$(IDASDK)\lib;$(OutDir) Scylla.lib;ntdll\ntdll_$(PlatformShortName).lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) DebugFull /NOVCFEATURE /NOCOFFGRPINFO %(AdditionalOptions) diff --git a/ScyllaHide.sln b/ScyllaHide.sln index ab7675f4..4e105983 100644 --- a/ScyllaHide.sln +++ b/ScyllaHide.sln @@ -89,11 +89,9 @@ Global {0520906F-4296-4BEC-BD5F-B370E1F7800A}.Debug|Win32.ActiveCfg = Debug|Win32 {0520906F-4296-4BEC-BD5F-B370E1F7800A}.Debug|Win32.Build.0 = Debug|Win32 {0520906F-4296-4BEC-BD5F-B370E1F7800A}.Debug|x64.ActiveCfg = Debug|x64 - {0520906F-4296-4BEC-BD5F-B370E1F7800A}.Debug|x64.Build.0 = Debug|x64 {0520906F-4296-4BEC-BD5F-B370E1F7800A}.Release|Win32.ActiveCfg = Release|Win32 {0520906F-4296-4BEC-BD5F-B370E1F7800A}.Release|Win32.Build.0 = Release|Win32 {0520906F-4296-4BEC-BD5F-B370E1F7800A}.Release|x64.ActiveCfg = Release|x64 - {0520906F-4296-4BEC-BD5F-B370E1F7800A}.Release|x64.Build.0 = Release|x64 {79774D44-ED2A-4FD2-9224-40AF0A590410}.Debug|Win32.ActiveCfg = Debug|Win32 {79774D44-ED2A-4FD2-9224-40AF0A590410}.Debug|Win32.Build.0 = Debug|Win32 {79774D44-ED2A-4FD2-9224-40AF0A590410}.Debug|x64.ActiveCfg = Debug|Win32 @@ -108,10 +106,12 @@ Global {9EEA6D78-4E74-47B9-8746-B8754B15525D}.Release|x64.ActiveCfg = Release|Win32 {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Debug|Win32.ActiveCfg = Debug|Win32 {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Debug|Win32.Build.0 = Debug|Win32 - {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Debug|x64.ActiveCfg = Debug|Win32 + {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Debug|x64.ActiveCfg = Debug|x64 + {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Debug|x64.Build.0 = Debug|x64 {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Release|Win32.ActiveCfg = Release|Win32 {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Release|Win32.Build.0 = Release|Win32 - {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Release|x64.ActiveCfg = Release|Win32 + {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Release|x64.ActiveCfg = Release|x64 + {A94B6222-ABEF-41A0-BE48-06801157AAA5}.Release|x64.Build.0 = Release|x64 {4506D672-19C3-439B-8E1B-F1BA8BE28844}.Debug|Win32.ActiveCfg = Debug|Win32 {4506D672-19C3-439B-8E1B-F1BA8BE28844}.Debug|Win32.Build.0 = Debug|Win32 {4506D672-19C3-439B-8E1B-F1BA8BE28844}.Debug|x64.ActiveCfg = Debug|x64 @@ -127,7 +127,6 @@ Global {B00C9DA1-867E-4438-9C6E-1B53AE0506B7}.Release|Win32.ActiveCfg = Release|Win32 {B00C9DA1-867E-4438-9C6E-1B53AE0506B7}.Release|Win32.Build.0 = Release|Win32 {B00C9DA1-867E-4438-9C6E-1B53AE0506B7}.Release|x64.ActiveCfg = Release|x64 - {B00C9DA1-867E-4438-9C6E-1B53AE0506B7}.Release|x64.Build.0 = Release|x64 {C2B5EC30-CF03-4963-B963-7576E9F1D01E}.Debug|Win32.ActiveCfg = Debug|Win32 {C2B5EC30-CF03-4963-B963-7576E9F1D01E}.Debug|Win32.Build.0 = Debug|Win32 {C2B5EC30-CF03-4963-B963-7576E9F1D01E}.Debug|x64.ActiveCfg = Debug|x64 @@ -172,4 +171,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {09A990FB-0F69-497E-AB3E-03CDDBFA57FB} + EndGlobalSection EndGlobal diff --git a/ScyllaHideGenericPlugin/ScyllaHideGenericPlugin.cpp b/ScyllaHideGenericPlugin/ScyllaHideGenericPlugin.cpp index 5985cdc6..74d1b974 100644 --- a/ScyllaHideGenericPlugin/ScyllaHideGenericPlugin.cpp +++ b/ScyllaHideGenericPlugin/ScyllaHideGenericPlugin.cpp @@ -6,7 +6,8 @@ #include #include "..\PluginGeneric\Injector.h" - + +//---------------------------------------------------------------------------------- struct HookStatus { HookStatus() @@ -21,12 +22,12 @@ struct HookStatus bool specialPebFix; }; -typedef void(__cdecl * t_AttachProcess)(DWORD dwPID); +typedef void (__cdecl * t_AttachProcess)(DWORD dwPID); #ifdef _WIN64 -const WCHAR g_scyllaHideDllFilename[] = L"HookLibraryx64.dll"; + const WCHAR g_scyllaHideDllFilename[] = L"HookLibraryx64.dll"; #else -const WCHAR g_scyllaHideDllFilename[] = L"HookLibraryx86.dll"; + const WCHAR g_scyllaHideDllFilename[] = L"HookLibraryx86.dll"; #endif scl::Settings g_settings; @@ -39,17 +40,20 @@ HOOK_DLL_DATA g_hdd; //globals static HMODULE hNtdllModule = 0; static std::unordered_map hookStatusMap; - + +//---------------------------------------------------------------------------------- static void LogCallback(const wchar_t *msg) { _putws(msg); } - + +//---------------------------------------------------------------------------------- DLL_EXPORT void ScyllaHideDebugLoop(const DEBUG_EVENT* DebugEvent) { auto pid = DebugEvent->dwProcessId; auto status = HookStatus(); - auto found = hookStatusMap.find(pid); + auto found = hookStatusMap.find(pid); + if (found == hookStatusMap.end()) hookStatusMap[pid] = status; else @@ -72,69 +76,72 @@ DLL_EXPORT void ScyllaHideDebugLoop(const DEBUG_EVENT* DebugEvent) switch (DebugEvent->dwDebugEventCode) { - case CREATE_PROCESS_DEBUG_EVENT: - { - status.ProcessId = DebugEvent->dwProcessId; - status.bHooked = false; - ZeroMemory(&g_hdd, sizeof(HOOK_DLL_DATA)); - - if (DebugEvent->u.CreateProcessInfo.lpStartAddress == NULL) + case CREATE_PROCESS_DEBUG_EVENT: { - //ATTACH - if (g_settings.opts().killAntiAttach) + status.ProcessId = DebugEvent->dwProcessId; + status.bHooked = false; + ZeroMemory(&g_hdd, sizeof(HOOK_DLL_DATA)); + + if (DebugEvent->u.CreateProcessInfo.lpStartAddress == NULL) { - if (!ApplyAntiAntiAttach(status.ProcessId)) + //ATTACH + if (g_settings.opts().killAntiAttach) { - g_log.LogError(L"Anti-Anti-Attach failed"); + if (!ApplyAntiAntiAttach(status.ProcessId)) + { + g_log.LogError(L"Anti-Anti-Attach failed"); + } } } - } - break; - } + break; + } - case LOAD_DLL_DEBUG_EVENT: - { - if (status.bHooked) + case LOAD_DLL_DEBUG_EVENT: { - startInjection(status.ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), false); - } + if (status.bHooked) + startInjection(status.ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), false); - break; - } + break; + } - case EXCEPTION_DEBUG_EVENT: - { - switch (DebugEvent->u.Exception.ExceptionRecord.ExceptionCode) + case EXCEPTION_DEBUG_EVENT: { - case STATUS_BREAKPOINT: - { - if (!status.bHooked) + switch (DebugEvent->u.Exception.ExceptionRecord.ExceptionCode) { - ReadNtApiInformation(&g_hdd); + case STATUS_BREAKPOINT: + { + if (!status.bHooked) + { + ReadNtApiInformation(&g_hdd); + + status.bHooked = true; + startInjection(status.ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + } - status.bHooked = true; - startInjection(status.ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + break; + } } break; } - } - - break; - } } hookStatusMap[pid] = status; } - + +//---------------------------------------------------------------------------------- DLL_EXPORT void ScyllaHideReset() { ZeroMemory(&g_hdd, sizeof(HOOK_DLL_DATA)); hookStatusMap.clear(); } - -DLL_EXPORT void ScyllaHideInit(const WCHAR* Directory, LOGWRAPPER Logger, LOGWRAPPER ErrorLogger) + +//---------------------------------------------------------------------------------- +DLL_EXPORT void ScyllaHideInit( + const WCHAR *Directory, + LOGWRAPPER Logger, + LOGWRAPPER ErrorLogger) { hNtdllModule = GetModuleHandleW(L"ntdll.dll"); diff --git a/ScyllaHideIDAProPlugin/IdaServerClient.cpp b/ScyllaHideIDAProPlugin/IdaServerClient.cpp index fc73aa47..8537b6b6 100644 --- a/ScyllaHideIDAProPlugin/IdaServerClient.cpp +++ b/ScyllaHideIDAProPlugin/IdaServerClient.cpp @@ -10,13 +10,13 @@ extern scl::Settings g_settings; - SOCKET serverSock = INVALID_SOCKET; WSADATA wsaData; IDA_SERVER_EXCHANGE idaExchange = {0}; extern wchar_t DllPathForInjection[MAX_PATH]; - + +//---------------------------------------------------------------------------------- bool StartWinsock() { bool isWinsockUp = true; @@ -29,59 +29,61 @@ bool StartWinsock() return isWinsockUp; } - + +//---------------------------------------------------------------------------------- bool SendInjectToServer(unsigned long ProcessId) { return SendEventToServer(inject_dll, ProcessId); } - + +//---------------------------------------------------------------------------------- bool SendEventToServer(unsigned long notif_code, unsigned long ProcessId) { idaExchange.notif_code = notif_code; idaExchange.ProcessId = ProcessId; - idaExchange.EnablePebBeingDebugged = g_settings.opts().fixPebBeingDebugged; - idaExchange.EnablePebHeapFlags = g_settings.opts().fixPebHeapFlags; - idaExchange.EnablePebNtGlobalFlag = g_settings.opts().fixPebNtGlobalFlag; - idaExchange.EnablePebStartupInfo = g_settings.opts().fixPebStartupInfo; - idaExchange.EnablePebOsBuildNumber = g_settings.opts().fixPebOsBuildNumber; - idaExchange.EnableOutputDebugStringHook = g_settings.opts().hookOutputDebugStringA; - idaExchange.EnableNtSetInformationThreadHook = g_settings.opts().hookNtSetInformationThread; + idaExchange.EnablePebBeingDebugged = g_settings.opts().fixPebBeingDebugged; + idaExchange.EnablePebHeapFlags = g_settings.opts().fixPebHeapFlags; + idaExchange.EnablePebNtGlobalFlag = g_settings.opts().fixPebNtGlobalFlag; + idaExchange.EnablePebStartupInfo = g_settings.opts().fixPebStartupInfo; + idaExchange.EnablePebOsBuildNumber = g_settings.opts().fixPebOsBuildNumber; + idaExchange.EnableOutputDebugStringHook = g_settings.opts().hookOutputDebugStringA; + idaExchange.EnableNtSetInformationThreadHook = g_settings.opts().hookNtSetInformationThread; idaExchange.EnableNtQueryInformationProcessHook = g_settings.opts().hookNtQueryInformationProcess; - idaExchange.EnableNtQuerySystemInformationHook = g_settings.opts().hookNtQuerySystemInformation; - idaExchange.EnableNtQueryObjectHook = g_settings.opts().hookNtQueryObject; - idaExchange.EnableNtYieldExecutionHook = g_settings.opts().hookNtYieldExecution; - idaExchange.EnableNtCloseHook = g_settings.opts().hookNtClose; - idaExchange.EnableNtCreateThreadExHook = g_settings.opts().hookNtCreateThreadEx; - idaExchange.EnablePreventThreadCreation = g_settings.opts().preventThreadCreation; - - idaExchange.EnableNtGetContextThreadHook = g_settings.opts().hookNtGetContextThread; - idaExchange.EnableNtSetContextThreadHook = g_settings.opts().hookNtSetContextThread; - idaExchange.EnableNtContinueHook = g_settings.opts().hookNtContinue; + idaExchange.EnableNtQuerySystemInformationHook = g_settings.opts().hookNtQuerySystemInformation; + idaExchange.EnableNtQueryObjectHook = g_settings.opts().hookNtQueryObject; + idaExchange.EnableNtYieldExecutionHook = g_settings.opts().hookNtYieldExecution; + idaExchange.EnableNtCloseHook = g_settings.opts().hookNtClose; + idaExchange.EnableNtCreateThreadExHook = g_settings.opts().hookNtCreateThreadEx; + idaExchange.EnablePreventThreadCreation = g_settings.opts().preventThreadCreation; + + idaExchange.EnableNtGetContextThreadHook = g_settings.opts().hookNtGetContextThread; + idaExchange.EnableNtSetContextThreadHook = g_settings.opts().hookNtSetContextThread; + idaExchange.EnableNtContinueHook = g_settings.opts().hookNtContinue; idaExchange.EnableKiUserExceptionDispatcherHook = g_settings.opts().hookKiUserExceptionDispatcher; - idaExchange.EnableNtSetInformationProcessHook = g_settings.opts().hookNtSetInformationProcess; - idaExchange.EnableMalwareRunPeUnpacker = g_settings.opts().malwareRunpeUnpacker; - - idaExchange.EnableGetTickCountHook = g_settings.opts().hookGetTickCount; - idaExchange.EnableGetTickCount64Hook = g_settings.opts().hookGetTickCount64; - idaExchange.EnableGetLocalTimeHook = g_settings.opts().hookGetLocalTime; - idaExchange.EnableGetSystemTimeHook = g_settings.opts().hookGetSystemTime; - idaExchange.EnableNtQuerySystemTimeHook = g_settings.opts().hookNtQuerySystemTime; + idaExchange.EnableNtSetInformationProcessHook = g_settings.opts().hookNtSetInformationProcess; + idaExchange.EnableMalwareRunPeUnpacker = g_settings.opts().malwareRunpeUnpacker; + + idaExchange.EnableGetTickCountHook = g_settings.opts().hookGetTickCount; + idaExchange.EnableGetTickCount64Hook = g_settings.opts().hookGetTickCount64; + idaExchange.EnableGetLocalTimeHook = g_settings.opts().hookGetLocalTime; + idaExchange.EnableGetSystemTimeHook = g_settings.opts().hookGetSystemTime; + idaExchange.EnableNtQuerySystemTimeHook = g_settings.opts().hookNtQuerySystemTime; idaExchange.EnableNtQueryPerformanceCounterHook = g_settings.opts().hookNtQueryPerformanceCounter; - idaExchange.EnableNtUserBlockInputHook = g_settings.opts().hookNtUserBlockInput; - idaExchange.EnableNtUserFindWindowExHook = g_settings.opts().hookNtUserFindWindowEx; - idaExchange.EnableNtUserBuildHwndListHook = g_settings.opts().hookNtUserBuildHwndList; - idaExchange.EnableNtUserQueryWindowHook = g_settings.opts().hookNtUserQueryWindow; + idaExchange.EnableNtUserBlockInputHook = g_settings.opts().hookNtUserBlockInput; + idaExchange.EnableNtUserFindWindowExHook = g_settings.opts().hookNtUserFindWindowEx; + idaExchange.EnableNtUserBuildHwndListHook = g_settings.opts().hookNtUserBuildHwndList; + idaExchange.EnableNtUserQueryWindowHook = g_settings.opts().hookNtUserQueryWindow; idaExchange.EnableNtUserGetForegroundWindowHook = g_settings.opts().hookNtUserGetForegroundWindow; - idaExchange.EnableNtSetDebugFilterStateHook = g_settings.opts().hookNtSetDebugFilterState; - idaExchange.DllInjectNormal = g_settings.opts().dllNormal; - idaExchange.DllInjectStealth = g_settings.opts().dllStealth; - idaExchange.UnloadDllAfterInjection = g_settings.opts().dllUnload; + idaExchange.EnableNtSetDebugFilterStateHook = g_settings.opts().hookNtSetDebugFilterState; + idaExchange.DllInjectNormal = g_settings.opts().dllNormal; + idaExchange.DllInjectStealth = g_settings.opts().dllStealth; + idaExchange.UnloadDllAfterInjection = g_settings.opts().dllUnload; + idaExchange.KillAntiAttach = g_settings.opts().killAntiAttach; wcscpy_s(idaExchange.DllPathForInjection, DllPathForInjection); - int iResult = send(serverSock, (char*)&idaExchange, (int)sizeof(IDA_SERVER_EXCHANGE), 0); if (iResult == SOCKET_ERROR) { @@ -96,42 +98,40 @@ bool SendEventToServer(unsigned long notif_code, unsigned long ProcessId) if (iResult == sizeof(IDA_SERVER_EXCHANGE)) { if (idaExchange.result == RESULT_SUCCESS) - { return true; - } } return false; } - + +//---------------------------------------------------------------------------------- void CloseServerSocket() { closesocket(serverSock); serverSock = INVALID_SOCKET; } - -bool ConnectToServer(const char * host, const char * port) + +//---------------------------------------------------------------------------------- +bool ConnectToServer(const char *host, const char *port) { int iResult; - struct addrinfo *result = NULL, - *ptr = NULL, - hints; + struct addrinfo *result = NULL, hints; - ZeroMemory( &hints, sizeof(hints) ); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; // Resolve the server address and port iResult = getaddrinfo(host, port, &hints, &result); - if ( iResult != 0 ) + if (iResult != 0) { //printf("getaddrinfo failed with error: %d\n", iResult); return false; } // Attempt to connect to an address until one succeeds - for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) + for (auto ptr=result; ptr != NULL ;ptr=ptr->ai_next) { // Create a SOCKET for connecting to server @@ -168,22 +168,23 @@ bool ConnectToServer(const char * host, const char * port) return true; } } - + +//---------------------------------------------------------------------------------- //input: tcp:port=5000,server=localhost //OR //input: IP //IDA v6 BUG!!!!!!! -bool GetHost(char * input, char * output) +bool GetHost(const qstring& input, qstring& output) { - char * t = strstr(input, "server="); + const char *t = strstr(input.c_str(), "server="); if (t) { t += 7; - strcpy(output, t); + output = t; } else { - strcpy(output, input); + output = input; } return true; diff --git a/ScyllaHideIDAProPlugin/IdaServerClient.h b/ScyllaHideIDAProPlugin/IdaServerClient.h index bb67328a..26140998 100644 --- a/ScyllaHideIDAProPlugin/IdaServerClient.h +++ b/ScyllaHideIDAProPlugin/IdaServerClient.h @@ -1,8 +1,10 @@ #pragma once + +#include bool StartWinsock(); bool ConnectToServer(const char * host, const char * port); bool SendEventToServer(unsigned long notif_code, unsigned long ProcessId); void CloseServerSocket(); -bool GetHost(char * input, char * output); +bool GetHost(const qstring &input, qstring &output); bool SendInjectToServer(unsigned long ProcessId); diff --git a/ScyllaHideIDAProPlugin/ScyllaHideIDAProPlugin.cpp b/ScyllaHideIDAProPlugin/ScyllaHideIDAProPlugin.cpp index 8d35662a..0b2c201e 100644 --- a/ScyllaHideIDAProPlugin/ScyllaHideIDAProPlugin.cpp +++ b/ScyllaHideIDAProPlugin/ScyllaHideIDAProPlugin.cpp @@ -1,22 +1,11 @@ -#define USE_STANDARD_FILE_FUNCTIONS -#pragma warning(disable : 4996 4512 4127 4201) - - -//for 64bit - p64 -#ifdef BUILD_IDA_64BIT -#define __EA64__ -#pragma comment(lib, "x86_win_vc_64/ida.lib") +#ifdef __EA64__ + #pragma comment(lib, "x64_win_vc_64/ida.lib") #else -//for 32bit - plw -#pragma comment(lib, "x86_win_vc_32/ida.lib") + #pragma comment(lib, "x64_win_vc_32/ida.lib") #endif #include -#include -#include -#include -#include -#include + #include #include #include @@ -27,58 +16,58 @@ #include "..\PluginGeneric\OptionsDialog.h" #include "IdaServerClient.h" #include "resource.h" + +#pragma warning(push) +#pragma warning(disable: 4267 4244 4305 4309) +#include +#include +#include +#include +#include +#pragma warning(pop) -typedef void(__cdecl * t_AttachProcess)(DWORD dwPID); +typedef void (__cdecl * t_AttachProcess)(DWORD dwPID); extern t_AttachProcess _AttachProcess; -const WCHAR g_scyllaHideDllFilename[] = L"HookLibraryx86.dll"; +const WCHAR g_scyllaHideDllFilename[] = L"HookLibraryx86.dll"; const WCHAR g_scyllaHidex64ServerFilename[] = L"ScyllaHideIDAServerx64.exe"; -scl::Settings g_settings; -scl::Logger g_log; -std::wstring g_scyllaHideDllPath; -std::wstring g_scyllaHideIniPath; -std::wstring g_scyllaHidex64ServerPath; +scl::Settings g_settings; +scl::Logger g_log; +std::wstring g_scyllaHideDllPath; +std::wstring g_scyllaHideIniPath; +std::wstring g_scyllaHidex64ServerPath; -HOOK_DLL_DATA g_hdd; +HOOK_DLL_DATA g_hdd; -//globals -HINSTANCE hinst; -DWORD ProcessId = 0; -bool bHooked = false; -HMODULE hNtdllModule = 0; +// Globals +HINSTANCE hinst; +DWORD ProcessId = 0; +bool bHooked = false; +HMODULE hNtdllModule = 0; PROCESS_INFORMATION ServerProcessInfo = { 0 }; -STARTUPINFO ServerStartupInfo = { 0 }; -bool isAttach = false; +STARTUPINFO ServerStartupInfo = { 0 }; +bool isAttach = false; +//---------------------------------------------------------------------------------- static void LogCallback(const char *message) { msg("[%s] %s\n", SCYLLA_HIDE_NAME_A, message); } +//---------------------------------------------------------------------------------- static void AttachProcess(DWORD dwPID) { int res = attach_process((pid_t)dwPID); - switch (res) { - case -1: - { - MessageBoxA((HWND)callui(ui_get_hwnd).vptr, - "Can't attach to that process !", - "ScyllaHide Plugin", MB_OK | MB_ICONERROR); - break; - } - case -2: - { - MessageBoxA((HWND)callui(ui_get_hwnd).vptr, - "Can't find that PID !", - "ScyllaHide Plugin", MB_OK | MB_ICONERROR); - break; - } - } + if (res == -1) + warning("Can't attach to that process !"); + else if (res == -2) + warning("Can't find that PID !"); } +//---------------------------------------------------------------------------------- static bool SetDebugPrivileges() { TOKEN_PRIVILEGES Debug_Privileges; @@ -97,109 +86,114 @@ static bool SetDebugPrivileges() CloseHandle(hToken); } } - return retVal; } -//callback for various debug events -static int idaapi debug_mainloop(void *user_data, int notif_code, va_list va) +//---------------------------------------------------------------------------------- +static void RunScyllaHideServer() { - switch (notif_code) + if (!scl::FileExistsW(g_scyllaHidex64ServerPath.c_str())) + g_log.LogError(L"Cannot find server executable %s\n", g_scyllaHidex64ServerPath.c_str()); + + DWORD dwRunningStatus = 0; + if (ServerProcessInfo.hProcess) + GetExitCodeProcess(ServerProcessInfo.hProcess, &dwRunningStatus); + + if (dwRunningStatus != STILL_ACTIVE) { - case dbg_process_attach: + if (ServerProcessInfo.hProcess) + { + CloseHandle(ServerProcessInfo.hProcess); + CloseHandle(ServerProcessInfo.hThread); + } + + ZeroMemory(&ServerStartupInfo, sizeof(ServerStartupInfo)); + ZeroMemory(&ServerProcessInfo, sizeof(ServerProcessInfo)); + + WCHAR commandline[MAX_PATH * 2] = { 0 }; + wcscpy(commandline, g_scyllaHidex64ServerPath.c_str()); + wcscat(commandline, L" "); + wcscat(commandline, g_settings.opts().idaServerPort.c_str()); + ServerStartupInfo.cb = sizeof(ServerStartupInfo); + if (!CreateProcessW(0, commandline, NULL, NULL, FALSE, 0, NULL, NULL, &ServerStartupInfo, &ServerProcessInfo)) + g_log.LogError(L"Cannot start server, error %d", GetLastError()); + else + g_log.LogInfo(L"Started IDA Server successfully"); + } +} + +//---------------------------------------------------------------------------------- +static bool DoConnectToServer() +{ + qstring hoststring; + qstring host; + char port[6] = { 0 }; + wcstombs(port, g_settings.opts().idaServerPort.c_str(), _countof(port)); + + get_process_options(NULL, NULL, NULL, &hoststring, NULL, NULL); + GetHost(hoststring, host); +#ifdef __EA64__ + // Autostart server if necessary + if (g_settings.opts().idaAutoStartServer) + RunScyllaHideServer(); +#endif + if (!ConnectToServer(host.c_str(), port)) { - isAttach = true; - break; //attaching not supported + g_log.LogError(L"Cannot connect to host %s", host); + return false; } - case dbg_process_start: + return true; +} + +//---------------------------------------------------------------------------------- +static ssize_t idaapi debug_mainloop( + void *user_data, + int notif_code, + va_list va) +{ + switch (notif_code) { - isAttach = false; + case dbg_process_attach: + { + if (!dbg->is_remote()) + break; + + auto dbgEvent = va_arg(va, const debug_event_t *); + ProcessId = dbgEvent->pid; + + isAttach = true; + bHooked = false; + + if (DoConnectToServer()) + { + if (!SendEventToServer(notif_code, ProcessId)) + g_log.LogError(L"SendEventToServer failed"); + } + + break; + } - const debug_event_t* dbgEvent = va_arg(va, const debug_event_t*); + case dbg_process_start: + { + auto dbgEvent = va_arg(va, const debug_event_t *); + ProcessId = dbgEvent->pid; - ProcessId = dbgEvent->pid; - bHooked = false; - ZeroMemory(&g_hdd, sizeof(HOOK_DLL_DATA)); + isAttach = false; + bHooked = false; - if (dbg != nullptr) - { - //char text[1000]; - //wsprintfA(text, "dbg->id %d processor %s", dbg->id , dbg->processor); - //MessageBoxA(0, text, text,0); - // dbg->id DEBUGGER_ID_WINDBG -> 64bit and 32bit - // dbg->id DEBUGGER_ID_X86_IA32_WIN32_USER -> 32bit + ZeroMemory(&g_hdd, sizeof(HOOK_DLL_DATA)); if (dbg->is_remote()) { - qstring hoststring; - char host[MAX_PATH] = { 0 }; - char port[6] = { 0 }; - wcstombs(port, g_settings.opts().idaServerPort.c_str(), _countof(port)); - - get_process_options(NULL, NULL, NULL, &hoststring, NULL, NULL); - GetHost((char*)hoststring.c_str(), host); - - //msg("Host-String: %s\n", hoststring.c_str()); - //msg("Host: %s\n", host); - -#ifdef BUILD_IDA_64BIT - //autostart server if necessary - if(g_settings.opts().idaAutoStartServer) - { - if (!scl::FileExistsW(g_scyllaHidex64ServerPath.c_str())) - { - g_log.LogError(L"Cannot find server executable %s\n", g_scyllaHidex64ServerPath.c_str()); - } - - DWORD dwRunningStatus = 0; - if (ServerProcessInfo.hProcess) - { - GetExitCodeProcess(ServerProcessInfo.hProcess, &dwRunningStatus); - } - - if(dwRunningStatus != STILL_ACTIVE) - { - if (ServerProcessInfo.hProcess) - { - CloseHandle(ServerProcessInfo.hProcess); - CloseHandle(ServerProcessInfo.hThread); - } - - ZeroMemory(&ServerStartupInfo, sizeof(ServerStartupInfo)); - ZeroMemory(&ServerProcessInfo, sizeof(ServerProcessInfo)); - - WCHAR commandline[MAX_PATH*2] = {0}; - wcscpy(commandline, g_scyllaHidex64ServerPath.c_str()); - wcscat(commandline, L" "); - wcscat(commandline, g_settings.opts().idaServerPort.c_str()); - ServerStartupInfo.cb = sizeof(ServerStartupInfo); - if (!CreateProcessW(0, commandline, NULL, NULL, FALSE, 0, NULL, NULL, &ServerStartupInfo, &ServerProcessInfo)) - { - g_log.LogError(L"Cannot start server, error %d", GetLastError()); - } - else - { - g_log.LogInfo(L"Started IDA Server successfully"); - } - } - } -#endif - if (ConnectToServer(host, port)) + if (DoConnectToServer()) { if (!SendEventToServer(notif_code, ProcessId)) - { g_log.LogError(L"SendEventToServer failed"); - } - } - else - { - g_log.LogError(L"Cannot connect to host %s", host); } } else { - -#ifndef BUILD_IDA_64BIT +#ifndef __EA64__ if (!scl::IsWindows64() && !bHooked) // Only apply on native x86 OS, see dbg_library_unload below { ReadNtApiInformation(&g_hdd); @@ -211,102 +205,126 @@ static int idaapi debug_mainloop(void *user_data, int notif_code, va_list va) g_log.LogError(L"Error IDA_64BIT please contact ScyllaHide developers!"); #endif } + break; } - } - break; - - case dbg_process_exit: - { - if (!isAttach && dbg->is_remote()) + + case dbg_process_detach: + case dbg_process_exit: { - if (!SendEventToServer(notif_code, ProcessId)) + if (dbg->is_remote()) { - g_log.LogError(L"SendEventToServer failed"); - } + if (!SendEventToServer(notif_code, ProcessId)) + g_log.LogError(L"SendEventToServer failed"); - CloseServerSocket(); + CloseServerSocket(); + } + bHooked = false; + break; } - ProcessId = 0; - bHooked = false; - } - break; - case dbg_library_load: - { - - if (!isAttach && dbg->is_remote()) + case dbg_library_load: { - if (!SendEventToServer(notif_code, ProcessId)) + if (!isAttach && dbg->is_remote()) { - g_log.LogError(L"SendEventToServer failed"); + if (!SendEventToServer(notif_code, ProcessId)) + g_log.LogError(L"SendEventToServer failed"); } - } - else if (!isAttach) - { -#ifndef BUILD_IDA_64BIT - if (bHooked) + else if (!isAttach) { - startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), false); - } +#ifndef __EA64__ + if (bHooked) + startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), false); #endif + } + break; } - } - break; - -#ifndef BUILD_IDA_64BIT - case dbg_library_unload: - { - if (scl::IsWindows64() && !bHooked) +#ifndef __EA64__ + case dbg_library_unload: { - // Bogus unload event which is actually a load of a native x64 DLL (ntdll, wow64, wow64cpu, wow64win) - ReadNtApiInformation(&g_hdd); + if (scl::IsWindows64() && !bHooked) + { + // Bogus unload event which is actually a load of a native x64 DLL (ntdll, wow64, wow64cpu, wow64win) + ReadNtApiInformation(&g_hdd); - bHooked = true; - startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + bHooked = true; + startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + } + break; } - } - break; #endif + case dbg_bpt: + { + thid_t tid = va_arg(va, thid_t); + ea_t breakpoint_ea = va_arg(va, ea_t); + va_arg(va, int*); + break; + } - case dbg_bpt: - { - thid_t tid = va_arg(va, thid_t); - ea_t breakpoint_ea = va_arg(va, ea_t); - va_arg(va, int*); - } - break; - - case dbg_exception: - { - const debug_event_t* dbgEvent = va_arg(va, const debug_event_t*); - - } - break; + case dbg_exception: + { + const debug_event_t* dbgEvent = va_arg(va, const debug_event_t*); + break; + } } return 0; } -//cleanup on plugin unload +//---------------------------------------------------------------------------------- +// Cleanup on plugin unload static void idaapi IDAP_term(void) { unhook_from_notification_point(HT_DBG, debug_mainloop, NULL); } -//called when user clicks in plugin menu or presses hotkey -static void idaapi IDAP_run(int arg) +//---------------------------------------------------------------------------------- +// Called when user clicks in plugin menu or presses hotkey +static bool idaapi IDAP_run(size_t arg) { - DialogBoxW(hinst, MAKEINTRESOURCE(IDD_OPTIONS), (HWND)callui(ui_get_hwnd).vptr, &OptionsDlgProc); + DialogBoxW( + hinst, + MAKEINTRESOURCE(IDD_OPTIONS), + GetForegroundWindow(), + &OptionsDlgProc); + return true; } -//init the plugin -static int idaapi IDAP_init(void) +//---------------------------------------------------------------------------------- +// Init the plugin +static plugmod_t *idaapi IDAP_init(void) { - //ensure target is PE executable - if (inf.filetype != f_PE) return PLUGIN_SKIP; + // Ensure target is PE executable + if (inf.filetype != f_PE) + return PLUGIN_SKIP; + + _AttachProcess = AttachProcess; + hNtdllModule = GetModuleHandleW(L"ntdll.dll"); + + auto wstrPath = scl::GetModuleFileNameW(hinst); + wstrPath.resize(wstrPath.find_last_of(L'\\') + 1); + + g_scyllaHideDllPath = wstrPath + g_scyllaHideDllFilename; + g_scyllaHideIniPath = wstrPath + scl::Settings::kFileName; + g_scyllaHidex64ServerPath = wstrPath + g_scyllaHidex64ServerFilename; + + auto log_file = wstrPath + scl::Logger::kFileName; + g_log.SetLogFile(log_file.c_str()); + g_log.SetLogCb(scl::Logger::Info, LogCallback); + g_log.SetLogCb(scl::Logger::Error, LogCallback); + + g_settings.Load(g_scyllaHideIniPath.c_str()); + + if (!SetDebugPrivileges()) + { + g_log.LogInfo(L"Failed to set debug privileges"); + msg("ScyllaHide: failed to set debug privileges"); + } + + if (!StartWinsock()) + warning("Failed to start Winsock!"); - //install hook for debug mainloop + // Install hook for debug mainloop if (!hook_to_notification_point(HT_DBG, debug_mainloop, NULL)) { g_log.LogError(L"Error hooking notification point"); @@ -325,16 +343,18 @@ static int idaapi IDAP_init(void) return PLUGIN_KEEP; } +//---------------------------------------------------------------------------------- // There isn't much use for these yet, but I set them anyway. -static char IDAP_comment[] = SCYLLA_HIDE_NAME_A " usermode Anti-Anti-Debug Plugin"; +static char IDAP_comment[] = SCYLLA_HIDE_NAME_A " Usermode Anti-Anti-Debug Plugin"; static char IDAP_help[] = SCYLLA_HIDE_NAME_A; // The name of the plug-in displayed in the Edit->Plugins menu static char IDAP_name[] = SCYLLA_HIDE_NAME_A; // The hot-key the user can use to run your plug-in. -static char IDAP_hotkey[] = "Alt-X"; +static char IDAP_hotkey[] = "Alt-Shift-X"; +//---------------------------------------------------------------------------------- // The all-important exported PLUGIN object idaman ida_module_data plugin_t PLUGIN = { @@ -349,37 +369,16 @@ idaman ida_module_data plugin_t PLUGIN = IDAP_hotkey }; -BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD dwReason, LPVOID lpReserved) +//---------------------------------------------------------------------------------- +BOOL WINAPI DllMain( + HINSTANCE hInstDll, + DWORD dwReason, + LPVOID lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { hinst = hInstDll; - _AttachProcess = AttachProcess; - hNtdllModule = GetModuleHandleW(L"ntdll.dll"); - - auto wstrPath = scl::GetModuleFileNameW(hInstDll); - wstrPath.resize(wstrPath.find_last_of(L'\\') + 1); - - g_scyllaHideDllPath = wstrPath + g_scyllaHideDllFilename; - g_scyllaHideIniPath = wstrPath + scl::Settings::kFileName; - g_scyllaHidex64ServerPath = wstrPath + g_scyllaHidex64ServerFilename; - - auto log_file = wstrPath + scl::Logger::kFileName; - g_log.SetLogFile(log_file.c_str()); - g_log.SetLogCb(scl::Logger::Info, LogCallback); - g_log.SetLogCb(scl::Logger::Error, LogCallback); - - g_settings.Load(g_scyllaHideIniPath.c_str()); - - if (!SetDebugPrivileges()) - { - g_log.LogInfo(L"Failed to set debug privileges"); - } - - if (!StartWinsock()) - { - MessageBoxW(0, L"Failed to start Winsock!", L"Error", MB_ICONERROR); - } + ::DisableThreadLibraryCalls(hInstDll); } return TRUE; diff --git a/ScyllaHideIDAProPlugin/ScyllaHideIDAProPlugin.vcxproj b/ScyllaHideIDAProPlugin/ScyllaHideIDAProPlugin.vcxproj index 076b8471..28818535 100644 --- a/ScyllaHideIDAProPlugin/ScyllaHideIDAProPlugin.vcxproj +++ b/ScyllaHideIDAProPlugin/ScyllaHideIDAProPlugin.vcxproj @@ -1,112 +1,189 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - 16.0 - {A94B6222-ABEF-41A0-BE48-06801157AAA5} - Win32Proj - ScyllaHideIDAProPlugin - 10.0 - - - - DynamicLibrary - true - Unicode - v142 - false - false - - - DynamicLibrary - false - true - Unicode - v142 - false - false - - - - - - - - - - - - - - - - - - - false - .plw - - - false - .plw - - - - WIN32;_DEBUG;_WINDOWS;__NT__;__IDP__;%(PreprocessorDefinitions) - - - Windows - - - - - WIN32;NDEBUG;_WINDOWS;__NT__;__IDP__;%(PreprocessorDefinitions) - - - Windows - false - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + 16.0 + {A94B6222-ABEF-41A0-BE48-06801157AAA5} + Win32Proj + ScyllaHideIDAProPlugin + 10.0 + + + + DynamicLibrary + true + Unicode + v142 + false + false + + + DynamicLibrary + true + Unicode + v142 + false + false + + + DynamicLibrary + false + true + Unicode + v142 + false + false + + + DynamicLibrary + false + true + Unicode + v142 + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + .plw + + + false + .dll + $(ProjectName)64 + $(SolutionDir)build\$(Configuration)\$(PlatformName)\ + + + false + .plw + + + false + .dll + $(ProjectName)64 + $(SolutionDir)build\$(Configuration)\$(PlatformName)\ + + + + WIN32;_DEBUG;_WINDOWS;__NT__;__IDP__;%(PreprocessorDefinitions) + $(SolutionDir);$(SolutionDir)3rdparty;$(IDASDK)\include; + + + Windows + + + + + __IDP__;__EA64__;WIN32;_DEBUG;_WINDOWS;__NT__;__IDP__;%(PreprocessorDefinitions) + $(SolutionDir);$(SolutionDir)3rdparty;$(IDASDK)\include; + + + Windows + $(SolutionDir)3rdparty;$(IDASDK)\lib;$(OutDir) + + + copy /y $(TargetPath) $(IDASDK)\bin\plugins\$(TargetFileName) + + + + + WIN32;NDEBUG;_WINDOWS;__NT__;__IDP__;%(PreprocessorDefinitions) + + + Windows + false + true + true + + + + + __IDP__;__EA64__;WIN32;NDEBUG;_WINDOWS;__NT__;__IDP__;%(PreprocessorDefinitions) + $(SolutionDir);$(SolutionDir)3rdparty;$(IDASDK)\include; + + + Windows + false + true + true + $(SolutionDir)3rdparty;$(IDASDK)\lib;$(OutDir) + + + copy /y $(TargetPath) $(IDASDK)\bin\plugins\$(TargetFileName) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ScyllaHideIDAServer/IdaServerExchange.h b/ScyllaHideIDAServer/IdaServerExchange.h index fb106439..ae07aaf3 100644 --- a/ScyllaHideIDAServer/IdaServerExchange.h +++ b/ScyllaHideIDAServer/IdaServerExchange.h @@ -1,86 +1,16 @@ #pragma once + +#pragma warning(push) +#pragma warning(disable: 4244 4267) +#include +#pragma warning(pop) #define IDA_SERVER_DEFAULT_PORT_TEXT "1337" #define IDA_SERVER_DEFAULT_PORT 1337 enum server_dbg_notification_t { - dbg_null = 0, - - // debugger low-level event notifications (see IDD.HPP for details). - - dbg_process_start, // Parameter: const debug_event_t *event - // This event notification is also an asynchronous - // function result notification for start_process() ! - - dbg_process_exit, // Parameter: const debug_event_t *event - // This event notification is also an asynchronous - // function result notification for exit_process() ! - - dbg_process_attach, // Parameter: const debug_event_t *event - // This event notification is also an asynchronous - // function result notification for attach_process() ! - - dbg_process_detach, // Parameter: const debug_event_t *event - // This event notification is also an asynchronous - // function result notification for detach_process() ! - - dbg_thread_start, // Parameter: const debug_event_t *event - - dbg_thread_exit, // Parameter: const debug_event_t *event - - dbg_library_load, // Parameter: const debug_event_t *event - - dbg_library_unload, // Parameter: const debug_event_t *event - - dbg_information, // Parameter: const debug_event_t *event - - dbg_exception, // Parameters: const debug_event_t *event - // int *warn = -1 - // Return (in *warn): - // -1 - to display an exception warning dialog - // if the process is suspended. - // 0 - to never display an exception warning dialog. - // 1 - to always display an exception warning dialog. - - // debugger high-level event notifications - - dbg_suspend_process, // The process is now suspended. - // Parameter: const debug_event_t *event - // This event notification is also an asynchronous - // function result notification for suspend_process() ! - - dbg_bpt, // A user defined breakpoint was reached. - // Parameters: thid_t tid - // ea_t bptea - // int *warn = -1 - // Return (in *warn): - // -1 - to display a breakpoint warning dialog - // if the process is suspended. - // 0 - to never display a breakpoint warning dialog. - // 1 - to always display a breakpoint warning dialog. - - dbg_trace, // A step occured (one instruction was executed). This event - // notification is only generated if step tracing is enabled. - // Parameters: thid_t tid - // ea_t ip - // Returns: 1-do not log this trace event; 0-log it - - dbg_request_error, // An error occured during the processing of a request. - // Parameters: ui_notification_t failed_command - // dbg_notification_t failed_dbg_notification - - dbg_step_into, // Parameter: const debug_event_t *event - - dbg_step_over, // Parameter: const debug_event_t *event - - dbg_run_to, // Parameter: const debug_event_t *event - - dbg_step_until_ret, // Parameter: const debug_event_t *event - - dbg_bpt_changed, // Breakpoint has been changed - - inject_dll + inject_dll = dbg_last }; #define RESULT_SUCCESS 1 @@ -89,7 +19,7 @@ enum server_dbg_notification_t typedef struct _IDA_SERVER_EXCHANGE { unsigned long result; - unsigned long notif_code; //server_dbg_notification_t + unsigned long notif_code; // IDA dbg_notification_t unsigned long ProcessId; unsigned char EnablePebBeingDebugged; @@ -112,7 +42,7 @@ typedef struct _IDA_SERVER_EXCHANGE unsigned char EnablePreventThreadCreation; unsigned char EnableNtCreateThreadExHook; - //Protect and Hide Hardware Breakpoints + // Protect and Hide hardware breakpoints unsigned char EnableNtGetContextThreadHook; unsigned char EnableNtSetContextThreadHook; unsigned char EnableNtContinueHook; @@ -131,9 +61,11 @@ typedef struct _IDA_SERVER_EXCHANGE unsigned char EnableGetSystemTimeHook; unsigned char EnableNtQuerySystemTimeHook; unsigned char EnableNtQueryPerformanceCounterHook; + + unsigned char KillAntiAttach; unsigned char DllInjectStealth; unsigned char DllInjectNormal; unsigned char UnloadDllAfterInjection; wchar_t DllPathForInjection[300]; -} IDA_SERVER_EXCHANGE; \ No newline at end of file +} IDA_SERVER_EXCHANGE; diff --git a/ScyllaHideIDAServer/ScyllaHideIDAServer.vcxproj b/ScyllaHideIDAServer/ScyllaHideIDAServer.vcxproj index 5aa4854b..e36fd78f 100644 --- a/ScyllaHideIDAServer/ScyllaHideIDAServer.vcxproj +++ b/ScyllaHideIDAServer/ScyllaHideIDAServer.vcxproj @@ -1,162 +1,166 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - 16.0 - {4506D672-19C3-439B-8E1B-F1BA8BE28844} - Win32Proj - ScyllaHideIDAServer - 10.0 - - - - Application - true - Unicode - v142 - false - false - - - Application - true - Unicode - v142 - false - false - - - Application - false - true - Unicode - v142 - false - false - - - Application - false - true - Unicode - v142 - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - $(TargetName)x86 - - - false - $(TargetName)x64 - - - false - $(TargetName)x86 - - - false - $(TargetName)x64 - - - - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - - - Console - - - - - _DEBUG;_WINDOWS;%(PreprocessorDefinitions) - - - Console - - - - - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - - - Console - - - - - NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - - - Console - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + 16.0 + {4506D672-19C3-439B-8E1B-F1BA8BE28844} + Win32Proj + ScyllaHideIDAServer + 10.0 + + + + Application + true + Unicode + v142 + false + false + + + Application + true + Unicode + v142 + false + false + + + Application + false + true + Unicode + v142 + false + false + + + Application + false + true + Unicode + v142 + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + $(TargetName)x86 + + + false + $(TargetName)x64 + + + false + $(TargetName)x86 + + + false + $(TargetName)x64 + + + + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Console + + + + + __IDP__;__EA64__;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + $(SolutionDir);$(SolutionDir)3rdparty;$(IDASDK)\include; + + + Console + $(SolutionDir)3rdparty;$(IDASDK)/lib;$(OutDir) + + + + + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Console + + + + + __IDP__;__EA64__;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + $(SolutionDir);$(SolutionDir)3rdparty;$(IDASDK)\include; + + + Console + $(SolutionDir)3rdparty;$(IDASDK)/lib;$(OutDir) + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ScyllaHideIDAServer/idaserver.cpp b/ScyllaHideIDAServer/idaserver.cpp index 13323615..3c8a47b5 100644 --- a/ScyllaHideIDAServer/idaserver.cpp +++ b/ScyllaHideIDAServer/idaserver.cpp @@ -22,18 +22,19 @@ std::wstring g_scyllaHideDllPath; HOOK_DLL_DATA g_hdd; WSADATA wsaData; -char * ListenPortString = IDA_SERVER_DEFAULT_PORT_TEXT; +char *ListenPortString = IDA_SERVER_DEFAULT_PORT_TEXT; unsigned short ListenPort = IDA_SERVER_DEFAULT_PORT; IDA_SERVER_EXCHANGE idaExchange = { 0 }; -DWORD ProcessId = 0; bool bHooked = false; - -static void LogCallback(const wchar_t * msg) + +//---------------------------------------------------------------------------------- +static void LogCallback(const wchar_t *msg) { _putws(msg); } - -static void checkPaths(const std::wstring & wstrPath) + +//---------------------------------------------------------------------------------- +static void checkPaths(const std::wstring &wstrPath) { g_scyllaHideDllPath = wstrPath + g_scyllaHideDllFilename; @@ -57,7 +58,8 @@ static void checkPaths(const std::wstring & wstrPath) ExitProcess(0); } } - + +//---------------------------------------------------------------------------------- static void startListen() { int iResult; @@ -141,83 +143,87 @@ static void startListen() WSACleanup(); } - -void MapSettings() + +//---------------------------------------------------------------------------------- +static void MapSettings() { - g_settings.opts().dllUnload = idaExchange.UnloadDllAfterInjection; - g_settings.opts().dllNormal = idaExchange.DllInjectNormal; - g_settings.opts().dllStealth = idaExchange.DllInjectStealth; + g_settings.opts().dllUnload = idaExchange.UnloadDllAfterInjection; + g_settings.opts().dllNormal = idaExchange.DllInjectNormal; + g_settings.opts().dllStealth = idaExchange.DllInjectStealth; g_settings.opts().hookKiUserExceptionDispatcher = idaExchange.EnableKiUserExceptionDispatcherHook; - g_settings.opts().hookNtClose = idaExchange.EnableNtCloseHook; - g_settings.opts().hookNtContinue = idaExchange.EnableNtCloseHook; - g_settings.opts().hookNtCreateThreadEx = idaExchange.EnableNtCreateThreadExHook; - g_settings.opts().hookNtGetContextThread = idaExchange.EnableNtGetContextThreadHook; + g_settings.opts().hookNtClose = idaExchange.EnableNtCloseHook; + g_settings.opts().hookNtContinue = idaExchange.EnableNtCloseHook; + g_settings.opts().hookNtCreateThreadEx = idaExchange.EnableNtCreateThreadExHook; + g_settings.opts().hookNtGetContextThread = idaExchange.EnableNtGetContextThreadHook; g_settings.opts().hookNtQueryInformationProcess = idaExchange.EnableNtQueryInformationProcessHook; - g_settings.opts().hookNtQueryObject = idaExchange.EnableNtQueryObjectHook; - g_settings.opts().hookNtQuerySystemInformation = idaExchange.EnableNtQuerySystemInformationHook; - g_settings.opts().hookNtSetContextThread = idaExchange.EnableNtSetContextThreadHook; - g_settings.opts().hookNtSetDebugFilterState = idaExchange.EnableNtSetDebugFilterStateHook; - g_settings.opts().hookNtSetInformationThread = idaExchange.EnableNtSetInformationThreadHook; - g_settings.opts().hookNtUserBlockInput = idaExchange.EnableNtUserBlockInputHook; - g_settings.opts().hookNtUserBuildHwndList = idaExchange.EnableNtUserBuildHwndListHook; - g_settings.opts().hookNtUserFindWindowEx = idaExchange.EnableNtUserFindWindowExHook; - g_settings.opts().hookNtUserQueryWindow = idaExchange.EnableNtUserQueryWindowHook; - g_settings.opts().hookNtYieldExecution = idaExchange.EnableNtYieldExecutionHook; - g_settings.opts().preventThreadCreation = idaExchange.EnablePreventThreadCreation; - g_settings.opts().hookOutputDebugStringA = idaExchange.EnableOutputDebugStringHook; - g_settings.opts().hookNtSetInformationProcess = idaExchange.EnableNtSetInformationProcessHook; - - g_settings.opts().hookGetTickCount = idaExchange.EnableGetTickCountHook; - g_settings.opts().hookGetTickCount64 = idaExchange.EnableGetTickCount64Hook; - g_settings.opts().hookGetLocalTime = idaExchange.EnableGetLocalTimeHook; - g_settings.opts().hookGetSystemTime = idaExchange.EnableGetSystemTimeHook; - g_settings.opts().hookNtQuerySystemTime = idaExchange.EnableNtQuerySystemTimeHook; + g_settings.opts().hookNtQueryObject = idaExchange.EnableNtQueryObjectHook; + g_settings.opts().hookNtQuerySystemInformation = idaExchange.EnableNtQuerySystemInformationHook; + g_settings.opts().hookNtSetContextThread = idaExchange.EnableNtSetContextThreadHook; + g_settings.opts().hookNtSetDebugFilterState = idaExchange.EnableNtSetDebugFilterStateHook; + g_settings.opts().hookNtSetInformationThread = idaExchange.EnableNtSetInformationThreadHook; + g_settings.opts().hookNtUserBlockInput = idaExchange.EnableNtUserBlockInputHook; + g_settings.opts().hookNtUserBuildHwndList = idaExchange.EnableNtUserBuildHwndListHook; + g_settings.opts().hookNtUserFindWindowEx = idaExchange.EnableNtUserFindWindowExHook; + g_settings.opts().hookNtUserQueryWindow = idaExchange.EnableNtUserQueryWindowHook; + g_settings.opts().hookNtYieldExecution = idaExchange.EnableNtYieldExecutionHook; + g_settings.opts().preventThreadCreation = idaExchange.EnablePreventThreadCreation; + g_settings.opts().hookOutputDebugStringA = idaExchange.EnableOutputDebugStringHook; + g_settings.opts().hookNtSetInformationProcess = idaExchange.EnableNtSetInformationProcessHook; + + g_settings.opts().hookGetTickCount = idaExchange.EnableGetTickCountHook; + g_settings.opts().hookGetTickCount64 = idaExchange.EnableGetTickCount64Hook; + g_settings.opts().hookGetLocalTime = idaExchange.EnableGetLocalTimeHook; + g_settings.opts().hookGetSystemTime = idaExchange.EnableGetSystemTimeHook; + g_settings.opts().hookNtQuerySystemTime = idaExchange.EnableNtQuerySystemTimeHook; g_settings.opts().hookNtQueryPerformanceCounter = idaExchange.EnableNtQueryPerformanceCounterHook; - g_settings.opts().fixPebBeingDebugged = idaExchange.EnablePebBeingDebugged; - g_settings.opts().fixPebHeapFlags = idaExchange.EnablePebHeapFlags; - g_settings.opts().fixPebNtGlobalFlag = idaExchange.EnablePebNtGlobalFlag; - g_settings.opts().fixPebStartupInfo = idaExchange.EnablePebStartupInfo; - - g_settings.opts().malwareRunpeUnpacker = idaExchange.EnableMalwareRunPeUnpacker; + g_settings.opts().fixPebBeingDebugged = idaExchange.EnablePebBeingDebugged; + g_settings.opts().fixPebHeapFlags = idaExchange.EnablePebHeapFlags; + g_settings.opts().fixPebNtGlobalFlag = idaExchange.EnablePebNtGlobalFlag; + g_settings.opts().fixPebStartupInfo = idaExchange.EnablePebStartupInfo; + + g_settings.opts().killAntiAttach = idaExchange.KillAntiAttach; + g_settings.opts().malwareRunpeUnpacker = idaExchange.EnableMalwareRunPeUnpacker; } - -static void DoSomeBitCheck() + +//---------------------------------------------------------------------------------- +static void DoProcessBitnessCheck(DWORD ProcessId) { - if (scl::IsWindows64()) - { - HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, ProcessId); - if (hProcess) - { + if (!scl::IsWindows64()) + return; + + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, ProcessId); + if (hProcess == NULL) + return; #ifdef _WIN64 - if (scl::IsWow64Process(hProcess)) - { - printf("WARNING: This is a 32bit process and I am 64bit!"); - getchar(); - ExitProcess(0); - } + if (scl::IsWow64Process(hProcess)) + { + printf("WARNING: This is a 32bit process and I am 64bit!"); + getchar(); + ExitProcess(0); + } #else - if (!scl::IsWow64Process(hProcess)) - { - printf("WARNING: This is a 64bit process and I am 32bit!"); - getchar(); - ExitProcess(0); - } -#endif - CloseHandle(hProcess); - } + if (!scl::IsWow64Process(hProcess)) + { + printf("WARNING: This is a 64bit process and I am 32bit!"); + getchar(); + ExitProcess(0); } +#endif + CloseHandle(hProcess); } - + +//---------------------------------------------------------------------------------- static void handleClient(SOCKET ClientSocket) { int iResult; bool once = false; - + DWORD ProcessId; do { iResult = recv(ClientSocket, (char*)&idaExchange, sizeof(IDA_SERVER_EXCHANGE), 0); + ProcessId = idaExchange.ProcessId; if (iResult == sizeof(IDA_SERVER_EXCHANGE)) { @@ -225,59 +231,61 @@ static void handleClient(SOCKET ClientSocket) switch (idaExchange.notif_code) { - case dbg_process_attach: - { - - break; - } - case dbg_process_start: - { - - ProcessId = idaExchange.ProcessId; - bHooked = false; - ZeroMemory(&g_hdd, sizeof(HOOK_DLL_DATA)); - - if (!once) + case dbg_process_attach: + case dbg_process_start: { - DoSomeBitCheck(); - once = true; + bHooked = false; + ZeroMemory(&g_hdd, sizeof(HOOK_DLL_DATA)); + + ReadNtApiInformation(&g_hdd); + + // Attach? + if (idaExchange.notif_code == dbg_process_attach && g_settings.opts().killAntiAttach) + { + if (!ApplyAntiAntiAttach(ProcessId)) + wprintf(L"Anti-Anti-Attach failed\n"); + } + + if (!once) + { + DoProcessBitnessCheck(ProcessId); + once = true; + } + + if (!bHooked) + { + bHooked = true; + startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + } + + break; } - - if (!bHooked) + + case dbg_process_exit: { - bHooked = true; - startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); - } - break; - } - case dbg_process_exit: - { + iResult = -1; // Terminate loop + break; + } - iResult = -1; //terminate loop - break; - } - case dbg_library_load: - { - - if (bHooked) + case dbg_library_load: { - startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), false); + if (bHooked) + startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), false); + break; } - break; - } - case inject_dll: - { - if (!once) + case inject_dll: { - DoSomeBitCheck(); - once = true; + if (!once) + { + DoProcessBitnessCheck(ProcessId); + once = true; + } + + injectDll(ProcessId, idaExchange.DllPathForInjection); + break; } - - injectDll(ProcessId, idaExchange.DllPathForInjection); - break; - } } idaExchange.result = RESULT_SUCCESS; @@ -298,7 +306,7 @@ static void handleClient(SOCKET ClientSocket) } while (iResult > 0); } - +//---------------------------------------------------------------------------------- static BOOL startWinsock() { BOOL isWinsockUp = TRUE; @@ -312,7 +320,8 @@ static BOOL startWinsock() return isWinsockUp; } - + +//---------------------------------------------------------------------------------- static bool SetDebugPrivileges() { TOKEN_PRIVILEGES Debug_Privileges; @@ -334,7 +343,8 @@ static bool SetDebugPrivileges() return retVal; } - + +//---------------------------------------------------------------------------------- int main(int argc, char *argv[]) { auto wstrPath = scl::GetModuleFileNameW(); @@ -365,7 +375,6 @@ int main(int argc, char *argv[]) startListen(); } - getchar(); return 0; } diff --git a/ScyllaHideX64DBGPlugin/ScyllaHideX64DBGPlugin.cpp b/ScyllaHideX64DBGPlugin/ScyllaHideX64DBGPlugin.cpp index 15039e44..aa2a42fe 100644 --- a/ScyllaHideX64DBGPlugin/ScyllaHideX64DBGPlugin.cpp +++ b/ScyllaHideX64DBGPlugin/ScyllaHideX64DBGPlugin.cpp @@ -148,62 +148,62 @@ static void cbDebugloop(CBTYPE cbType, void* callbackInfo) switch (d->DebugEvent->dwDebugEventCode) { - case CREATE_PROCESS_DEBUG_EVENT: - { - ProcessId = d->DebugEvent->dwProcessId; - bHooked = false; - ZeroMemory(&g_hdd, sizeof(HOOK_DLL_DATA)); - - if (d->DebugEvent->u.CreateProcessInfo.lpStartAddress == NULL) + case CREATE_PROCESS_DEBUG_EVENT: { - //ATTACH - if (g_settings.opts().killAntiAttach) + ProcessId = d->DebugEvent->dwProcessId; + bHooked = false; + ZeroMemory(&g_hdd, sizeof(HOOK_DLL_DATA)); + + if (d->DebugEvent->u.CreateProcessInfo.lpStartAddress == NULL) { - if (!ApplyAntiAntiAttach(ProcessId)) + //ATTACH + if (g_settings.opts().killAntiAttach) { - MessageBoxW(hwndDlg, L"Anti-Anti-Attach failed", L"Error", MB_ICONERROR); + if (!ApplyAntiAntiAttach(ProcessId)) + { + MessageBoxW(hwndDlg, L"Anti-Anti-Attach failed", L"Error", MB_ICONERROR); + } } - } - //In newest x64dbg version the auto break on attach was removed so ScyllaHide would never inject. - if (!bHooked) - { - ReadNtApiInformation(&g_hdd); + //In newest x64dbg version the auto break on attach was removed so ScyllaHide would never inject. + if (!bHooked) + { + ReadNtApiInformation(&g_hdd); - bHooked = true; - startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + bHooked = true; + startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + } } - } - break; - } - case LOAD_DLL_DEBUG_EVENT: - { - if (bHooked) - { - startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), false); + break; } - break; - } - case EXCEPTION_DEBUG_EVENT: - { - switch (d->DebugEvent->u.Exception.ExceptionRecord.ExceptionCode) + case LOAD_DLL_DEBUG_EVENT: { - case STATUS_BREAKPOINT: - { - if (!bHooked) + if (bHooked) { - ReadNtApiInformation(&g_hdd); - - bHooked = true; - startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), false); } break; } + case EXCEPTION_DEBUG_EVENT: + { + switch (d->DebugEvent->u.Exception.ExceptionRecord.ExceptionCode) + { + case STATUS_BREAKPOINT: + { + if (!bHooked) + { + ReadNtApiInformation(&g_hdd); - } + bHooked = true; + startInjection(ProcessId, &g_hdd, g_scyllaHideDllPath.c_str(), true); + } + break; + } - break; - } + } + + break; + } } } diff --git a/ScyllaTest/main.cpp b/ScyllaTest/main.cpp index 17c8763e..53550dc1 100644 --- a/ScyllaTest/main.cpp +++ b/ScyllaTest/main.cpp @@ -23,14 +23,16 @@ const bool is_x64 = false; #endif static HANDLE g_proc_handle, g_stopEvent; - + +//---------------------------------------------------------------------------------- static BOOL NTAPI CtrlHandler(ULONG) { // Signal test stop, and don't pass to next handler NtSetEvent(g_stopEvent, nullptr); return TRUE; } - + +//---------------------------------------------------------------------------------- static HANDLE GetRealCurrentProcess() { auto pseudo_handle = GetCurrentProcess(); @@ -38,7 +40,8 @@ static HANDLE GetRealCurrentProcess() DuplicateHandle(pseudo_handle, pseudo_handle, pseudo_handle, &hRealHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); return hRealHandle; } - + +//---------------------------------------------------------------------------------- static NTSTATUS GetOtherOperationCount(PULONGLONG otherOperationCount) { *otherOperationCount = 0; @@ -50,10 +53,12 @@ static NTSTATUS GetOtherOperationCount(PULONGLONG otherOperationCount) ULONG size; NTSTATUS status = NtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &size); if (status != STATUS_INFO_LENGTH_MISMATCH) - return status; + return status; + const PSYSTEM_PROCESS_INFORMATION SystemProcessInfo = (PSYSTEM_PROCESS_INFORMATION)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, size * 2); if (SystemProcessInfo == nullptr) - return STATUS_INSUFFICIENT_RESOURCES; + return STATUS_INSUFFICIENT_RESOURCES; + status = NtQuerySystemInformation(SystemProcessInformation, SystemProcessInfo, size * 2, nullptr); if (!NT_SUCCESS(status)) { @@ -85,10 +90,12 @@ static NTSTATUS GetOtherOperationCount(PULONGLONG otherOperationCount) // NtQSI(SystemExtendedProcessInformation) status = NtQuerySystemInformation(SystemExtendedProcessInformation, nullptr, 0, &size); if (status != STATUS_INFO_LENGTH_MISMATCH) - return status; + return status; + const PSYSTEM_PROCESS_INFORMATION systemExtendedProcessInfo = (PSYSTEM_PROCESS_INFORMATION)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, size * 2); if (SystemProcessInfo == nullptr) - return STATUS_INSUFFICIENT_RESOURCES; + return STATUS_INSUFFICIENT_RESOURCES; + status = NtQuerySystemInformation(SystemExtendedProcessInformation, systemExtendedProcessInfo, size * 2, nullptr); if (!NT_SUCCESS(status)) { @@ -164,20 +171,24 @@ static NTSTATUS GetOtherOperationCount(PULONGLONG otherOperationCount) if (otherOperationCountSystemProcessInformation != otherOperationCountSystemExtendedProcessInformation || otherOperationCountSystemProcessInformation != otherOperationCountSystemSessionProcessInformation || otherOperationCountSystemProcessInformation != ioCounters.OtherOperationCount) + { return STATUS_DATA_NOT_ACCEPTED; + } // Return final count *otherOperationCount = otherOperationCountSystemProcessInformation; return STATUS_SUCCESS; } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_PEB_BeingDebugged() { const auto peb = scl::GetPebAddress(g_proc_handle); SCYLLA_TEST_FAIL_IF(!peb); return SCYLLA_TEST_CHECK(peb->BeingDebugged == 0); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_Wow64PEB64_BeingDebugged() { const auto peb64 = scl::Wow64GetPeb64(g_proc_handle); @@ -185,7 +196,8 @@ static ScyllaTestResult Check_Wow64PEB64_BeingDebugged() return SCYLLA_TEST_CHECK(peb64->BeingDebugged == 0); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_PEB_NtGlobalFlag() { const DWORD bad_flags = FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS; @@ -193,7 +205,8 @@ static ScyllaTestResult Check_PEB_NtGlobalFlag() SCYLLA_TEST_FAIL_IF(!peb); return SCYLLA_TEST_CHECK((peb->NtGlobalFlag & bad_flags) == 0); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_Wow64PEB64_NtGlobalFlag() { const DWORD bad_flags = FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS; @@ -201,7 +214,8 @@ static ScyllaTestResult Check_Wow64PEB64_NtGlobalFlag() SCYLLA_TEST_FAIL_IF(!peb64); return SCYLLA_TEST_CHECK((peb64->NtGlobalFlag & bad_flags) == 0); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_PEB_HeapFlags() { const DWORD bad_flags = HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED | HEAP_SKIP_VALIDATION_CHECKS | HEAP_VALIDATE_PARAMETERS_ENABLED; @@ -221,7 +235,8 @@ static ScyllaTestResult Check_PEB_HeapFlags() return ScyllaTestOk; } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_Wow64PEB64_HeapFlags() { const DWORD bad_flags = HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED | HEAP_SKIP_VALIDATION_CHECKS | HEAP_VALIDATE_PARAMETERS_ENABLED; @@ -248,7 +263,8 @@ static ScyllaTestResult Check_Wow64PEB64_HeapFlags() return ScyllaTestOk; } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_PEB_ProcessParameters() { const auto peb = scl::GetPebAddress(g_proc_handle); @@ -258,7 +274,8 @@ static ScyllaTestResult Check_PEB_ProcessParameters() return SCYLLA_TEST_CHECK((rupp->Flags & 0x4000) != 0); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_Wow64PEB64_ProcessParameters() { const auto peb64 = scl::GetPebAddress(g_proc_handle); @@ -270,19 +287,22 @@ static ScyllaTestResult Check_Wow64PEB64_ProcessParameters() return SCYLLA_TEST_CHECK((rupp.Flags & 0x4000) != 0); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_IsDebuggerPresent() { return SCYLLA_TEST_CHECK(!IsDebuggerPresent()); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_CheckRemoteDebuggerPresent() { BOOL present; CheckRemoteDebuggerPresent(g_proc_handle, &present); return SCYLLA_TEST_CHECK(!present); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_OutputDebugStringA_LastError() { const DWORD last_error = 0xDEAD; @@ -290,7 +310,8 @@ static ScyllaTestResult Check_OutputDebugStringA_LastError() OutputDebugStringA("test"); return SCYLLA_TEST_CHECK(GetLastError() != last_error); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_OutputDebugStringA_Exception() { char text[] = "test"; @@ -308,7 +329,8 @@ static ScyllaTestResult Check_OutputDebugStringA_Exception() return ScyllaTestOk; } } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_OutputDebugStringW_Exception() { wchar_t text_w[] = L"test"; @@ -332,14 +354,16 @@ static ScyllaTestResult Check_OutputDebugStringW_Exception() return ScyllaTestOk; } } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_NtQueryInformationProcess_ProcessDebugPort() { HANDLE handle = nullptr; SCYLLA_TEST_FAIL_IF(!NT_SUCCESS(NtQueryInformationProcess(g_proc_handle, ProcessDebugPort, &handle, sizeof(handle), nullptr))); return SCYLLA_TEST_CHECK(handle == nullptr); } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_NtQuerySystemInformation_KernelDebugger() { SYSTEM_KERNEL_DEBUGGER_INFORMATION SysKernDebInfo; @@ -347,12 +371,12 @@ static ScyllaTestResult Check_NtQuerySystemInformation_KernelDebugger() SCYLLA_TEST_FAIL_IF(!NT_SUCCESS(NtQuerySystemInformation(SystemKernelDebuggerInformation, &SysKernDebInfo, sizeof(SysKernDebInfo), NULL))); if (SysKernDebInfo.KernelDebuggerEnabled || !SysKernDebInfo.KernelDebuggerNotPresent) - { return ScyllaTestDetected; - } + return ScyllaTestOk; } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_NtQuery_OverlappingReturnLength() // https://github.com/x64dbg/ScyllaHide/issues/47 { UCHAR Buffer[sizeof(OBJECT_TYPE_INFORMATION) + 64]; @@ -380,7 +404,8 @@ static ScyllaTestResult Check_NtQuery_OverlappingReturnLength() // https://githu return ScyllaTestOk; } - + +//---------------------------------------------------------------------------------- static ScyllaTestResult Check_NtClose() { __try @@ -395,8 +420,10 @@ static ScyllaTestResult Check_NtClose() : ScyllaTestFail; } } - -static ScyllaTestResult Check_OtherOperationCount() // https://everdox.blogspot.com/2013/11/debugger-detection-with.html + +//---------------------------------------------------------------------------------- +// https://everdox.blogspot.com/2013/11/debugger-detection-with.html +static ScyllaTestResult Check_OtherOperationCount() { // Open some file IO_STATUS_BLOCK ioStatusBlock; @@ -473,7 +500,8 @@ static ScyllaTestResult Check_OtherOperationCount() // https://everdox.blogspot. ? ScyllaTestDetected : ScyllaTestOk; } - + +//---------------------------------------------------------------------------------- static void PrintScyllaTestResult(ScyllaTestResult result, ULONG charsPrinted) { // Neither stdout nor GetStdHandle() work and I cba with this kernel32/CRT shit anymore. Pay me @@ -488,37 +516,30 @@ static void PrintScyllaTestResult(ScyllaTestResult result, ULONG charsPrinted) switch (result) { - case ScyllaTestOk: - { - SetConsoleTextAttribute(stdOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY); - printf("OK\n"); - break; - } - case ScyllaTestFail: - { - SetConsoleTextAttribute(stdOut, FOREGROUND_RED | BACKGROUND_BLUE | FOREGROUND_INTENSITY); - printf("FAIL\n"); - break; - } - case ScyllaTestDetected: - { - SetConsoleTextAttribute(stdOut, FOREGROUND_RED | FOREGROUND_INTENSITY); - printf("DETECTED\n"); - break; - } - case ScyllaTestSkip: - { - SetConsoleTextAttribute(stdOut, FOREGROUND_GREEN | FOREGROUND_BLUE); - printf("SKIP\n"); - break; - } - default: - printf("UNKNOWN\n"); - break; + case ScyllaTestOk: + SetConsoleTextAttribute(stdOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY); + printf("OK\n"); + break; + case ScyllaTestFail: + SetConsoleTextAttribute(stdOut, FOREGROUND_RED | BACKGROUND_BLUE | FOREGROUND_INTENSITY); + printf("FAIL\n"); + break; + case ScyllaTestDetected: + SetConsoleTextAttribute(stdOut, FOREGROUND_RED | FOREGROUND_INTENSITY); + printf("DETECTED\n"); + break; + case ScyllaTestSkip: + SetConsoleTextAttribute(stdOut, FOREGROUND_GREEN | FOREGROUND_BLUE); + printf("SKIP\n"); + break; + default: + printf("UNKNOWN\n"); + break; } SetConsoleTextAttribute(stdOut, defaultColours); } - + +//---------------------------------------------------------------------------------- static bool OpenConsole() { if (!AllocConsole()) @@ -537,11 +558,19 @@ static bool OpenConsole() return true; } - -int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) + +//---------------------------------------------------------------------------------- +int WINAPI wWinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, + int nCmdShow) { if (!OpenConsole()) return -1; + + // Command line argument to give a chance to pause the test, inject the ScyllaHide, then resume + bool bPauseAtStart = lpCmdLine != nullptr && wcsstr(lpCmdLine, L"--pause-at-start"); g_proc_handle = GetRealCurrentProcess(); if (g_proc_handle == INVALID_HANDLE_VALUE) @@ -558,7 +587,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi } WCHAR title[64]; - _snwprintf_s(title, sizeof(title), L"[ScyllaTest] PID: %u", (ULONG)(ULONG_PTR)NtCurrentTeb()->ClientId.UniqueProcess); + _snwprintf_s(title, sizeof(title), L"[ScyllaTest] PID: %u", ULONG(ULONG_PTR(NtCurrentTeb()->ClientId.UniqueProcess))); SetConsoleTitleW(title); auto is_wow64 = scl::IsWow64Process(g_proc_handle); @@ -566,10 +595,27 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi return -1; #define SCYLLA_TEST_IF(condition, x) \ - { ULONG n = printf("%s: ", #x); \ - if (!(condition)) { PrintScyllaTestResult(ScyllaTestSkip, n); } \ - else { auto ret = Check_ ## x(); PrintScyllaTestResult(ret, n); } } -#define SCYLLA_TEST(x) SCYLLA_TEST_IF(true, x) + { \ + ULONG n = printf("%s: ", #x); \ + if (!(condition)) \ + { \ + PrintScyllaTestResult(ScyllaTestSkip, n); \ + } \ + else \ + { \ + auto ret = Check_ ## x(); \ + PrintScyllaTestResult(ret, n); \ + } \ + } + +#define SCYLLA_TEST(x) \ + SCYLLA_TEST_IF(true, x) + + if (bPauseAtStart) + { + printf("Inject ScyllaHide then press ENTER to resume the test. Press Ctrl+C to abort the test."); + getchar(); + } printf("Starting test loop. Press CTRL+C or the power button on your PC to exit.\n\n"); while (true) diff --git a/no_NtApiCollection.bat b/no_NtApiCollection.bat new file mode 100644 index 00000000..daaa2267 --- /dev/null +++ b/no_NtApiCollection.bat @@ -0,0 +1 @@ +git difftool 6817d32581b7a420322f34e36b1a1c8c3e4b434c