2022-07-18 23:59:14 +00:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
2021-07-05 19:02:15 +00:00
# https://raw.githubusercontent.com/SecureAuthCorp/impacket/master/examples/rpcdump.py
2023-03-30 20:36:58 +00:00
from impacket import uuid
2021-07-05 19:02:15 +00:00
from impacket . dcerpc . v5 import transport , epm
2023-05-02 15:17:59 +00:00
from impacket . dcerpc . v5 . rpch import (
RPC_PROXY_INVALID_RPC_PORT_ERR ,
RPC_PROXY_CONN_A1_0X6BA_ERR ,
RPC_PROXY_CONN_A1_404_ERR ,
RPC_PROXY_RPC_OUT_DATA_404_ERR ,
)
2021-07-05 19:02:15 +00:00
KNOWN_PROTOCOLS = {
2023-05-02 15:17:59 +00:00
135 : { " bindstr " : r " ncacn_ip_tcp: %s [135] " } ,
445 : { " bindstr " : r " ncacn_np: %s [ \ pipe \ epmapper] " } ,
2023-03-29 18:19:31 +00:00
}
2021-07-05 19:02:15 +00:00
2023-03-09 23:31:32 +00:00
2023-09-17 20:20:40 +00:00
class NXCModule :
2023-03-29 18:19:31 +00:00
"""
2023-03-30 20:36:58 +00:00
For printnightmare : detect if print spooler is enabled or not . Then use @cube0x0 ' s project https://github.com/cube0x0/CVE-2021-1675 or Mimikatz from Benjamin Delpy
Module by @mpgn_x64
2023-03-29 18:19:31 +00:00
"""
2023-05-02 15:17:59 +00:00
2023-04-04 13:39:54 +00:00
name = " spooler "
description = " Detect if print spooler is enabled or not "
2023-08-30 04:20:21 +00:00
supported_protocols = [ " smb " , " wmi " ]
2023-03-09 23:31:32 +00:00
opsec_safe = True
2021-07-05 19:02:15 +00:00
multiple_hosts = True
2023-04-04 13:39:54 +00:00
def __init__ ( self , context = None , module_options = None ) :
self . context = context
self . module_options = module_options
self . __string_binding = None
self . port = None
2021-07-05 19:02:15 +00:00
def options ( self , context , module_options ) :
2023-04-04 13:39:54 +00:00
"""
PORT Port to check ( defaults to 135 )
"""
2021-07-05 19:02:15 +00:00
self . port = 135
2023-05-02 15:17:59 +00:00
if " PORT " in module_options :
self . port = int ( module_options [ " PORT " ] )
2021-07-05 19:02:15 +00:00
def on_login ( self , context , connection ) :
entries = [ ]
lmhash = getattr ( connection , " lmhash " , " " )
nthash = getattr ( connection , " nthash " , " " )
2023-05-02 15:17:59 +00:00
self . __stringbinding = KNOWN_PROTOCOLS [ self . port ] [ " bindstr " ] % connection . host
context . log . debug ( " StringBinding %s " % self . __stringbinding )
2021-07-05 19:02:15 +00:00
rpctransport = transport . DCERPCTransportFactory ( self . __stringbinding )
2023-05-08 18:39:36 +00:00
rpctransport . set_credentials ( connection . username , connection . password , connection . domain , lmhash , nthash )
rpctransport . setRemoteHost ( connection . host if not connection . kerberos else connection . hostname + " . " + connection . domain )
2021-07-05 19:02:15 +00:00
rpctransport . set_dport ( self . port )
2023-04-07 14:49:39 +00:00
if connection . kerberos :
rpctransport . set_kerberos ( connection . kerberos , connection . kdcHost )
2021-07-05 19:02:15 +00:00
try :
2023-04-07 16:37:18 +00:00
entries = self . __fetch_list ( rpctransport )
2021-07-05 19:02:15 +00:00
except Exception as e :
2023-05-02 15:17:59 +00:00
error_text = " Protocol failed: %s " % e
2023-03-29 18:19:31 +00:00
context . log . critical ( error_text )
2021-07-05 19:02:15 +00:00
2023-05-08 18:39:36 +00:00
if RPC_PROXY_INVALID_RPC_PORT_ERR in error_text or RPC_PROXY_RPC_OUT_DATA_404_ERR in error_text or RPC_PROXY_CONN_A1_404_ERR in error_text or RPC_PROXY_CONN_A1_0X6BA_ERR in error_text :
context . log . critical ( " This usually means the target does not allow " " to connect to its epmapper using RpcProxy. " )
2021-07-05 19:02:15 +00:00
return
# Display results.
endpoints = { }
2023-03-09 23:31:32 +00:00
# Let's group the UUIDS
2021-07-05 19:02:15 +00:00
for entry in entries :
2023-05-02 15:17:59 +00:00
binding = epm . PrintStringBinding ( entry [ " tower " ] [ " Floors " ] )
tmp_uuid = str ( entry [ " tower " ] [ " Floors " ] [ 0 ] )
2023-04-04 13:39:54 +00:00
if ( tmp_uuid in endpoints ) is not True :
endpoints [ tmp_uuid ] = { }
2023-05-02 15:17:59 +00:00
endpoints [ tmp_uuid ] [ " Bindings " ] = list ( )
2023-05-08 18:39:36 +00:00
if uuid . uuidtup_to_bin ( uuid . string_to_uuidtup ( tmp_uuid ) ) [ : 18 ] in epm . KNOWN_UUIDS :
endpoints [ tmp_uuid ] [ " EXE " ] = epm . KNOWN_UUIDS [ uuid . uuidtup_to_bin ( uuid . string_to_uuidtup ( tmp_uuid ) ) [ : 18 ] ]
2021-07-05 19:02:15 +00:00
else :
2023-05-02 15:17:59 +00:00
endpoints [ tmp_uuid ] [ " EXE " ] = " N/A "
endpoints [ tmp_uuid ] [ " annotation " ] = entry [ " annotation " ] [ : - 1 ] . decode ( " utf-8 " )
endpoints [ tmp_uuid ] [ " Bindings " ] . append ( binding )
2021-07-05 19:02:15 +00:00
2023-04-04 13:39:54 +00:00
if tmp_uuid [ : 36 ] in epm . KNOWN_PROTOCOLS :
2023-05-02 15:17:59 +00:00
endpoints [ tmp_uuid ] [ " Protocol " ] = epm . KNOWN_PROTOCOLS [ tmp_uuid [ : 36 ] ]
2021-07-05 19:02:15 +00:00
else :
2023-05-02 15:17:59 +00:00
endpoints [ tmp_uuid ] [ " Protocol " ] = " N/A "
2021-07-05 19:02:15 +00:00
for endpoint in list ( endpoints . keys ( ) ) :
2023-05-02 15:17:59 +00:00
if " MS-RPRN " in endpoints [ endpoint ] [ " Protocol " ] :
context . log . debug ( " Protocol: %s " % endpoints [ endpoint ] [ " Protocol " ] )
context . log . debug ( " Provider: %s " % endpoints [ endpoint ] [ " EXE " ] )
2023-05-08 18:39:36 +00:00
context . log . debug ( " UUID : %s %s " % ( endpoint , endpoints [ endpoint ] [ " annotation " ] ) )
2023-03-29 18:19:31 +00:00
context . log . debug ( " Bindings: " )
2023-05-02 15:17:59 +00:00
for binding in endpoints [ endpoint ] [ " Bindings " ] :
2023-03-29 18:19:31 +00:00
context . log . debug ( " %s " % binding )
context . log . debug ( " " )
2023-05-02 15:17:59 +00:00
context . log . highlight ( " Spooler service enabled " )
2023-03-09 23:38:42 +00:00
try :
2023-03-12 02:25:23 +00:00
host = context . db . get_hosts ( connection . host ) [ 0 ]
2023-05-02 15:17:59 +00:00
context . db . add_host (
host . ip ,
host . hostname ,
host . domain ,
host . os ,
host . smbv1 ,
host . signing ,
spooler = True ,
)
2023-03-09 23:38:42 +00:00
except Exception as e :
2023-03-29 18:19:31 +00:00
context . log . debug ( f " Error updating spooler status in database " )
2021-07-05 19:02:15 +00:00
break
if entries :
num = len ( entries )
if 1 == num :
2023-03-29 18:19:31 +00:00
context . log . debug ( f " [Spooler] Received one endpoint " )
2021-07-05 19:02:15 +00:00
else :
2023-03-29 18:19:31 +00:00
context . log . debug ( f " [Spooler] Received { num } endpoints " )
2021-07-05 19:02:15 +00:00
else :
2023-03-29 18:19:31 +00:00
context . log . debug ( f " [Spooler] No endpoints found " )
2021-07-05 19:02:15 +00:00
2023-04-04 13:39:54 +00:00
def __fetch_list ( self , rpctransport ) :
2021-07-05 19:02:15 +00:00
dce = rpctransport . get_dce_rpc ( )
dce . connect ( )
resp = epm . hept_lookup ( None , dce = dce )
dce . disconnect ( )
return resp