#include<Windows.h>
#include<tchar.h>
#include<Shlobj.h>
//可以把这个函数当Windows API来用。这个函数返回BOOL,当函数返回TRUE的时候,函数成功,当函数返回FALSE的话
//函数失败。
/*
TOKEN_ELEVATION_TYPE* pElevationType:令牌提升类型。
BOOL* pIsAdmin :是否是管理员。保存结果
这个函数,确定了,运行当前程序的帐号,是否为管理员帐号,以及当前进程的令牌,是哪种令牌。甚至你还可以确定,当前
的这个操作系统是否启动了UAC功能。
*/
BOOL GetProcessElevation(TOKEN_ELEVATION_TYPE* pElevationType, BOOL* pIsAdmin)
{
HANDLE hToken = NULL;
DWORD dwSize;
// 获得当前进程的令牌句柄。
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
return(FALSE);
BOOL bResult = FALSE;
// 看看这个令牌的权限提升类型是哪一种:
/*
TokenElevationTypeDefault:进程以缺省的用户身份运行,或者没有使用UAC功能,简单来说,就是用户没有启动UAC功能,那么程序使用的令牌,一定不是Filter Token。
TokenElevationTypeFull:进程的权限已经被提升,进程令牌没有使用filter令牌
TokenElevationTypeLimited:进程使用的令牌是Filter令牌。此时通过GetTokenInformation函数,并使用TokenLinkedToken标志,来获取原令牌。
*/
if (GetTokenInformation(hToken, TokenElevationType,
pElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize))
{
// 创建一个管理员SID
BYTE adminSID[SECURITY_MAX_SID_SIZE];
dwSize = sizeof(adminSID);
CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID,
&dwSize);
if (*pElevationType == TokenElevationTypeLimited)
{
//通过Filter Token来获得原始的Token
HANDLE hUnfilteredToken = NULL;
//TokenLinkedToken标志,表示要获得Filter Token的原始Token。
GetTokenInformation(hToken, TokenLinkedToken, (VOID*)
&hUnfilteredToken, sizeof(HANDLE), &dwSize);
// 检查原始Token中,管理员账户adminSID是否被激活,如果被激活,那么说明启动这个
//程序的帐号是管理员帐号,否则不是。
if (CheckTokenMembership(hUnfilteredToken, &adminSID, pIsAdmin))
//这个CheckTokenMembership函数,结果被保存在pIsAdmin参数中,而这个函数的返回值
//只是表示,这个函数是否成功。
{
bResult = TRUE;
}
// 不要忘了关闭原始令牌。
CloseHandle(hUnfilteredToken);
}
else //如果是原始令牌,只要IsUsrAndmin就可以确定,启动当前程序的帐号是否是管理员帐号。
{
*pIsAdmin = IsUserAnAdmin();
bResult = TRUE;
}
}
// 不要忘了关闭进程令牌。
CloseHandle(hToken);
return(bResult);
}
// 以管理员身份运行程序
void adminRun()
{
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = L"runas"; //这个参数设置,就是让ShellExecuteEx函数 启动的进程已管理员身份运行,而不使用过滤令牌。
ShExecInfo.lpFile = L"cmd"; //这个就是你要启动的程序
ShExecInfo.lpParameters = L"";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW; //如果这个参数不设置,那么你看不见被启动程序的
//窗口。
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
}
#include<Windows.h>
//这个函数,将进程权限提升成具有调试权限的进程,这个权限应该是进程
//所能具有的最大权限。
//这个函数成功的前提,必须是,启动这个进程的帐号必须是管理员帐号。
//当fEnable=TRUE的时候,授予当前进程权限
//当fEnable=FALSE的时候,取消当前进程权限。
//当函数返回TRUE时,说明权限调整成功,否则失败。
BOOL EnablePrivilege(PCTSTR szPrivilege, BOOL fEnable) {
//启用debug特权允许应用程序查看 szPrivilege = SE_DEBUG_NAME
//关于服务应用程序的信息
BOOL fOk = FALSE; // 假设函数失败
HANDLE hToken;
// 尝试打开此进程的访问令牌 TOKEN_ADJUST_PRIVILEGES 需要启用或禁用访问令牌中的特权
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,
&hToken)) {
// 试图修改给定的权限
TOKEN_PRIVILEGES tp;
/*
typedef struct _TOKEN_PRIVILEGES {
DWORD PrivilegeCount;
//这个结构体,有几个权限,也就是第二个成员变量Privaileges数组,有几个元素。
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
typedef struct _LUID_AND_ATTRIBUTES {
LUID Luid;//本地唯一标识符。不肯能重复的一个数组。这个东西和GUID是一个东西
DWORD Attributes;//权限属性。
} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;
*/
tp.PrivilegeCount = 1;
// LookupPrivilegeValue函数检索在指定系统上使用的本地惟一标识符(LUID),以本地表示指定的特权名称。
LookupPrivilegeValue(NULL, szPrivilege, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
fOk = (GetLastError() == ERROR_SUCCESS);
// Don't forget to close the token handle
CloseHandle(hToken);
}
return(fOk);
}