Adjusting DCOM Settings via Script

Share on:

This post was previously released under a different blog and is being republished by me below. That site is no longer available. I am the original author.

I was recently tasked with adjusting the DCOM Security Settings (DCOM: Machine Access Restrictions and DCOM: Machine Launch Restrictions) in the local security policy on a number of computers. These can be changed manually by opening the Local Security Policy and browsing to Local Policies and then Security Options, but it needed to be more automated than that and needed to be rolled out to a few hundred Windows XP Computers.

The requirements of the script were as follows:

  • Add two groups to each of the policy settings
  • Do not try and add them again if they already exist
  • Do not overwrite the users/groups that are already there
  • Group Policy is not an option for this project
  • Log Everything

I played around for about 45 minutes with secedit and applying a policy that way but I couldn’t get it to import and append the existing policy correctly. I decided that the changes were going to need to be made through script, and probably through the registry.

I first used REGMON (from Microsoft SysInternals) to find out where these settings were stored in the registry. I found they are both in the same spot under HKLM\Software\Policies\Microsoft\Windows NT\DCOM. Unfortunately, it wasn’t just a comma delimited list of users and rights.

On the bright side, at least it wasn’t some binary key that made even less sense. These strings seemed workable; it seemed like there was a pattern.

I’ll save you the paragraphs I could write about how I added and removed users, changed their permissions, etc. just to see the changes on these keys to break the pattern and just bring you to my end result. The strings are in SDDL (Security Descriptor Definition Language) format. While Microsoft had some light write-ups on MSDN about SDDL, the best resource I found on the matter was at this University of Washington page.

While reading about SDDL from that site is important if you’re looking to take on a similar task, the short version is that SDDL strings can be first broken up into five groups (Header, DACL, SACL, Primary Group, and Owner). Each of these fields is separated by a colon. I wont go into details about each of these as the University of Washington site will do this for you, but for the purposes of this project the only thing that needs to be changed for the DCOM policies is the last field in the string. In my screen shot above, that’s the one that looks like this:

(A;;CCDCLC;;;AN)(A;;CCDCLC;;;WD)

In a nutshell, each user or group in the string is represented by a parentheses grouping. You can see in the one in bold that there are two groupings, representing two users/groups. These grouping are further broken down by fields that are separated by semicolons. You can see there are six fields and they are:

  • Type
  • Flags
  • Permissions
  • ObjectType
  • Trustee (SID)

Again, read up on either MSDN or the University of Washington page to learn about what each of these fields mean. You can see from the existing SDDL strings that the DCOM policy only uses three of these fields: Type, Permissions, and Trustee. By digesting all of this, I was now ready to create a script to parse the existing users/groups, modify their permissions if necessary, and add the users if they didn’t exist.

The script below is the product of this effort. You are welcome to use, however please keep the header intact and provide credit to this post if you share it with others. I’ve commented on how the script works beneath it.

  1; ==============================================================================================================================================
  2; Windows XP Local Security Policy DCOM Permissions Change
  3; ==============================================================================================================================================
  4 
  5; Script Version:	1.0
  6; AutoIt Version: 	3.0
  7; Language: 		English
  8; Description: 		Modifies DCOM Security Settings
  9 
 10; 2-Sept-2009:		Created First Revision of Script
 11 
 12#include 
 13 
 14; Setup Logs
 15$logFolder = @TempDir & "\\DCOM"
 16$log = $logFolder & "\\DCOMModifier.log"
 17 
 18If Not FileExists($logFolder) then DirCreate($logFolder)
 19 
 20If FileExists($log) then FileWriteLine($log, "")
 21 
 22FileWriteLine($log, "\[" & \_now() & "\] Capturing Current DCOM Settings")
 23$Access = RegRead("HKLM\\Software\\Policies\\Microsoft\\Windows NT\\DCOM", "MachineAccessRestriction")
 24$Launch = RegRead("HKLM\\Software\\Policies\\Microsoft\\Windows NT\\DCOM", "MachineLaunchRestriction")
 25 
 26FileWriteLine($log, "\[" & \_now() & "\] MachineAccessRestriction=" & $access)
 27FileWriteLine($log, "\[" & \_now() & "\] MachineLaunchRestriction=" & $launch)
 28 
 29; MACHINE ACCESS RESTRICTIONS
 30FileWriteLine($log, "\[" & \_now() & "\] Beginning Parse of MachineAccessRestrictions")
 31 
 32$SDDL = StringSplit($access,":")
 33 
 34FileWriteLine($log, "\[" & \_now() & "\]      O = " & $SDDL\[1\])
 35FileWriteLine($log, "\[" & \_now() & "\]      OWNER\_SID = " & $SDDL\[2\])
 36FileWriteLine($log, "\[" & \_now() & "\]      GROUP\_SID = " & $SDDL\[3\])
 37FileWriteLine($log, "\[" & \_now() & "\]      DACL\_FLAGS = " & $SDDL\[4\])
 38 
 39$newSDDL = $SDDL\[1\] & ":" & $SDDL\[2\] & ":" & $SDDL\[3\]
 40FileWriteLine($log, "\[" & \_now() & "\]      New SDDL = " & $newSDDL)
 41 
 42$DACLS = StringSplit($SDDL\[4\],")")
 43 
 44; Position 0 of array will be found
 45; Position n (last) of array will be empty because of the way we stringsplit on the end paren
 46 
 47$sidANON = False
 48$sidEVERYONE = False
 49 
 50For $i = 1 to UBOUND($DACLS)-2
 51	$DACLS\[$i\] = StringReplace($DACLS\[$i\], "(", "")
 52	FileWriteLine($log, "\[" & \_now() & "\]      DACL #" & $i & "=" & $DACLS\[$i\])
 53	$ACES = StringSplit($DACLS\[$i\],";")
 54	FileWriteLine($log, "\[" & \_now() & "\]           ACE TYPE=" & $ACES\[1\])
 55	FileWriteLine($log, "\[" & \_now() & "\]           ACE Flags=" & $ACES\[2\])
 56	FileWriteLine($log, "\[" & \_now() & "\]           ACE Permissions=" & $ACES\[3\])
 57	FileWriteLine($log, "\[" & \_now() & "\]           ACE ObjectType=" & $ACES\[4\])
 58	FileWriteLine($log, "\[" & \_now() & "\]           ACE Inherited ObjectType=" & $ACES\[5\])
 59	FileWriteLine($log, "\[" & \_now() & "\]           ACE Trustee=" & $ACES\[6\])
 60	if $ACES\[6\] = "AN" Then
 61		FileWriteLine($log, "\[" & \_now() & "\]                Trustee is ANONYMOUS, changing permissions to CCDCLC")
 62		if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
 63		$newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";CCDCLC;" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
 64		$sidANON = true
 65	elseif $ACES\[6\] = "WD" Then
 66		FileWriteLine($log, "\[" & \_now() & "\]                Trustee is EVERYONE, changing permissions to CCDCLC")
 67		if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
 68		$newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";CCDCLC;" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
 69		$sidEVERYONE = True
 70	else
 71		FileWriteLine($log, "\[" & \_now() & "\]                Trustee is not on filter list, permissions will be unchanged")
 72		if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
 73		$newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";" & $ACES\[3\] & ";" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
 74	endif
 75	FileWriteLine($log, "\[" & \_now() & "\]           New SDDL = " & $newSDDL)
 76next
 77 
 78If $sidANON = false Then
 79	FileWriteLine($log, "\[" & \_now() & "\] Anonymous Trustee not found in SDDL, adding.")
 80	if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"	
 81	$newSDDL = $newSDDL & "(A;;CCDCLC;;;AN)"
 82	FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
 83EndIf
 84If $sidEVERYONE = false Then
 85	FileWriteLine($log, "\[" & \_now() & "\] Everyone Trustee not found in SDDL, adding.")
 86	if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
 87	$newSDDL = $newSDDL & "(A;;CCDCLC;;;WD)"
 88	FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
 89EndIf
 90 
 91FileWriteLine($log, "\[" & \_now() & "\] Writing New SID to Registry")
 92RegWrite("HKLM\\Software\\Policies\\Microsoft\\Windows NT\\DCOM", "MachineAccessRestriction","REG\_SZ",$newSDDL)
 93
 94; LAUNCH ACCESS RESTRICTIONS
 95FileWriteLine($log, "\[" & \_now() & "\] Beginning Parse of MachineLaunchRestrictions")
 96 
 97$SDDL = StringSplit($launch,":")
 98 
 99FileWriteLine($log, "\[" & \_now() & "\]      O = " & $SDDL\[1\])
100FileWriteLine($log, "\[" & \_now() & "\]      OWNER\_SID = " & $SDDL\[2\])
101FileWriteLine($log, "\[" & \_now() & "\]      GROUP\_SID = " & $SDDL\[3\])
102FileWriteLine($log, "\[" & \_now() & "\]      DACL\_FLAGS = " & $SDDL\[4\])
103 
104$newSDDL = $SDDL\[1\] & ":" & $SDDL\[2\] & ":" & $SDDL\[3\]
105FileWriteLine($log, "\[" & \_now() & "\]      New SDDL = " & $newSDDL)
106 
107$DACLS = StringSplit($SDDL\[4\],")")
108 
109; Position 0 of array will be found
110; Position n (last) of array will be empty because of the way we stringsplit on the end paren
111 
112$sidADMIN = False
113$sidEVERYONE = False
114 
115For $i = 1 to UBOUND($DACLS)-2
116	$DACLS\[$i\] = StringReplace($DACLS\[$i\], "(", "")
117	FileWriteLine($log, "\[" & \_now() & "\]      DACL #" & $i & "=" & $DACLS\[$i\])
118	$ACES = StringSplit($DACLS\[$i\],";")
119	FileWriteLine($log, "\[" & \_now() & "\]           ACE TYPE=" & $ACES\[1\])
120	FileWriteLine($log, "\[" & \_now() & "\]           ACE Flags=" & $ACES\[2\])
121	FileWriteLine($log, "\[" & \_now() & "\]           ACE Permissions=" & $ACES\[3\])
122	FileWriteLine($log, "\[" & \_now() & "\]           ACE ObjectType=" & $ACES\[4\])
123	FileWriteLine($log, "\[" & \_now() & "\]           ACE Inherited ObjectType=" & $ACES\[5\])
124	FileWriteLine($log, "\[" & \_now() & "\]           ACE Trustee=" & $ACES\[6\])
125	if $ACES\[6\] = "BA" Then
126		FileWriteLine($log, "\[" & \_now() & "\]                Trustee is ADMINISTRATORS, changing permissions to CCDCLCSWRP")
127		if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
128		$newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";CCDCLCSWRP;" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
129		$sidADMIN = true
130	elseif $ACES\[6\] = "WD" Then
131		FileWriteLine($log, "\[" & \_now() & "\]                Trustee is EVERYONE, changing permissions to CCDCLCSWRP")
132		if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
133		$newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";CCDCLCSWRP;" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
134		$sidEVERYONE = True
135	else
136		FileWriteLine($log, "\[" & \_now() & "\]                Trustee is not on filter list, permissions will be unchanged")
137		if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
138		$newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";" & $ACES\[3\] & ";" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
139	endif
140	FileWriteLine($log, "\[" & \_now() & "\]           New SDDL = " & $newSDDL)
141next
142 
143If $sidADMIN = false Then
144	FileWriteLine($log, "\[" & \_now() & "\] Admin Trustee not found in SDDL, adding.")
145	if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"	
146	$newSDDL = $newSDDL & "(A;;CCDCLCSWRP;;;BA)"
147	FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
148EndIf
149If $sidEVERYONE = false Then
150	FileWriteLine($log, "\[" & \_now() & "\] Everyone Trustee not found in SDDL, adding.")
151	if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
152	$newSDDL = $newSDDL & "(A;;CCDCLCSWRP;;;WD)"
153	FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
154EndIf
155 
156FileWriteLine($log, "\[" & \_now() & "\] Writing New SID to Registry")
157RegWrite("HKLM\\Software\\Policies\\Microsoft\\Windows NT\\DCOM", "MachineLaunchRestriction","REG\_SZ",$newSDDL)

Basically, the meat of the script is that after setting up our log file, we read the two registry keys that we need to possibly modify. We then break them down into their 5 parts and log them, and then break the fifth field down into it’s six parts so that we can look at all the users.

We then loop over each user and pull out who the user is and what their permissions are. If they are a user that we want to modify, we update our temporary SDDL string to set the permissions to what we want (see the tables on the University of Washington site). If they are not a user that we care about, we insert them as-is into our temporary SDDL string. If at the end of it all we haven’t found the users we want to modify, we add them. Once all is said and done, we insert the new SDDL right back into the registry.



No comments