<think>我们遇到了“Failed to get SYSTEM token”错误,这通常是因为无法从winlogon.exe(或类似系统进程)获取令牌。让我们改进令牌获取方法,并增加兼容性和错误处理。
改进点:
1. 尝试多个系统进程(winlogon.exe, services.exe, svchost.exe等)
2. 处理令牌复制失败的情况
3. 更健壮的错误日志
以下是改进后的GetSystemToken函数:
</think>### SYSTEM 令牌获取失败的解决方案
当出现 "Failed to get SYSTEM token" 错误时,通常是由于权限不足或目标进程选择不当。以下是改进后的完整解决方案,解决了令牌获取问题并增强了兼容性:
```cpp
#include <windows.h>
#include <iostream>
#include <tchar.h>
#include <vector>
#include <psapi.h>
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "psapi.lib")
// 提升为调试权限
bool EnableDebugPrivilege() {
HANDLE hToken;
TOKEN_PRIVILEGES tp;
// 打开当前进程令牌
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
std::cerr << "OpenProcessToken failed: " << GetLastError() << std::endl;
return false;
}
// 获取调试权限LUID
LUID luid;
if (!LookupPrivilegeValue(nullptr, SE_DEBUG_NAME, &luid)) {
std::cerr << "LookupPrivilegeValue failed: " << GetLastError() << std::endl;
CloseHandle(hToken);
return false;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// 调整令牌权限
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) {
std::cerr << "AdjustTokenPrivileges failed: " << GetLastError() << std::endl;
CloseHandle(hToken);
return false;
}
CloseHandle(hToken);
return true;
}
// 获取SYSTEM令牌(改进版本)
HANDLE GetSystemToken() {
std::vector<DWORD> processIds(1024);
DWORD cbNeeded;
// 枚举所有进程ID
if (!EnumProcesses(processIds.data(), static_cast<DWORD>(processIds.size() * sizeof(DWORD)), &cbNeeded)) {
std::cerr << "EnumProcesses failed: " << GetLastError() << std::endl;
return nullptr;
}
DWORD processCount = cbNeeded / sizeof(DWORD);
HANDLE hToken = nullptr;
// 尝试多个系统进程
const TCHAR* systemProcesses[] = {
_T("winlogon.exe"),
_T("services.exe"),
_T("svchost.exe"),
_T("lsass.exe"),
_T("csrss.exe")
};
for (DWORD i = 0; i < processCount; i++) {
if (processIds[i] == 0) continue;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIds[i]);
if (!hProcess) continue;
TCHAR szProcessName[MAX_PATH] = { 0 };
if (GetProcessImageFileName(hProcess, szProcessName, MAX_PATH)) {
// 提取文件名
TCHAR* pBaseName = _tcsrchr(szProcessName, _T('\\'));
if (pBaseName) pBaseName++;
else pBaseName = szProcessName;
// 检查是否是系统进程
for (int j = 0; j < sizeof(systemProcesses) / sizeof(systemProcesses[0]); j++) {
if (_tcsicmp(pBaseName, systemProcesses[j]) == 0) {
HANDLE hProcToken = nullptr;
// 尝试打开进程令牌
if (OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &hProcToken)) {
// 尝试复制令牌
if (DuplicateTokenEx(hProcToken, MAXIMUM_ALLOWED, nullptr,
SecurityImpersonation, TokenPrimary, &hToken)) {
CloseHandle(hProcToken);
CloseHandle(hProcess);
return hToken;
}
CloseHandle(hProcToken);
}
break; // 找到匹配进程后跳出内部循环
}
}
}
CloseHandle(hProcess);
}
std::cerr << "Failed to find a suitable system process token" << std::endl;
return nullptr;
}
// 以SYSTEM权限启动程序
bool RunAsSystem(LPCTSTR lpExePath) {
// 1. 提升调试权限
if (!EnableDebugPrivilege()) {
std::cerr << "Warning: Failed to enable debug privilege. Trying to proceed anyway..." << std::endl;
}
// 2. 获取SYSTEM令牌
HANDLE hSystemToken = GetSystemToken();
if (!hSystemToken) {
std::cerr << "Failed to get SYSTEM token" << std::endl;
return false;
}
// 3. 准备创建进程
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR szCommandLine[MAX_PATH];
// 复制路径(CreateProcessAsUser需要可写缓冲区)
_tcscpy_s(szCommandLine, MAX_PATH, lpExePath);
// 4. 创建进程
BOOL result = CreateProcessAsUser(
hSystemToken, // SYSTEM令牌
nullptr, // 应用程序名
szCommandLine, // 命令行
nullptr, // 进程安全属性
nullptr, // 线程安全属性
FALSE, // 不继承句柄
CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, // 创建标志
nullptr, // 环境块(继承)
nullptr, // 当前目录(继承)
&si, // 启动信息
&pi // 进程信息
);
DWORD lastError = GetLastError();
if (result) {
std::wcout << L"[+] Successfully started: " << lpExePath << std::endl;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
} else {
std::cerr << "CreateProcessAsUser failed: " << lastError << std::endl;
// 尝试替代方法:使用CreateProcessWithTokenW(Vista+)
HMODULE hAdvapi = LoadLibrary(_T("advapi32.dll"));
if (hAdvapi) {
typedef BOOL(WINAPI* CreateProcessWithTokenWFunc)(
HANDLE, DWORD, LPCWSTR, LPWSTR, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
CreateProcessWithTokenWFunc pCreateProcessWithTokenW =
(CreateProcessWithTokenWFunc)GetProcAddress(hAdvapi, "CreateProcessWithTokenW");
if (pCreateProcessWithTokenW) {
result = pCreateProcessWithTokenW(
hSystemToken,
LOGON_WITH_PROFILE,
nullptr,
szCommandLine,
CREATE_NEW_CONSOLE,
nullptr,
nullptr,
&si,
&pi);
if (result) {
std::wcout << L"[+] Created with CreateProcessWithTokenW: " << lpExePath << std::endl;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
} else {
std::cerr << "CreateProcessWithTokenW failed: " << GetLastError() << std::endl;
}
}
FreeLibrary(hAdvapi);
}
}
CloseHandle(hSystemToken);
return result;
}
// 获取当前目录下的文件路径
bool GetCurrentDirFilePath(LPCTSTR fileName, LPTSTR buffer, DWORD bufferSize) {
if (!GetModuleFileName(nullptr, buffer, bufferSize)) {
return false;
}
TCHAR* pLastSlash = _tcsrchr(buffer, _T('\\'));
if (!pLastSlash) return false;
*(pLastSlash + 1) = _T('\0');
_tcscat_s(buffer, bufferSize, fileName);
return true;
}
int main() {
// 1. 检查管理员权限
BOOL isAdmin = FALSE;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID adminGroup;
if (AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminGroup)) {
CheckTokenMembership(nullptr, adminGroup, &isAdmin);
FreeSid(adminGroup);
}
if (!isAdmin) {
std::cerr << "Error: Program must be run as administrator!" << std::endl;
system("pause");
return 1;
}
// 2. 获取XE.exe路径
TCHAR szPath[MAX_PATH];
if (!GetCurrentDirFilePath(_T("XE.exe"), szPath, MAX_PATH)) {
std::cerr << "Failed to get current directory" << std::endl;
return 1;
}
// 3. 检查文件是否存在
if (GetFileAttributes(szPath) == INVALID_FILE_ATTRIBUTES) {
std::wcerr << L"File not found: " << szPath << std::endl;
return 1;
}
// 4. 以SYSTEM权限运行
if (RunAsSystem(szPath)) {
std::cout << "[+] Process launched successfully" << std::endl;
} else {
std::cerr << "[-] Failed to launch process" << std::endl;
}
system("pause");
return 0;
}
```
### 关键改进点:
1. **多进程令牌获取**:
```cpp
// 尝试多个系统进程
const TCHAR* systemProcesses[] = {
_T("winlogon.exe"),
_T("services.exe"),
_T("svchost.exe"),
_T("lsass.exe"),
_T("csrss.exe")
};
```
2. **改进的错误处理**:
```cpp
// 详细错误输出
std::cerr << "OpenProcessToken failed: " << GetLastError() << std::endl;
```
3. **替代API动态加载**:
```cpp
// 动态加载CreateProcessWithTokenW
HMODULE hAdvapi = LoadLibrary(_T("advapi32.dll"));
if (hAdvapi) {
typedef BOOL(WINAPI* CreateProcessWithTokenWFunc)(...);
// ...
}
```
4. **权限处理优化**:
```cpp
// 添加必要的令牌权限
OpenProcessToken(hProcess,
TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY,
&hProcToken);
```
### 常见问题解决方案:
1. **权限不足错误**:
- 确保程序以管理员身份运行
- 检查SE_DEBUG_NAME权限是否启用
- 使用更全面的系统进程列表
2. **进程创建失败**:
```cpp
// 添加创建标志
CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT
```
3. **路径问题**:
```cpp
// 使用GetProcessImageFileName代替GetModuleBaseName
GetProcessImageFileName(hProcess, szProcessName, MAX_PATH);
```
4. **兼容性问题**:
```cpp
// 动态加载API支持旧版Windows
LoadLibrary(_T("advapi32.dll"));
```
### 替代方案:使用计划任务
如果令牌方法仍然失败,可以使用更可靠的任务计划程序方法:
```cpp
#include <windows.h>
#include <taskschd.h>
#include <comdef.h>
#include <iostream>
#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsuppw.lib")
bool RunAsSystemViaTaskScheduler(LPCTSTR exePath) {
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr)) return false;
ITaskService* pService = nullptr;
hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER,
IID_ITaskService, (void**)&pService);
if (FAILED(hr)) goto cleanup;
hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr)) goto cleanup;
ITaskFolder* pRootFolder = nullptr;
hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
if (FAILED(hr)) goto cleanup;
IRegisteredTask* pRegisteredTask = nullptr;
hr = pRootFolder->DeleteTask(_bstr_t(L"TempSystemRunner"), 0);
// 忽略删除错误
ITaskDefinition* pTask = nullptr;
hr = pService->NewTask(0, &pTask);
if (FAILED(hr)) goto cleanup;
IPrincipal* pPrincipal = nullptr;
hr = pTask->get_Principal(&pPrincipal);
if (SUCCEEDED(hr)) {
pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
pPrincipal->put_UserId(_bstr_t(L"SYSTEM"));
pPrincipal->Release();
}
IExecAction* pExecAction = nullptr;
IActionCollection* pActionCollection = nullptr;
hr = pTask->get_Actions(&pActionCollection);
if (SUCCEEDED(hr)) {
hr = pActionCollection->Create(TASK_ACTION_EXEC, &pExecAction);
if (SUCCEEDED(hr)) {
pExecAction->put_Path(_bstr_t(exePath));
pExecAction->Release();
}
pActionCollection->Release();
}
IRegistrationInfo* pRegInfo = nullptr;
hr = pTask->get_RegistrationInfo(&pRegInfo);
if (SUCCEEDED(hr)) {
pRegInfo->put_Author(_bstr_t(L"System Runner"));
pRegInfo->Release();
}
hr = pRootFolder->RegisterTaskDefinition(_bstr_t(L"TempSystemRunner"), pTask,
TASK_CREATE_OR_UPDATE, _variant_t(), _variant_t(),
TASK_LOGON_SERVICE_ACCOUNT, _variant_t(L""), &pRegisteredTask);
if (SUCCEEDED(hr)) {
IRunningTask* pRunningTask = nullptr;
hr = pRegisteredTask->Run(_variant_t(), &pRunningTask);
if (SUCCEEDED(hr)) {
pRunningTask->Release();
}
}
cleanup:
if (pRegisteredTask) pRegisteredTask->Release();
if (pRootFolder) pRootFolder->Release();
if (pTask) pTask->Release();
if (pService) pService->Release();
CoUninitialize();
return SUCCEEDED(hr);
}
```