Skip to content

Commit

Permalink
Added remove stale agents and remove/kill all agents to CLI (#46)
Browse files Browse the repository at this point in the history
* added remove stale agents and all agents to CLI

* combined kill/remove and removed deleting agents from the database

* added killed flag to stale agents

* updated remove_stale agents into kill command

* deleted remove_stale_agents

* misc fixes
  • Loading branch information
Cx01N authored Mar 7, 2021
1 parent ef5711e commit f5d4198
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 37 deletions.
1 change: 1 addition & 0 deletions changelog
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ X/XX/2021
- Integrated server and client into Empire (@Cx01N, @Vinnybod)
- Added new launch parameters for starting server/client (@Cx01N, @Vinnybod)
- Removed old Empire CLI and cmdloop from server (@Cx01N)
- Simplified kill/remove commands and added 'all' and 'stale' options (@Cx01N)

2/5/2021
------------
Expand Down
7 changes: 7 additions & 0 deletions empire/client/src/EmpireCliState.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ def remove_agent(self, agent_name: str):

return json.loads(response.content)

def remove_stale_agents(self):
response = requests.delete(url=f'{self.host}:{self.port}/api/agents/stale',
verify=False,
params={'token': self.token})

return json.loads(response.content)

def update_agent_comms(self, agent_name: str, listener_name: str):
response = requests.put(url=f'{self.host}:{self.port}/api/agents/{agent_name}/update_comms',
json={'listener': listener_name},
Expand Down
55 changes: 34 additions & 21 deletions empire/client/src/menus/AgentMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ def autocomplete(self):
return self._cmd_registry + super().autocomplete()

def get_completions(self, document, complete_event, cmd_line, word_before_cursor):
if cmd_line[0] in ['kill', 'clear', 'rename'] and position_util(cmd_line, 2, word_before_cursor):
if cmd_line[0] in ['kill'] and position_util(cmd_line, 2, word_before_cursor):
for agent in filtered_search_list(word_before_cursor, state.agents.keys()):
yield Completion(agent, start_position=-len(word_before_cursor))
yield Completion('all', start_position=-len(word_before_cursor))
yield Completion('stale', start_position=-len(word_before_cursor))
elif cmd_line[0] in ['clear', 'rename'] and position_util(cmd_line, 2, word_before_cursor):
for agent in filtered_search_list(word_before_cursor, state.agents.keys()):
yield Completion(agent, start_position=-len(word_before_cursor))
elif position_util(cmd_line, 1, word_before_cursor):
Expand Down Expand Up @@ -51,16 +56,24 @@ def list(self) -> None:
table_util.print_agent_table(agent_list, agent_formatting, 'Agents')

@command
def kill(self, agent_name: string) -> None:
def kill(self, agent_name: str) -> None:
"""
Kill the selected listener
Kills and removes specified agent [agent_name, stale, or all].
Usage: kill <agent_name>
"""
state.kill_agent(agent_name)
if agent_name == 'all':
for agent_name in state.get_agents().keys():
self.kill_agent(agent_name)
elif agent_name == 'stale':
for agent_name, agent in state.get_agents().items():
if agent['stale'] == True:
self.kill_agent(agent_name)
else:
self.kill_agent(agent_name)

@command
def clear(self, agent_name: string) -> None:
def clear(self, agent_name: str) -> None:
"""
Clear tasks for selected listener
Expand All @@ -69,29 +82,29 @@ def clear(self, agent_name: string) -> None:
state.clear_agent(agent_name)

@command
def remove(self, agent_name: string) -> None:
"""
Removes an agent from the controller specified by agent_name. Doesn't kill the agent first.
Usage: remove <agent_name>
"""
response = state.remove_agent(agent_name)
if 'success' in response.keys():
print(print_util.color('[*] Removed agent ' + agent_name))
elif 'error' in response.keys():
print(print_util.color('[!] Error: ' + response['error']))

@command
def rename(self, agent_name: string, new_agent_name: string) -> None:
def rename(self, agent_name: str, new_agent_name: str) -> None:
"""
Rename selected listener
Usage: rename <agent_name> <new_agent_name>
"""
state.rename_agent(agent_name, new_agent_name)


def trunc(value: string = '', limit: int = 1) -> string:
@staticmethod
def kill_agent(agent_name: str) -> None:
kill_response = state.kill_agent(agent_name)
if 'success' in kill_response.keys():
print(print_util.color('[*] Kill command sent to agent ' + agent_name))
remove_response = state.remove_agent(agent_name)
if 'success' in remove_response.keys():
print(print_util.color('[*] Removed agent ' + agent_name + ' from list'))
elif 'error' in remove_response.keys():
print(print_util.color('[!] Error: ' + remove_response['error']))
elif 'error' in kill_response.keys():
print(print_util.color('[!] Error: ' + kill_response['error']))


def trunc(value: str = '', limit: int = 1) -> str:
if value:
if len(value) > limit:
return value[:limit - 2] + '..'
Expand Down
4 changes: 2 additions & 2 deletions empire/client/src/menus/ListenerMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def list(self) -> None:
table_util.print_table(listener_list, 'Listeners List')

@command
def options(self, listener_name: string) -> None:
def options(self, listener_name: str) -> None:
"""
Get option details for the selected listener
Expand All @@ -63,7 +63,7 @@ def options(self, listener_name: string) -> None:
table_util.print_table(listener_list, listener_name)

@command
def kill(self, listener_name: string) -> None:
def kill(self, listener_name: str) -> None:
"""
Kill the selected listener
Expand Down
2 changes: 1 addition & 1 deletion empire/client/src/menus/UseStagerMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def on_enter(self, **kwargs) -> bool:
self.options()
return True

def use(self, module: string) -> None:
def use(self, module: str) -> None:
"""
Use the selected stager.
Expand Down
12 changes: 6 additions & 6 deletions empire/server/common/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ def add_agent(self, sessionID, externalIP, delay, jitter, profile, killDate, wor
working_hours=workingHours,
lost_limit=lostLimit,
listener=listener,
language=language
language=language,
killed=False,
))
Session().commit()

Expand Down Expand Up @@ -1680,20 +1681,19 @@ def process_agent_packet(self, session_id, response_name, task_id, data):
dispatcher.send(signal, sender="agents/{}".format(session_id))

# update the agent results and log
# self.update_agent_results(sessionID, data)
self.save_agent_log(session_id, data)

# remove this agent from the cache/database
self.remove_agent_db(session_id)

# set agent to killed in the database
agent = Session().query(models.Agent).filter(models.Agent.session_id == session_id).first()
agent.killed = True
Session().commit()

elif response_name == "TASK_SHELL":
# shell command response
self.update_agent_results_db(session_id, data)
# update the agent log
self.save_agent_log(session_id, data)


elif response_name == "TASK_DOWNLOAD":
# file download
if isinstance(data, bytes):
Expand Down
1 change: 1 addition & 0 deletions empire/server/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class Agent(Base):
taskings = Column(String(255)) # Queue of tasks. Should refactor to manage queued tasks from the taskings table itself.
results = Column(String(255))
notes = Column(Text)
killed = Column(Boolean, nullable=False)

@hybrid_property # todo @stale.expression
def stale(self):
Expand Down
12 changes: 5 additions & 7 deletions empire/server/empire.py
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ def get_agents():
"""
Returns JSON describing all currently registered agents.
"""
active_agents_raw = Session().query(models.Agent).all()
active_agents_raw = Session().query(models.Agent).filter(models.Agent.killed == False).all()
agents = []

for active_agent in active_agents_raw:
Expand Down Expand Up @@ -820,16 +820,15 @@ def get_agents_stale():
@app.route('/api/agents/stale', methods=['DELETE'])
def remove_stale_agent():
"""
Removes stale agents from the controller.
Removes all stale agents from the controller.
WARNING: doesn't kill the agent first! Ensure the agent is dead.
"""
agents_raw = Session().query(models.Agent).all()

for agent in agents_raw:

if agent.stale:
Session().delete(agent)
agent.killed = True
Session().commit()

return jsonify({'success': True})
Expand All @@ -841,12 +840,12 @@ def remove_agent(agent_name):
WARNING: doesn't kill the agent first! Ensure the agent is dead.
"""
agent = main.agents.get_agent_from_name_or_session_id(agent_name)
agent = Session().query(models.Agent).filter(models.Agent.name == agent_name).first()

if not agent:
return make_response(jsonify({'error': 'agent name %s not found' % agent_name}), 404)

Session().delete(agent)
agent.killed = True
Session().commit()

return jsonify({'success': True})
Expand Down Expand Up @@ -1829,7 +1828,6 @@ def thread_websocket(empire_menu, suppress=False):
except SystemExit as e:
pass


def thread_api(empire_menu):
try:
start_restful_api(empireMenu=empire_menu, suppress=True, username=args.username, password=args.password,
Expand Down

0 comments on commit f5d4198

Please sign in to comment.