在 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++;
}
};
我想获取文件夹的权限。我正在使用库 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++;
}
};