Skip to content

Commit 40ce234

Browse files
committed
Preserve anti-debug state across lifecycle edges
1 parent 35eaa4a commit 40ce234

8 files changed

Lines changed: 617 additions & 105 deletions

File tree

TitanHide/TitanHide.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ static NTSTATUS DriverWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
6969

7070
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
7171
{
72+
Hider::Initialize();
73+
7274
// Initialize name buffers
7375
RtlInitEmptyUnicodeString(&DeviceName, DeviceNameBuffer, sizeof(DeviceNameBuffer));
7476
RtlAppendUnicodeToString(&DeviceName, L"\\Device\\");

TitanHide/hider.cpp

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "hider.h"
22
#include "log.h"
33
#include "threadhidefromdbg.h"
4+
#include "hooks.h"
45

56
struct HIDE_ENTRY
67
{
@@ -12,6 +13,7 @@ struct HIDE_ENTRY
1213

1314
static HIDE_ENTRY HideEntries[MAX_HIDE_ENTRIES];
1415
static LONG TotalHideEntries = 0;
16+
static KSPIN_LOCK HideEntriesLock;
1517

1618
//entry management
1719
static void EntryAdd(HIDE_ENTRY* NewEntry)
@@ -38,12 +40,9 @@ static void EntryDel(int EntryIndex)
3840
EntryClear();
3941
return;
4042
}
41-
if(!EntryIndex)
42-
RtlCopyMemory(&HideEntries[0], &HideEntries[1], NewTotalHideEntries * sizeof(HIDE_ENTRY));
43-
else
44-
{
45-
RtlCopyMemory(&HideEntries[EntryIndex], &HideEntries[EntryIndex + 1], (NewTotalHideEntries - EntryIndex)*sizeof(HIDE_ENTRY));
46-
}
43+
// Entry order is irrelevant; replace the removed slot with the last
44+
// entry so updates remain bounded while the spin lock is held.
45+
HideEntries[EntryIndex] = HideEntries[NewTotalHideEntries];
4746
InterlockedExchange(&TotalHideEntries, NewTotalHideEntries);
4847
}
4948
}
@@ -87,6 +86,12 @@ static void EntryUnset(int EntryIndex, ULONG Type)
8786
}
8887

8988
//usable functions
89+
void Hider::Initialize()
90+
{
91+
KeInitializeSpinLock(&HideEntriesLock);
92+
TotalHideEntries = 0;
93+
}
94+
9095
bool Hider::ProcessData(PVOID Buffer, ULONG Size)
9196
{
9297
if(Size % sizeof(HIDE_INFO))
@@ -99,6 +104,8 @@ bool Hider::ProcessData(PVOID Buffer, ULONG Size)
99104
{
100105
case HidePid:
101106
{
107+
KIRQL Irql;
108+
KeAcquireSpinLock(&HideEntriesLock, &Irql);
102109
int FoundEntry = EntryFind(HideInfo[i].Pid);
103110
if(FoundEntry == -1)
104111
{
@@ -111,6 +118,7 @@ bool Hider::ProcessData(PVOID Buffer, ULONG Size)
111118
{
112119
EntrySet(FoundEntry, HideInfo[i].Type);
113120
}
121+
KeReleaseSpinLock(&HideEntriesLock, Irql);
114122

115123
// Use DKOM to disable HideThreadHideFromDebugger in any threads in the target process that already have this flag set
116124
if((HideInfo[i].Type & (ULONG)HideThreadHideFromDebugger) != 0 && CrossThreadFlagsOffset != 0)
@@ -126,19 +134,28 @@ bool Hider::ProcessData(PVOID Buffer, ULONG Size)
126134

127135
case UnhidePid:
128136
{
137+
KIRQL Irql;
138+
KeAcquireSpinLock(&HideEntriesLock, &Irql);
129139
int FoundEntry = EntryFind(HideInfo[i].Pid);
130140
if(FoundEntry != -1)
131141
{
132142
EntryUnset(FoundEntry, HideInfo[i].Type);
133143
if(!EntryGet(FoundEntry)) //nothing left to hide for PID
134144
EntryDel(FoundEntry);
135145
}
146+
KeReleaseSpinLock(&HideEntriesLock, Irql);
147+
if((HideInfo[i].Type & (ULONG)HideThreadHideFromDebugger) != 0)
148+
Hooks::RestoreVirtualThreadHides(HideInfo[i].Pid, false);
136149
}
137150
break;
138151

139152
case UnhideAll:
140153
{
154+
KIRQL Irql;
155+
KeAcquireSpinLock(&HideEntriesLock, &Irql);
141156
EntryClear();
157+
KeReleaseSpinLock(&HideEntriesLock, Irql);
158+
Hooks::RestoreVirtualThreadHides(0, true);
142159
}
143160
break;
144161
}
@@ -148,11 +165,15 @@ bool Hider::ProcessData(PVOID Buffer, ULONG Size)
148165

149166
bool Hider::IsHidden(ULONG Pid, HIDE_TYPE Type)
150167
{
168+
bool Hidden = false;
169+
KIRQL Irql;
170+
KeAcquireSpinLock(&HideEntriesLock, &Irql);
151171
int FoundEntry = EntryFind(Pid);
152-
if(FoundEntry == -1)
153-
return false;
154-
ULONG uType = (ULONG)Type;
155-
if((EntryGet(FoundEntry)&uType) == uType)
156-
return true;
157-
return false;
172+
if(FoundEntry != -1)
173+
{
174+
ULONG uType = (ULONG)Type;
175+
Hidden = (EntryGet(FoundEntry) & uType) == uType;
176+
}
177+
KeReleaseSpinLock(&HideEntriesLock, Irql);
178+
return Hidden;
158179
}

TitanHide/hider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
class Hider
88
{
99
public:
10+
static void Initialize();
1011
static bool ProcessData(PVOID Buffer, ULONG Size);
1112
static bool IsHidden(ULONG Pid, HIDE_TYPE Type);
1213
};

0 commit comments

Comments
 (0)