精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
First, why do you need to know if you are an administrator? If there's a directory or registry key that you are denied access to, why not check the security descriptor of that folder? If there's an API that doesn't work, it may be because you don't have the right privilege enabled. Second, what are you doing that requires administrative privileges? Are you trying to access Program Files (write to "Application data" or "My documents" instead)? Or are you trying install some kind of malware (which requires admin privileges to do its damage)? Third, why do you have to be an Administrator specifically? Why can't it be someone like Power User or Domain Account Operator? Fourth, note that you can accomplish this by using the Net*Info functions, or by calling WMI, or even using the Shell provided function: IsUserAnAdmin().首先,为什么需要知道您是否是管理员?如果存在拒绝您访问的目录或注册表项,为什么不检查该文件夹的安全描述符?如果某个API不起作用,则可能是因为您没有启用正确的特权。其次,您在做什么需要管理权限?您是否要访问程序文件(改为写入“应用程序数据”或“我的文档”)?还是您正在尝试安装某种恶意软件(需要管理员特权才能对其进行破坏)?第三,为什么必须专门成为管理员?为什么不能像Power User或Domain Account Operator这样的人?第四,请注意,您可以通过使用Net*Info函数,调用WMI甚至使用Shell提供的函数来完成此操作:IsUserAnAdmin()
int IsAdminRunning(void) { bool IsMember = FALSE; ATL::CAccessToken ProcToken; ATL::CAccessToken ImpersonationToken; ATL::CSid UserSid(Sids::Admins()); ProcToken.GetEffectiveToken(TOKEN_READ | TOKEN_DUPLICATE); ProcToken.CreateImpersonationToken(&ImpersonationToken); ImpersonationToken.CheckTokenMembership(UserSid, &IsMember); return IsMember; }
Figure 11: Determining if the user is an admin.
If you're dealing with a domain situation, you also need to lookup the domain administrators SID ("DA" in SDDL). A sample in the Platform SDK contains another sample solution.如果要处理域问题,还需要查找域管理员SID(DA在SDDL中为“ ”)。Platform SDK中的一个示例包含另一个示例解决方案。
void SetPrivilege( const ATL::CStringT< <TCHAR, ATL::StrTraitATL< <TCHAR> > &lpszPrivilege, bool bEnablePrivilege) { ATL::CAccessToken ProcToken; ProcToken.GetEffectiveToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES); if(bEnablePrivilege) { ProcToken.EnablePrivilege(lpszPrivilege); } else { ProcToken.DisablePrivilege(lpszPrivilege); } }
Group policy privileges are turned off by default, even when enabled in group policy. You have to turn them on by changing your access token. You should be prepared to handle the case when the privilege is disabled in group policy (and you can't turn it on, no matter how hard you try). When you've finished with the privilege, don't forget to turn it back off.即使在组策略中启用了组策略特权,默认情况下也会将其关闭。您必须通过更改访问令牌来打开它们。当组策略中的特权被禁用时,您应该准备好处理这种情况(无论您如何努力,都无法将其打开)。完成特权后,别忘了将其关闭。
This is a Whoami clone. To make life easier, we won't decrypt the attributes from a number to text (unlike what Whoami does).这是Whoami克隆。为了使生活更轻松,我们不会解密从数字到文本的属性(与Whoami有所不同)。
void DoWhoAmI(void) { size_t i = 0; ATL::CAccessToken ProcToken; ATL::CSid SidUser; ProcToken.GetEffectiveToken(TOKEN_QUERY); /* First print off the user. */ ProcToken.GetUser(&SidUser); std::wcout << _T("Owner: ") << SidUser.AccountName() << _T("\r\n"); /* Now print the groups */ ATL::CTokenGroups pGroups; ProcToken.GetGroups(&pGroups); ATL::CSid::CSidArray pSids; ATL::CAtlArraypAttributes; pGroups.GetSidsAndAttributes(&pSids, &pAttributes); /* Iterate both pSids and pAttributes simultaneously */ std::wcout << _T("\r\nGroups\r\n"); for(i = 0; i < pGroups.GetCount() ; i++) std::wcout << pSids[i].AccountName() << _T(": ") << pAttributes.GetAt(i) << _T("\r\n"); /* Get the list of Privileges */ ATL::CTokenPrivileges pPrivileges; ProcToken.GetPrivileges(&pPrivileges); ATL::CTokenPrivileges::CNames pNames; ATL::CTokenPrivileges::CAttributes pGroupAttributes; pPrivileges.GetNamesAndAttributes(&pNames, &pGroupAttributes); /* Printing Privileges is very similar to */ std::wcout << _T("\r\nPrivileges\r\n"); for(i = 0; i < pGroups.GetCount() ; i++) std::wcout << static_cast (pNames.GetAt(i)) << _T(": ") << pGroupAttributes.GetAt(i) << _T("\r\n"); /** TODO: the DWORDs are printed out as numbers. Convert these * DWORDs into text, the same text that whoami displays. **/ }
Figure 13: Regenerating the information from Whoami.
This technique only applies to just Windows XP and Server 2003. The next version of Windows will change this technique.
For method 2, I wrapped the SAFER routines into a class (to abstract object management from the caller).
该技术仅适用于Windows XP和Server2003。Windows的下一版本将更改此技术。
对于方法2,我将SAFER例程包装到一个类中(以从调用方抽象对象管理)。
class SaferRaiiWrapper { public: /** Error handling has been added in the *downloadable version of this class **/ explicit SaferRaiiWrapper( const DWORD dwScopeIdIn = SAFER_LEVELID_NORMALUSER, const HANDLE hTokenIn = NULL) : hToken(hTokenIn), LevelHandle(NULL), dwScopeId(dwScopeIdIn) { ::SaferCreateLevel(SAFER_SCOPEID_USER, this->dwScopeId, SAFER_LEVEL_OPEN, &LevelHandle, NULL); ::SaferComputeTokenFromLevel(this->get_LevelHandle(), NULL, &hToken, NULL, NULL); } ; virtual PROCESS_INFORMATION CreateProcessAsUser(const const std::basic_string&lpCommandLine, STARTUPINFO *lpStartupInfoIn = NULL, DWORD dwCreationFlags = CREATE_NEW_CONSOLE, const std::basic_string &lpApplicationName = _T(""), const std::basic_string &lpCurrentDirectory = _T(""), LPVOID lpEnvironment = NULL, BOOL bInheritHandles = FALSE, SECURITY_ATTRIBUTES *lpProcessAttributes = NULL, SECURITY_ATTRIBUTES *lpThreadAttributes = NULL) { STARTUPINFO StartupInfoAlt = {0}; LPSTARTUPINFO lpStartupInfoActual = (lpStartupInfoIn != NULL) ? lpStartupInfoIn : &StartupInfoAlt; PROCESS_INFORMATION Result = {0}; TCHAR *lpCmdLineWritable = new TCHAR[sCmdLine.capacity() + 1]; /** The command line needs to be writable. * So make a writable copy of our command line. **/ sCmdLine.copy(lpCmdLineWritable, sCmdLine.size()); lpCmdLineWritable[sCmdLine.size()] = _T('\0'); lpStartupInfoActual->cb = sizeof(STARTUPINFO); lpStartupInfoActual->lpDesktop = NULL; ::CreateProcessAsUser(this->hToken, (sAppName.empty() ? NULL : sAppName.c_str()), lpCmdLineWritable, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, (sCurDir.empty() ? NULL : sCurDir.c_str()), lpStartupInfoActual, &Result); delete [] lpCmdLineWritable; return Result; } ; HANDLE get_hToken(void) const { return hToken; } ; virtual ~SaferRaiiWrapper() { ::CloseHandle(this->hToken); ::SaferCloseLevel(this->LevelHandle); } ; protected: const SAFER_LEVEL_HANDLE &get_LevelHandle(void) const { return LevelHandle; } ; void set_LevelHandle(const SAFER_LEVEL_HANDLE &LevelHandleIn) { this->LevelHandle = LevelHandleIn; } ; void set_hToken(const HANDLE hToken) { this->hToken = hToken; } ; private: HANDLE hToken; SAFER_LEVEL_HANDLE LevelHandle; const DWORD dwScopeId; };
Figure 14: Creating a restricted token using the Software Restriction Policies.
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州市文化路47号院1号楼4层(47-1楼位于文化路和红专路十字路口东北角,郑州大学工学院招待所南边,工学院科技报告厅西边。)