在 node.js 中使用本机 Windows 函数 GetNamedSecurityInfoA

Using Native Windows Function GetNamedSecurityInfoA in node.js

我想获取文件夹的权限。我正在使用库 ffi 和 ref 来调用本机 Windows 函数。我正在调用函数 GetNamedSecurityInfoA 来获取 DACL,但返回的结构包含错误的值。请你帮助我好吗?谢谢!

编辑 20191208:函数 GetAce 似乎可以正常工作...

一些结构和定义:


/*typedef struct _ACE_HEADER {
  BYTE AceType;
  BYTE AceFlags;
  WORD AceSize;
} ACE_HEADER;*/

export const ACE_HEADER = struct({
   AceType:win32types.UCHAR,
   AceFlags:win32types.UCHAR,
   AceSize:win32types.WORD
});

/*typedef struct _ACCESS_ALLOWED_ACE {
    ACE_HEADER  Header;
    ACCESS_MASK Mask;
    DWORD       SidStart;
} ACCESS_ALLOWED_ACE;*/

export const ACCESS_ALLOWED_ACL = struct({
    Header:ACE_HEADER,
    Mask:win32types.DWORD,
    SidStart:win32types.DWORD
});


export const ACL = struct({
    AclRevision:win32types.UCHAR,
    Sbz1:win32types.UCHAR,
    AclSize:win32types.USHORT,
    AceCount:win32types.USHORT,
    Sbz2:win32types.USHORT
});

/*
typedef struct _SECURITY_DESCRIPTOR {
  BYTE                        Revision;
  BYTE                        Sbz1;
  SECURITY_DESCRIPTOR_CONTROL Control;
  PSID                        Owner;
  PSID                        Group;
  PACL                        Sacl;
  PACL                        Dacl;
} SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR;
**/
export const SECURITY_DESCRIPTOR = struct({
    Revision:win32types.UCHAR,
    Sbz1:win32types.UCHAR,
    Control:win32types.WORD,
    Owner:win32types.PVOID,
    Group:win32types.PVOID,
    Sacl:win32types.PVOID,
    Dacl:win32types.PVOID
});

const PACL = ref.refType(ACL);
const PSECURITY_DESCRIPTOR = ref.refType(SECURITY_DESCRIPTOR);
const PACE = ref.refType(ACCESS_ALLOWED_ACL);

export const advApi = ffi.Library('Advapi32', {
    /*
    DWORD GetNamedSecurityInfoW(
    LPCWSTR              pObjectName,
    SE_OBJECT_TYPE       ObjectType,
    SECURITY_INFORMATION SecurityInfo,
    PSID                 *ppsidOwner,
    PSID                 *ppsidGroup,
    PACL                 *ppDacl,
    PACL                 *ppSacl,
    PSECURITY_DESCRIPTOR *ppSecurityDescriptor);
     */
    GetNamedSecurityInfoW:[win32types.DWORD,[win32types.LPCTSTR,'int','uint', 'pointer', 'pointer', PACL, PACL, PSECURITY_DESCRIPTOR]],
    /*
    BOOL GetAce(
    PACL   pAcl,
    DWORD  dwAceIndex,
    LPVOID *pAce);
     */
    GetAce:[win32types.BOOL, [ACL, win32types.DWORD, ref.refType(PACE)]],
});

函数的调用方式:


import {advApi} from "../win32";
import {ACL as defACL, SECURITY_DESCRIPTOR as defSecDesc, ACCESS_ALLOWED_ACL as ace} from "../win32defs"

                let dAclRef = new defACL().ref();
                let securityDescriptorRef = new defSecDesc().ref();

                let childPathBuffer = Buffer.from(newChild.path+'[=13=]', 'ucs-2');

                await advApi.GetNamedSecurityInfoW
                    .async(childPathBuffer, 1, 4, null, null, dAclRef, null, securityDescriptorRef,
                        (err, res) => {
                        if(err) throw err;


                        if(res === 0)
                        {
                             let aclValue = dAclRef.deref();
                             let i = 0;
                             let success = true;

                            while(i<aclValue.AceCount && success)
                            {
                                let aceRefRef = new ace().ref().ref();
                                success = advApi.GetAce(aclValue, i, aceRefRef);
                                if(success)
                                {
                                }

                                i++;
                            }
                        };
        });

返回的 ACL 结构包含错误值,AceCount > 500。

我终于能够取回权限(这并不容易)。

我还是不知道为什么 AceCount 这么大。

这里有一些代码摘录:


/*typedef struct _ACE_HEADER {
  BYTE AceType;
  BYTE AceFlags;
  WORD AceSize;
} ACE_HEADER;*/

export const ACE_HEADER = struct({
   AceType:win32types.UCHAR,
   AceFlags:win32types.UCHAR,
   AceSize:win32types.WORD
});

/*typedef struct _ACCESS_ALLOWED_ACE {
    ACE_HEADER  Header;
    ACCESS_MASK Mask;
    DWORD       SidStart;
} ACCESS_ALLOWED_ACE;*/

export const ACCESS_ALLOWED_ACL = struct({
    Header:ACE_HEADER,
    Mask:win32types.DWORD,
    SidStart:win32types.DWORD
});


export const ACL = struct({
    AclRevision:win32types.UCHAR,
    Sbz1:win32types.UCHAR,
    AclSize:win32types.USHORT,
    AceCount:win32types.USHORT,
    Sbz2:win32types.USHORT
});

/*
typedef struct _SECURITY_DESCRIPTOR {
  BYTE                        Revision;
  BYTE                        Sbz1;
  SECURITY_DESCRIPTOR_CONTROL Control;
  PSID                        Owner;
  PSID                        Group;
  PACL                        Sacl;
  PACL                        Dacl;
} SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR;
**/
export const SECURITY_DESCRIPTOR = struct({
    Revision:win32types.UCHAR,
    Sbz1:win32types.UCHAR,
    Control:win32types.WORD,
    Owner:win32types.PVOID,
    Group:win32types.PVOID,
    Sacl:win32types.PVOID,
    Dacl:win32types.PVOID
});

const PACL = ref.refType(ACL);
const PSECURITY_DESCRIPTOR = ref.refType(SECURITY_DESCRIPTOR);
const PACE = ref.refType(ACCESS_ALLOWED_ACL);

export const advApi = ffi.Library('Advapi32', {
    /*
    DWORD GetNamedSecurityInfoW(
    LPCWSTR              pObjectName,
    SE_OBJECT_TYPE       ObjectType,
    SECURITY_INFORMATION SecurityInfo,
    PSID                 *ppsidOwner,
    PSID                 *ppsidGroup,
    PACL                 *ppDacl,
    PACL                 *ppSacl,
    PSECURITY_DESCRIPTOR *ppSecurityDescriptor);
     */
    GetNamedSecurityInfoW:[win32types.DWORD,[win32types.LPCTSTR,'int','uint', 'pointer', 'pointer', PACL, PACL, PSECURITY_DESCRIPTOR]],
    /*
    BOOL GetAce(
    PACL   pAcl,
    DWORD  dwAceIndex,
    LPVOID *pAce);
     */
    GetAce:[win32types.BOOL, [ACL, win32types.DWORD, ref.refType(PACE)]],
    /*BOOL IsValidSid(
     PSID pSid
    )*/
    IsValidSid:[win32types.BOOL, [win32types.LPVOID]],

    /*BOOL LookupAccountSidW(
    LPCWSTR       lpSystemName,
    PSID          Sid,
    LPWSTR        Name,
    LPDWORD       cchName,
    LPWSTR        ReferencedDomainName,
    LPDWORD       cchReferencedDomainName,
    PSID_NAME_USE peUse
    );*/
    LookupAccountSidW:[win32types.BOOL, [win32types.LPCTSTR, win32types.LPVOID, win32types.LPCTSTR, win32types.LPDWORD, win32types.LPCTSTR, win32types.LPDWORD, ref.refType('int')]],
});

如何调用函数。 这里最重要的一点是:让 sidBuffer = ref.reinterpret(aceRef, 4, 8).


import {advApi} from "../win32";
import {ACL as defACL, SECURITY_DESCRIPTOR as defSecDesc, ACCESS_ALLOWED_ACL as ace} from "../win32defs"

                let dAclRef = new defACL().ref();
                let securityDescriptorRef = new defSecDesc().ref();

                let childPathBuffer = Buffer.from(newChild.path+'[=11=]', 'ucs-2');

                await advApi.GetNamedSecurityInfoW
                    .async(childPathBuffer, 1, 4, null, null, dAclRef, null, securityDescriptorRef,
                        (err, res) => {
                        if(err) throw err;


                        if(res === 0)
                        {
                            let aclValue = dAclRef.deref();
                            let i = 0;
                            let success = true;

                            while(i<aclValue.AceCount && success)
                            {
                                let aceRefRef = new ace().ref().ref();
                                success = advApi.GetAce(aclValue, i, aceRefRef);
                                if(success)
                                {
                                    let aceRef = aceRefRef.deref();
                                    let sidBuffer = ref.reinterpret(aceRef, 4, 8);

                                    if(advApi.IsValidSid(sidBuffer))
                                    {
                                        let cchNameRef = ref.alloc(win32types.DWORD, new Buffer(ref.sizeof.pointer));
                                        let cchReferencedDomainNameRef = ref.alloc(win32types.DWORD, new Buffer(ref.sizeof.pointer));
                                        let peUseRef = ref.alloc('int', new Buffer(ref.sizeof.pointer));

                                        advApi.LookupAccountSidW(null, sidBuffer, null, cchNameRef, null, cchReferencedDomainNameRef, peUseRef);

                                        let nameRef = Buffer.alloc(cchNameRef.deref()*2);
                                        let domainNameRef = Buffer.alloc(cchReferencedDomainNameRef.deref()*2);


                                        let accessArray = [];

                                        if(advApi.LookupAccountSidW(null, sidBuffer, nameRef, cchNameRef, domainNameRef, cchReferencedDomainNameRef, peUseRef))
                                        {
                                            let aceValue = aceRef.deref();

                                            ...
                                        }

                                    }
                                }
                                i++;
                            }
                        };