Code Monkey home page Code Monkey logo

titanhide's Introduction

Do not come here and open issues about problems with installation, crashes with bug check 0x109: CRITICAL_STRUCTURE_CORRUPTION or questions on how to disable PatchGuard. I will permanently ban you from the issue tracker. If you don't know how to properly install the tool you don't know enough to use it responsibly and you should use something else like ScyllaHide. To disable PatchGuard, try EfiGuard, UPGDSED or Shark.

Overview

TitanHide is a driver intended to hide debuggers from certain processes. The driver hooks various Nt* kernel functions (using SSDT table hooks) and modifies the return values of the original functions. To hide a process, you must pass a simple structure with a ProcessID and the hiding option(s) to enable, to the driver. The internal API is designed to add hooks with little effort, which means adding features is really easy.

The idea for this project was thought of together with cypher, shoutout man!

Features

  • ProcessDebugFlags (NtQueryInformationProcess)
  • ProcessDebugPort (NtQueryInformationProcess)
  • ProcessDebugObjectHandle (NtQueryInformationProcess)
  • DebugObject (NtQueryObject)
  • SystemKernelDebuggerInformation (NtQuerySystemInformation)
  • SystemDebugControl (NtSystemDebugControl)
  • NtClose (STATUS_INVALID_HANDLE/STATUS_HANDLE_NOT_CLOSABLE exceptions)
  • ThreadHideFromDebugger (NtSetInformationThread)
  • Protect DRx (HW BPs) (NtGetContextThread/NtSetContextThread)

Test environments

  • Windows 10 x64 & x86
  • Windows 8.1 x64 & x86
  • Windows 7 x64 & x86 (SP1)
  • Windows XP x86 (SP3)
  • Windows XP x64 (SP1)

Compiling

  1. Install Visual Studio 2013 (Express Edition untested).
  2. Install the WDK10/WDK8/WDK7.
  3. Open TitanHide.sln and hit compile!

Installation Method 1

  1. Copy TitanHide.sys to %systemroot%\system32\drivers.
  2. Run the command sc create TitanHide binPath= %systemroot%\system32\drivers\TitanHide.sys type= kernel to create the TitanHide service.
  3. Run the command sc start TitanHide to start the TitanHide service.
  4. Run the command sc query TitanHide to check if TitanHide is running.

Installation Method 2

  1. Copy TitanHide.sys to %systemroot%\system32\drivers.
  2. Start ServiceManager.exe (available on the download page).
  3. Delete the old service (when present).
  4. Install a new service (specify the full path to TitanHide.sys).
  5. Start the service you just created.
  6. Use TitanHideGUI.exe to set hide options for a PID.

Testsigning & PatchGuard

To enable testsigning run the following command:

bcdedit /set testsigning on

To disable PatchGuard, find a tool like KPP Destroyer to disable it (Google is your friend). To check if TitanHide is working correctly, use DebugView or check C:\TitanHide.log. You can also try EfiGuard, UPGDSED or Shark.

Remarks

  • When using x64dbg, you can use the TitanHide plugin (available on the download page).
  • NEVER RUN THIS DRIVER ON A PRODUCTION SYSTEM, ALWAYS USE A VM!

titanhide's People

Contributors

brandonros avatar hfiref0x avatar hypersine avatar mattiwatti avatar mrexodia avatar philicious avatar thehlopster avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

titanhide's Issues

Not working for Win 8.1(ver: 6.3.9600)

Hi,

I am getting the following logs and tested that it isn't hiding properly:

[TITANHIDE] Device \Device\TitanHide created successfully!
[TITANHIDE] Symbolic link \DosDevices\TitanHide->\Device\TitanHide created!
[TITANHIDE] SSDT RVA: 0x35CA80
[TITANHIDE] SSDT not found...
[TITANHIDE] SSDT RVA: 0x35CA80
[TITANHIDE] SSDT not found...
[TITANHIDE] SSDT RVA: 0x35CA80
[TITANHIDE] SSDT not found...
[TITANHIDE] SSDT RVA: 0x35CA80
[TITANHIDE] SSDT not found...
[TITANHIDE] HooksInit() returned 0
[TITANHIDE] HiderProcessData OK!
[TITANHIDE] HiderProcessData OK!
[TITANHIDE] HiderProcessData OK!
[TITANHIDE] HiderProcessData OK!
[TITANHIDE] HiderProcessData OK!
[TITANHIDE] HiderProcessData OK!

I have ran the TitanHideTest and used TitanHideGUI to hide that process. Then I attached a debugger on it and every debugger check returned 1.

Did Windows update 8.1 recently or something?

Currently I am creating a Windows 7 dual boot to see if it works there.

ShadowSSDT hook

Hi, is it possible to hook also some functions in ShadowSSDT? I have protector, that looking for window hwnds, strings to catch debuggers,etc.

Win64+Ollydbg2+TitanHide not working

Originally reported by: Anonymous


Hello, i installed TitanHide, disabled driver signature enforcement, downloaded TitanHide plugin for OllyDbg. When i open that TitanHideTest from x86 directory in OllyDbg, everything is 0 (that probably means it works). When i open .dll (in Olly) that is packed probably with Themida+Winlicense, it still detects the debugger.
So TitanHide should work if that test.exe passed?


Kernel debugger presence leakage through KUSER_SHARED_DATA

The following will detect a kernel debugger on any system running Windows 2000 or later:

#include <stdio.h>
#include <conio.h>
int main(int argc, char* argv[])
{
    unsigned char b = *(unsigned char*)0x7ffe02d4;
    if ((b & 0x01) || (b & 0x02))
        printf("Kernel debugger detected!\n");
    else
        printf("No kernel debugger detected\n");
    _getch();
    return 0;
}

The headers and CRT functions are only there to make the output readable; if you want you can turn this into a one liner that doesn't use any syscall or even a single DLL import!

So how does it work? Well, 0x7ffe02d4 is actually 0x7ffe0000 + 0x2d4. 0x7ffe0000 is the fixed user mode address of the KUSER_SHARED_DATA structure that contains data that is shared between user mode and the kernel (though user mode doesn't have write access to it). I stumbled upon this struct in the Windows Research Kernel sources, but it's actually part of the DDK and even mostly-commented (some fields better than others). The struct has some interesting properties: (a) its address is fixed and has been in all Windows versions since it was introduced. (b) its user mode address is the same in 32 bit and 64 bit mode. (c) all offsets and sizes are strictly fixed, and new fields are only ever appended or added in place of unused padding space. Hence why this program will work in 32 bit Windows 2000 and 64 bit Windows 10 without recompiling.

I found some much more detailed documentation of the struct at http://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kuser_shared_data.htm. Other than that the struct seems to be relatively unknown (at least for anti-debug purposes), I didn't find many references to it other than people trying to use the time fields as jump pads for malware... The 'b' in the program at +0x2d4 is the 'BOOL KdDebuggerEnabled' field. When I found the struct I tested it with

BOOL KdDebuggerEnabled = *(BOOL*)SharedUserData->KdDebuggerEnabled; // exact same code as above

Since I am not a filthy Javascript programmer, I do all my boolean checks with strict type equality to avoid issues with MS's ever-changing giant forest of typedefs that change your program depending on which headers you include. I found that if (KdDebuggerEnabled == TRUE) evaluated to false on both my own machine and a debugged VM, so at first I thought it was just an outdated field kept for compatibility reasons. But closer inspection revealed that the value is actually a bitfield and not a boolean, of which the first two bits are set to 1 if a debugger is attached! So if you do if (KdDebuggerEnabled) like a pleb, the check will work! Microsoft rewarding laziness and bad form again.

After I found out about this (and then afterwards of course found the above link, where the bitfield factoid was already documented...) I tried to nuke the field at both its KM and UM address from a kernel module - only to find that it was immediately overwritten with 0x3 again. Then I remembered I had a kernel debugger and set a HWBP:

> 0: kd> ba w 1 0xFFFFF780000002D4
> 0: kd> g
> Breakpoint 0 hit
> kdbazis!KdReceivePacket+0x75f:
> fffff80000ba2bff 8b45e7          mov     eax,dword ptr [rbp-19h]
> 1: kd> kb
>  # RetAddr           : Args to Child                                                           : Call Site
> 00 fffff80000ba24bc : 0000000000000008 0000000000000001 0000000000000000 0000000000000000 : kdbazis!KdReceivePacket+0x75f
> 01 fffff80002885e1d : fffffa800410c280 fffff8a0003cf890 0000000000000000 fffffa8004284c30 : kdbazis!KdReceivePacket+0x1c
> 02 fffff8000288873f : 0000000000000001 fffff880009f1180 0000000000000002 000000000002625a : nt!KdPollBreakIn+0xec`

(kdbazis.dll is VirtualKD's replacement for kdcom.dll, I recommend it if you want to do kernel debugging in a VM without wanting to kill yourself)
Trying this with kdcom.dll won't work, it seems to go into an infinite loop where it keeps sending itself messages that the breakpoint has been hit, which cause it to write to the breakpoint address, which triggers the breakpoint... etc. But the basic idea is the same regardless of which DLL you use: the debugger interface writes to the address on every KdReceivePacket, and kdcom.dll additionally writes to it in KdSendPacket as well.

The good news is that both DLLs can be patched not to do this with no negative consequences. Since VirtualKD is open source, patching it is left as an exercise for the reader... Patching kdcom.dll is more of a challenge, since it is one of the first modules to be loaded at boot and seems to have stricter code signing requirements than other drivers (test signing is not enough). So I found runtime patching to work best. This is possible from TitanHide and I've written a 'PatchKdCom()' to do this, but no PR yet as the code is quite messy and could use a review at least. Or maybe it's not even interesting enough to warrant adding; I've never seen anyone use KUSER_SHARED_DATA for anti-debug (as far as I'm aware anyway, but I'm definitely going to be setting more HWBPs in the future ;)).

Gist here: https://gist.github.com/anonymous/b5024c25634fc36e699cd9d041224531
Some issues:

  • Because there are so many almost-but-not-quite-the-same patches, the function is huge for what it really does
  • All of the repeated memcmp's are basically an unrolled loop that shouldn't have been unrolled. Is there a clean way to do this with the C-style (no STL) C++ you have to use in drivers? The problem is that the patches are of variable size, so you can't make a 2D array with constant dimensions
  • The patch is one way - if you want the rat behaviour back, you need to reboot :)

BSOD on Windows 7 64

Originally reported by: janfry janfry (Bitbucket: Janfry, GitHub: Janfry)


On Windows 7 64 I'm getting a BSOD a couple of minutes after running the TitanHide service.

Here's my installing and running commands:

  • copied TitanHide.sys (the 64 bit version) to %systemroot%\system32\drivers .
  • created service from an admin shell with "sc create TitanHide binPath= %systemroot%\system32\drivers\TitanHide.sys type= kernel"
  • used driver signator from http://www.ngohq.com/?page=dseo to signate the driver with a test certificate and enable test mode (rather than disable PatchGuard, is that ok?)
  • rebooted
  • ran the service with sc start TitanHide to start the TitanHide service.

As expected in C: root folder I could find a TitanHide.log file reporting \Device\TitanHide created succedssfully

Then I ran TitanHideTest.exe 64 and tried changing flags with TitanHideGui 64 but I that the flags always remained at 0 either after hiding or unhiding.

After a couple of minutes, while I was browsing to ollydbg plugin folder to install the ollydbg plugin, I got a BSOD.

I could replicate that exact behaviour twice, and both of the times I had disabled the AV before starting the service.. What could it be?


PAGE_FAULT_IN_NONPAGED_AREA on Windows 10 x64(19042)

Hi might be my fault, so I am still investigating. Maybe this is useful for future people who run into the same issue.

  • freshly installed windows 10 pro on a VM with EFI enabled
  • used EfiGuard to patch the kernel and disable DSE
  • compiled TitanHide for x64 sucessfully

However once attempting to start the service, Windows freezes and I get a PAGE_FAULT_IN_NONPAGED_AREA in the kernel log.
I am not sure what the issue could be, but I will continue to investigate and update this report.

MEMORY.DMP


Microsoft (R) Windows Debugger Version 10.0.19041.685 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.


Loading Dump File [C:\Windows\MEMORY.DMP]
Kernel Bitmap Dump File: Kernel address space is available, User address space may not be available.

Symbol search path is: srv*
Executable search path is: 
Windows 10 Kernel Version 19041 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 19041.1.amd64fre.vb_release.191206-1406
Machine Name:
Kernel base = 0xfffff807`1401f000 PsLoadedModuleList = 0xfffff807`14c49490
Debug session time: Thu Mar 25 02:29:54.479 2021 (UTC - 7:00)
System Uptime: 0 days 5:18:09.713
Loading Kernel Symbols
...............................................................
................................................................
....................................
Loading User Symbols

Loading unloaded module list
......................
For analysis of this file, run !analyze -v
1: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced.  This cannot be protected by try-except.
Typically the address is just plain bad or it is pointing at freed memory.
Arguments:
Arg1: fffff8071416d000, memory referenced.
Arg2: 0000000000000000, value 0 = read operation, 1 = write operation.
Arg3: fffff8071441d426, If non-zero, the instruction address which referenced the bad memory
    address.
Arg4: 0000000000000000, (reserved)

Debugging Details:
------------------


KEY_VALUES_STRING: 1

    Key  : Analysis.CPU.Sec
    Value: 2

    Key  : Analysis.DebugAnalysisProvider.CPP
    Value: Create: 8007007e on DESKTOP-GH9U662

    Key  : Analysis.DebugData
    Value: CreateObject

    Key  : Analysis.DebugModel
    Value: CreateObject

    Key  : Analysis.Elapsed.Sec
    Value: 9

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 69

    Key  : Analysis.System
    Value: CreateObject


VIRTUAL_MACHINE:  VirtualBox

BUGCHECK_CODE:  50

BUGCHECK_P1: fffff8071416d000

BUGCHECK_P2: 0

BUGCHECK_P3: fffff8071441d426

BUGCHECK_P4: 0

READ_ADDRESS:  fffff8071416d000 

MM_INTERNAL_CODE:  0

BLACKBOXBSD: 1 (!blackboxbsd)


BLACKBOXNTFS: 1 (!blackboxntfs)


BLACKBOXPNP: 1 (!blackboxpnp)


BLACKBOXWINLOGON: 1

PROCESS_NAME:  System

TRAP_FRAME:  ffff858fcc8ca610 -- (.trap 0xffff858fcc8ca610)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000001045ff3 rbx=0000000000000000 rcx=0000000000000001
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff8071441d426 rsp=ffff858fcc8ca7a8 rbp=ffff858fcc8ca800
 r8=0000000000000005  r9=ffff858fcc8ca7e8 r10=ffffaa043d400160
r11=0000000000000001 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
nt!RtlCompareMemory+0x36:
fffff807`1441d426 f348a7          repe cmps qword ptr [rsi],qword ptr [rdi]
Resetting default scope

STACK_TEXT:  
ffff858f`cc8ca368 fffff807`1443ddb1 : 00000000`00000050 fffff807`1416d000 00000000`00000000 ffff858f`cc8ca610 : nt!KeBugCheckEx
ffff858f`cc8ca370 fffff807`1422b960 : 00000000`00000114 00000000`00000000 ffff858f`cc8ca690 00000000`00000000 : nt!MiSystemFault+0x1f45a1
ffff858f`cc8ca470 fffff807`14422d5e : 00000000`0014c0c8 fffff807`1441b6a5 fffff807`1401f000 fffff807`14416cb5 : nt!MmAccessFault+0x400
ffff858f`cc8ca610 fffff807`1441d426 : fffff807`1b6a47d0 fffff807`1401f000 fffff807`1b6a2d9d 00000000`00000000 : nt!KiPageFault+0x35e
ffff858f`cc8ca7a8 fffff807`1b6a2d9d : 00000000`00000000 fffff807`0000bda8 fffff807`1b6a47d0 00000000`00000000 : nt!RtlCompareMemory+0x36
ffff858f`cc8ca7c0 fffff807`1b6a2a6f : 00000000`00000000 ffffaa04`44bb3bc0 00000000`00000000 00000000`00000000 : TitanHide!SSDTfind+0x79 [C:\Users\User\source\repos\TitanHide\TitanHide\ssdt.cpp @ 45] 
ffff858f`cc8ca810 fffff807`1b6a3b8c : 00000000`00000000 ffffaa04`428e53d0 00000000`001ef000 00000000`001ee320 : TitanHide!SSDT::GetFunctionAddress+0x17 [C:\Users\User\source\repos\TitanHide\TitanHide\ssdt.cpp @ 75] 
ffff858f`cc8ca840 fffff807`1b6a3551 : ffffaa04`44bb3a70 00000000`00000000 ffff858f`cc8ca930 fffff807`1437a41c : TitanHide!Undocumented::UndocumentedInit+0x22c [C:\Users\User\source\repos\TitanHide\TitanHide\undocumented.cpp @ 385] 
ffff858f`cc8ca880 fffff807`1b729020 : 00000000`00000000 ffffaa04`3df25000 00000000`00000002 ffffffff`800011e0 : TitanHide!DriverEntry+0x75 [C:\Users\User\source\repos\TitanHide\TitanHide\TitanHide.cpp @ 90] 
ffff858f`cc8ca8d0 fffff807`1477a644 : ffffaa04`3df25000 00000000`00000000 ffffaa04`44bb3a70 00000000`00000000 : TitanHide!GsDriverEntry+0x20 [minkernel\tools\gs_support\kmode\gs_support.c @ 117] 
ffff858f`cc8ca900 fffff807`1474547d : 00000000`00000014 00000000`00000000 00000000`00000000 00000000`00001000 : nt!PnpCallDriverEntry+0x4c
ffff858f`cc8ca960 fffff807`1478a967 : 00000000`00000000 00000000`00000000 fffff807`14d44440 ffffaa04`42602050 : nt!IopLoadDriver+0x4e5
ffff858f`cc8cab30 fffff807`14244975 : ffffaa04`00000000 ffffffff`800011e0 ffffaa04`47b4c040 ffffaa04`00000000 : nt!IopLoadUnloadDriver+0x57
ffff858f`cc8cab70 fffff807`14336e85 : ffffaa04`47b4c040 00000000`00000080 ffffaa04`3d85b040 06b2b19a`0002bebd : nt!ExpWorkerThread+0x105
ffff858f`cc8cac10 fffff807`1441c2a8 : ffffe681`b81ce180 ffffaa04`47b4c040 fffff807`14336e30 80044016`82004018 : nt!PspSystemThreadStartup+0x55
ffff858f`cc8cac60 00000000`00000000 : ffff858f`cc8cb000 ffff858f`cc8c5000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x28


FAULTING_SOURCE_LINE:  C:\Users\User\source\repos\TitanHide\TitanHide\ssdt.cpp

FAULTING_SOURCE_FILE:  C:\Users\User\source\repos\TitanHide\TitanHide\ssdt.cpp

FAULTING_SOURCE_LINE_NUMBER:  45

FAULTING_SOURCE_CODE:  
    41:         bool found = false;
    42:         ULONG KiSSSOffset;
    43:         for(KiSSSOffset = 0; KiSSSOffset < kernelSize - signatureSize; KiSSSOffset++)
    44:         {
>   45:             if(RtlCompareMemory(((unsigned char*)kernelBase + KiSSSOffset), KiSystemServiceStartPattern, signatureSize) == signatureSize)
    46:             {
    47:                 found = true;
    48:                 break;
    49:             }
    50:         }


SYMBOL_NAME:  TitanHide!SSDTfind+79

MODULE_NAME: TitanHide

IMAGE_NAME:  TitanHide.sys

STACK_COMMAND:  .thread ; .cxr ; kb

BUCKET_ID_FUNC_OFFSET:  79

FAILURE_BUCKET_ID:  AV_R_INVALID_TitanHide!SSDTfind

OS_VERSION:  10.0.19041.1

BUILDLAB_STR:  vb_release

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

FAILURE_ID_HASH:  {1ef56748-c8e8-8a36-05ec-c231bfb01fd2}

Followup:     MachineOwner
---------

image

not actually hidden?

Using titanhidegui, everything seems to be working successfully, but the process is not actually hidden? Still able to see it in task manager. This is with all the options checked and it is saying "Data written!" Windows 10 17134

NtTerminateProcess hook failed SYSTEM_SERVICE_EXCEPTION

hNtTerminateProcess = SSDT::Hook("NtTerminateProcess", (void*)HookNtTerminateProcess);
if (hNtTerminateProcess)
    hook_count++;

NTSTATUS HookNtTerminateProcess(
__in_opt HANDLE ProcessHandle,
__in NTSTATUS ExitStatus
)
{
ULONG uPID;
NTSTATUS rtStatus;
rtStatus = Undocumented::NtTerminateProcess(ProcessHandle, ExitStatus);
return rtStatus;
}

typedef NTSTATUS(*NTTERMINATEPROCESS)(
__in_opt HANDLE ProcessHandle,
__in NTSTATUS ExitStatus
);
static NTTERMINATEPROCESS NtTP = 0;
NTSTATUS NTAPI Undocumented::NtTerminateProcess(
__in_opt HANDLE ProcessHandle,
__in NTSTATUS ExitStatus)
{
return NtTP(ProcessHandle, ExitStatus);
}

Achilles' heel of SSDT Hook ThreadFromDebugger

This hook is completely disabled for targets that can only be attached
Because the target executes the ThreadFromDebugger flag at the beginning of the program
It crashes when the target is debugged in an additional way
Can you set it to remove the ThreadFromDebugger flag as an add-on so that it can be debuggable

NtQueryObject = 1 ?

Originally reported by: janfry janfry (Bitbucket: Janfry, GitHub: Janfry)


Not exactly sure if this is a issue..

As I've read in another bug submission, TitanHide does not set an entry in the plugins menu in Ollydbg, it just work by setting the flags in the Kernel when a process is attached or started in Ollydbg.

What I am seeing is if I let TitanHideTest program run, it outputs that the flag are all set to 0, but as soon as I run a process in Ollydbg, I see that the NtQueryObject gets set to 1.
Is this ok??


Green screen on win11 x64

after starting the TitanHide service

do disabled patchguard and DSE fixed. seems to not working on win11 x64

work fine on x86-32

NtCreateFile UNEXPECTED_KERNEL_MODE_TRAP

hooks.cpp

hNtCreateFile = SSDT::Hook("NtCreateFile", (void*)HookNtCreateFile);
if (hNtCreateFile)
hook_count++;

undocumented.h

static NTSTATUS NTAPI NtCreateFile(
Out PHANDLE FileHandle,
In ACCESS_MASK DesiredAccess,
In POBJECT_ATTRIBUTES ObjectAttributes,
Out PIO_STATUS_BLOCK IoStatusBlock,
In_opt PLARGE_INTEGER AllocationSize,
In ULONG FileAttributes,
In ULONG ShareAccess,
In ULONG CreateDisposition,
In ULONG CreateOptions,
In_reads_bytes_opt(EaLength) PVOID EaBuffer,
In ULONG EaLength);

undocumented.cpp

static NTCREATEFILE NtCF = 0;
//Exported kernel functions after this on UndocumentedInit
if (!NtCF)
{
UNICODE_STRING routineName;
RtlInitUnicodeString(&routineName, L"NtCreateFile");
NtCF = (NTCREATEFILE)MmGetSystemRoutineAddress(&routineName);
if (!NtCF)
return false;
}

NTSTATUS NTAPI Undocumented::NtCreateFile(
Out PHANDLE FileHandle,
In ACCESS_MASK DesiredAccess,
In POBJECT_ATTRIBUTES ObjectAttributes,
Out PIO_STATUS_BLOCK IoStatusBlock,
In_opt PLARGE_INTEGER AllocationSize,
In ULONG FileAttributes,
In ULONG ShareAccess,
In ULONG CreateDisposition,
In ULONG CreateOptions,
In_reads_bytes_opt(EaLength) PVOID EaBuffer,
In ULONG EaLength)
{
Log("undocumented Ntcf:%p", NtCF);
return NtCF(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions,EaBuffer,EaLength);
}

BlueScreen 0x109: CRITICAL_STRUCTURE_CORRUPTION on Win7 64-Bit

Originally reported by: qwe (Bitbucket: Djamana, GitHub: Djamana)


I enabled test signing to finally get TitanHide.sys [from TitanHide_0013.rar] loaded.

Creating and starting the x64-driver works well.
...I used TitanHideGUI.exe & TitanHideTest.exe to test,
But it doesn't work entered TitanHideTest PID checked one clicked hide.
Checked all & clicked hide - values at the Tester stay at '0'

But BOOM with a delay of about 30-60 seconds somehow that shitty:
Bug Check 0x109: CRITICAL_STRUCTURE_CORRUPTION occurs.

That's what MS writes about this:

#!c++

There are generally three different causes for this bug check:

A driver has inadvertently, or deliberately, modified critical kernel code or data. Microsoft Windows Server 2003 with Service Pack 1 (SP1) and later versions of Windows for x64-based computers do not allow the kernel to be patched except through authorized Microsoft-originated hot patches. For more information, see Patching Policy for x64-based Systems.

A developer attempted to set a normal kernel breakpoint using a kernel debugger that was not attached when the system was started. Normal breakpoints (bp) can only be set if the debugger is attached at start time. Processor breakpoints (ba) can be set at any time.

A hardware corruption occurred. For example, the kernel code or data could have been stored in memory that failed.

Hmm sounds pretty nasty,
Seem like downgrading / installing some 32-Bit system the only option or any ideas how to 'fix' that?

Update:
This crap is called Kernel_Patch_Protection it's a security through obscurity base approach of M$ to avoid that stuff like IDT or GDT get touched by any other device driver.

Wow didn't know that but since 2005 there's a real fight going on of breaking and fixing the KPP.

Edit/Update: Oh dear I see - RTFM. I got KPP-Destroyer (7.Feb-2015) and not it work.

I also worked on a little on that fucking manual improving it a little.
...and attached it here.
Quick'n'Dirty pdf patching - however like this I'll work for a while. ;)


Debugger/application freeze on resume

Issue itself is when i run any target (32/64bit) and attempt to hide debugger through either x64dbg plugin or TitanHideGUI.exe - both debugger and target freeze. It is impossible to kill these processes. The only way to get rid of them is to reboot.

OS: Windows 10 Enterprise 2016 LTSB x64 build 14393
TitanHide.log:

[TITANHIDE] FileSize of ntdll.dll is 001CCCB0!
[TITANHIDE] UndocumentedInit() was successful!
[TITANHIDE] Device \Device\TitanHide created successfully!
[TITANHIDE] Symbolic link \DosDevices\TitanHide->\Device\TitanHide created!
[TITANHIDE] Range: 0xFFFFF803CAD6A250-0xFFFFF803DAD6A24F
[TITANHIDE] CodeStart: 0xFFFFF803CAE57000, CodeSize: 0x313600
[TITANHIDE] Range: 0xFFFFF803CAE57000-0xFFFFF803CB16A600
[TITANHIDE] CaveAddress: 0xFFFFF803CAE68E14
[TITANHIDE] hook(0xFFFFF803CAE68E14, 0xFFFFF805356D1A80)
[TITANHIDE] SSDThook(NtQueryInformationProcess:0x00000000014B0101, 0x0000000000FEBC41)
[TITANHIDE] CaveAddress: 0xFFFFF803CAE68EA1
[TITANHIDE] hook(0xFFFFF803CAE68EA1, 0xFFFFF805356D1BB4)
[TITANHIDE] SSDThook(NtQueryObject:0x0000000001072501, 0x0000000000FEC511)
[TITANHIDE] CaveAddress: 0xFFFFF803CAE6B283
[TITANHIDE] hook(0xFFFFF803CAE6B283, 0xFFFFF805356D1D6C)
[TITANHIDE] SSDThook(NtQuerySystemInformation:0x00000000011AA600, 0x0000000001010330)
[TITANHIDE] CaveAddress: 0xFFFFF803CAE6C712
[TITANHIDE] hook(0xFFFFF803CAE6C712, 0xFFFFF805356D1EE8)
[TITANHIDE] SSDThook(NtSetInformationThread:0x0000000001495200, 0x0000000001024C20)
[TITANHIDE] CaveAddress: 0xFFFFF803CAE6F072
[TITANHIDE] hook(0xFFFFF803CAE6F072, 0xFFFFF805356D19CC)
[TITANHIDE] SSDThook(NtClose:0x0000000001853100, 0x000000000104E220)
[TITANHIDE] CaveAddress: 0xFFFFF803CAE6F1E2
[TITANHIDE] hook(0xFFFFF803CAE6F1E2, 0xFFFFF805356D1E04)
[TITANHIDE] SSDThook(NtSetContextThread:0x0000000003907CC0, 0x000000000104F920)
[TITANHIDE] CaveAddress: 0xFFFFF803CAE6F672
[TITANHIDE] hook(0xFFFFF803CAE6F672, 0xFFFFF805356D1FAC)
[TITANHIDE] SSDThook(NtSystemDebugControl:0x0000000001A72102, 0x0000000001054222)
[TITANHIDE] Hooks::Initialize() hooked 7 functions
[TITANHIDE] HiderProcessData OK!
[TITANHIDE] ProcessDebugPort by 4920

P.S. Is readme still accurate? Log does not indicate any failures so it seems hardcoding SSDT address is no longer necessary on W10 right?

在不使用VT的情况下

在不使用VT的情况下 过了PG 是否可以监控 某内核地址的读 或写 硬件断点这种

实现躲避SSDT 挂钩的检测

Attach to process failed! GetLastError() = 5 (ERROR_ACCESS_DENIED)

Hello,

can't attach to target :(
haven’t load any module.

Attach to process failed! GetLastError() = 5 (ERROR_ACCESS_DENIED)
Saving database to F:\Program Files\x64dbg\release\x32\db\xxx.exe.dd32 16ms
Debugging stopped!

how to resolve this anti-attach, thank you

BSOD after unload driver when verifier enabled

I used the code for SSDT hook in my project, BSOD after unload driver when verifier enabled
windbg !analyze -v show:

DRIVER_VERIFIER_DETECTED_VIOLATION (c4)
A device driver attempting to corrupt the system has been caught. This is
because the driver was specified in the registry as being suspect (by the
administrator) and the kernel has enabled substantial checking of this driver.
If the driver attempts to corrupt the system, bugchecks 0xC4, 0xC1 and 0xA will
be among the most commonly seen crashes.
Arguments:
Arg1: 00000060, A driver has forgotten to free its pool allocations prior to unloading.
Arg2: 00000000, paged bytes
Arg3: 00000288, nonpaged bytes,
Arg4: 00000012, total # of (paged+nonpaged) allocations that weren't freed.
To get the name of the driver at fault, type
dp ViBadDriver l1; dS @$p
Then type !verifier 3 drivername.sys for info on the allocations
that were leaked that caused the bugcheck.

!verifier 3 xxx.sys show:

0x831d4fd8 0x00000024 EDIH 0xbaa30155 xxx!RtlAllocateMemory

Seems on x86, SSDT::Hook called RtlAllocateMemory, but SSDT::Unhook forgot to free it. X64 version using Hooklib::Hook and Hooklib::Unhook seems OK (I'v not tested x64 version).

Maybe fixed by this:

     if(free)
         Hooklib::Unhook(hHook, true);
 #else
-    UNREFERENCED_PARAMETER(free);
+    if (free)
+        RtlFreeMemory(hHook);
 #endif
 }

Bug on x64 hook

LONG oldValue = SSDT->pServiceTable[FunctionIndex];

on x64, oldValue can be 0xff*, take Win8 x64 for example:

kd> dd nt!KiServiceTable
fffff800`8b174d00  ffac52c0 034eac02 04a58c40 02a2b100
fffff800`8b174d10  ffffc400 029f8405 02a54606 02ace485
fffff800`8b174d20  02783101 032be100 030b8340 0309cec0
fffff800`8b174d30  027ea100 02bc6600 0299d200 02b00e01
fffff800`8b174d40  02a05d01 023c7700 028993c2 0286c380
fffff800`8b174d50  033ee600 02b6c501 02b61402 02a54c02
fffff800`8b174d60  02fab201 0277a401 0244b145 0302ee80
fffff800`8b174d70  02407843 ff159c00 049d3a00 02bc7fc0

then the calculation of the address of SSDT functions are wrong.
my fix code is:

-    ULONG oldValue = SSDT->pServiceTable[FunctionIndex];
-    ULONG newValue;
+    LONG oldValue = SSDT->pServiceTable[FunctionIndex];
+    LONG newValue;

-        CodeStart = PE::GetPageBase(Undocumented::GetKernelBase(), &CodeSize, (PVOID)((oldValue >> 4) + SSDTbase));
+        CodeStart = PE::GetPageBase(Undocumented::GetKernelBase(), &CodeSize, (PVOID)((LONGLONG)(oldValue >> 4) + SSDTbase));

-    hHook->SSDTaddress = (oldValue >> 4) + SSDTbase;
+    hHook->SSDTaddress = (LONGLONG)(oldValue >> 4) + SSDTbase;

the code is just work, for reference only. I'm a little headache on the LONG ULONG stuff. Actually, I use the hook code to hook shadow SSDT functions, and finally find the bug.

BSOD when shutdown on Win8 x64 (using KPP Destroyer for disable patchguard)

I use KPP Destroyer to disable patchguard on win8 x64, it seem patched nt!MiValidateSectionCreate:
orignal:

PAGE:000000014038B326 E8 15 FC FF FF                                call    SeValidateImageHeader
PAGE:000000014038B32B 8B F8                                         mov     edi, eax
PAGE:000000014038B32D 3D 2D 01 00 00                                cmp     eax, 12Dh
PAGE:000000014038B332 0F 84 6F 5B 1A 00                             jz      loc_140530EA7
PAGE:000000014038B338
PAGE:000000014038B338                               loc_14038B338:                          ; CODE XREF: MiValidateSectionCreate+2BE�j
PAGE:000000014038B338                                                                       ; MiValidateSectionCreate+560�j ...
PAGE:000000014038B338 4C 3B AC 24 80 00 00 00                       cmp     r13, [rsp+188h+var_108]

patched:

fffff802`03da2326 e815fcffff      call    nt!SeValidateImageHeader (fffff802`03da1f40)
fffff802`03da232b 90              nop
fffff802`03da232c 90              nop
fffff802`03da232d 90              nop
fffff802`03da232e 90              nop
fffff802`03da232f 90              nop
fffff802`03da2330 90              nop
fffff802`03da2331 90              nop
fffff802`03da2332 90              nop
fffff802`03da2333 90              nop
fffff802`03da2334 90              nop
fffff802`03da2335 90              nop
fffff802`03da2336 90              nop
fffff802`03da2337 90              nop
fffff802`03da2338 4c3bac2480000000 cmp     r13,qword ptr [rsp+80h]

you can see, there are many nops, which count is 13 > 12, the FindCaveAddress will find the address as the CaveAddress. So after hook, BSOD will comes when calling nt!MiValidateSectionCreate.
So I suggest FindCaveAddress not use nop area to hook.
It's easy to reproduce BSOD when shutdown.

Bug in NtGetContextThread hook

NtGetContextThread hook has some problems, TitanHide.log contains these lines:

[TITANHIDE] NtGetContextThread by 4920
[TITANHIDE] NtGetContextThread by 4920
[TITANHIDE] NtGetContextThread by 4920
[TITANHIDE] NtGetContextThread by 4920
[TITANHIDE] NtGetContextThread by 4920
[TITANHIDE] NtGetContextThread by 4920
[TITANHIDE] NtGetContextThread by 4920
[TITANHIDE] NtGetContextThread by 4920
[TITANHIDE] NtGetContextThread by 4920

5 lines writing to log file per second and Hardware breakpoints don't work on any program (protected or unprotected).

Hоw to use with OllyDbg

When i compile it and install, copy plugin to ollydbg.... Target always terminated with error!

Driver installation issues

Originally reported by: siilky (Bitbucket: siilky, GitHub: Unknown)


I have clean WinXP SP3 installed with some updates and trying to install TH driver of latest release (013).

  1. OS is missing KMDF by default and sc/serviceManager are ending with "file not found" error when starting service.
    I spent another day discovering this error source ended up with KMDF installation, done with Microsoft Kernel-Mode Driver Framework Install-v1.9-Win2k-WinXP-Win2k3.exe found somewhere at internets since MS has ended support for XP and corresponding KB cannot be downloaded probably.

So, now it attemps to start and StartService fails with error 6 "Invalid Handle"
Here is more detailed wdf log from kernel debugger:

#!

WdfLdr: FxDllInitialize - OsVersion(5.1)
WdfLdr: WdfVersionBind - WdfLdr: WdfVersionBind: enter
WdfLdr: GetVersionRegistryHandle - Component path \Registry\Machine\System\CurrentControlSet\Control\Wdf\Kmdf\KmdfLibrary\Versions
WdfLdr: GetVersionServicePath - GetVersionServicePath (\Registry\Machine\System\CurrentControlSet\Services\Wdf01000)
WdfLdr: GetImageName - Version Image Name "wdf01000.sys"
WdfLdr: WdfLdrDiagnosticsValueByNameAsULONG - Value 0x1
WdfLdr: WdfLdrDiagnosticsValueByNameAsULONG - Status 0x0
Wdf01000: DriverEntry
WdfLdr: WdfRegisterLibrary - Module(85F71F70)
Wdf01000: LibraryCommission
Wdf01000: OsVersion(5.1)
WdfLdr: GetImageName - Version Image Name "TitanHide.sys"
WdfLdr: LibraryLinkInClient - Client Image Name: TitanHide.sys
Wdf01000: LibraryRegisterClient: enter
WdfLdr: WdfVersionBind - WdfLdr: libraryRegisterClient: LibraryLinkInClient failed C0000024
WdfLdr: ClientCleanupAndFree - Client Image Name: TitanHide.sys
WdfLdr: LibraryReleaseClientReference - WdfLdr: LibraryReleaseClientReference: Dereference module \Registry\Machine\System\CurrentControlSet\Services\Wdf01000
Wdf01000: LibraryDecommission: enter
Wdf01000: LibraryDecommission: exit
WdfLdr: LibraryUnload - WdfLdr: LibraryUnload: Unload module \Registry\Machine\System\CurrentControlSet\Services\Wdf01000
Wdf01000: DriverUnload
WdfLdr: WdfVersionUnbind - WdfLdr: WdfVersionUnbind: exit: 0
WdfLdr: WdfVersionBind - Returning with Status 0xc0000024
WdfLdr: DllUnload - WdfLdr: DllUnload: enter
WdfLdr: DllUnload - WdfLdr: DllUnload: exit

Quick googling leads us to possible KMDF version mismatch http://stackoverflow.com/questions/13254487/why-am-i-getting-error-code-6-on-startservice

  1. TitanHideTest / TitanHideGui cannot be started and explorer says it's "not valid win32 application". Probably also dll/os version mismatch but I didn't dig into it yet.

Windows 10 x64 (1607) A device attached to the system is not functioning.

Hello there,
i followed the instructions also disabled patch guard.
But when i try to start the service i get the error "A device attached to the system is not functioning."

Error Log:
[TITANHIDE] FileSize of ntdll.dll is 001CBE88!
[TITANHIDE] Failed to find pattern...
[TITANHIDE] SSDT not found...
[TITANHIDE] UndocumentedInit() failed...
[TITANHIDE] FileSize of ntdll.dll is 001CBE88!
[TITANHIDE] Failed to find pattern...
[TITANHIDE] SSDT not found...
[TITANHIDE] UndocumentedInit() failed...
[TITANHIDE] FileSize of ntdll.dll is 001CBE88!
[TITANHIDE] Failed to find pattern...
[TITANHIDE] SSDT not found...
[TITANHIDE] UndocumentedInit() failed...
[TITANHIDE] FileSize of ntdll.dll is 001CBE88!
[TITANHIDE] Failed to find pattern...
[TITANHIDE] SSDT not found...
[TITANHIDE] UndocumentedInit() failed...
[TITANHIDE] FileSize of ntdll.dll is 001CBE88!
[TITANHIDE] Failed to find pattern...
[TITANHIDE] SSDT not found...
[TITANHIDE] UndocumentedInit() failed...
[TITANHIDE] FileSize of ntdll.dll is 001CBE88!
[TITANHIDE] Failed to find pattern...
[TITANHIDE] SSDT not found...
[TITANHIDE] UndocumentedInit() failed...
[TITANHIDE] FileSize of ntdll.dll is 001CBE88!
[TITANHIDE] Failed to find pattern...
[TITANHIDE] SSDT not found...
[TITANHIDE] UndocumentedInit() failed...
[TITANHIDE] FileSize of ntdll.dll is 001CBE88!
[TITANHIDE] Failed to find pattern...
[TITANHIDE] SSDT not found...
[TITANHIDE] UndocumentedInit() failed...
[TITANHIDE] FileSize of ntdll.dll is 001CBE88!
[TITANHIDE] Failed to find pattern...
[TITANHIDE] SSDT not found...
[TITANHIDE] UndocumentedInit() failed...

NVM: compiling the latest driver solved it.

NtQueryInformationProcess anti-debug

An anti-debugging technique was found in SProtect (virtualization protector,like vmprotect).
Think about the following code:


void* Information = malloc(InfoSize);
status = X64_NtQueryInformationProcess(CurrentProcess, ProcessDebugObjectHandle, Information, 8, (PULONG)Information);


//ReturnLength and ProcessInformation point to same memory area

TitanHide is unable to close debugobject handle because handle is overwrite (handle==sizeof(handle)==8)

if(CantTouchThis != nullptr){
BOOLEAN AuditOnClose;
const NTSTATUS HandleStatus = ObQueryObjectAuditingByHandle(CantTouchThis, &AuditOnClose); //"CantTouchThis" is 8 in windows x64
if(HandleStatus != STATUS_INVALID_HANDLE)
ObCloseHandle(CantTouchThis, ExGetPreviousMode());

}

Attachment3

Summary:
--------
TitanHide is an open-source driver intended to hide debuggers from certain
processes. The driver hooks various Nt* kernel functions (using SSDT table
hooks) and modifies the return values of the original functions. The below
highlights generic ways the driver's design allows debugger detection.

Location:
---------
Hook functions in TitanHide/Hooks.cpp.

Impact: 
-------
A hostile binary expecting to be debugged under TitanHide can leverage the
driver's design described below in order to achieve debugger detection.

Details:
--------
- Most hooks are vulnerable to race conditions where the debugged process can
  check the return code of the original NT call before TitanHide overwrites it
- The device object (\\Device\\TitanHide by default) and its dos devices link
  can be accessed to detect the presence of TitanHide and to unprotect the 
  current process.
- The hooks check whether the current process (rather than target process) is
  registered by TitanHide as hidden. Executing code outside of process (via
  process or remote thread creation for instance) can be used to get around
  TitanHide's debug detection.

Recommendation:
----------------
- Do not write data back to user mode memory until it has been sanitized.
- While relying on users to rename the device object or link would increase
  attack complexity, a more robust approach could be to filter IO calls to
  TitanHide device object from monitored processes
- Consider using the target process when filtering NT system calls

If U use the methods do not work, U can do this way

U should use the newest visual stdio, and download the wdk with your system version, and to compile it.win10 1809 can use the release version of this sys file.U just to compile it, and it well work well

HookNtSetContextThread race condition and detection vector

I am aware that detection vectors and race conditions have low priority due to nobody abusing them, but this one may be in actual use (not 100% sure yet, as understanding obfuscated code without breakpoints is not fun).

Race condition

TitanHide strips the ContextFlags in HookNtSetContextThread so that the debug registers will not be overwritten:

 Context->ContextFlags = OriginalContextFlags & ~0x10; //CONTEXT_DEBUG_REGISTERS ^ CONTEXT_AMD64/CONTEXT_i386

However TitanHide assumes that the ContextFlags cannot be set after the strip, and just passes the Context pointer to the actual function:

NTSTATUS ret = Undocumented::NtSetContextThread(ThreadHandle, Context);

This gives the caller plenty of time to try to un-strip the ContextFlags - consider the following proof of concept code:

void RaceFunction(CONTEXT* ptr, bool* run)
{
	while (*run)
	{
		ptr->ContextFlags = 0x10;
	}
}

void TryStealHardwareBreakpoints()
{
	CONTEXT ctx = {};
	ctx.ContextFlags = 0x10;
	if (!GetThreadContext(GetCurrentThread(), &ctx))
		return;
	// Dr0, ... are all 0 if this is run through TitanHide :)

	auto run = true;
	std::thread race(RaceFunction, &ctx, &run);
	SetThreadContext(GetCurrentThread(), &ctx);
	
	run = false;
	race.join();
}

Detection vector

An additional detection vector that I believe is being used in my target program is that GetThreadContext does not return a previously set hardware breakpoint when running under TitanHide. Proof of concept:

void DummyFunction() {}

bool HasTitanHide()
{
	const auto dummy_breakpoint = reinterpret_cast<DWORD64>(&DummyFunction);
	
	CONTEXT ctx = {};
	ctx.Dr0 = dummy_breakpoint;
	ctx.Dr7 = 1;
	ctx.ContextFlags = 0x10;

	if (!SetThreadContext(GetCurrentThread(), &ctx))
		return false;

	if (!GetThreadContext(GetCurrentThread(), &ctx))
		return false;

	if (ctx.Dr0 == dummy_breakpoint)
		return false;
	
	return true;
}

Possible fix

I understand that you guys are not trying to be super stealthy, but at least copying the Context before checking it and passing it on, to avoid the race condition, would be nice :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.