tannerli Posted July 15, 2010 Share Posted July 15, 2010 I am trying to write a programm for reading out file permissions, using GetNamedSecurityInfo() from advapi32.dll DWORD WINAPI GetNamedSecurityInfo( __in LPTSTR pObjectName, __in SE_OBJECT_TYPE ObjectType, __in SECURITY_INFORMATION SecurityInfo, __out_opt PSID *ppsidOwner, __out_opt PSID *ppsidGroup, __out_opt PACL *ppDacl, __out_opt PACL *ppSacl, __out_opt PSECURITY_DESCRIPTOR *ppSecurityDescriptor ); http://msdn.microsoft.com/en-us/library/aa446645%28VS.85%29.aspx <-- Complete function reference Using the forum search i stumbled upon this topic from example script section http://www.autoitscript.com/forum/index.php?showtopic=41050&view=findpost&p=305384&hl=getnamedsecurityinfo Now my question: How do i find out what parameters to pass to the function? I cannot find what datatype f.e. a "SECURITY INFORMATION" or a "PSID" is. Even to figure out wheter the parameter ObjectType where I want to pass SE_FILE_OBJECT I don't know wheter the function wants the String "SE_FILE_OBJECT" or wheter this is just a constant for a numeric value to pass... If anyone could give me a hint on how to approach these things I'd be grateful Cheers tannerli Link to comment Share on other sites More sharing options...
AndyG Posted July 15, 2010 Share Posted July 15, 2010 Hi, an example how to get the return of the call. The * after the ptr is described in the help of dllcall() #include <Array.au3> $dll=dllopen("advapi32.dll") local $ppsidOwner,$ppsidGroup,$ppDacl,$ppSacl, $ppSecurityDescriptor local $ObjectType=1 ;file http://msdn.microsoft.com/en-us/library/aa379593(v=VS.85).aspx local $pObjectName="c:\windows\explorer.exe" local $SecurityInfo=1 ;http://msdn.microsoft.com/en-us/library/cc230369(PROT.10).aspx if fileexists($pObjectName) then $erg=dllcall($dll,"int","GetNamedSecurityInfo","str",$pObjectName,"int",$ObjectType,"dword",$SecurityInfo, _ "ptr*", $ppsidOwner, _ "ptr*", $ppsidGroup, _ "ptr*", $ppDacl, _ "ptr*", $ppSacl, _ "ptr*", $ppSecurityDescriptor) _arraydisplay($erg) endif Link to comment Share on other sites More sharing options...
tannerli Posted July 15, 2010 Author Share Posted July 15, 2010 Perfect, this helps a lot. So the ObjectType would just be the index of the enumeration (I have already seen the mentioned msdn article before, but could not figure out what to pass) So f.e. if I want to have the Dacl, I just create an appropriate struc using DllStructCreate() pass the pointer to the function using DllStructGetPtr() and then can access the result with DllStructGetData() Thank you for the informative reply Cheers tannerli Link to comment Share on other sites More sharing options...
tannerli Posted July 15, 2010 Author Share Posted July 15, 2010 As i now see... easier said than done... I've extended your code this far: #include <Array.au3> $dll=dllopen("advapi32.dll") local $ppsidOwner,$ppsidGroup,$ppDacl,$ppSacl, $ppSecurityDescriptor local $ObjectType=1 ;file http://msdn.microsoft.com/en-us/library/aa379593(v=VS.85).aspx local $pObjectName="c:\windows\explorer.exe" local $SecurityInfo=6 ;http://msdn.microsoft.com/en-us/library/cc230369(PROT.10).aspx ;~ typedef struct _ACL { ;~ BYTE AclRevision; ;~ BYTE Sbz1; ;~ WORD AclSize; ;~ WORD AceCount; ;~ WORD Sbz2; ;~ } ACL, *PACL; $ppDacl = DllStructCreate("BYTE AclRevision;Byte Sbz1;WORD AclSize;WORD AceCount;WORD Sbz2;") if fileexists($pObjectName) then $erg=dllcall($dll,"int","GetNamedSecurityInfo","str",$pObjectName,"int",$ObjectType,"dword",$SecurityInfo, _ "ptr*", $ppsidOwner, _ "ptr*", $ppsidGroup, _ "ptr*", DllStructGetPtr($ppDacl), _ "ptr*", $ppSacl, _ "ptr*", $ppSecurityDescriptor) _arraydisplay($erg) endif $var = DllStructGetData($ppDacl, "AceCount") ConsoleWrite($var & @CRLF) Mainly I have changed the $SecurityInfo that I receive the DACL info and created a struct to store the return value. But however I change it, I do not seem to get any valid output, every single structmember is set to 0 What am I missing? Link to comment Share on other sites More sharing options...
Authenticity Posted July 15, 2010 Share Posted July 15, 2010 expandcollapse popupGlobal Const $_ACCESS_ALLOWED_ACE = _ "byte;" & _ ; AceType "byte;" & _ ; AceFlags "word;" & _ ; AceSize "uint;" & _ ; ACCESS_MASK "uint;" ; SidStart $dll=dllopen("advapi32.dll") local $ppsidOwner,$ppsidGroup,$ppDacl,$ppSacl, $ppSecurityDescriptor local $ObjectType=1 ;file http://msdn.microsoft.com/en-us/library/aa379593(v=VS.85).aspx local $pObjectName="c:\windows\explorer.exe" local $SecurityInfo=6 ;http://msdn.microsoft.com/en-us/library/cc230369(PROT.10).aspx ;~ typedef struct _ACL { ;~ BYTE AclRevision; ;~ BYTE Sbz1; ;~ WORD AclSize; ;~ WORD AceCount; ;~ WORD Sbz2; ;~ } ACL, *PACL; If fileexists($pObjectName) Then $erg=dllcall($dll,"int","GetNamedSecurityInfo","str",$pObjectName,"int",$ObjectType,"dword",$SecurityInfo, _ "ptr*", 0, _ "ptr*", 0, _ "ptr*", 0, _ ; ppDacl "ptr*", 0, _ "ptr*", 0) EndIf If @error = 0 And $erg[0] = 0 Then $tACL = DllStructCreate("byte AclRevision;byte Sbz1;word AclSize;word AceCount;word Sbz2;", $erg[6]) $iSize = DllStructGetData($tACL, "AclSize") - DllStructGetSize($tACL) $tACEs = DllStructCreate("byte ACE[" & $iSize & "];", $erg[6]+DllStructGetSize($tACL)) ConsoleWrite(DllStructGetData($tACEs, "ACE") & @CRLF) EndIfNote that it's specified somewhere in the See also links that an application should not directly access the ACE structures members. Link to comment Share on other sites More sharing options...
tannerli Posted July 15, 2010 Author Share Posted July 15, 2010 Thanks authenticity I see now what I made wrong in my code... Maybe I should roll up my idea from the beginning: I wanted to read the ACE's, use LookupAccountSID() to resolve it to a useful name and then use the Active Directory to Display the groups members. I need to make a documentation over the permissions on a complex folder structure in my company, and since I'm too lazy to do this manuall, I'd rather take the challenging approach But it looks like it is a bit too advance for my skills, as I am just a humble admin, not really a programmer. I am stuck now anyway since I expected the DACL to contain a list of SID's... However, thanks for your help, I learned a lot Link to comment Share on other sites More sharing options...
Authenticity Posted July 15, 2010 Share Posted July 15, 2010 expandcollapse popup#Include <Memory.au3> Global Const $_ACCESS_ALLOWED_ACE = _ "byte AceType;" & _ "byte AceFlags;" & _ "word AceSize;" & _ "uint Mask;" & _ "uint SidStart;" $dll=dllopen("advapi32.dll") local $ppsidOwner,$ppsidGroup,$ppDacl,$ppSacl, $ppSecurityDescriptor local $ObjectType=1 ;file http://msdn.microsoft.com/en-us/library/aa379593(v=VS.85).aspx local $pObjectName="c:\windows\explorer.exe" local $SecurityInfo=6 ;http://msdn.microsoft.com/en-us/library/cc230369(PROT.10).aspx ;~ typedef struct _ACL { ;~ BYTE AclRevision; ;~ BYTE Sbz1; ;~ WORD AclSize; ;~ WORD AceCount; ;~ WORD Sbz2; ;~ } ACL, *PACL; If fileexists($pObjectName) Then $erg=dllcall($dll,"int","GetNamedSecurityInfo","str",$pObjectName,"int",$ObjectType,"dword",$SecurityInfo, _ "ptr*", 0, _ "ptr*", 0, _ "ptr*", 0, _ ; ppDacl "ptr*", 0, _ "ptr*", 0) EndIf If @error = 0 And $erg[0] = 0 Then $tACL = DllStructCreate("byte AclRevision;byte Sbz1;word AclSize;word AceCount;word Sbz2;", $erg[6]) $iSize = DllStructGetData($tACL, "AclSize") - DllStructGetSize($tACL) $tACEs = DllStructCreate("byte ACE[" & $iSize & "];", $erg[6]+DllStructGetSize($tACL)) $pOffset = DllStructGetPtr($tACEs) $pStartofACEs = DllStructGetPtr($tACEs) Do $tACE = DllStructCreate($_ACCESS_ALLOWED_ACE, $pOffset) $sStringSid = _WinAPI_ConvertSidToStringSid(DllStructGetPtr($tACE, "SidStart")) ConsoleWrite($sStringSid & @CRLF) $pOffset += DllStructGetData($tACE, "AceSize") Until ($pOffset - $pStartofACEs) >= $iSize EndIf Func _WinAPI_ConvertSidToStringSid($pSid) Local $aResult, $tStringSid, $sStringSid, $hMemory $aResult = DllCall("Advapi32.dll", "bool", "ConvertSidToStringSidW", "ptr", $pSid, "ptr*", 0) If @error Then Return SetError(@error, @extended, 0) If $aResult[0] Then $hMemory = $aResult[2] $tStringSid = DllStructCreate("wchar[" & _MemGlobalSize($hMemory) & "]", $hMemory) $sStringSid = DllStructGetData($tStringSid, 1) _MemGlobalFree($hMemory) Return SetError(0, 0, $sStringSid) EndIf Return SetError(_WinAPI_GetLastError(), 0, "") EndFuncI really don't know if the SID's are correct. If you're an obedient API user you should call GetACE function instead of directly accessing the ACE structures members. Link to comment Share on other sites More sharing options...
tannerli Posted July 16, 2010 Author Share Posted July 16, 2010 (edited) Great, thanks a lot, these SID's look very authentic to me... I feel rather guilty for letting you do all the work here... therefore I will work now with this code you provided and try to figure out the rest myself and only ask for your help if I'm really stuck. And of course i will keep you posted on the endresult, once it can be used for anything. Thanks again Edited July 16, 2010 by tannerli Link to comment Share on other sites More sharing options...
tannerli Posted July 21, 2010 Author Share Posted July 21, 2010 (edited) Hey guys, As promised, here the results of your and my combined efforts As written in the remarks below, I still need to process the collected data to some useful output format, but I'm not sure how I want it yet. (And it isn't really relevant to the topic as anyone can write an _ExportToCSV() or something similar) I'm open to any comments, hints and improvement suggestions expandcollapse popup;====================================================================================== ; _PermissionReport($sRootDir, $fFileType = 1, $iMaxDepth = 0, $sFilter = "") ;Collect Permission Information on a folder ; ;Parameters: ; string $sRootDir The starting directory ; flag $fFileType Flag wheter to collect info on files or folders, this can ; be a combination of: ; 1 = Folders ; 2 = Files ; int $iMaxDepth Specifies how many levels of subfolders will be reported, ; use -1 for no limit (effective limit would be 127 due to ; AutoIt recursion limit) ; string $sFilter Report only ACE's starting with $sFilter ; ;Return Value: ; Success: ; Returns 0 ; ; Failure: ; Returns -1 ; ;Remarks: ; The function only collects the info, output is yet to be done. (I used my own log ; function for this example) -> Modify to your needs where slog() is called. ; ;Author: Marco Tanner ;====================================================================================== #include <Security.au3> Global Const $_READ = 1179785 Global Const $_EXEC = 1179808 Global Const $_READEXEC = 1179817 Global Const $_WRITE = 1179926 Global Const $_MODIFY = 1245631 Global Const $_FULL = 2032127 Global Const $_ACCESS_ALLOWED_ACE = _ "byte AceType;" & _ "byte AceFlags;" & _ "word AceSize;" & _ "uint Mask;" & _ "uint SidStart;" Func _PermissionReport($sRootDir, $fFileType = 1, $iMaxDepth = 1, $sFilter = "") $hSearch = FileFindFirstFile($sRootDir & "\*.*") If @error Then Return -1 While 1 $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If StringInStr(FileGetAttrib($sRootDir & "\" & $sFile), "D") Then If BitAND($fFileType, 1) Then _ReadACL($sRootDir & "\" & $sFile, $sFilter) If $iMaxDepth <> 0 Then _PermissionReport($sRootDir & "\" & $sFile, $fFileType, $iMaxDepth - 1, $sFilter) Else If BitAND($fFileType, 2) Then _ReadACL($sRootDir & "\" & $sFile, $sFilter) EndIf WEnd Return 0 EndFunc Func _ReadACL($sFile, $sFilter) Local $ObjectType = 1 ;file http://msdn.microsoft.com/en-us/library/aa379593(v=VS.85).aspx Local $SecurityInfo = 6 ;http://msdn.microsoft.com/en-us/library/cc230369(PROT.10).aspx slog(0, $sFile) If FileExists($sFile) Then $erg=DllCall("Advapi32.dll", "int", "GetNamedSecurityInfo", "str", $sFile, "int", $ObjectType, "dword", $SecurityInfo, _ "ptr*", 0, _ "ptr*", 0, _ "ptr*", 0, _ ; ppDacl "ptr*", 0, _ "ptr*", 0) Else Return -1 EndIf If @error = 0 And $erg[0] = 0 Then $tACL = DllStructCreate("byte AclRevision;byte Sbz1;word AclSize;word AceCount;word Sbz2;", $erg[6]) $iSize = DllStructGetData($tACL, "AclSize") - DllStructGetSize($tACL) $tACEs = DllStructCreate("byte ACE[" & $iSize & "];", $erg[6]+DllStructGetSize($tACL)) $pOffset = DllStructGetPtr($tACEs) $pStartofACEs = DllStructGetPtr($tACEs) Do $tACE = DllStructCreate($_ACCESS_ALLOWED_ACE, $pOffset) $bSid = DllStructGetPtr($tACE, "SidStart") $aAcct = _Security__LookupAccountSid($bSid) $iAccessMask = DllStructGetData($tACE, "Mask") If $sFilter <> "" Then If(StringLeft($aAcct[0], StringLen($sFilter)) = $sFilter) Then slog(0, StringFormat("%-25s %s %s", $aAcct[0], _AccessMaskToString($iAccessMask))) EndIf EndIf $pOffset += DllStructGetData($tACE, "AceSize") Until ($pOffset - $pStartofACEs) >= $iSize EndIf EndFunc Func _AccessMaskToString($iAccessMask) Switch $iAccessMask Case $_READ Return "Read" Case $_WRITE Return "Write" Case $_MODIFY Return "Modify" Case $_READEXEC Return "Read&Exec" Case $_FULL Return "FullAccess" EndSwitch EndFunc Func slog($lvl, $msg) ;~ Select ;~ Case $lvl = 0 ;~ If $LOGLVL < 3 Then Return ;~ Case $lvl = 1 ;~ If $LOGLVL < 2 Then Return ;~ Case $lvl = 2 ;~ If $LOGLVL < 1 Then Return ;~ EndSelect ;~ If @Compiled = 1 Then ;~ FileWriteLine($LOG, $msg) ;~ Else ConsoleWrite($msg & @CRLF) ;~ EndIf EndFunc Func die($msg) slog(2,"FATAL:" & $msg & @CRLF & "@Error: " & @error) Exit EndFunc So long, and thanks for all the fish tannerli Edited July 21, 2010 by tannerli Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now