参考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的修改貌似只能以整个安全描述符为单位进行修改, 不知道是不是我孤陋寡闻的原因

 #include <windows.h>
#include <aclapi.h>
#include <sddl.h>
bool MyCreateEvent()
{
HANDLE g_HEStop =NULL;
bool result = false;
DWORD ret = ;
PACL pDACL11 = NULL;
PSECURITY_DESCRIPTOR pSE = NULL;
PSID pAdminSID = NULL;
wchar_t *domainName = NULL;
do
{
//get sid
LogToFile(L"find administrators sid");
DWORD domainSize = ;
DWORD sidSize = ;
SID_NAME_USE sidType = SidTypeGroup;
ret = LookupAccountNameW(NULL, L"Administrators", NULL, &sidSize, NULL, &domainSize, &sidType);
if (!(ret == && GetLastError() ==ERROR_INSUFFICIENT_BUFFER))
{ LogErr(L"LookupAccountName err1", GetLastError());
break;
}
std::wstring str = std::to_wstring(sidSize);
str += L" ";
str += std::to_wstring(domainSize);
LogToFile(str.c_str()); pAdminSID = new char[sidSize];
domainName = new wchar_t[domainSize];
if (!pAdminSID || !domainName)
{
LogToFile(L"alloc buffer err");
break;
} ret = LookupAccountNameW(NULL, L"Administrators", pAdminSID, &sidSize, domainName, &domainSize, &sidType);
if (ret == )
{
LogErr(L"LookupAccountName err2", GetLastError());
break;
}
else
{
LogErr(L"sidType", sidType);
LPWSTR str = NULL;
if (ConvertSidToStringSidW(pAdminSID, &str))
{
LogToFile(str);
LocalFree(str);
str = NULL;
}
} // create event
LogToFile(L"create event");
g_HEStop = CreateEventW(NULL, TRUE, FALSE, STOP_EVENT_NAME);
if (!g_HEStop)
{
LogToFile(L"create event err");
break;
} // modify dacl
LogToFile(L"modify dacl");
ret = GetSecurityInfo(g_HEStop, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL11, NULL, &pSE);
if (ret != ERROR_SUCCESS)
{
LogErr(L"get Dacl err",ret);
break;
} ACL_SIZE_INFORMATION aclSInfo;
ret = GetAclInformation(pDACL11, &aclSInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
if (ret == )
{
LogErr(L"get acl info err", GetLastError());
break;
} LogToFile(L"enum ace"); PACE_HEADER aceHeader = NULL;
bool find = false;
PSID pSidInAce = NULL;
LPWSTR StringSid = NULL;
for (DWORD index = ; index < aclSInfo.AceCount; ++index)
{
ret = GetAce(pDACL11, index, (LPVOID*)&aceHeader);
if (ret)
{
// 目前来说各中ace的结构是一样的, 可以这么写, 将来可能会变
pSidInAce = (PSID)((DWORD)aceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
if (ConvertSidToStringSidW(pSidInAce, &StringSid))
{
LogToFile(StringSid);
LocalFree(StringSid);
StringSid = NULL;
}
else
LogErr(L"ConvertSidToStringSidW err: ", GetLastError()); if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
{
PACCESS_ALLOWED_ACE aceAl = (PACCESS_ALLOWED_ACE)aceHeader;
if (EqualSid(pSidInAce, pAdminSID))
{
aceAl->Mask |= GENERIC_WRITE;
find = true;
break;
}
}
}
}
if (find)
{
ret = SetSecurityInfo(g_HEStop, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pDACL11, NULL);
if (ret == ERROR_SUCCESS)
result = true;
else
LogErr(L"SetSecurityInfo err: ", ret);
}
else
LogToFile(L"not find allow ace");
} while (false);
if (pAdminSID)
delete[] pAdminSID;
if (domainName)
delete[] domainName;
if (pSE)
LocalFree(pSE); if (!result && IsStopEventValid())
CloseHandle(g_HEStop);
return result;
}

Windows下访问控制管理的更多相关文章

  1. windows下python管理右键菜单

    实现很简单,不记得什么时候写的了,贴出来希望能有所价值 """ Windows中创建右键菜单 """ import os import sy ...

  2. 分享Nginx在Windows下的管理命令(bat文件)

    话不多说,复制下面的内容,存成bat文件,放到nginx目录下. ====================================================@echo offrem 当前 ...

  3. windows下进程管理常用命令

    1.查看当前正在运行的进程 tasklist 注: /im 后为映像名称参数:/f  为强行终止,可以通过 taskkill /? 查看更多帮助 2.强制杀死映像名称为imagename的进程,映像名 ...

  4. windows下运行的linux服务器批量管理工具(带UI界面)

    产生背景: 由于做服务器运维方面的工作,需要一人对近千台LINUX服务器进行统一集中的管理,如同时批量对LINUX服务器执行相关的指令.同时批量对LINUX服务器upload程序包.同时批量对LINU ...

  5. Windows下安装Cygwin及包管理器apt-cyg(转)

    本文为转载文章: http://www.2cto.com/os/201212/176551.html Cygwin可以在Windows下使用unix环境Bash和各种功能强大的工具,对于Linux管理 ...

  6. 【亲测可用,亦可配置同一平台的不同账号,例如阿里云的两个不同账号】Windows下Git多账号配置,同一电脑多个ssh-key的管理

    Windows下Git多账号配置,同一电脑多个ssh-key的管理   这一篇文章是对上一篇文章<Git-TortoiseGit完整配置流程>的拓展,所以需要对上一篇文章有所了解,当然直接 ...

  7. windows 下node版管理

    linux 下的node 多版本管理有nvm,windows 下同样有这样的工具gnvm 安装步骤(无node环境): 1.下载并解压缩 gnvm.exe 保存到任意文件夹,并将此文件夹加入到环境变量 ...

  8. windows下安装php依赖关系管理工具composer

    1.安装Composer Composer是PHP的依赖管理工具之一,官方网站 http://getcomposer.org/ .它支持多种安装方式,对于在win下做开发的草来说,最便捷的方式就是下载 ...

  9. [源码管理] Windows下搭建SVN服务器

    前文所述SVN客户端使用的时候,用的SVN服务器通常为外部,例如Google Code的服务器,不过,做为一个程序开发人员,就算自己一个人写程序,也应该有一个SVN版本控制系统,以便对开发代码进行有效 ...

随机推荐

  1. 您只能在 HTML 输出中使用 document.write。如果您在文档加载后使用该方法,会覆盖整个文档

    https://blog.csdn.net/qq_37425546/article/details/54868908

  2. Notepad++的实用技巧

    一. 安装notepad + +  notepad++的下载.安装非常easy.下一步下一步,所有选项都默认就可以安装好.但有几点需要注意.   截止到写这篇博文,notepad++的最新版本为7.5 ...

  3. python基础1-转自金角大王

    Python之路,Day1 - Python基础1---转自金角大王   本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 ...

  4. qt 利用 HTML 生成PDF文档,不能显示jpg图片

    利用 QPrinter 和html 生成 pdf文档 其中用html语句有显示图片的语句 但只能显示png格式的图片,不能显示jpg格式图片. 经过排查:语法,文件路径等都正确,最终在stack ov ...

  5. CCF 消息传递接口 (队列) 201903-4 (100分)

    [题目描述] 老师给了 T 份 MPI 的样例代码,每份代码都实现了 n 个进程通信.这些进程标号 从 0 到 n − 1,每个进程会顺序执行自己的收发指令,如:“S x”,“R x”.“S x”表示 ...

  6. css计算属性 calc()

    left: calc((100vw - 400px) / 2);   calc 进行简单的运算时,运算符号左右各要有一个空格,不然不起作用.

  7. ztree模糊筛选展开选中节点

    树呢是一个最简单的树,并没有做一异步加载,也就是一个筛选,然后跳到第一个符合删选的数据下,并且所有符合的都会被展开和选中.其中ztreeAry是一个模拟的本地数组json.在test.json中,如果 ...

  8. springmvc 在非controller下使用@autowired

    在SpringMVC框架中,我们经常要使用@Autowired注解注入Service或者Mapper接口,我们也知道,在controller层中注入service接口,在service层中注入其它的s ...

  9. 在Django中使用ForeignKey()报错问题的解决

    在Django2的models中建立一对多的关系使用ForeignKey(): student = models.ForeignKey("Classes") 报错: TypeErr ...

  10. spring定时器cron

    关于cron表达式(参考资料):Cron 表达式包括以下 7 个字段: 秒 分 小时 月内日期 月 周内日期 年(可选字段) 特殊字符Cron 触发器利用一系列特殊字符,如下所示: 反斜线(/)字符表 ...