[笔记] Windows 审计《一》判断是否SACL系统记录权限、DACL管理权限是否继承

文章目录


前言

安全对象:由微软定义为可以具有安全描述符的对象,包括诸如文件,线程,远程注册表,Active Directory对象等许多东西。

安全描述符:包含许多字段的二进制结构,包括对象的所有者,以及指向对象的SACL和DACL的指针,这其中还包括头控制位和其他字段。

ACL:访问控制列表,SACL和DACL的超集的通用术语。

SACL:系统访问控制列表,一组控制审计访问或修改对象的ACE。

DACL:自主访问控制列表,这是一组定义哪些主体(或受托人)对给定对象具有特定权限的ACE集合。

ACE:访问控制条目,控制(如果包含在DACL中)或监控器(如果包含在SACL中)指定受托人访问对象的单独规则。

如下SACL的启用继承
在这里插入图片描述
如下DACL的启用继承
在这里插入图片描述

基本思路:

  1. 程序提权
  2. 获得已知SECURITY_INFORMATION (DACL,SACL)安全信息
  3. 判断标志位是否有(SE_SACL_PROTECTED、SE_DACL_PROTECTED)

代码

#include <windows.h>
#include <stdio.h>
#include <AccCtrl.h>
#include <AclAPI.h>
#include <string>
#include <sddl.h>
#include <algorithm>
#include <iostream>

static PSTR WINAPI SIDToName(PSID lpSID);

static BOOL UpProcessPriority() {
    HANDLE h_token_handle = nullptr;
    TOKEN_PRIVILEGES token_privileges;
    BOOL result = FALSE;

    result =
        OpenProcessToken(GetCurrentProcess(),
            static_cast<unsigned>(TOKEN_QUERY) |
            static_cast<unsigned>(TOKEN_ADJUST_PRIVILEGES),
            &h_token_handle);

    if (result != 0) {
        result = LookupPrivilegeValueW(nullptr, SE_SECURITY_NAME,
            &token_privileges.Privileges[0].Luid);
        if (result != 0) {
            token_privileges.PrivilegeCount = 1;
            token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

            result = AdjustTokenPrivileges(
                h_token_handle, FALSE, &token_privileges, 0, nullptr, nullptr);
        }
    }

    if (h_token_handle != nullptr) {
        CloseHandle(h_token_handle);
    }
    return result;
}

int main(int argc, char *argv[])
{
    UpProcessPriority();
    SECURITY_INFORMATION requestedInfo = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
    PSECURITY_DESCRIPTOR pSecDes = NULL; DWORD secSize = 0;
    /*CHAR filePath[MAX_PATH] = "C:\\Program Files\\zsw";*/
    CHAR filePath[MAX_PATH] = "C:\\Program Files\\zsw\\zsw2";
    if (!GetFileSecurityA(filePath, requestedInfo, pSecDes, secSize, &secSize))
    {
        pSecDes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, secSize);
        if (!GetFileSecurityA(filePath, requestedInfo, pSecDes, secSize, &secSize)) {
            std::cout << GetLastError() << std::endl;
        }
    }

    SECURITY_DESCRIPTOR_CONTROL pControl; DWORD revision;
    if (GetSecurityDescriptorControl(pSecDes, &pControl, &revision))
    {
        if ((pControl & SE_DACL_PROTECTED) == SE_DACL_PROTECTED) {
            std::cout << "安全描述符DACL是否可以传播: 不可传播,禁用继承" << std::endl;
        }
        else {
            std::cout << "安全描述符DACL是否可以传播: 可传播,启用继承" << std::endl;
        }

        if ((pControl & SE_SACL_PROTECTED) == SE_SACL_PROTECTED) {
            std::cout << "安全描述符SACL是否可以传播: 不可传播,禁用继承" << std::endl;
        }
        else {
            std::cout << "安全描述符SACL是否可以传播: 可传播,启用继承" << std::endl;
        }

    }

    BOOL daclPresent; BOOL daclDefaulted; PACL lpACL = NULL;
    if (!GetSecurityDescriptorDacl(pSecDes, &daclPresent, &lpACL, &daclDefaulted))
        std::cout << GetLastError() << std::endl;

    ACL_SIZE_INFORMATION aclInfo; DWORD aclInfoSize = sizeof(ACL_SIZE_INFORMATION);
    ACE_HEADER *aceHeader = NULL; ACCESS_ALLOWED_ACE *accessAllowed = NULL; LPVOID unknown = NULL;
    if (GetAclInformation(lpACL, &aclInfo, aclInfoSize, AclSizeInformation))
    {
        for (int i = 0; i < aclInfo.AceCount; i++)
        {
            if (GetAce(lpACL, i, &unknown))
            {
                aceHeader = (ACE_HEADER *)unknown;
                if ((aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) || (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE))
                {
                    accessAllowed = (ACCESS_ALLOWED_ACE *)unknown;
                    std::cout << " ACE[" << i << "]: " << std::endl;
                    std::cout << "  > 类型: " << (INT)accessAllowed->Header.AceFlags << std::endl;
                    std::cout << "  > SID 账户名: " << SIDToName(&accessAllowed->SidStart) << std::endl;
                }
            }
        }
    }
    return 0;
}

PSTR WINAPI SIDToName(PSID lpSID)
{
    LPSTR userName = NULL; LPSTR domainName = NULL; DWORD nameSize = 0; DWORD domainSize = 0; SID_NAME_USE peUse;
    if (!LookupAccountSidA(NULL, lpSID, userName, &nameSize, domainName, &domainSize, &peUse))
    {
        userName = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nameSize);
        domainName = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, domainSize);
        if (!LookupAccountSidA(NULL, lpSID, userName, &nameSize, domainName, &domainSize, &peUse))
            std::cout << GetLastError() << std::endl;
    }
    return userName;
}

总结

参考:
什么是DACL和SACL
利用SACL审核文件操作思路分享
访问控制列表


关于博主

wx/qq:binary-monster/1113673178
wxgzh: 二进制怪兽
CSDN:https://blog.csdn.net/qq1113673178
码云:https://gitee.com/shiver
Github: https://github.com/ShiverZm
个人博客:www.shiver.fun

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二进制怪兽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值