Jump to content
FredAI

Set Acl permissions UDF

Recommended Posts

I love the UDF, but I'm having a tough time using it to add permissions. I have a Win2k8 machine that I'm trying to add the users to the Windows directory. Its owner is "Trusted Installer". Every time I execute the code below, it wipes out the current permissions and adds only the ones I specify in the array. This works great on other folders, but I can't seem to simply add two users to the permissions without clearing the rest.

What am I doing wrong?

#include <permissions.au3>
Dim $aPerm[2][3]
$aPerm[0][0] = "Authenticated Users"
$aPerm[0][1] = 1
$aPerm[0][2] = $GENERIC_ALL
$aPerm[1][0] = "Network Service"
$aPerm[1][1] = 1
$aPerm[1][2] = $GENERIC_ALL
$file = @WindowsDir
$setPerms = _SetObjectPermissions($file, $aPerm, $SE_FILE_OBJECT, "", 0, 1)

Share this post


Link to post
Share on other sites

FredAI,

Thank you for creating this solution, I really appreciate it!

Would it be possible for you to post two additional examples?

Specifically, I'm having difficulty assigning file object permissions for specific domain users/groups. I use the function included herein to obtain the domain name. If the @LogonDomain and $Domain variables do not match I'd like to add the 'DOMAINDomain Users' group, for example, to the DACL permissions array. I'm assuming the answer involves looking up the SID?

The second example I'm looking for would be code showing how to modify thread permissions, specifically Terminate, Suspend/Resume, and Change Owner. I'm guess looking up the Pid is involved?

$Domain = _DomainComputerBelongs()
MsgBox(0 , @LogonDomain , 'Domain: ' & $ComputerDomain)

Func _DomainComputerBelongs($strComputer = "localhost")
$Domain = ''
$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$objWMIService = ObjGet("winmgmts:" & $strComputer & "rootCIMV2")
If Not IsObj($objWMIService) Then Return SetError(1, 0, '')
  $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
If IsObj($colItems) then
  For $objItem In $colItems
   $Domain = $objItem.Domain
  Next
Endif
Return $Domain
EndFunc

Hi.

I've been working on this for a while. I think now it's good enough to post it here.

Functions to do most everything with the DACL and ownership on all types of objects: Files or folders, Registry keys, services, Kernel and WMI objects, etc.

Thanks!!

Share this post


Link to post
Share on other sites

You'll have to use the SID string instead of the group's name. The only groups you may use the names are "Administrators", "System" and "Everyone". However, for users (not groups) you may use the name string.

Take a look here: http://support.microsoft.com/kb/243330

It will give you the SID strings for the groups you need.

Share this post


Link to post
Share on other sites

@buymeapc

Not that I'm gonna buy you a pc :D , but I'm working in a new function which will edit the DACL instead of creating a new one. It's already working, just have to run some tests and document it. I'll update tonight, or tomorrow the latest.

Also, have you tried taking ownership of the folder?

#include <permissions.au3>
Dim $aPerm[2][3]
$aPerm[0][0] = "Authenticated Users"
$aPerm[0][1] = 1
$aPerm[0][2] = $GENERIC_ALL
$aPerm[1][0] = "Network Service"
$aPerm[1][1] = 1
$aPerm[1][2] = $GENERIC_ALL
$file = @WindowsDir
$setPerms = _SetObjectPermissions($file, $aPerm, $SE_FILE_OBJECT, "Administrators", 0, 1)

Share this post


Link to post
Share on other sites

Are the English terms you use as 'administrators' or 'everyone' valid for all other languages or should i translate them ?

Yes, they are valid for all languages. If you take a look at the _GetSidStruct you'll se I'm using the corresponding universal SID strings to get the structure. I can add other universal SIDs for well known groups, like the "Authenticated Users" or "Network Service".

I'm working on it right now, but I'm not a very fast script writer, so maybe tomorrow it will be ready. :D

Share this post


Link to post
Share on other sites

@buymeapc

Not that I'm gonna buy you a pc :) , but I'm working in a new function which will edit the DACL instead of creating a new one. It's already working, just have to run some tests and document it. I'll update tonight, or tomorrow the latest.

Also, have you tried taking ownership of the folder?

#include <permissions.au3>
Dim $aPerm[2][3]
$aPerm[0][0] = "Authenticated Users"
$aPerm[0][1] = 1
$aPerm[0][2] = $GENERIC_ALL
$aPerm[1][0] = "Network Service"
$aPerm[1][1] = 1
$aPerm[1][2] = $GENERIC_ALL
$file = @WindowsDir
$setPerms = _SetObjectPermissions($file, $aPerm, $SE_FILE_OBJECT, "Administrators", 0, 1)

@FredAI - That's wonderful news! Thanks for the update. I have, in fact, taken ownership of the folder prior to changing the DACL. I thought I might have been doing something wrong. I can't wait to try out your new function! Thanks!!

Share this post


Link to post
Share on other sites

Updated! Uff! This one wasn't easy. I had to read all the aces from the existing Dacl, compare the aces with the ones to add and create a new array of permissions that include the existing aces.

Since editing the access to the Windows folder can be dangerous, I added a function to restore the default access permissions for any directory.

Edit: I added some examples to test the new function in the first post. Just a recall: We can't use the TrustedInstaller SID in windows xp/2003, because the service doesn't exist.

Edited by FredAI

Share this post


Link to post
Share on other sites

Wonderful! I tested it on Windows 2008, simply taking temporary ownership (from TrustedInstaller), adding "Authenticated Users" and "Network Service", and restoring ownership to the original owner and it worked like a dream! Great job!

I do have one more question...

How could I get a string respresentation of the permissions of a file/folder? I'd like to remove all dependancy from external executables. An example would be to run the following function:

(I'm just checking to see if I find "Authenticated Users" using StringInStr within the return message)

Func GetPerms($path)
Local $pid, $line, $message
$pid = Run(@ComSpec & " /c cacls " & '"'&$path&'"', @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
While 1
  $line = StdoutRead($pid)
  If @error Then ExitLoop
  If $line <> "" Then $message = $line & $message;MsgBox(0, "STDOUT read:", $line)
WEnd
Return $message
EndFunc

Thank you!!

Edited by buymeapc

Share this post


Link to post
Share on other sites

Humm... Nice thought. Well, for now, you'll have to use the _GetObjectStringSecurityDescriptor() function, and check if the string ";AU" is present in the returned string.

Maybe in the future I'll ad a new function that returns an array of permissions like the one we use to set tem.

Share this post


Link to post
Share on other sites

You can learn more about the security descriptor strings here: http://msdn.microsoft.com/en-us/library/aa379570%28v=VS.85%29.aspx

Too bad you didn't read all the thread. This has already been covered.

Share this post


Link to post
Share on other sites

Hi,

I've written a script in Python which successfully modifies the DACL for a given SE_KERNEL_OBJECT process ID.

I'd like to convert this into AutoIt, and Permissions.au3 seems to be the place to do it. :)

Specifically, we'll need to add the GetSecurityInfo(), SetKernelObjectSecurity(), and GetKernelObjectSecurity() functions.

Func _getSecurityInfo($handle, $ObjectType, $SecurityInfo)
Local $ppsidOwner = DllStructCreate("ptr")
Local $ppsidGroup = DllStructCreate("ptr")
Local $ppDacl = DllStructCreate("ptr")
Local $ppSacl = DllStructCreate("ptr")
Local $ppSecurityDescriptor = DllStructCreate("ptr")
Local $aResult = DllCall($h__Advapi32Dll, "long", "GetSecurityInfo", _
   "ptr", $handle, _
   "int", $ObjectType, _
   "dword", $SecurityInfo, _
   "ptr", DllStructGetPtr($ppsidOwner, 0), _
   "ptr", DllStructGetPtr($ppsidGroup, 0), _
   "ptr", DllStructGetPtr($ppDacl, 1), _
   "ptr", DllStructGetPtr($ppSacl, 0), _
   "ptr", DllStructGetPtr($ppSecurityDescriptor, 0))
If @error Then Return SetError(@error, @extended, -1)
Return $aResult
EndFunc   ;==>getSecurityInfo

Func _GetKernelObjectSecurity($handle, $RequestedInformation)
If $ResourcesState = 0 Then _InitiatePermissionResources()
Local $pSecurityDescriptor = DllStructCreate("ptr")
Local $lpnLengthNeeded = DllStructCreate("ptr")
Local $aRet = DllCall($h__Advapi32Dll, "dword", "GetKernelObjectSecurity ", _
    "handle", $handle, _
    "dword", $RequestedInformation, _
    "ptr", DllStructGetPtr($pSecurityDescriptor, 1), _
    "dword", 0, _
    "ptr", DllStructGetPtr($lpnLengthNeeded, 1))
If @error Then Return SetError(@error,0,0)
Return $aRet
EndFunc ;==>_GetKernelObjectSecurity

Working Python Script - This prevents users from Terminating, Suspending, Changing Rights, and Changing Ownership of any given process ID.

import win32security,win32api,win32con,win32process,sys
if (len(sys.argv) > 1):
pid=int(sys.argv[1])
print "Process:",pid
else:
    pid=win32api.GetCurrentProcessId()
#
# Find the SIDs for Everyone, the Admin group and the current user
#
everyone, domain, type = win32security.LookupAccountName ("", "Everyone")
print everyone,"Everyone"
admins, domain, type = win32security.LookupAccountName ("", "Administrators")
print admins,"Admins"
user, domain, type = win32security.LookupAccountName ("", win32api.GetUserName ())
print user,"User"
new_privs = ((win32security.LookupPrivilegeValue('',win32security.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_TCB_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_SHUTDOWN_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_TAKE_OWNERSHIP_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_CREATE_PERMANENT_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_ENABLE_DELEGATION_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_CHANGE_NOTIFY_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_DEBUG_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_PROF_SINGLE_PROCESS_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_SYSTEM_PROFILE_NAME),win32con.SE_PRIVILEGE_ENABLED),
             (win32security.LookupPrivilegeValue('',win32security.SE_LOCK_MEMORY_NAME),win32con.SE_PRIVILEGE_ENABLED)
            )

print ""
print new_privs,"new_privs"
  
all_info=win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION| 
     win32security.DACL_SECURITY_INFORMATION|win32security.SACL_SECURITY_INFORMATION
ph=win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS,0,pid)
## PROCESS_ALL_ACCESS does not contain ACCESS_SYSTEM_SECURITY (neccessy to do SACLs)
th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS)  ##win32con.TOKEN_ADJUST_PRIVILEGES)
old_privs=win32security.AdjustTokenPrivileges(th,0,new_privs)
my_sid = user
pwr_sid = everyone
## reopen process with ACCESS_SYSTEM_SECURITY now that sufficent privs are enabled
ph=win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS|win32con.ACCESS_SYSTEM_SECURITY,0,pid)
sd=win32security.GetSecurityInfo(ph,win32security.SE_KERNEL_OBJECT,all_info)
dacl=sd.GetSecurityDescriptorDacl()
if dacl is None:
    dacl=win32security.ACL()
else:
print ""
#print dacl,"DACL"
str_dacl = win32security.ConvertSecurityDescriptorToStringSecurityDescriptor(sd,
  win32security.SDDL_REVISION_1, win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION|
  win32security.DACL_SECURITY_INFORMATION|win32security.SACL_SECURITY_INFORMATION )
print str_dacl
strSECURITY_DESCRIPTOR = 'O:'+win32security.ConvertSidToStringSid(everyone)+'G:'+win32security.ConvertSidToStringSid(everyone)+'D:(D;;0xe0801;;;DU)(D;;0xe0801;;;SY)(D;;0xe0801;;;WD)S:P'
PySECURITY_DESCRIPTOR = win32security.ConvertStringSecurityDescriptorToSecurityDescriptor( strSECURITY_DESCRIPTOR, win32security.SDDL_REVISION_1 )
print ""
print strSECURITY_DESCRIPTOR

sacl=sd.GetSecurityDescriptorSacl()
if sacl is None:
    sacl=win32security.ACL()
else:
print ""
#print sacl,"SACL"

win32security.SetKernelObjectSecurity(ph,all_info,PySECURITY_DESCRIPTOR)
new_sd=win32security.GetKernelObjectSecurity(ph,all_info)
if win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorOwner())[0]!='Everyone':
    print 'Owner not successfully set to Everyone!'
else:
print 'Owner successfully set to Everyone!'
if win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorGroup())[0]!='Everyone':
    print 'Group not successfully set to Everyone!'
else:
print 'Group successfully set to Everyone!'

Share this post


Link to post
Share on other sites

Definitely interesting, superg, but I wonder what you need this for. I hope you're not trying to create an unkilable trojan.

But I may need those functions for one of my apps in the future, so I'll see what I can do.

I made this UDF basically to replace some command line tools like setacl, subinacl and icacls, and it's specially destinated to objects that we can use their names, like registry keys, files, folders services, printers, etc. hence the use of the SetNamedSecurityInfo and GetNamedSecurityInfo functions.

Share this post


Link to post
Share on other sites

No trojan plans here... more like security policy enforcement. :) I'm actually working on my own in-house "policy enforcement" program to ensure certain IT sec/mgt related programs are not uninstalled, suspended, terminated, or disabled by certain non-admin domain users. There are a several processes I need to ensure are always available (unless I, as the domain administrator, specifically disable them) such as backup and monitoring agents. Certain domain users have been disabling these at will. Besides, as you can see, I already posted working code (in Python) so converting to AutoIt shouldn't be much more of a "security risk", IMHOP. I suppose the same argument could be made for file security DACL's... deny all rights except for read and execute. All that being said, if one has administrator rights all these protections could be undone easily enough, so the benefit is really the ability to restrict non-domain admin users (and to permit rights for admins (think of an advanced killtasker which grants all necessary rights to a process prior to killing it)).

Anyhow, I appreciate you looking into it! I enjoy SetACL myself and have requested they extend functionality to secure processes as well in their forum, so perhaps we'll see more of this!

superg

MCNE, MCSE, Security+

Edited by superg

Share this post


Link to post
Share on other sites

OK I got it all ready, just have to run some more tests and document.

Still I would like to have an advice from a moderator or administrator. I denied everyone access to the script's process and I couldn't kill it from the task manager.

This will certainly be useful for malware writers.

The best news is that the kernel and window objects will be edited with the same functions as named objects.

#include 'Permissions.au3'

Local $Hndl = _Permissions_OpenProcess(@AutoItPID)
Local $aRegPerm[1][3]
$aRegPerm[0][0] = 'Everyone'
$aRegPerm[0][1] = 0
$aRegPerm[0][2] = $GENERIC_ALL

MsgBox(0,'',_EditObjectPermissions($Hndl,$aRegPerm,$SE_KERNEL_OBJECT,'Administrators'))

Share this post


Link to post
Share on other sites

Try killing your "protected process" with pskill -t {pid} or taskkill /pid {pid} from the command prompt (ran as administrator), you should be able to.

If not, perhaps another test would be to write a separate script granting yourself termination (or all) rights to the "protected" process and then terminating it. You should be able to... hence not a major issue for anyone other than those without administrator rights.

Edited by superg

Share this post


Link to post
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...