首先,一个进程要进行特权操作,例如修改其他进程内存数据的话,必须要有比较大的特权,一般来说,只有管理员账号有这个权限,那么我们程序该如何处理呢。

1. 确认账号的权限

,就是确认当前启动这个进程的账号,是否是管理员账号。

  1. BOOL GetProcessElevation(TOKEN_ELEVATION_TYPE pElevationType, BOOL pIsAdmin) {
  2. HANDLE hToken = NULL;
  3. DWORD dwSize;
  4. // Get current process token
  5. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
  6. return(FALSE);
  7. BOOL bResult = FALSE;
  8. // Retrieve elevation type information
  9. if (GetTokenInformation(hToken, TokenElevationType,
  10. pElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize)) {
  11. // Create the SID corresponding to the Administrators group
  12. byte adminSID[SECURITY_MAX_SID_SIZE];
  13. dwSize = sizeof(adminSID);
  14. CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID,
  15. &dwSize);
  16. if (*pElevationType == TokenElevationTypeLimited) {
  17. // Get handle to linked token (will have one if we are lua)
  18. HANDLE hUnfilteredToken = NULL;
  19. GetTokenInformation(hToken, TokenLinkedToken, (VOID*)
  20. &hUnfilteredToken, sizeof(HANDLE), &dwSize);
  21. // Check if this original token contains admin SID
  22. if (CheckTokenMembership(hUnfilteredToken, &adminSID, pIsAdmin)) {
  23. bResult = TRUE;
  24. }
  25. // Don't forget to close the unfiltered token
  26. CloseHandle(hUnfilteredToken);
  27. } else {
  28. *pIsAdmin = IsUserAnAdmin();
  29. bResult = TRUE;
  30. }
  31. }
  32. // Don't forget to close the process token
  33. CloseHandle(hToken);
  34. return(bResult);
  35. }

2. 用户权限提升

如果当前操作系统使用了UAT机制,那么我们当前运行的程序有可能是以过滤令牌的身份在运行,此时,如果我们想使用高级的权限,必须开通我们令牌中的一些特权,例如调试权限。这时,就用到了用户权限提升。

  1. BOOL EnablePrivilege(PCTSTR szPrivilege, BOOL fEnable)
  2. {
  3. // Enabling the debug privilege allows the application to see
  4. // information about service applications
  5. BOOL fOk = FALSE; // Assume function fails
  6. HANDLE hToken;
  7. // Try to open this process's access token
  8. if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,
  9. &hToken)) {
  10. // Attempt to modify the given privilege
  11. TOKEN_PRIVILEGES tp;
  12. tp.PrivilegeCount = 1;
  13. LookupPrivilegeValue(NULL, szPrivilege, &tp.Privileges[0].Luid);
  14. tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
  15. AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
  16. fOk = (GetLastError() == ERROR_SUCCESS);
  17. // Don't forget to close the token handle
  18. CloseHandle(hToken);
  19. }
  20. return(fOk);
  21. }

3.管理员身份启动一个进程

如果一个老的程序,没有考虑到特权问题,需要用户手动去提升权限,如何将这个老程序进行封装,使用户不用手动提升权限,直接运行这个程序。这个就用到了以管理员身份启动一个进程。

  1. DWORD StartElevatedProcess(LPCTSTR szExecutable, LPCTSTR szCmdLine)
  2. {
  3. // Initialize the structure.
  4. SHELLEXECUTEINFO sei = { sizeof(SHELLEXECUTEINFO) };
  5. // Ask for privileges elevation.
  6. sei.lpVerb = TEXT("runas");
  7. // Pass the application to start with high privileges.
  8. sei.lpFile = szExecutable;
  9. // Pass the command line.
  10. sei.lpParameters = szCmdLine;
  11. // Don't forget this parameter otherwise the window will be hidden.
  12. sei.nShow = SW_SHOWNORMAL;
  13. ShellExecuteEx(&sei);
  14. return(GetLastError());
  15. }

4.判断程序是运行在32位还是64位操作系统

如何让一个程序自动判断是64位操作系统,并选择合适的应用程序版本进行运行。

  1. #include<Windows.h>
  2. #include<tchar.h>
  3. typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
  4. LPFN_ISWOW64PROCESS fnIsWow64Process;//定义了一个函数指针变量。
  5. BOOL IsWow64()
  6. {
  7. BOOL bIsWow64 = FALSE; //说明当前操作系统是64位
  8. //IsWow64Process is not available on all supported versions of Windows.
  9. //Use GetModuleHandle to get a handle to the DLL that contains the function
  10. //and GetProcAddress to get a pointer to the function if available.
  11. fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
  12. if(NULL != fnIsWow64Process)
  13. {
  14. ////返回值是true or false 返回false报错,返回true指向_tprintf(L"This process under Wow64!\n")
  15. if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
  16. {
  17. //handle error
  18. }
  19. }
  20. return bIsWow64;
  21. }
  22. int _tmain()
  23. {
  24. if(IsWow64())
  25. {
  26. _tprintf(L"This process under Wow64!\n");
  27. //说明当前操作系统是64位
  28. //启动我们64位版本的应用程序
  29. }
  30. else
  31. {
  32. _tprintf(L"This process on 64 operating System\n");
  33. //说明当前操作系统是32位。
  34. //启动我们32位版本的应用程序
  35. }
  36. _gettchar();
  37. return 0;
  38. }

4.1 先运行一个32为的程序,并判断当前程序是否运行在wow64下;
4.2 如果是,那么启动64为版本的应用程序,本程序推出
4.3 如果否,继续运行32位应用程序。