Windows下访问控制管理

参考URL:

 https://blog.csdn.net/u011801161/article/details/45567289

 http://blog.nsfocus.net/analysis-windows-access-authority-inspection-mechanism/

 https://blog.csdn.net/eggfly178/article/details/41773601

一 Windows访问控制概述: 

Windows访问控制中最主要的部分:访问令牌(Access Token)和安全描述符(Security Descriptor),window通过查看访问者AT与被访问对象SD中的内容来确定访问者是否能访问对象。

Windows访问控制概念介绍: 
① SID:Secure Identifier(安全标识符),每个用户和账户组都有一个唯一的SID(通常情况下唯一)。它是标识用户、用户组和计算机账户唯一的号码,由计算机名、当前时间、当前用户态线程的CPU耗费时间三个参数来确定。 
② Access Token:与特定的windows账户关联,账户环境下启动的所有进程都会获得该令牌的副本,进程中的线程默认获得这个令牌。由关联账户的SID、当前登录账户所属组的SID列表、受限制的SID列表、当前登录账户与所属组的Privilege列表组成。 
③ Security Descriptor:安全描述符,与被访问对象关联。由对象所有者的SID、属组SID、DACL、SACL组成。DACL(随机访问控制列表)是SD最重要的一部分,描述允许或拒绝特定用户或组的某些访问权限,它包含零个或多个访问控制实体(ACE,Access Control Entry)。 
④ ACE:访问控制实体,用于指定特定用户/组的访问权限,由SID、SIZE、Type、Access Mask、Inheritance/Audit Flags组成。

Windows访问控制流程图: 
当一个线程尝试去访问一个对象时,系统会检查线程持有的令牌以及被访问对象的安全描述符中的DACL。 
如果安全描述符中不存在DACL,则系统会允许线程进行访问。如果存在DACL,系统会顺序遍历DACL中的每个ACE,检查ACE中的SID在线程的令牌中是否存在。以访问者中的User SID或Group SID作为关键字查询被访问对象中的DACL。顺序:先查询类型为DENY的ACE,若命中且权限符合则访问拒绝;未命中再在ALLOWED类型的ACE中查询,若命中且类型符合则可以访问;以上两步后还没命中那么访问拒绝。 
这里写图片描述

此外, SACL是系统访问控制列表,是用来做审计用的,一般不用关心。

二 一个修改特定对象DACL

  以下代码实现了以默认权限创建一个event内核对象(默认权限下Administrators组没有修改权限), 然后给该对象的Administrators组添加修改权限的功能. 注意: 以下代码必须在system权限下运行(就是服务进程里边), 只展示了核心代码部分, DACL的修改貌似只能以整个安全描述符为单位进行修改, 不知道是不是我孤陋寡闻的原因

  1 #include <windows.h>
  2 #include <aclapi.h>
  3 #include <sddl.h>
  4 bool MyCreateEvent()
  5 {
  6     HANDLE g_HEStop =NULL;
  7     bool result = false;
  8     DWORD ret = 0;
  9     PACL pDACL11 = NULL;
 10     PSECURITY_DESCRIPTOR pSE = NULL;
 11     PSID pAdminSID = NULL;
 12     wchar_t *domainName = NULL;
 13     do
 14     {
 15         //get sid
 16         LogToFile(L"find administrators sid");
 17         DWORD domainSize = 0;
 18         DWORD sidSize = 0;
 19         SID_NAME_USE sidType = SidTypeGroup;
 20         ret = LookupAccountNameW(NULL, L"Administrators", NULL, &sidSize, NULL, &domainSize, &sidType);
 21         if (!(ret == 0 && GetLastError() ==ERROR_INSUFFICIENT_BUFFER))
 22         {
 23 
 24             LogErr(L"LookupAccountName err1", GetLastError());
 25             break;
 26         }
 27         std::wstring str = std::to_wstring(sidSize);
 28         str += L" ";
 29         str += std::to_wstring(domainSize);
 30         LogToFile(str.c_str());
 31 
 32         pAdminSID = new char[sidSize];
 33         domainName = new wchar_t[domainSize];
 34         if (!pAdminSID || !domainName)
 35         {
 36             LogToFile(L"alloc buffer err");
 37             break;
 38         }
 39 
 40         ret = LookupAccountNameW(NULL, L"Administrators", pAdminSID, &sidSize, domainName, &domainSize, &sidType);
 41         if (ret == 0)
 42         {
 43             LogErr(L"LookupAccountName err2", GetLastError());
 44             break;
 45         }
 46         else
 47         {
 48             LogErr(L"sidType", sidType);
 49             LPWSTR str = NULL;
 50             if (ConvertSidToStringSidW(pAdminSID, &str))
 51             {
 52                 LogToFile(str);
 53                 LocalFree(str);
 54                 str = NULL;
 55             }
 56         }
 57 
 58         // create event
 59         LogToFile(L"create event");
 60         g_HEStop = CreateEventW(NULL, TRUE, FALSE, STOP_EVENT_NAME);
 61         if (!g_HEStop)
 62         {
 63             LogToFile(L"create event err");
 64             break;
 65         }
 66 
 67         // modify dacl
 68         LogToFile(L"modify dacl");
 69         ret = GetSecurityInfo(g_HEStop, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL11, NULL, &pSE);
 70         if (ret != ERROR_SUCCESS)
 71         {
 72             LogErr(L"get Dacl err",ret);
 73             break;
 74         }
 75 
 76         ACL_SIZE_INFORMATION aclSInfo;
 77         ret = GetAclInformation(pDACL11, &aclSInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
 78         if (ret == 0)
 79         {
 80             LogErr(L"get acl info err", GetLastError());
 81             break;
 82         }
 83         
 84         LogToFile(L"enum ace");
 85 
 86         PACE_HEADER aceHeader = NULL;
 87         bool find = false;
 88         PSID pSidInAce = NULL;
 89         LPWSTR  StringSid = NULL;
 90         for (DWORD index = 0; index < aclSInfo.AceCount; ++index)
 91         {
 92             ret = GetAce(pDACL11, index, (LPVOID*)&aceHeader);
 93             if (ret)
 94             {
 95                 // 目前来说各中ace的结构是一样的, 可以这么写, 将来可能会变
 96                 pSidInAce = (PSID)((DWORD)aceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
 97                 if (ConvertSidToStringSidW(pSidInAce, &StringSid))
 98                 {
 99                     LogToFile(StringSid);
100                     LocalFree(StringSid);
101                     StringSid = NULL;
102                 }
103                 else
104                     LogErr(L"ConvertSidToStringSidW err: ", GetLastError());
105 
106                 if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
107                 {
108                     PACCESS_ALLOWED_ACE aceAl = (PACCESS_ALLOWED_ACE)aceHeader;
109                     if (EqualSid(pSidInAce, pAdminSID))
110                     {
111                         aceAl->Mask |= GENERIC_WRITE;
112                         find = true;
113                         break;
114                     }
115                 }
116             }
117         }
118         if (find)
119         {
120             ret = SetSecurityInfo(g_HEStop, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pDACL11, NULL);
121             if (ret == ERROR_SUCCESS)
122                 result = true;
123             else
124                 LogErr(L"SetSecurityInfo err: ", ret);
125         }
126         else
127             LogToFile(L"not find allow ace");
128     } while (false);
129     if (pAdminSID)
130         delete[] pAdminSID;
131     if (domainName)
132         delete[] domainName;
133     if (pSE)
134         LocalFree(pSE);
135 
136     if (!result && IsStopEventValid())
137         CloseHandle(g_HEStop);
138     return result;
139 }
原文地址:https://www.cnblogs.com/talenth/p/9365558.html