UAC编程
2011-09-13 16:14:17| 分类:
笔记
| 标签:
|举报
|字号大中小 订阅
七、手动提升进程权限
shellExecutEx函数
BOOL ShellExecuteEx(LPSHELLEXECUTEINFO pExecInfo);
typedef struct _SHELLEXECUTEINFO {
DWORD cbSize;
ULONG fMask;
HWND hwnd;
PCTSTR lpVerb; // 必须设为runas
PCTSTR lpFile; // 提升后的权限启动一个可执行文件路径
PCTSTR lpParameters;
PCTSTR lpDirectory;
int nShow;
HINSTANCE hInstApp;
PVOID lpIDList;
PCTSTR lpClass;
HKEY hkeyClass;
DWORD dwHotKey;
union {
HANDLE hIcon;
HANDLE hMonitor;
} DUMMYUNIONNAME;
HANDLE hProcess;
} SHELLEXECUTEINFO,*LPSHELLEXECUTEINFO;
========================================================================
实用例子:
// Initialize the structure.
SHELLEXECUTEINFO sei = { sizeof(SHELLEXECUTEINFO) };
// Ask for privileges elevation.
sei.lpVerb = TEXT("runas");
// Create a Command Prompt fromwhich you will be able to start
// other elevated applications.
sei.lpFile = TEXT("cmd.exe");
// Don't forget this parameter; otherwise, the window will be hidden.
sei.nShow = SW_SHOWNORMAL;
if (!ShellExecuteEx(&sei)) {
DWORD dwStatus = GetLastError();
if (dwStatus == ERROR_CANCELLED) {
// The user refused to allow privileges elevation.
}
else
if (dwStatus == ERROR_FILE_NOT_FOUND) {
// The file defined by lpFile wasnot found and
// an error message popped up.
}
}
用户拒绝提升权限,shellExecutEx返回Flase,GetLastError通过使用一个ERROR_CANCELLED值来指出情况
当父进程以已经用shellExecutEx函数取得相关权限时,有继承权的子进程就不要在用CreateProcess函数
去申请同样释放权限,否则调用会失败的,GetLastError会返回 ERROR_ELEVATION_REQUIRED
八、 何为当前权限上下文
我们可以通过GetProcessElevation函数 来返回提升类型和一个指出进程是否正以管理员身份运行的布尔值。
BOOL GetProcessElevation(TOKEN_ELEVATION_TYPE* pElevationType, BOOL* pIsAdmin) {
HANDLE hToken = NULL;
DWORD dwSize;
// Get current process token
//获得当前的访问令牌
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
return(FALSE);
BOOL bResult = FALSE;
// Retrieve elevation type information
//函数检索一个指定的 的访问令牌 信息。可以读出是否是受限权限pElevationType,
//如果要判断一个用户是一个特定组的成员,使用 CheckTokenMembership 功能。
if (GetTokenInformation(hToken,TokenElevationType,
pElevationType, sizeof(TOKEN_ELEVATION_TYPE),&dwSize)) {
// Create the SID corresponding to the Administrators group
BYTE adminSID[SECURITY_MAX_SID_SIZE];
dwSize = sizeof(adminSID);
//CreateWellKnownSid创建预定义的sid
CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID,
&dwSize);
//如果以受限制权限运行的话。
if (*pElevationType == TokenElevationTypeLimited) {
// Get handle to linked token (will have one if we are lua)
HANDLE hUnfilteredToken = NULL;
GetTokenInformation(hToken, TokenLinkedToken, (VOID*)
&hUnfilteredToken, sizeof(HANDLE), &dwSize);
// Check if this original tokencontains admin SID
if (CheckTokenMembership(hUnfilteredToken, &adminSID, pIsAdmin)) {
bResult = TRUE;
}
// Don't forget to close the unfiltered token
CloseHandle(hUnfilteredToken);
} else {
*pIsAdmin = IsUserAnAdmin();
bResult = TRUE;
}
}
// Don't forget to close the process token
CloseHandle(hToken);
return(bResult);
}
其中GetTokenInformation使用的与进程关联的安全令牌和 TokenElevationType 参数获得提升类型,
提升类型的值由TOKEN_ELEVATION_TYPE 枚举类型来定义。
TOKEN_ELEVATION_TYPE 的值
值 说明
TokenElevationTypeDefault 默认运行用户运行,UAC被禁用
TokenElevationTypeFull 权限被成功提升,而且令牌没有被筛选过
TokenElevationTypeLimited 进程以受限的权限运行,它对应于一个筛选过的令牌
根据这些值我们可以知道进程在运行时使用的令牌时候被涮选过。下一步是判断用户是否是管理员。如果令牌没有被帅选过。为了知道是否正在以管理员的身份运行。IsUserAnAdmin函数最理想。在令牌被帅选的情况下。我们需要获取未帅选的令牌(把TokenLinkedToken传给GetToKenInfomation),然后判断其中时候包含一个管理员SID(借助CreateWellKnownSid和CheckTokenMembership)
评论这张
转发至微博
转发至微博
评论