mirror of
https://github.com/Pennyw0rth/NetExec
synced 2026-06-06 16:34:30 +00:00
111 lines
4.6 KiB
Python
111 lines
4.6 KiB
Python
from impacket.dcerpc.v5 import transport, epm
|
|
from impacket.http import AUTH_NTLM
|
|
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
|
|
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
|
|
from impacket import uuid
|
|
import requests
|
|
from nxc.helpers.misc import CATEGORY
|
|
|
|
|
|
class NXCModule:
|
|
"""
|
|
-------
|
|
Module by @0xjbb, original code from Impacket rpcdump.py
|
|
"""
|
|
KNOWN_PROTOCOLS = {
|
|
135: {"bindstr": r"ncacn_ip_tcp:%s[135]"},
|
|
139: {"bindstr": r"ncacn_np:%s[\pipe\epmapper]"},
|
|
443: {"bindstr": r"ncacn_http:[593,RpcProxy=%s:443]"},
|
|
445: {"bindstr": r"ncacn_np:%s[\pipe\epmapper]"},
|
|
593: {"bindstr": r"ncacn_http:%s"}
|
|
}
|
|
|
|
name = "enum_ca"
|
|
description = "Anonymously uses RPC endpoints to hunt for ADCS CAs"
|
|
supported_protocols = ["smb"]
|
|
category = CATEGORY.ENUMERATION
|
|
|
|
def __init__(self, context=None, module_options=None):
|
|
self.context = context
|
|
self.module_options = module_options
|
|
|
|
def options(self, context, module_options):
|
|
"""No options available"""
|
|
|
|
def on_login(self, context, connection):
|
|
self.__username = connection.username
|
|
self.__password = connection.password
|
|
self.__domain = connection.domain
|
|
self.__lmhash = ""
|
|
self.__nthash = ""
|
|
self.__port = 135.
|
|
self.__stringbinding = ""
|
|
|
|
if context.hash and ":" in context.hash[0]:
|
|
hashList = context.hash[0].split(":")
|
|
self.__nthash = hashList[-1]
|
|
self.__lmhash = hashList[0]
|
|
elif context.hash and ":" not in context.hash[0]:
|
|
self.__nthash = context.hash[0]
|
|
self.__lmhash = "00000000000000000000000000000000"
|
|
|
|
self.__stringbinding = self.KNOWN_PROTOCOLS[self.__port]["bindstr"] % connection.host
|
|
context.log.debug(f"StringBinding {self.__stringbinding}")
|
|
|
|
rpctransport = transport.DCERPCTransportFactory(self.__stringbinding)
|
|
|
|
if self.__port in [139, 445]:
|
|
# Setting credentials for SMB
|
|
rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
|
|
rpctransport.setRemoteHost(connection.host)
|
|
rpctransport.set_dport(self.__port)
|
|
elif self.__port == 443:
|
|
# Setting credentials only for RPC Proxy, but not for the MSRPC level
|
|
rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
|
|
rpctransport.set_auth_type(AUTH_NTLM)
|
|
else:
|
|
rpctransport.setRemoteHost(connection.host)
|
|
|
|
try:
|
|
entries = self.__fetchList(connection.kerberos, rpctransport)
|
|
except Exception as e:
|
|
error_text = f"Protocol failed: {e}"
|
|
context.log.fail(error_text)
|
|
|
|
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.fail("This usually means the target does not allow "
|
|
"to connect to its epmapper using RpcProxy.")
|
|
return
|
|
|
|
for entry in entries:
|
|
tmpUUID = str(entry["tower"]["Floors"][0])
|
|
|
|
if uuid.uuidtup_to_bin(uuid.string_to_uuidtup(tmpUUID))[:18] in epm.KNOWN_UUIDS:
|
|
exename = epm.KNOWN_UUIDS[uuid.uuidtup_to_bin(uuid.string_to_uuidtup(tmpUUID))[:18]]
|
|
context.log.debug(f"EXEs {exename}")
|
|
if exename == "certsrv.exe":
|
|
context.log.highlight("Active Directory Certificate Services Found.")
|
|
url = f"http://{connection.host}/certsrv/certfnsh.asp"
|
|
context.log.highlight(url)
|
|
try:
|
|
response = requests.get(url, timeout=5)
|
|
if response.status_code == 401 and "WWW-Authenticate" in response.headers and "ntlm" in response.headers["WWW-Authenticate"].lower():
|
|
context.log.highlight("Web enrollment found on HTTP (ESC8).")
|
|
except requests.RequestException as e:
|
|
context.log.debug(e)
|
|
return
|
|
|
|
def __fetchList(self, doKerberos, rpctransport):
|
|
dce = rpctransport.get_dce_rpc()
|
|
if doKerberos:
|
|
dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
|
|
dce.connect()
|
|
resp = epm.hept_lookup(None, dce=dce)
|
|
dce.disconnect()
|
|
return resp
|