Skip to content

Commit

Permalink
NtClose hook improvements: (#31)
Browse files Browse the repository at this point in the history
- Change the fast mutex guarding the NtClose hook to a kernel mutex. This is slower but safer since it prevents a deadlock in the case that NtClose recursively calls itself, which is highly unlikely but possible
- Use ObQueryObjectAuditingByHandle() to test handle validity. This has the advantage of not needing to clear and reset the process debug port each time ObCloseHandle is called. This way other kernel threads will never see a NULL debug port on a process that is actually being debugged
- Remove the DebugPort class, which was mostly a lot of hairy version specific code to find the debug port offset. This is no longer needed due to above change

Also add a bunch of casts (HANDLE to ULONG) to satisfy the VS2017 compiler
  • Loading branch information
Mattiwatti authored and mrexodia committed Sep 2, 2018
1 parent fdf6022 commit 5340a7d
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 167 deletions.
2 changes: 0 additions & 2 deletions TitanHide/TitanHide.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@
<FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="debugport.h" />
<ClInclude Include="hider.h" />
<ClInclude Include="hooklib.h" />
<ClInclude Include="hooks.h" />
Expand All @@ -149,7 +148,6 @@
<ClInclude Include="_global.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="debugport.cpp" />
<ClCompile Include="hider.cpp" />
<ClCompile Include="hooklib.cpp" />
<ClCompile Include="hooks.cpp" />
Expand Down
6 changes: 0 additions & 6 deletions TitanHide/TitanHide.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@
<ClInclude Include="ntdll.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="debugport.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="_global.cpp">
Expand Down Expand Up @@ -86,8 +83,5 @@
<ClCompile Include="ntdll.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="debugport.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
126 changes: 0 additions & 126 deletions TitanHide/debugport.cpp

This file was deleted.

12 changes: 0 additions & 12 deletions TitanHide/debugport.h

This file was deleted.

48 changes: 28 additions & 20 deletions TitanHide/hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
#include "ssdt.h"
#include "hider.h"
#include "misc.h"
#include "pe.h"
#include "log.h"
#include "debugport.h"

static HOOK hNtQueryInformationProcess = 0;
static HOOK hNtQueryObject = 0;
Expand All @@ -14,7 +12,7 @@ static HOOK hNtClose = 0;
static HOOK hNtSetInformationThread = 0;
static HOOK hNtSetContextThread = 0;
static HOOK hNtSystemDebugControl = 0;
static FAST_MUTEX gDebugPortMutex;
static KMUTEX gDebugPortMutex;

//https://forum.tuts4you.com/topic/40011-debugme-vmprotect-312-build-886-anti-debug-method-improved/#comment-192824
//https://github.com/x64dbg/ScyllaHide/issues/47
Expand All @@ -37,7 +35,7 @@ static NTSTATUS NTAPI HookNtSetInformationThread(
//Bug found by Aguila, thanks!
if(ThreadInformationClass == ThreadHideFromDebugger && !ThreadInformationLength)
{
ULONG pid = (ULONG)PsGetCurrentProcessId();
ULONG pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
if(Hider::IsHidden(pid, HideThreadHideFromDebugger))
{
Log("[TITANHIDE] ThreadHideFromDebugger by %d\r\n", pid);
Expand Down Expand Up @@ -76,22 +74,32 @@ static NTSTATUS NTAPI HookNtSetInformationThread(
static NTSTATUS NTAPI HookNtClose(
IN HANDLE Handle)
{
ULONG pid = (ULONG)PsGetCurrentProcessId();
NTSTATUS ret;
ULONG pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
if(Hider::IsHidden(pid, HideNtClose))
{
//NCC Group Security Advisory
ExAcquireFastMutex(&gDebugPortMutex);
PVOID OldDebugPort = DebugPort::Set(PsGetCurrentProcess(), 0);
ret = Undocumented::NtClose(Handle);
DebugPort::Set(PsGetCurrentProcess(), OldDebugPort);
ExReleaseFastMutex(&gDebugPortMutex);
if(!NT_SUCCESS(ret))
KeWaitForSingleObject(&gDebugPortMutex, Executive, KernelMode, FALSE, nullptr);

// Check if this is a valid handle without raising exceptionss
BOOLEAN AuditOnClose;
const NTSTATUS ObStatus = ObQueryObjectAuditingByHandle(Handle, &AuditOnClose);

NTSTATUS Status;
if(ObStatus != STATUS_INVALID_HANDLE) // Don't change the return path for any status except this one
{
Status = ObCloseHandle(Handle, PreviousMode);
}
else
{
Log("[TITANHIDE] NtClose(0x%p) by %d\r\n", Handle, pid);
Status = STATUS_INVALID_HANDLE;
}

KeReleaseMutex(&gDebugPortMutex, FALSE);

return Status;
}
else
ret = Undocumented::NtClose(Handle);
return ret;
return ObCloseHandle(Handle, PreviousMode);
}

static NTSTATUS NTAPI HookNtQuerySystemInformation(
Expand All @@ -103,7 +111,7 @@ static NTSTATUS NTAPI HookNtQuerySystemInformation(
NTSTATUS ret = Undocumented::NtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
if(NT_SUCCESS(ret) && SystemInformation)
{
ULONG pid = (ULONG)PsGetCurrentProcessId();
ULONG pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
if(SystemInformationClass == SystemKernelDebuggerInformation)
{
if(Hider::IsHidden(pid, HideSystemDebuggerInformation))
Expand Down Expand Up @@ -144,7 +152,7 @@ static NTSTATUS NTAPI HookNtQueryObject(
NTSTATUS ret = Undocumented::NtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength);
if(NT_SUCCESS(ret) && ObjectInformation)
{
ULONG pid = (ULONG)PsGetCurrentProcessId();
ULONG pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
UNICODE_STRING DebugObject;
RtlInitUnicodeString(&DebugObject, L"DebugObject");
if(ObjectInformationClass == ObjectTypeInformation && Hider::IsHidden(pid, HideDebugObject))
Expand Down Expand Up @@ -335,7 +343,7 @@ static NTSTATUS NTAPI HookNtSystemDebugControl(
IN ULONG OutputBufferLength,
OUT PULONG ReturnLength)
{
ULONG pid = (ULONG)PsGetCurrentProcessId();
ULONG pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
if(Hider::IsHidden(pid, HideNtSystemDebugControl))
{
Log("[TITANHIDE] NtSystemDebugControl by %d\r\n", pid);
Expand All @@ -348,7 +356,7 @@ static NTSTATUS NTAPI HookNtSystemDebugControl(

int Hooks::Initialize()
{
ExInitializeFastMutex(&gDebugPortMutex);
KeInitializeMutex(&gDebugPortMutex, 0);
int hook_count = 0;
hNtQueryInformationProcess = SSDT::Hook("NtQueryInformationProcess", (void*)HookNtQueryInformationProcess);
if(hNtQueryInformationProcess)
Expand Down
2 changes: 1 addition & 1 deletion TitanHide/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ULONG Misc::GetProcessIDFromThreadHandle(HANDLE ThreadHandle)
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
THREAD_BASIC_INFORMATION TBI;
if(NT_SUCCESS(Undocumented::ZwQueryInformationThread(ThreadHandle, ThreadBasicInformation, &TBI, sizeof(TBI), NULL)))
return (ULONG)TBI.ClientId.UniqueProcess;
return (ULONG)(ULONG_PTR)TBI.ClientId.UniqueProcess;
else
return 0;
}
9 changes: 9 additions & 0 deletions TitanHide/undocumented.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ typedef enum _SYSDBG_COMMAND
SysDbgGetTriageDump = 29,
} SYSDBG_COMMAND, *PSYSDBG_COMMAND;

// This is in ntifs.h, but some say Alan Turing died trying to parse that file
extern "C"
NTKERNELAPI
NTSTATUS
ObQueryObjectAuditingByHandle(
_In_ HANDLE Handle,
_Out_ PBOOLEAN GenerateOnClose
);

class Undocumented
{
public:
Expand Down

0 comments on commit 5340a7d

Please sign in to comment.