我们一般使用的是管理员账户,如果开启了UAC,那么默认情况下双击一个程序时是以medium权限运行,称为受限的管理员权限,如果右键程序“以管理员权限运行”,那么程序是high权限,称为不受限的管理员权限。
权限由高到低分别为Low Medium High System权限,Low权限很少见,浏览器的某些进程就是Low权限的,Windows服务一般是System权限。
下面先说权限由低到高,需要使用的代码
如果受限管理员权限要启动一个不受限管理员权限,需要使用如下代码:
HINSTANCE hRet = ::ShellExecute(NULL, L"runas", pszFileName, NULL, NULL, SW_SHOWNORMAL);
if (32 < (DWORD)hRet)
{
return TRUE;
}
return FALSE;
使用此代码后,如果当前是受限管理员,那么会弹出一个UAC框,点击确定后,会启动一个管理员程序。
管理员启动一个system级别的cmd进程,
1、使用PsExec.exe,使用管理员启动cmd,运行PsExec.exe -i -s cmd.exe 启动的就是一个system的cmd了
2、使用管理员权限创建服务,在服务程序中启动cmd进程,但是服务进程默认都是运行在session 0下,Windows存在会话隔离机制,session 0下面的窗口,当前用户一般是session 1、2、3........ 所以当前用户看不到session 0启动的cmd窗口。使用下面代码可以在服务程序中启动一个会话1的system级别的cmd进程,代码如下:
BOOL createcmd()
{
HANDLE hPToken = NULL;
HANDLE hUserTokenDup = NULL;
PROCESS_INFORMATION pi;
TOKEN_PRIVILEGES tp;
LUID luid;
BOOL bRet = FALSE;
__try
{
if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
| TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
| TOKEN_READ | TOKEN_WRITE, &hPToken))
__leave;
if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hUserTokenDup))
{
__leave;
}
DWORD dwSessionId = 1; //会话1
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{
DWORD error = GetLastError();
__leave;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hUserTokenDup, FALSE, &tp, sizeof (TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, NULL))
{
DWORD error = GetLastError();
__leave;
}
if (!SetTokenInformation(hUserTokenDup, TokenSessionId, (void *)& dwSessionId, sizeof (DWORD)))
{
DWORD error = GetLastError();
__leave;
}
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
//si.dwXSize = 120;
si.lpDesktop = L"WinSta0\\Default";
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
LPVOID pEnv = NULL;
TCHAR buffCmd[MAX_PATH] = { 0 };
_tcscat_s(buffCmd, _countof(buffCmd) - 1, L"C:\\Windows\\System32\\CMD.exe");
bRet = CreateProcessAsUser(hUserTokenDup, NULL, buffCmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
}
__finally
{
if (hPToken)
{
CloseHandle(hPToken);
hPToken = NULL;
}
if (hUserTokenDup)
{
CloseHandle(hUserTokenDup);
hUserTokenDup = NULL;
}
if (pi.hProcess)
{
CloseHandle(pi.hProcess);
pi.hProcess = NULL;
}
if (pi.hThread)
{
CloseHandle(pi.hThread);
pi.hThread = NULL;
}
}
return bRet;
}
上面代码设置新启动进程的会话id为1,不仅可以设置会话id,还可以设置更多的属性,服务进程入口启动代码如下:
int _tmain(int argc, _TCHAR* argv[])
{
createcmd(); //这是只启动cmd 不管服务状态
return 0;
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = L"ServerCMD";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);
return 0;
}
启动一个管理员权限的cmd,使用如下命令创建服务
sc create ServerCMD binpath= C:\Users\admin\Desktop\TestServerCmd\TestServerCmd.exe
在win7下,binpath等于号后面有一个空格,服务名为ServerCmd。
net stop ServerCMD 可以停止服务
sc delete ServerCMD 可以删除服务
net start ServerCMD 可以启动服务
上面介绍了从管理员从到system的两种方法。
接下来介绍降权,从高级别到低级别,顺序为从system到 high medium low级别,使用如下代码:
#include <Windows.h>
#include <sddl.h>
#pragma comment(lib, "Advapi32.lib")
void CreateIntegritySidProcess(WCHAR* wszIntegritySid)
{
BOOL bRet = FALSE;
HANDLE hToken = NULL;
HANDLE hNewToken = NULL;
// Notepad is used as an example
WCHAR wszProcessName[MAX_PATH] =L"C:\\Windows\\System32\\Notepad.exe";
PSID pIntegritySid = NULL;
TOKEN_MANDATORY_LABEL TIL = { 0 };
PROCESS_INFORMATION ProcInfo = { 0 };
STARTUPINFO StartupInfo = { 0 };
ULONG ExitCode = 0;
__try
{
if (FALSE == OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hToken))
{
__leave;
}
if (FALSE == DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,
SecurityImpersonation, TokenPrimary, &hNewToken))
{
__leave;
}
if (FALSE == ConvertStringSidToSid(wszIntegritySid, &pIntegritySid))
{
__leave;
}
TIL.Label.Attributes = SE_GROUP_INTEGRITY;
TIL.Label.Sid = pIntegritySid;
// Set the process integrity level
if (FALSE == SetTokenInformation(hNewToken, TokenIntegrityLevel, &TIL,
sizeof(TOKEN_MANDATORY_LABEL)+GetLengthSid(pIntegritySid)))
{
__leave;
}
bRet = CreateProcessAsUser(hNewToken, NULL,
wszProcessName, NULL, NULL, FALSE,
0, NULL, NULL, &StartupInfo, &ProcInfo);
}
__finally
{
if (NULL != pIntegritySid)
{
LocalFree(pIntegritySid);
pIntegritySid = NULL;
}
if (NULL != hNewToken)
{
CloseHandle(hNewToken);
hNewToken = NULL;
}
if (NULL != hToken)
{
CloseHandle(hToken);
hToken = NULL;
}
}
printf("%ls bRet:%d\n", wszIntegritySid, bRet);//%ls打印宽字符
}
int _tmain(int argc, _TCHAR* argv[])
{
/*
Low (SID: S-1-16-4096),
Medium (SID: S-1-16-8192),
High (SID: S-1-16-12288)
System (SID: S-1-16-16384).
*/
//创建不同权限的进程
CreateIntegritySidProcess(L"S-1-16-4096");//low权限进程
CreateIntegritySidProcess(L"S-1-16-8192");//medium权限进程
CreateIntegritySidProcess(L"S-1-16-12288");//high权限进程
CreateIntegritySidProcess(L"S-1-16-16384");//system权限进程
printf("end\n");
getchar();
return 0;
}
上面的代码如果以system进程启动,那么可以启动low、medium、high、system权限的进程,如果以medium权限启动,那么只能启动low和medium权限的进程,只能启动当前级别权限和更低级别的权限进程,实现进程降权,但是用户名是没变的,而且环境变量也没变。如果是system进程启动的low进程,环境变量也继承的system进程的环境变量。
还可以通过枚举explorer进程,获取sessionid,获取sessionid的token,来模拟用户。
标签:__,NULL,Windows,TOKEN,管理员,进程,权限 From: https://www.cnblogs.com/ps12345678/p/16821904.html