-
Notifications
You must be signed in to change notification settings - Fork 71
Expand file tree
/
Copy pathUnregisterAllLdrRegisterDllNotification.c
More file actions
202 lines (166 loc) · 6.3 KB
/
UnregisterAllLdrRegisterDllNotification.c
File metadata and controls
202 lines (166 loc) · 6.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/* UnregisterAllLdrRegisterDllNotification.c by @rad9800
* Credit goes to:
* - Whoever at mdsec discovered the technique
* - Proofpoint threatinsight team for their detailed analysis
*
* Removes the LdrRegisterDllNotification by located the head of the
* doubly-linked list in the .data section of NTDLL and then walking
* it and removing each link entry.
*
*/
#include <Windows.h>
#include <winternl.h>
#include <stdio.h> // printf
#define NtCurrentThread() ( ( HANDLE ) ( LONG_PTR ) -2 )
#define NtCurrentProcess() ( ( HANDLE ) ( LONG_PTR ) -1 )
#define IMPORTAPI( DLLFILE, FUNCNAME, RETTYPE, ...)\
typedef RETTYPE( WINAPI* type##FUNCNAME )( __VA_ARGS__ );\
type##FUNCNAME FUNCNAME = (type##FUNCNAME)GetProcAddress((LoadLibraryW(DLLFILE), GetModuleHandleW(DLLFILE)), #FUNCNAME);
typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA {
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_UNLOADED_NOTIFICATION_DATA, * PLDR_DLL_UNLOADED_NOTIFICATION_DATA;
typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA {
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_LOADED_NOTIFICATION_DATA, * PLDR_DLL_LOADED_NOTIFICATION_DATA;
typedef union _LDR_DLL_NOTIFICATION_DATA {
LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
} LDR_DLL_NOTIFICATION_DATA, * PLDR_DLL_NOTIFICATION_DATA;
typedef VOID(CALLBACK* LdrDllNotification)(ULONG, const PLDR_DLL_NOTIFICATION_DATA, PVOID);
VOID DllloadCallback(ULONG NotificationReason, const PLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context)
{
if (NotificationReason == 1)
{
if (NotificationData->Loaded.FullDllName)
{
printf("DllloadCallback: DLL loaded %wZ\n", NotificationData->Loaded.FullDllName);
}
}
else
{
if (NotificationData->Unloaded.FullDllName)
{
printf("DllloadCallback: DLL Un-loaded %wZ\n", NotificationData->Unloaded.FullDllName);
}
}
}
VOID DllloadCallback2(ULONG NotificationReason, const PLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context)
{
if (NotificationReason == 1)
{
if (NotificationData->Loaded.FullDllName)
{
printf("DllloadCallback2: DLL loaded %wZ\n", NotificationData->Loaded.FullDllName);
}
}
else
{
if (NotificationData->Unloaded.FullDllName)
{
printf("DllloadCallback2: DLL Un-loaded %wZ\n", NotificationData->Unloaded.FullDllName);
}
}
}
LIST_ENTRY* getDllLoadNotifications()
{
IMPORTAPI(L"NTDLL.dll", LdrRegisterDllNotification, NTSTATUS, ULONG, LdrDllNotification, PVOID, PVOID*);
IMPORTAPI(L"NTDLL.dll", LdrUnregisterDllNotification, NTSTATUS, PVOID);
PVOID cookie;
NTSTATUS status = LdrRegisterDllNotification(0, (LdrDllNotification)DllloadCallback, NULL, &cookie);
if (NT_SUCCESS(status))
{
printf("Original Cookie: 0x%p\n", cookie);
const LIST_ENTRY* LdrpDllNotificationList = cookie;
//
// Get .data size
//
const LIST_ENTRY* head = &NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList;
LIST_ENTRY* next = head->Flink;
while (next != head)
{
LDR_DATA_TABLE_ENTRY* entry =
CONTAINING_RECORD(next, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
const UNICODE_STRING* basename = (UNICODE_STRING*)((BYTE*)&entry->FullDllName
+ sizeof(UNICODE_STRING));
if (_wcsicmp(basename->Buffer, L"ntdll.dll") == 0)
{
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((ULONG_PTR)entry->DllBase
+ ((PIMAGE_DOS_HEADER)entry->DllBase)->e_lfanew);
for (int j = 0; j < nt->FileHeader.NumberOfSections; j++) {
const PIMAGE_SECTION_HEADER section =
(PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(nt) +
(DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * j);
if ((*(ULONG*)section->Name | 0x20202020) == 'tad.') {
PVOID dataBase = (PVOID)((ULONG_PTR)entry->DllBase
+ section->VirtualAddress);
PVOID dataEnd = (PVOID)((PULONG)dataBase + section->Misc.VirtualSize);
LIST_ENTRY* LdrpDllNotificationListNext = LdrpDllNotificationList->Flink;
while (LdrpDllNotificationListNext != LdrpDllNotificationList)
{
if (LdrpDllNotificationListNext >= dataBase &&
LdrpDllNotificationListNext <= dataEnd)
{
printf("Found LdrpDllNotificationList: 0x%p\n", LdrpDllNotificationListNext);
printf("0x%p >= 0x%p &&\n0x%p <= 0x%p\n",
LdrpDllNotificationListNext, dataBase, LdrpDllNotificationListNext, dataEnd);
LdrUnregisterDllNotification(cookie);
return LdrpDllNotificationListNext;
}
LdrpDllNotificationListNext = LdrpDllNotificationListNext->Flink;
}
break;
}
}
}
next = next->Flink;
}
}
}
LIST_ENTRY* removeDllLoadNotifications()
{
LIST_ENTRY* dllNotificationList = NULL;
if (dllNotificationList = getDllLoadNotifications())
{
LIST_ENTRY* head = dllNotificationList;
LIST_ENTRY* next = dllNotificationList->Flink;
while (next != head)
{
printf("Un-registering 0x%p\n", next);
LIST_ENTRY* oldFlink;
LIST_ENTRY* oldBlink;
oldFlink = next->Flink;
oldBlink = next->Blink;
oldFlink->Blink = oldBlink;
oldBlink->Flink = oldFlink;
next->Flink = NULL;
next->Blink = NULL;
next = oldFlink;
}
}
return dllNotificationList;
}
int main()
{
IMPORTAPI(L"NTDLL.dll", LdrRegisterDllNotification, NTSTATUS, ULONG, LdrDllNotification, PVOID, PVOID*);
PVOID cookie;
LIST_ENTRY* LdrpDllNotificationListHead;
LdrRegisterDllNotification(0, (LdrDllNotification)DllloadCallback, NULL, &cookie);
LdrRegisterDllNotification(0, (LdrDllNotification)DllloadCallback2, NULL, &cookie);
LoadLibraryA("DBGHELP.dll");
// Uncomment this if ya like
//LoadLibraryA("DBGENG.dll");
LdrpDllNotificationListHead = removeDllLoadNotifications();
//
// None of our the registered DLL notifications will see the DLL loads
// to see the effect just uncomment the earlier LoadLibraryA
//
LoadLibraryA("DBGENG.dll");
}