windows核心编程-进程权限总结

来源:互联网 发布:tscttp244pro打印软件 编辑:程序博客网 时间:2024/06/10 02:01

1、首先,一个进程要进行特权操作,例如修改其他进程内存数据的话,必须要有比较大的特权,

一般来说,只有管理员账号有这个权限,那么我们程序的第一件事情,就是确认当前启动这个进程

的账号,是否为管理员账号

  1. //可以把这个函数当windows API来使用,这个函数返回BOOL值,当函数返回TRUE成功,当为FALSE失败  
  2. /* 
  3. TOKEN_ELEVATION_TYPE* pElevationType:令牌提升类型。 
  4. BOOL*pIsAdmin:是否是管理员,保存结果 
  5.  
  6. 这个函数确定了,运行当前程序的账号,是否为管理员账号,以及当前进程的令牌,是哪种令牌 
  7. 甚至你还可以确定,当前的这个操作系统是否启用了UAC功能 
  8. */  
  9. BOOL GetProcessElevation(TOKEN_ELEVATION_TYPE* pElevationType, BOOL* pIsAdmin)  
  10. {  
  11.     HANDLE hToken = NULL;  
  12.     DWORD dwSize;  
  13.     //Get Current process token获得当前进程的令牌句柄  
  14.     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))  
  15.         return FALSE;  
  16.   
  17.     BOOL bResult = FALSE;  
  18.   
  19.     //Retrive elevation type information看这个令牌的权限提升类型是哪一种  
  20.     /* 
  21.     typedef enum _TOKEN_ELEVATION_TYPE { 
  22.     TokenElevationTypeDefault = 1, 
  23.     TokenElevationTypeFull, 
  24.     TokenElevationTypeLimited, 
  25.     } TOKEN_ELEVATION_TYPE, *PTOKEN_ELEVATION_TYPE; 
  26.     */  
  27.     if (GetTokenInformation(hToken, TokenElevationType,  
  28.         pElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize))  
  29.     {  
  30.         //创建一个管理员SID  
  31.         BYTE adminSID[SECURITY_MAX_SID_SIZE];  
  32.         dwSize = sizeof(adminSID);  
  33.         CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID,  
  34.             &dwSize);  
  35.   
  36.         if (*pElevationType == TokenElevationTypeLimited)  
  37.         {  
  38.             //通过FilterToken来获得原始的Token  
  39.             HANDLE hUnfilteredToken = NULL;  
  40.             //TokenLinkedToken标志,表示要获得的FilterToken的原始Token  
  41.             GetTokenInformation(hToken, TokenLinkedToken, (void*)  
  42.                 &hUnfilteredToken, sizeof(HANDLE), &dwSize);  
  43.   
  44.   
  45.             //检查原始Token中,管理员adminSID是否被激活,如果被激活,那么说明启动这个  
  46.             //程序的账号是管理员账号,否则不是  
  47.             if (CheckTokenMembership(hUnfilteredToken, &adminSID, pIsAdmin))  
  48.                 //这个CheckTokenMembership函数,结果被保存在pIsAdmin参数中,  
  49.                 //而这个函数的返回值只是表示,这个函数是否成功  
  50.             {  
  51.                 bResult = TRUE;  
  52.             }  
  53.   
  54.   
  55.             //不要忘记关闭原始令牌  
  56.             CloseHandle(hUnfilteredToken);  
  57.         }  
  58.         else//如果是原始令牌,只要IsUserAnAdmin就可以确定,启动当前程序的账号是否是管理员账号  
  59.             *pIsAdmin = IsUserAnAdmin();  
  60.             bResult = TRUE;  
  61.         }  
  62.         CloseHandle(hToken);//不要忘记关闭进程令牌  
  63.         return bResult;  
  64.     }  
  65.   
  66. }  

2、如果当前操作系统使用了UAT机制,那么我们当前运行的程序有可能是以过滤令牌的身份在运行,

此时,如果我们想使用高级权限,必须开通我们令牌中的一些特权,例如调试权限,这是,就用到了

用户权限提升

BOOL EnableDebugPrivilege(BOOL fEnable)  {      //Enable the debug privilege allows the application to see      //information about service application      BOOL fok = FALSE; //Assume function fails      HANDLE hToken;             //获取当前进程的令牌      //这个函数第一个参数是当前进程句柄,第二个参数是:进程对获得的令牌有哪些操作权限      if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))      {          //开始激活当前令牌的调试权限          TOKEN_PRIVILEGES tp;   //结构体,表示令牌权限            /*             typedef struct _TOKEN_PRIVILEGES {                 DWORD PrivilegeCount;//这个结构体,有几个权限,也就是第二个成员变量privileges数组有几个元素                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;//此时我们值启动调试权限,所以是1          //下面一个函数,查找调试权限LUID,如果第一个参数是NULL          //表示获取本地的某个权限的LUID          LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);          //上面的LookUpPrivilegeValue函数,获取本地系统的调试权限LUID            //下面一句话,在tp.Privileges[0].Attributes属性中,设置开启这个权限还是关闭这个权限          tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;          //当Attributes=SE_PRIVILEGE_ENABLE时,激活权限          //当Attributes=0时,关闭权限          AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);          //AdjustTokenPrivileges激活或者关闭tp中给定的权限          fok = (GetLastError() == ERROR_SUCCESS);//确认激活是否成功          CloseHandle(hToken);      }      return fok;  }  

3、如果一个老的程序,没有考虑到特权问题,需要用户手动去提升特权,如何将这个老程序进行封装,

使用户不用手动提升特权,直接运行这个程序,这个就用到了以管理员身份启动一个进程

DWORD StartElevatedProcess(LPCTSTR szExecutable,LPCTSTR szCmdLine)

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

#include <windows.h>#include <tchar.h>typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);LPFN_ISWOW64PROCESS fnIsWow64Process;//定义的一个函数指针变量BOOL IsWow64(){BOOL bIsWow64 = FALSE;//IsWow64Process is not available on all supported versions of Windows.//Use GetModuleHandle to get a handle to the DLL that contains the function//and GetProcAddress to get a pointer to the function if available.fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");if (NULL != fnIsWow64Process){if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)){//handle error}}return bIsWow64;}int main(void){if (IsWow64())_tprintf(TEXT("The process is running under WOW64.\n"));//说明当前操作系统是64位的,程序是32位的else_tprintf(TEXT("The process is not running under WOW64.\n"));//说明当前操作系统是32位的return 0;}


0 0
原创粉丝点击