Not Your Grandfather’s Empire I’ve wanted to put this blog together since returning home from DEFCON. Anytime we ran into someone who recognized our swag, they mentioned how much they loved Empire back in the day and didn’t realize it was being actively maintained. This made me reflect on all [...]
Forget about feeling overwhelmed with a mess of data. With tags in Starkiller, you have more control over keeping everything organized. You can assign tags to various objects – Listeners, Agents, Agent Tasks, Plugin Tasks, Downloads, and Credentials. This means you can categorize and organize your engagements in a way that makes sense to you.
Tags are for you. Come up with your own system of organizing and color-coding your engagement data. Tags help you quickly identify and access the information you need without any hassle. When writing your reports, make tracking down key moments of your engagement easier by tagging the important agent tasks.
Tags are for your team. Use tags to communicate metadata about an object to your team, such as adding a tag to a credential indicating that it’s been successfully used. By assigning relevant tags to shared objects, you can make sure your whole team is on the same page. Everyone can easily find and work with the resources they need. Most of the objects that support tagging also support using those tags as filters on their data table pages.
Tags are for plugins. Do you have a custom plugin that executes tasks on agents automatically? Have it add a tag to those tasks to indicate where they came from to create clear associations and context. Have a plugin that should only execute on a set number of agents? Add a hook to the tag creation event for a new way to trigger plugins. Creating and updating tags trigger an event that plugins can listen to.
Let’s look at a very simple example plugin. We will call it the Preplanned Task Plugin for lack of a better name. This plugin will work based on the “hooks” feature added to Empire. See the Empire Wiki for more info on how that works.
This is the most basic code needed to execute our plugin. We will leave the execute function empty because we don’t actually need to manually trigger anything. It will all be based on the events. In the onLoad block, we register our hook function for the AFTER_TAG_CREATED event. When a tag gets created, we will log a message.
import logging
from empire.server.common.empire import MainMenu
from empire.server.common.plugins import Plugin
from empire.server.core.hooks import hooks
log = logging.getLogger(__name__)
class Plugin(Plugin):
def onLoad(self):
self.info = {
"Name": "preplanned_tasks",
# List of one or more authors for the plugin
"Authors": [
{
"Name": "Vince Rose",
"Handle": "@vinnybod",
"Link": "https://github.com/vinnybod",
}
],
"Description": (""),
"Software": "SXXXX",
"Techniques": ["TXXXX", "TXXXX"],
"Comments": [],
}
self.options = {}
hooks.register_hook(hooks.AFTER_TAG_CREATED_HOOK, 'preplanned_tasks', self.tag_created)
def register(self, mainMenu):
self.installPath = mainMenu.installPath
self.main_menu: MainMenu = mainMenu
def tag_created(self, db, tag, taggable):
taggable_type = type(taggable).__name__
log.info(f"Tag created: {tag.name}:{tag.value} on {taggable_type}")
def execute(self, command):
return True
def shutdown(self):
pass
Okay, now let’s enhance this a bit. When the tag event occurs on an agent, let’s execute a couple of tasks. We will execute pwd & whoami commands and a module.
def register(self, mainMenu):
self.installPath = mainMenu.installPath
self.main_menu: MainMenu = mainMenu
self.agent_task_service: AgentTaskService = self.main_menu.agenttasksv2
self.module_service: ModuleService = self.main_menu.modulesv2
def tag_created(self, db, tag, taggable):
taggable_type = type(taggable).__name__
log.info(f"Tag created: {tag.name}:{tag.value} on {taggable_type}")
if not isinstance(taggable, models.Agent):
return
log.info(f"Tag is on an agent: {taggable.name}")
if not tag.name == "preplanned_task":
return
log.info(f"Tag is a preplanned task: {tag.value}")
self.agent_task_service.create_task_shell(db, taggable, 'pwd')
self.agent_task_service.create_task_shell(db, taggable, 'whoami')
if 'windows' in taggable.os_details.lower():
module_req = ModulePostRequest(
module_id='powershell_collection_prompt',
options={'MsgTxt': 'Lost contact with the Domain Controller.'}
)
self.agent_task_service.create_task_module(db, taggable, module_req)
Since these tasks are generated by the plugin and not a human operator, let’s make that more clear by adding a tag to each of these tasks.
def register(self, mainMenu):
self.installPath = mainMenu.installPath
self.main_menu: MainMenu = mainMenu
self.agent_task_service: AgentTaskService = self.main_menu.agenttasksv2
self.module_service: ModuleService = self.main_menu.modulesv2
self.tag_service: TagService = self.main_menu.tagsv2
def tag_created(self, db, tag, taggable):
taggable_type = type(taggable).__name__
log.info(f"Tag created: {tag.name}:{tag.value} on {taggable_type}")
if not isinstance(taggable, models.Agent):
return
log.info(f"Tag is on an agent: {taggable.name}")
if not tag.name == "preplanned_task":
return
log.info(f"Tag is a preplanned task: {tag.value}")
tag_req = TagRequest(name='plugin', value='preplanned')
task, _ = self.agent_task_service.create_task_shell(db, taggable, 'pwd')
self.tag_service.add_tag(db, task, tag_req)
task, _ = self.agent_task_service.create_task_shell(db, taggable, 'whoami')
self.tag_service.add_tag(db, task, tag_req)
if 'windows' in taggable.os_details.lower():
plugin_task.output += f"Agent {taggable.name} is a windows agent\n"
module_req = ModulePostRequest(
module_id='powershell_collection_prompt',
options={'MsgTxt': 'Lost contact with the Domain Controller.'}
)
task, _ = self.agent_task_service.create_task_module(db, taggable, module_req, user_id=1)
self.tag_service.add_tag(db, task, tag_req)
This is looking pretty good. Let’s add one more thing. Empire 5.2 added “Plugin Tasks”. This means that plugins have their own tasks that we can go back and look at. We will create a Plugin Task any time this plugin is triggered and executed.
def tag_created(self, db, tag, taggable):
taggable_type = type(taggable).__name__
log.info(f"Tag created: {tag.name}:{tag.value} on {taggable_type}")
if not isinstance(taggable, models.Agent):
return
log.info(f"Tag is on an agent: {taggable.name}")
if not tag.name == "preplanned_task":
return
log.info(f"Tag is a preplanned task: {tag.value}")
plugin_task = models.PluginTask(
plugin_id='preplanned_tasks',
input=f'Executing preplanned task plugin on agent {taggable.name}',
input_full=f'Executing preplanned task plugin on agent {taggable.name}',
output = '',
status=PluginTaskStatus.completed
)
tag_req = TagRequest(name='plugin', value='preplanned')
task, _ = self.agent_task_service.create_task_shell(db, taggable, 'pwd')
self.tag_service.add_tag(db, task, tag_req)
plugin_task.output += f"Executed pwd on agent {taggable.name}\n"
task, _ = self.agent_task_service.create_task_shell(db, taggable, 'whoami')
self.tag_service.add_tag(db, task, tag_req)
plugin_task.output += f"Executed whoami on agent {taggable.name}\n"
if 'windows' in taggable.os_details.lower():
plugin_task.output += f"Agent {taggable.name} is a windows agent\n"
module_req = ModulePostRequest(
module_id='powershell_collection_prompt',
options={'MsgTxt': 'Lost contact with the Domain Controller.'}
)
task, _ = self.agent_task_service.create_task_module(db, taggable, module_req)
self.tag_service.add_tag(db, task, tag_req)
plugin_task.output += f"Executed powershell_collection_prompt on agent {taggable.name}\n"
db.add(plugin_task)
So there you have it! Starkiller’s tagging feature is here to help get your data organized and to enhance the possibilities of plugins and automation. If you’d like to learn about using Empire and Starkiller for Adversary Emulation, then check out our Advanced Threat Emulation: Red Teams course at Blackhat.
In cybersecurity, techniques evolve rapidly as defenders and attackers adapt to the ever-changing landscape. This article will explore an exemplary example of this evolution in transitioning from Domain Fronting to ...