Skip to content

Commit

Permalink
Merge pull request #596 from BC-SECURITY/release/v4.7.1
Browse files Browse the repository at this point in the history
v4.7.1 into master
  • Loading branch information
vinnybod committed Aug 2, 2022
2 parents 95019ab + 2b0a736 commit 48afaac
Show file tree
Hide file tree
Showing 34 changed files with 1,027 additions and 683 deletions.
3 changes: 3 additions & 0 deletions .github/ci-and-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ Once the first workflow runs, it will open two pull requests from the `release/v

Merge the two pull requests. **DO NOT SQUASH**

**Note**: If at this point there are additional changes for the release, merge them into the release branch, not
the `sponsors-master` or `sponsors-dev` branch. This will ensure the change ends up in the release properly.

### 4. Tag and Release
Once the pull requests are merged, run the `Sponsors - Tag Release` workflow on the `sponsors-master` branch.
The workflow will create a tag and release on the `HEAD` of `sponsors-master`, using the release notes from `CHANGELOG.md` for the body of the release.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
name: Test Python ${{ matrix.python-version }}
strategy:
matrix:
python-version: [ '3.8', '3.9' ]
python-version: [ '3.8', '3.9', '3.10' ]
steps:
- uses: actions/checkout@v2
with:
Expand Down
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@
[submodule "empire/server/csharp/Covenant/Data/ReferenceSourceLibraries/Certify"]
path = empire/server/csharp/Covenant/Data/ReferenceSourceLibraries/Certify
url = https://github.com/GhostPack/Certify.git
[submodule "empire/server/plugins/SocksProxyServer-Plugin"]
path = empire/server/plugins/SocksProxyServer-Plugin
url = https://github.com/BC-SECURITY/SocksProxyServer-Plugin.git
[submodule "empire/server/plugins/ChiselServer-Plugin"]
path = empire/server/plugins/ChiselServer-Plugin
url = https://github.com/BC-SECURITY/ChiselServer-Plugin.git
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/psf/black
rev: 22.1.0
rev: 22.3.0
hooks:
- id: black
language_version: python3.9
Expand Down
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [4.7.1] - 2022-07-29
- Fix write_dllhijacker.yaml script_path reference (@kevNii)

## [4.7.0] - 2022-06-25

- Update Python version on Dockerfile (@Vinnybod)
- Add Python 3.10 to CI tests (@Vinnybod)
- Add a resource file command to the client (@Vinnybod)
- Add PowerShell and C# to IronPython modules (@Cx01N)
- Add ChiselServer, SocksProxyServer plugin as a submodule (@Cx01N)
- Fixed Sharpire download function (@Cx01N)
- Fixed spawnas to work with new bat file format (@Cx01N)
- Fixed tasking error for IronPython launcher executable (@Cx01N)
- Remove some python dependencies (@Vinnybod)
- Make tkinter import failure a warning instead of a fatal error (@Vinnybod)

## [4.6.1] - 2022-06-10

- Use a BC-Security fork of Donut to resolve a python 3.10 issue (@Cx01N)
- Update reflective pick dlls (@Hubbl3)

Expand Down Expand Up @@ -265,7 +282,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated shellcoderdi to newest version (@Cx01N)
- Added a Nim launcher (@Hubbl3)

[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v4.6.1...HEAD
[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v4.7.1...HEAD

[4.7.1]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v4.7.0...v4.7.1

[4.7.0]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v4.6.1...v4.7.0

[4.6.1]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v4.6.0...v4.6.1

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# -----BUILD ENTRY-----

# image base
FROM python:3.9.9-buster
FROM python:3.9.13-buster

# extra metadata
LABEL maintainer="bc-security"
Expand Down
1 change: 0 additions & 1 deletion VERSION

This file was deleted.

81 changes: 60 additions & 21 deletions empire/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import sys
import threading
import time
from pathlib import Path
from typing import Dict, List, Optional, get_type_hints

import urllib3
from docopt import docopt
from prompt_toolkit import HTML, PromptSession
from prompt_toolkit.completion import Completer
from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.history import InMemoryHistory
from prompt_toolkit.patch_stdout import patch_stdout

Expand Down Expand Up @@ -37,6 +38,10 @@
from empire.client.src.MenuState import menu_state
from empire.client.src.ShortcutHandler import shortcut_handler
from empire.client.src.utils import file_util, print_util
from empire.client.src.utils.autocomplete_util import (
current_files,
filtered_search_list,
)


class MyCustomCompleter(Completer):
Expand Down Expand Up @@ -84,6 +89,20 @@ def get_completions(self, document, complete_event):
yield from self.empire_cli.menus["UseCredentialMenu"].get_completions(
document, complete_event, cmd_line, word_before_cursor
)
elif cmd_line[0] in ["resource"]:
if len(cmd_line) > 1 and cmd_line[1] == "-p":
file = state.search_files()
if file:
yield Completion(file, start_position=-len(word_before_cursor))
else:
for files in filtered_search_list(
word_before_cursor, current_files(state.directory["downloads"])
):
yield Completion(
files,
display=files.split("/")[-1],
start_position=-len(word_before_cursor),
)
else:
# Menu specific commands
yield from menu_state.current_menu.get_completions(
Expand Down Expand Up @@ -148,6 +167,32 @@ def update_in_bg(session: PromptSession):
session.message = HTML(menu_state.current_menu.get_prompt())
session.app.invalidate()

def run_resource_file(self, session, resource):
file_path = Path(resource)
if not file_path.exists():
print(print_util.color(f"[!] File {file_path.name} does not exist."))
return

with file_path.open() as resource_file:
print(print_util.color(f"[*] Executing Resource File: {file_path.name}"))
for cmd in resource_file:
with patch_stdout(raw=True):
try:
time.sleep(1)
text = session.prompt(accept_default=True, default=cmd.strip())
cmd_line = list(shlex.split(text))
self.parse_command_line(text, cmd_line, resource_file=True)
except CliExitException:
return
except Exception as e:
print(
print_util.color(
f"[*] Error parsing resource command: ", text
)
)

print(print_util.color(f"[*] Finished executing resource file: {resource}"))

def main(self):
if empire_config.yaml.get("suppress-self-cert-warning", True):
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
Expand Down Expand Up @@ -189,25 +234,7 @@ def main(self):
self.menus["MainMenu"].connect(autoserver, config=True)

if args.resource:
with open(args.resource) as resource_file:
print(print_util.color(f"[*] Executing Resource File: {args.resource}"))
for cmd in resource_file:
with patch_stdout(raw=True):
try:
time.sleep(1)
text = session.prompt(
accept_default=True, default=cmd.strip()
)
cmd_line = list(shlex.split(text))
self.parse_command_line(text, cmd_line, resource_file=True)
except CliExitException:
return
except Exception as e:
print(
print_util.color(
f"[*] Error parsing resource command: ", text
)
)
self.run_resource_file(session, args.resource)

while True:
try:
Expand All @@ -216,9 +243,21 @@ def main(self):
HTML(menu_state.current_menu.get_prompt()),
refresh_interval=None,
)

cmd_line = list(shlex.split(text))

if cmd_line[0] == "resource":
if len(cmd_line) == 1:
print(
print_util.color(
"[!] You must specify a resource file."
)
)
else:
self.run_resource_file(session, cmd_line[1])

# cmd_line = list(map(lambda s: s.lower(), shlex.split(text)))
# TODO what to do about case sensitivity for parsing options.
cmd_line = list(shlex.split(text))
self.parse_command_line(text, cmd_line)
except KeyboardInterrupt:
print(print_util.color("[!] Type exit to quit"))
Expand Down
32 changes: 24 additions & 8 deletions empire/client/src/EmpireCliState.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
import base64
import os
from tkinter import *
from tkinter import filedialog
from typing import Dict, Optional

import requests
import socketio
from prompt_toolkit import ANSI, HTML

from empire.client.src.EmpireCliConfig import empire_config
from empire.client.src.menus import Menu
from empire.client.src.MenuState import menu_state
from empire.client.src.utils import print_util

try:
from tkinter import Tk, filedialog
except ImportError:
Tk = None
filedialog = None
print(
print_util.color(
"[!] Failed to load tkinter. Please install tkinter to use the file prompts."
)
)
print(
print_util.color(
"[!] Check the wiki for more information: https://bc-security.gitbook.io/empire-wiki/quickstart/installation#modulenotfounderror-no-module-named-_tkinter"
)
)
pass


class EmpireCliState(object):
def __init__(self):
Expand Down Expand Up @@ -253,10 +266,13 @@ def search_files(self):
"""
Find a file and return filename.
"""
tk = Tk()
tk.withdraw()
file_directory = filedialog.askopenfilename(title="Select file")
return file_directory
if filedialog and Tk:
tk = Tk()
tk.withdraw()
file_directory = filedialog.askopenfilename(title="Select file")
return file_directory
else:
return None

def get_directories(self):
"""
Expand Down
6 changes: 3 additions & 3 deletions empire/client/src/menus/AdminMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ def get_completions(self, document, complete_event, cmd_line, word_before_cursor
cmd_line, 2, word_before_cursor
):
if len(cmd_line) > 1 and cmd_line[1] == "-p":
yield Completion(
state.search_files(), start_position=-len(word_before_cursor)
)
file = state.search_files()
if file:
yield Completion(file, start_position=-len(word_before_cursor))
else:
for files in filtered_search_list(
word_before_cursor, current_files(state.directory["downloads"])
Expand Down
6 changes: 3 additions & 3 deletions empire/client/src/menus/InteractMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ def get_completions(self, document, complete_event, cmd_line, word_before_cursor
)
elif cmd_line[0] in ["upload", "script_import"]:
if len(cmd_line) > 1 and cmd_line[1] == "-p":
yield Completion(
state.search_files(), start_position=-len(word_before_cursor)
)
file = state.search_files()
if file:
yield Completion(file, start_position=-len(word_before_cursor))
else:
for files in filtered_search_list(
word_before_cursor, current_files(state.directory["downloads"])
Expand Down
7 changes: 7 additions & 0 deletions empire/client/src/menus/MainMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ def help(self):
["interact", "Interact with active agents.", "interact <agent_name>"]
)
help_list.append(["sponsors", "List of Empire sponsors.", "sponsors"])
help_list.append(
[
"resource",
"Run the Empire commands in the specified resource file. Provide the -p flag for a file selection prompt.",
"resource <file>",
]
)

help_list.sort()
help_list.insert(0, ["Name", "Description", "Usage"])
Expand Down
1 change: 1 addition & 0 deletions empire/client/src/menus/Menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def autocomplete(self):
"listeners",
"main",
"plugins",
"resource",
"sponsors",
"uselistener",
"usemodule",
Expand Down
6 changes: 3 additions & 3 deletions empire/client/src/menus/UseMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ def get_completions(self, document, complete_event, cmd_line, word_before_cursor
yield Completion(agent, start_position=-len(word_before_cursor))
if len(cmd_line) > 1 and cmd_line[1] == "file":
if len(cmd_line) > 2 and cmd_line[2] == "-p":
yield Completion(
state.search_files(), start_position=-len(word_before_cursor)
)
file = state.search_files()
if file:
yield Completion(file, start_position=-len(word_before_cursor))
else:
for files in filtered_search_list(
word_before_cursor, current_files(state.directory["downloads"])
Expand Down
6 changes: 6 additions & 0 deletions empire/client/src/utils/print_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ def title(version, modules, listeners, agents):
print(
"========================================================================================"
)
print(
" [\x1b[1;32mDocumentation\x1b[0m] | [Web] https://bc-security.gitbook.io/empire-wiki/"
)
print(
"========================================================================================"
)
print(
"""
_______ ___ ___ ______ __ ______ _______
Expand Down
Loading

0 comments on commit 48afaac

Please sign in to comment.