4. Creating an AppLocker Entry
Creating an AppLocker entry is a difficult
and error-prone process because the entries appear in so many registry
keys. You literally have to search the registry looking for the proper
places to put the keys. Consequently, this part of the application
starts with the recursive search routine shown in Listing 2.
Example 2. Using a recursive routine to search the registry
private List<String> SearchReg( RegistryKey StartHive, String StartPath, String SearchKey, List<String> Results) { RegistryKey Start; // Defines a starting point for the search.
// This operation will fail when processing certain users. try { // Open the specified registry key. Start = StartHive.OpenSubKey(StartPath); } catch (SecurityException SE) { // The application can't process this key. return Results; }
// Start may be null after an attempt to open some user keys. if (Start == null) return Results;
// Get a list of subkeys for that key.
String[] Subkeys = Start.GetSubKeyNames();
// If there aren't any subkeys to process, exit. if (Subkeys.Length != 0)
// Process each of the subkeys in turn. foreach (String Name in Subkeys)
// When the key is equal to the search term. if (Name == SearchKey) { // Add the string to the list. Results.Add(StartPath + @"\" + Name); } else // Otherwise, keep searching. Results = SearchReg( StartHive, StartPath + @"\" + Name, SearchKey, Results);
return Results; }
|
The code begins by attempting to open a supplied
registry key. In some cases, attempting to open the key will generate
an error because the key isn't meant to be opened for any sort of use
(such as the secure keys of the default user's account). It's actually
easier to let the exception occur in this case and catch it, than it is
to generate a list of keys that could cause problems. If the OpenSubKey() call succeeds, the result could still be a null entry, meaning the key doesn't exist. The example handles both issues by returning the current results to the caller.
If the supplied key is valid and it opens properly, the code generates a list of subkeys to check using the GetSubKeyNames()
method. The code checks each of these subkeys in turn for the search
key name. When the code finds a key that matches, it adds the key to Results for return to the caller. Otherwise, the code recursively calls SearchReg() to process the next level of subkeys.
Now that you know how the search routine works, it's time to look at the code for adding an AppLock entry. Listing 3 shows this code.
Example 3. Adding a new path AppLock entry
private void btnAdd_Click(object sender, EventArgs e) { // Open the AppLocker registry key. RegistryKey AppLock = Registry.LocalMachine.OpenSubKey( @"SOFTWARE\Policies\Microsoft\Windows\SrpV2\Exe", true);
// Create a new GUID.
Guid EntryGuid = Guid.NewGuid();
// Use the new GUID to create a subkey and then open the subkey. RegistryKey EntryKey = AppLock.CreateSubKey(EntryGuid.ToString());
// Create the XML required for the entry value. XmlDocument TheRule = new XmlDocument();
// Define the condition. XmlElement Condition = TheRule.CreateElement("FilePathCondition"); XmlAttribute Path = TheRule.CreateAttribute("Path"); Path.Value = Application.ExecutablePath; Condition.Attributes.Append(Path);
// Add the condition to a list of conditions. XmlElement Conditions = TheRule.CreateElement("Conditions"); Conditions.AppendChild(Condition);
// Create the root node. XmlElement Root = TheRule.CreateElement("FilePathRule");
// Define the rule attributes. XmlAttribute Id = TheRule.CreateAttribute("Id"); Id.Value = EntryGuid.ToString(); Root.Attributes.Append(Id);
XmlAttribute Name = TheRule.CreateAttribute("Name"); Name.Value = "My Generated AppLocker Rule"; Root.Attributes.Append(Name);
XmlAttribute Description = TheRule.CreateAttribute("Description"); Description.Value = "Test rule generated by an application."; Root.Attributes.Append(Description);
XmlAttribute SID = TheRule.CreateAttribute("UserOrGroupSid"); SID.Value = "S-1-1-0"; Root.Attributes.Append(SID);
XmlAttribute Action = TheRule.CreateAttribute("Action"); Action.Value = "Allow"; Root.Attributes.Append(Action);
// Add the conditions to the root. Root.AppendChild(Conditions);
// Add the root to the rule. TheRule.AppendChild(Root);
// Set the value of the registry entry to the XML rule. EntryKey.SetValue("Value", TheRule.OuterXml);
// Close the keys. EntryKey.Close();
AppLock.Close();
// Check for the 64-bit key. AppLock = Registry.LocalMachine.OpenSubKey( @"SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\SrpV2\Exe", true);
// If the entry exists, add the data to it. if (AppLock != null) { // Use the GUID to create a subkey and then open the subkey. EntryKey = AppLock.CreateSubKey(EntryGuid.ToString());
// Set the value of the registry entry to the XML rule. EntryKey.SetValue("Value", TheRule.OuterXml);
// Close the keys. EntryKey.Close(); AppLock.Close(); }
// Create a list of registry strings that require // the addition of the registry information. List<String> RegKeys = new List<string>(); RegKeys = SearchReg( Registry.CurrentUser, @"Software\Microsoft\Windows\CurrentVersion\Group Policy Objects", "SrpV2", RegKeys);
// Process each of the current user entries. foreach (String KeyString in RegKeys) { // Open the base key. RegistryKey Key = Registry.CurrentUser.OpenSubKey(KeyString + @"\Exe", true);
// Create the new rule key. RegistryKey NewRule = Key.CreateSubKey(EntryGuid.ToString());
// Set the value. NewRule.SetValue("Value", TheRule.OuterXml);
// Close the keys. NewRule.Close(); Key.Close(); }
// Clear the old entries. RegKeys.Clear();
// Each user can have special entries, too.
String[] UserList = Registry.Users.GetSubKeyNames();
// Process each of the users in turn. foreach (String User in UserList) RegKeys = SearchReg( Registry.Users, User, "SrpV2", RegKeys);
// Process each of the user entries. foreach (String KeyString in RegKeys) { // Open the base key. RegistryKey Key = Registry.Users.OpenSubKey(KeyString + @"\Exe", true);
// Create the new rule key. RegistryKey NewRule = Key.CreateSubKey(EntryGuid.ToString());
// Set the value. NewRule.SetValue("Value", TheRule.OuterXml);
// Close the keys. NewRule.Close(); Key.Close(); }
// Display a success message. MessageBox.Show("AppLocker Entry Successful!"); }
|
This looks like a lot of code, but the process is repetitive. The code begins by opening the HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\SrpV2 key by calling Registry.LocalMachine.OpenSubKey(). Notice that you must add a second argument, true,
to open the key for writing, or the code will fail. The next step is to
generate a GUID because every AppLocker rule must have a unique
identifier. The code creates the new entry by calling CreateSubKey() with the new GUID found in EntryGuid.
At this point, the example has a new key to use. The next step is to start creating the XML for the value, Value. The code begins by creating a new XmlDocument object, TheRule. It then uses TheRule to create the rule condition. The rule condition contains a Path attribute that includes the application's path information. The condition is encased in a <Conditions> element.
It's time to create the root element, which is a <FilePathRule> element in this case. The <FilePathRule> element contains all the expected attributes, such as Id. After creating all the required attributes, the code adds the <Conditions> element using AppendChild(). Finally, the code adds the <FilePathRule> element to TheRule. Now that the XML is complete, the code creates the Value value and assigns the XML to it using the TheRule.OuterXml property.
The next step is to create an entry for the HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\SrpV2\Exe
key, which only appears on 64-bit systems. This second key is also
always found in the same location. However, now you have to begin
searching for SrpV2 keys that could appear just about anywhere in these areas:
Not every HKEY_USERS subkey will
have the required entry, which makes searching for user entries even
harder. To make this process easier, the code uses SearchReg(), described earlier, to locate keys and place them in a List. A foreach
loop makes the steps for creating the required keys and values easier.
The process for creating the keys and values is the same each time.
After running this part of the example, you must log out and then back
into the system to actually see the results in AppLocker.