Board logo

标题: [讨论]我对Delphi下调用EqualSid函数的困惑 [打印本页]

作者: 虚竹    时间: 2008-7-20 23:23     标题: [讨论]我对Delphi下调用EqualSid函数的困惑

[讨论]我对Delphi下调用EqualSid函数的困惑
议题作者:flyerboy
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

我前几天因工作原因需编写一个检查用户对NTFS分区下的文件夹访问权限的程序,其中有一个核心函数是判断指定的用户是否对指定的文件夹拥有访问权限,我最初是用Delphi编写以便利用其强大的组件。该函数代码如下:
type
ACE_HEADER=record
      AceType:Byte;
      AceFlags:Byte;
      AceSize:Word;
end;
ACCESS_ALLOWED_ACE=record
      Header:ACE_HEADER;
      Mask:ACCESS_MASK;
      SidStart:DWORD;
end;
ACL_SIZE_INFORMATION=record
      AceCount:DWORD;
      AclBytesInUse:DWORD;
      AclBytesFree:DWORD;
end;
//...
function HasRight(UserName:String;FileName:String):Boolean;
var
        snuType:SID_NAME_USE;
        szDomai:PChar;
        cbDomain:DWORD;
        pUserSID:Pointer;
        cbUserSID:DWORD;
        pFileSD:PSECURITY_DESCRIPTOR;
        cbFileSD:DWORD;
        p_ACL:PACL;
        fDaclPresent,fDaclDefaulted:LongBool;
        AclInfo:ACL_SIZE_INFORMATION;
        pTempAce:Pointer;
        TempAce:ACCESS_ALLOWED_ACE;
        CurrentAceIndex:Cardinal;
        ReturnValue:LongBool;
begin
        //初始化各个变量
        Result:=False;
        szDomain:=nil;
        cbDomain:=0;
        pUserSID:=nil;
        cbUserSID:=0;
        pFileSD:=nil;
        cbFileSD:=0;
        p_ACL:=nil;
        pTempAce:=nil;
        //第一次调用得到SID和Domain的大小
        ReturnValue:=LookupAccountName(nil,PChar(UserName),pUserSID,cbUserSID,szDomain,cbDomain,snuType);
        if (not ReturnValue) and (GetLastError<>ERROR_INSUFFICIENT_BUFFER) then        RaiseLastOSError;
        pUserSID:=AllocMem(cbUserSID);
        szDomain:=AllocMem(cbDomain);
        try
                //第二次正式调用以取得用户的SID
                ReturnValue:=LookupAccountName(nil,PChar(UserName),pUserSID,cbUserSID,szDomain,cbDomain,snuType);
                if (not ReturnValue) then RaiseLastOSError;
                //用类似的方法得指定文件的安全描述符
                ReturnValue:=GetFileSecurity(PChar(FileName),DACL_SECURITY_INFORMATION,pFileSD,0,cbFileSD);
                if (not ReturnValue) and (GetLastError<>ERROR_INSUFFICIENT_BUFFER) then RaiseLastOSError;
                pFileSD:=AllocMem(cbFileSD);
                ReturnValue:=GetFileSecurity(PChar(FileName),DACL_SECURITY_INFORMATION,pFileSD,cbFileSD,cbFileSD);
                if (not ReturnValue) then RaiseLastOSError;
                //从安全描述符中得到安全对象的访问控制列表
                if (not GetSecurityDescriptorDacl(pFileSD,fDaclPresent,p_ACL,fDaclDefaulted)) then RaiseLastOSError;
                AclInfo.AceCount:=0;
                AclInfo.AclBytesFree:=0;
                AclInfo.AclBytesInUse:=SizeOf(ACL);
                if (fDaclPresent and Assigned(p_ACL)) then
                begin
                        //取得访问控制列表的大小信息
                        if (not GetAclInformation(p_ACL^,@AclInfo,SizeOf(ACL_SIZE_INFORMATION),AclSizeInformation)) then RaiseLastOSError;
                        if (fDaclPresent and (AclInfo.AceCount>0)) then
                        begin
                                //循环访问控制列表,并判断是否包含指定的用户
                                for CurrentAceIndex:=0 to AclInfo.AceCount-1 do
                                begin
                                        if (not GetAce(p_ACL^,CurrentAceIndex,pTempAce)) then RaiseLastOSError;
                                        TempAce:=ACCESS_ALLOWED_ACE(pTempAce^);
                                        //EqualSid用于比较两个SID是否相等,但问题是在此处这个函数的返回值总是为False
                                        //如果改为C++版本,此处用以下语句时则能正确返回结果
                                        //if (EqualSid(pUserSID,&(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart))) break;
                                        if EqualSid(pUserSId,@(TempAce.SidStart)) then break;
                                end;
                                FreeSid(pUserSId);
                                //如果找到则设置函数返回值为True
                                if CurrentAceIndex<AclInfo.AceCount then Result:=True;
                        end;
                end;
        finally
                //释放动态分配的存储空间,比较奇怪是释放其它几个指针时会出现运行时异常
                if pUserSID<>nil then FreeMem(pUserSID);
                if szDomain<>nil then FreeMem(szDomain);
        end;
end;
但调用该函数时始终达不到目的,我在注释中已经指明:在Delphi代码中EqualSid函数无法返回预期的结果,但用C++语言来编写就能正确运行,盼各位大侠指点迷津!谢谢!

帖子5 精华0 积分6 阅读权限40 性别男 在线时间1 小时 注册时间2007-9-19 最后登录2008-5-18 查看详细资料引用 报告 回复 TOP 让女孩一夜变的更有女人味

siwen
晶莹剔透§烈日灼然
作者: dgbz    时间: 2008-7-20 23:23

ACCESS_ALLOWED_ACE=record
      Header:ACE_HEADER;
      Mask:ACCESS_MASK;
      SidStart:DWORD;
end;

中record -> packed record 试试?
帖子2 精华0 积分2 阅读权限40 在线时间3 小时 注册时间2008-3-3 最后登录2008-4-21 查看详细资料引用 报告 回复 TOP 少女暴富的隐秘(图)

flyerboy
晶莹剔透§烈日灼然




欢迎光临 【3.A.S.T】网络安全爱好者 (http://3ast.com/) Powered by Discuz! 7.2