Jump to content

Set Acl permissions UDF


Recommended Posts

In fact, with admin rights, UVK or the task manager were able to kill the process, which are not very good news for me. I was planning of using this to prevent UVK from being closed by third party applications.

Link to comment
Share on other sites

Hmm, sorry to hear that... it should still be protected from third party applications which aren't running with elevated privileges. That's better than all 3rd party apps. Perhaps creating a "companion process" which enforces file/process DACL's on UVK and will restart UVK if its' terminated unexpectedly? That could also be a step closer... :)

Edited by superg
Link to comment
Share on other sites

Yes, but it could also lead to an infinite loop of run/kill process. You see, modern malware writers know which are the most recent and effective malware removal tools, and create code to detect if they are started, and immediately close them.

Since UVK is getting known all over the world, soon, it will be on the kill list. I must find a way to prevent it.

Link to comment
Share on other sites

Ok I updated again. See the first post. Now it supports all object types.

@superg: I added a function to the example that denies everyone access to the current process (@AutoItPid).

To do exactly the same thing as your python script use:

#include 'Permissions.au3'
Local $Hndl = _Permissions_OpenProcess(@AutoItPID)
_SetObjectStringSecurityDescriptor($Hndl, 'O:S-1-1-0G:S-1-1-0D:(D;;0xe0801;;;DU)(D;;0xe0801;;;SY)(D;;0xe0801;;;WD)S:P', $SE_KERNEL_OBJECT)
MsgBox(0,'', _GetObjectStringSecurityDescriptor($Hndl, $SE_KERNEL_OBJECT))

However, to make this work for me, I had to delete the Domain Users ace (D;;0xe0801;;;DU). I think it's because my pc is not in a domain.

Anyway, since this security descriptor already has an access denied ace to everyone (D;;0xe0801;;;WD), the result will be the same as if you just use:

#include 'Permissions.au3'
Local $Hndl = _Permissions_OpenProcess(@AutoItPID)
_DenyAllAccess($Hndl, $SE_KERNEL_OBJECT,'Everyone')
MsgBox(0,'', _GetObjectStringSecurityDescriptor($Hndl, $SE_KERNEL_OBJECT))

I hope it's what you needed.

Link to comment
Share on other sites

Hi FredAl

First : great script ! really, I wanted to do something like this for years but didn't understood whole thing with security descriptor. So that's a great step

what you posted here.

I've a question actually : the script reads dacl, but not inherited dacl, maybe i'm missing something.

I use those two functions to retrieve this, from your udf :

Local $Dacl = _GetObjectDacl($oName)
if $Dacl <>  0 then
_MergeDaclToArray($Dacl, $aPermissions)

Is it normal or we have to make more programmation to get inheritance dacl ? I've seen getinheritancesource : http://msdn.microsoft.com/en-us/library/windows/desktop/aa446640(v=VS.85).aspx but I wonder.

Thanx you if you can explain this.

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Hi Arcker.

Glad you like the UDF. The inheritance, we must try to understand how it works.

You see, inherited aces are not part of the DACL of a child object. They are part of the Dacl of the parent, grand parent, or whatever is the object that propagates them.

An ace created with the $SUB_CONTAINERS_AND_OBJECTS_INHERIT flag is propagated trough the security descriptors of all the sub containers and objects. You can't edit this ace in a child object, because the ace doesn't belong to it, but you can remove it by clearing the Dacl, or editing the security descriptor.

When you edit an object's Dacl with _EditObjectPermissions, inherited aces are not deleted, unless you clear the Dacl.

To restore the inherited aces use the _TreeResetPermissions function.

Link to comment
Share on other sites

Hi Fred,

Yeah totally

I've found some articles that demonstrates it. I know the problem is you use the getexplicitaccess, that means, "access on this object only".

I'm making some modification, just for tests, and see if it works, to show inherited access.

The ACL Editor in windows already manages this, as you said, with "child" objects. So when you make a modification to the parent,

all of the acl of the child are changed too, but with "inherited" flag. This is not automatical : the acl editor just change child objects. So everytime we change the DACL on the parent, child object have to be edited too. That's what you do with your _TreeResetPermissions :)

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

For now, i've managed to get inherited aces too ! Now i've to get the SIDs properly, then I'll post here. Maybe it could help somebody.

Just listing for now, not more.

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

OK, I think I may have found your solution. Here's a new function that gets a Dacl containing all aces, including the inherited ones:

Func _GetObjectDaclIncludeInherit($oName, $_SE_OBJECT_TYPE = $SE_FILE_OBJECT)
Local $sSD = _GetObjectStringSecurityDescriptor($oName,$_SE_OBJECT_TYPE )
$sSD = StringReplace($sSD,'ID;',';')
Local $pSD = _ConvertStringSecurityDescriptorToSecurityDescriptor($sSD)
Return _GetSecurityDescriptorDacl($pSD)
EndFunc ;==> _GetObjectDaclIncludeInherit

Now, an important thing: I made the _MergeDaclToArray function filter the trustees, and add only one ace per trustee from the Dacl to the array. I thought this was obvious. Since access denied aces have priority over the access granted ones, then why use the latter if the trustee is the same?

To change this feature, you'll have to modify the function, and add a new parameter: $Filter. If $Filter is set to 0, all aces will be added to the array, even if the corresponding trustee is already present in it.

Func _MergeDaclToArray(ByRef $Dacl, ByRef $aPerm, $Filter = 1)
If Not IsArray($aPerm) Or UBound($aPerm,2) < 3 Then Return SetError(1,0,0)
Local $aCall = DllCall($h__Advapi32Dll,'DWORD','GetExplicitEntriesFromAcl','ptr',$Dacl,'ulong*',0,'ptr*',0)
If @error Or $aCall[0] Then Return SetError(2,0,0)
Local $uB = UBound($aPerm), $l = 0, $TrusteeExists, $E = $aCall[2], $eaSID, $aPermSid, $pEa = $aCall[3]
For $i = 2 To $E
For $i = 0 To $uB -1
If Not IsDllStruct($aPerm[$i][0]) Then $aPerm[$i][0] = _GetSidStruct($aPerm[$i][0])
For $i = 1 To $E
$eaSID = DllStructGetData($_EXPLICIT_ACCESS, $l+8)
If $eaSID = 0 Then ContinueLoop
$TrusteeExists = 0
If $Filter Then
For $c = 0 To $uB -1
$aCall = DllCall($h__Advapi32Dll,'BOOL','EqualSid','ptr',$eaSID,'ptr',DllStructGetPtr($aPerm[$c][0]))
If Not @error Then $TrusteeExists = $aCall[0]
If $TrusteeExists Then ExitLoop
If Not $TrusteeExists And _IsValidSid($eaSID) Then
ReDim $aPerm[$uB+1][3]
$aPerm[$uB][0] = DllStructCreate('byte SID['&_GetLengthSid($eaSID)&']',$eaSID)
$aPerm[$uB][1] = Number(DllStructGetData($_EXPLICIT_ACCESS,$l+2) = 1)
$aPerm[$uB][2] = DllStructGetData($_EXPLICIT_ACCESS,$l+1)
$uB += 1
$l += 8
Return $pEa
EndFunc ;==> _MergeDaclToArray

I'll update the UDF with these changes soon. Just have to test if everything is working fine.

Edit: I just can't find a way to indent the code. Can someone explain how it's done?

Edited by FredAI
Link to comment
Share on other sites

Hi fred,

Indeed :)

I've not finished. I've used MSDN docs with some new functions :

Maybe you use it as I do to get inherited access :

GetAclInformation to retrieve the ACEs count


GetAce to get the Ace on each ACL to retrieve SID and AceFlags + AceTypes.

Advantage : $aPerm doesn't need redim anymore, since we know the size before => faster

Tell me if you use the same, I won't spoil your work with my dirty work ;)

I don't see what you used to get inherited.

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Good News ! It works !

Just to have to clean the code then i'll post it.

Inside there is some code "tips" so I have to add comments since I play with binary a little.

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Well, I don't know if it will be faster, since your method envolves much more dll calls, but I hope so.

Here's what my method does:

I have a folder in my D: drive I created to test these functions. It has lots of sub folders and small files I use to ensure the permissions are propagated.

So, the first line of the function retrieves the security descriptor's string:

Local $sSD= _GetObjectStringSecurityDescriptor($oName,$_SE_OBJECT_TYPE)

In my test I got:


All the aces in this security descriptor are inherited. OICIID means Object inherit ace + Containers inherit ace + Inherited ace.

then the line sets all inherited aces as non inherited simply using a stringreplace statement:

$sSD = StringReplace($sSD,'ID;',';')

So the string became:


And the 3rd and 4th lines get the Dacl from the new string. Now all the aces can be edited with the UDF functions.

The array of permissions was initialized as follows:

Local $aPerm[1][3]
$aPerm[0][0] = 'Administrators'
$aPerm[0][1] = 1
$aPerm[0][2] = $GENERIC_ALL

The I called _MergeDaclToArray($Dacl,$aPerm,0) (the modified function, see my last post).

$aPerm had been redimmed to 5, meaning the 4 aces had been added.

Edited by FredAI
Link to comment
Share on other sites

Hi Fred.

So don't bother with my method, since yours only does one dllcall. Mine does, well, one call to get size,

then one call on each ACE, then, one memory allocation to get the sid, then one sid reverse.

I wonder why I didn't find the _GetObjectStringSecurityDescriptor to get the info needed.

For now I've no time to post the code as it, since it need more cleaning.

I'll post it tomorrow, but I think the function inside are more superseed functions than real fonctions with plusvalue

I post an extract ( replace mergedacl inside code ) but not $aPerm generated for now. Easy to add but, no time.

$tACLSIZE = DllStructCreate("DWORD AceCount;DWORD AclBytesInUse;DWORD AclBytesFree")

Local $tBuffer = DllStructCreate("int[4]")
Local $aCall = DllCall($h__Advapi32Dll, 'DWORD', 'GetAclInformation', 'ptr', $Dacl, 'ptr', DllStructGetPtr($tACLSIZE), 'dword', DllStructGetSize($tACLSIZE), "dword", 2)
If $aCall[0] = 0 Then
ConsoleWrite("+" & _WinAPI_GetLastError() & @CRLF)

ConsoleWrite("Size = " & DllStructGetData($tACLSIZE, 1) & @CRLF)

For $ACE = 0  To DllStructGetData($tACLSIZE, 1) - 1
$pace = DllStructCreate("ptr")

Local $aCall = DllCall($h__Advapi32Dll, 'int', 'GetAce', 'ptr', $Dacl, 'int', $ACE, 'ptr', DllStructGetPtr($pace))
If $aCall[0] = 0 Then
ConsoleWrite("+" & _WinAPI_GetLastErrorMessage() & @CRLF)
;$tACE = DllStructCreate("byte AceType;byte AceFlags;word AceSize",DllStructGetData($pace,1))
$tACE = DllStructCreate("byte AceType;byte AceFlags;word AceSize;dword ACCESS_MASK;dword SidStart",DllStructGetData($pace,1))
switch  DllStructGetData($tACE,2)
case 0
ConsoleWrite ("explicit access" )
;~  ConsoleWrite ("Inherited and propagate " )
case 18
ConsoleWrite ("Inherit from " )
ConsoleWrite ("Container Inherit " )
ConsoleWrite ("This object only " )
ConsoleWrite ("inherit only " )

ConsoleWrite ("inherited " )
case Else
ConsoleWrite ("Unknow ace flag " & DllStructGetData($tACE,2))
; Here we have to get the AceSize to retrieve SID
$sSIDLength = DllStructGetData($tACE,3)

; Here we have to get the SIDs - SIDStart
; So I've concatenate it to only one byte value of Lenght - dword (sidstart) - dword ACCESS_MASK ?
; 2 x dword = 8 bytes.
$tACE = DllStructCreate("byte AceType;byte AceFlags;word AceSize;dword ACCESS_MASK;byte["& _
$sSIDLength -8  & "]",DllStructGetData($pace,1))
;~  ConsoleWrite("+" & DllStructGetData($tACE, 1) & "|"   & DllStructGetData($tACE, 2)   & "|" & _
;~  DllStructGetData($tACE, 3) & "|"  & DllStructGetData($tACE, 4) & "|"  & DllStructGetData($tACE, 5) & @CRLF)
;~  _Security__SidToStringSid(
;ConsoleWrite("+" & DllStructGetData($tACE, 1) & "|"   & DllStructGetData($tACE, 2)   & "|" & _
;DllStructGetData($tACE, 3) & "|"   & @CRLF)

;~  _Security__GetLengthSid(
;~  _Security__IsValidSid(
;ConsoleWrite("!0x010500000000000515000000239D90439519480CBF939CF64F080000"& @CRLF)
;~  ConsoleWrite(">" & DllStructGetData($tACE, 5)  & DllStructGetData($tACE, 6) & @CRLF)
;~  ConsoleWrite(">" & _Security__IsValidSid(DllStructGetData($tACE, 5))  & @CRLF)
; Now : reverse SID !
;~  $tSID = DllStructCreate("byte[" & $sSIDLength & "]",DllStructGetPtr($tACE,5))
;~  DllStructSetData($tSID,1,DllStructGetData($tACE, 5))
$aLookup = _Security__LookupAccountSid(DllStructGetPtr($tACE,5))
  ConsoleWrite("Name : "  & $aLookup[0] & @crlf)
ConsoleWrite("Domain : "  & $aLookup[1] & @crlf)
ConsoleWrite("Type : "  & $aLookup[2] & @crlf)
Edited by arcker

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

  • 2 weeks later...


I would first like to say thank you very much for your posting. It is very helpful.

The only problem I have is that I also use some other of the included UDF's on occasion, and many of the constants you define are already used in various UDF's under the AutoIt Include folder. A great way to reproduce this issue is to add #include <Security.au3> to the beginning of a script that also uses the Perissions.au3 include. I found this out needing to use the _LookupAccountSid function in Security.au3. When trying to run it bombs out due to many conflicting constants in all of the includes.

I can think of a couple ways to potentially allow this to co-exist. One would be for the Permissions.au3 to include the other UDF's rather than redefining existing constants. This may be difficult though should you need a constant not yet in the standard UDFs, if newer AutoIt versions then incorporated.

The other way, that may have less potential for future conflict (at least with the packaged UDFs), would be to prefix all of the items in Permissions.au3 with your own unique prefix. I know the values may not exactly match the MSDN definitions this way, although functionally it may not matter.

Thanks again and keep up the great work!

Link to comment
Share on other sites


Yes I noticed that a few days ago, too. I'll rename the constants that conflict for the next update.

The thing is, I stopped including UDF's a few months ago, when I realized that most of them highly increase the memory usage of the script.

That's the reason why I hadn't noticed it before.

Link to comment
Share on other sites

This seems like a highly complexe UDF. Very impressive!

You mentioned in your first post to ask if someone needed a registry example. Well, I do. Here are the registry keys that need to be modified in order to hide the 'Network' item in the Windows 7 Explorer Navigation pane:

RegWrite('HKCRCLSID{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}ShellFolder',"Attributes","REG_DWORD",0xb0040064); Hide Network in Explorer Navigation Pane (Windows 32/64bit)
RegWrite('HKLMSoftwareWow6432NodeClassesCLSID{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}ShellFolder',"Attributes","REG_DWORD",0xb0040064); Hide Network in 'Save As' and 'Open' dialogs (Windows 64 bit only)

Both of these lines require 'Full Control' Permissions. How can I use your UDF to gain permission. Can you please post an example using the above code.

More info regarding hidding the 'Network' item can be found here:


Any help would be greatly appreciated!


Edited by intime69

Developer and Co-OwnerInTime Applicaitons Inc.

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...