• 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 }
  • 相关阅读:
    List<T>直接充当Combox控件DataSource并扩展自定义记录的方法
    List转Datatable 新方法
    CDM中,实体与实体快捷方式之间的联系不能重复,否则会造成外键重复
    PD中设置外键约束名称生成规则
    查询当前数据库用户会话信息
    Word中调整编号和文字的间距
    PDM/CDM中进行搜索
    PDM后续处理-驼峰规则、清除约束、外键改名
    列举当前用户或指定用户的所有表,所有字段,以及所有约束
    PDM中列举所有含取值范围、正则表达式约束的字段
  • 原文地址:https://www.cnblogs.com/talenth/p/9365558.html
Copyright © 2020-2023  润新知