From 8b4d39f1f9a6aa2c492acf0f8fc7828a6305dfb6 Mon Sep 17 00:00:00 2001 From: hypnoticpattern <> Date: Thu, 23 Jan 2020 23:54:31 -0800 Subject: [PATCH 1/7] Fixed stager for OSX and appbundle creation --- lib/common/stagers.py | 10 +++++----- lib/stagers/osx/application.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/common/stagers.py b/lib/common/stagers.py index e7e0f4798..027235205 100644 --- a/lib/common/stagers.py +++ b/lib/common/stagers.py @@ -274,10 +274,10 @@ def generate_appbundle(self, launcherCode, Arch, icon, AppName, disarm): if Arch == 'x64': - f = open(self.mainMenu.installPath + "/data/misc/apptemplateResources/x64/launcher.app/Contents/MacOS/launcher") + f = open(self.mainMenu.installPath + "/data/misc/apptemplateResources/x64/launcher.app/Contents/MacOS/launcher", "rb") directory = self.mainMenu.installPath + "/data/misc/apptemplateResources/x64/launcher.app/" else: - f = open(self.mainMenu.installPath + "/data/misc/apptemplateResources/x86/launcher.app/Contents/MacOS/launcher") + f = open(self.mainMenu.installPath + "/data/misc/apptemplateResources/x86/launcher.app/Contents/MacOS/launcher", "rb") directory = self.mainMenu.installPath + "/data/misc/apptemplateResources/x86/launcher.app/" macho = macholib.MachO.MachO(f.name) @@ -292,10 +292,10 @@ def generate_appbundle(self, launcherCode, Arch, icon, AppName, disarm): count = 0 if int(cmd[count].cmd) == macholib.MachO.LC_SEGMENT_64 or int(cmd[count].cmd) == macholib.MachO.LC_SEGMENT: count += 1 - if cmd[count].segname.strip('\x00') == '__TEXT' and cmd[count].nsects > 0: + if cmd[count].segname.strip(b'\x00') == b'__TEXT' and cmd[count].nsects > 0: count += 1 for section in cmd[count]: - if section.sectname.strip('\x00') == '__cstring': + if section.sectname.strip(b'\x00') == b'__cstring': offset = int(section.offset) placeHolderSz = int(section.size) - 52 @@ -304,7 +304,7 @@ def generate_appbundle(self, launcherCode, Arch, icon, AppName, disarm): if placeHolderSz and offset: - launcher = launcherCode + "\x00" * (placeHolderSz - len(launcherCode)) + launcher = launcherCode.encode('utf8') + b'\x00' * (placeHolderSz - len(launcherCode)) patchedBinary = template[:offset]+launcher+template[(offset+len(launcher)):] if AppName == "": AppName = "launcher" diff --git a/lib/stagers/osx/application.py b/lib/stagers/osx/application.py index 4059443d4..5e7375919 100644 --- a/lib/stagers/osx/application.py +++ b/lib/stagers/osx/application.py @@ -97,6 +97,6 @@ def generate(self): else: disarm = False - launcher = launcher.strip('echo').strip(' | /usr/bin/python &').strip("\"") + launcher = launcher.strip('echo').strip(' | /usr/bin/python3 &').strip("\"") ApplicationZip = self.mainMenu.stagers.generate_appbundle(launcherCode=launcher,Arch=arch,icon=icnsPath,AppName=AppName, disarm=disarm) return ApplicationZip From 4ebd594a8a3a16d6a6c24bd0e197c491c046ac77 Mon Sep 17 00:00:00 2001 From: roseaj Date: Fri, 24 Jan 2020 23:48:30 -0500 Subject: [PATCH 2/7] removed import future from python3 launcher - #81 --- data/agent/agent.py | 12 ------------ data/agent/stagers/http.py | 2 -- 2 files changed, 14 deletions(-) diff --git a/data/agent/agent.py b/data/agent/agent.py index 58e654088..04c02a7f7 100644 --- a/data/agent/agent.py +++ b/data/agent/agent.py @@ -1,13 +1,5 @@ -from __future__ import division -from future import standard_library -standard_library.install_aliases() -from builtins import str -from builtins import range -from builtins import object from past.utils import old_div -import __future__ import struct -import time import base64 import subprocess import random @@ -15,15 +7,12 @@ import datetime import os import sys -import trace -import shlex import zlib import threading import http.server import zipfile import io import imp -import marshal import re import shutil import pwd @@ -31,7 +20,6 @@ import math import stat import grp -from stat import S_ISREG, ST_CTIME, ST_MODE from os.path import expanduser from io import StringIO from threading import Thread diff --git a/data/agent/stagers/http.py b/data/agent/stagers/http.py index e13e781b4..ea5f7974f 100644 --- a/data/agent/stagers/http.py +++ b/data/agent/stagers/http.py @@ -10,9 +10,7 @@ stage_1 stage_2 """ -from __future__ import print_function -import copy import random import string import urllib.request as urllib From 1eaf59a4d86fea4520bc411ceb020297ed91501a Mon Sep 17 00:00:00 2001 From: roseaj Date: Sat, 25 Jan 2020 00:19:55 -0500 Subject: [PATCH 3/7] Fixed stagingkey encoding error - #85 --- lib/common/listeners.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/listeners.py b/lib/common/listeners.py index a9d948cf6..059a9661d 100644 --- a/lib/common/listeners.py +++ b/lib/common/listeners.py @@ -155,7 +155,7 @@ def set_listener_option(self, listenerName, option, value): # if the staging key isn't 32 characters, assume we're md5 hashing it value = str(value).strip() if len(value) != 32: - stagingKeyHash = hashlib.md5(value).hexdigest() + stagingKeyHash = hashlib.md5(value.encode('UTF-8')).hexdigest() print(helpers.color('[!] Warning: staging key not 32 characters, using hash of staging key instead: %s' % (stagingKeyHash))) listenerObject.options[option]['Value'] = stagingKeyHash else: From e5214308f631e5632dace38a17bbf35701a770d5 Mon Sep 17 00:00:00 2001 From: Vincent Rose Date: Wed, 29 Jan 2020 22:49:34 -0700 Subject: [PATCH 4/7] add stale flag to /api/agents and encoding session_key bug (#90) * add stale flag to /api/agents and encoding session_key bug * remove import from past --- data/agent/agent.py | 1 - empire | 12 ++++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/data/agent/agent.py b/data/agent/agent.py index 04c02a7f7..8b6708208 100644 --- a/data/agent/agent.py +++ b/data/agent/agent.py @@ -1,4 +1,3 @@ -from past.utils import old_div import struct import base64 import subprocess diff --git a/empire b/empire index 2e2ee5c23..3a6f4f131 100755 --- a/empire +++ b/empire @@ -775,11 +775,19 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None, for activeAgent in activeAgentsRaw: [ID, session_id, listener, name, language, language_version, delay, jitter, external_ip, internal_ip, username, high_integrity, process_name, process_id, hostname, os_details, session_key, nonce, checkin_time, lastseen_time, parent, children, servers, profile, functions, kill_date, working_hours, lost_limit, taskings, results] = activeAgent - agents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key, "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results}) + intervalMax = (delay + delay * jitter)+30 + + # get the agent last check in time + agentTime = time.mktime(time.strptime(lastseen_time, "%Y-%m-%d %H:%M:%S")) + + stale = agentTime < time.mktime(time.localtime()) - intervalMax + + agents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key.decode('latin-1').encode('utf-8'), "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results, "stale":stale}) return jsonify({'agents' : agents}) + @app.route('/api/agents/stale', methods=['GET']) def get_agents_stale(): """ @@ -801,7 +809,7 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None, if agentTime < time.mktime(time.localtime()) - intervalMax: - staleAgents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key, "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results}) + staleAgents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key.decode('latin-1').encode('utf-8'), "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results}) return jsonify({'agents' : staleAgents}) From 7b2e7e9fdc0cfdc1bfe2e1a908dd225412b2400e Mon Sep 17 00:00:00 2001 From: roseaj Date: Wed, 29 Jan 2020 23:52:36 -0500 Subject: [PATCH 5/7] fixed last_cipherblock in aes.py --- data/agent/stagers/common/aes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/agent/stagers/common/aes.py b/data/agent/stagers/common/aes.py index 80fa5dc38..7f2ee74b3 100644 --- a/data/agent/stagers/common/aes.py +++ b/data/agent/stagers/common/aes.py @@ -235,7 +235,8 @@ def __init__(self, key, iv=None): else: if isinstance(iv, str): self._last_cipherblock = _string_to_bytes(iv) - self._last_cipherblock = iv + else: + self._last_cipherblock = iv AESBlockModeOfOperation.__init__(self, key) From 847983b2d9e84fc6feae5fcb78da85fee8e25a4a Mon Sep 17 00:00:00 2001 From: Vince Rose Date: Wed, 29 Jan 2020 23:49:20 -0700 Subject: [PATCH 6/7] include old_div code --- data/agent/agent.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data/agent/agent.py b/data/agent/agent.py index 8b6708208..0f875fd6f 100644 --- a/data/agent/agent.py +++ b/data/agent/agent.py @@ -19,6 +19,7 @@ import math import stat import grp +import numbers from os.path import expanduser from io import StringIO from threading import Thread @@ -518,6 +519,15 @@ def process_packet(packetType, data, resultID): else: send_message(build_response_packet(0, "invalid tasking ID: %s" %(taskingID), resultID)) +def old_div(a, b): + """ + Equivalent to ``a / b`` on Python 2 without ``from __future__ import + division``. + """ + if isinstance(a, numbers.Integral) and isinstance(b, numbers.Integral): + return a // b + else: + return a / b ################################################ # From 8063cc728ddfe8386e445a10bd025f8cba04c9dc Mon Sep 17 00:00:00 2001 From: Vince Rose Date: Thu, 30 Jan 2020 00:12:30 -0700 Subject: [PATCH 7/7] changelog --- VERSION | 2 +- changelog | 27 +++++++++++++++++++-------- lib/common/empire.py | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/VERSION b/VERSION index eca690e73..818bd47ab 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.5 +3.0.6 diff --git a/changelog b/changelog index 0ac934f6c..21a60ff8d 100644 --- a/changelog +++ b/changelog @@ -1,14 +1,25 @@ +1/31/2020 +------------ +- Version 3.0.6 Master Release + - Fixed osx stager generation byte/str errors - #84 (@hypnoticpattern) + - Fixed osx appbundle generation which was stripping the wrong string - #84 (@hypnoticpattern) + - Removed future imports from python3 launcher, so it works without any extra libraries - #81 (@Cx01N) + - Staging key no longer needs to be exactly 32 characters - #85 (@Cx01N) + - Add "stale" property to agents endpoint - #90 (@Vinnybod) + - Agents endpoint now returns agents without failing due to session_key encoding - #90 (@Vinnybod) + - Fixed an indentation bug in aes.py (@Cx01N) + 1/21/2020 ------------ - Version 3.0.5 Master Release - - Fixed setup_database.py python3 issue - #75 (@linxon) - - Added loaded listener types to API - #78 (@Vinnybod) - - Fixed python launcherBase (@Cx01N) - - Updated Python 3.8 compatibility in stager - #72 (@complana) - - Fixed Powerup Invoke-allchecks issue - #64 (@SkiddieTech) - - Fixed shellcode stager - #76 (@Hubbl3) - - Fixed binary upload error - #55 (@Hubbl3) - - Fixed multi/bash error (@Cx01N) + - Fixed setup_database.py python3 issue - #75 (@linxon) + - Added loaded listener types to API - #78 (@Vinnybod) + - Fixed python launcherBase (@Cx01N) + - Updated Python 3.8 compatibility in stager - #72 (@complana) + - Fixed Powerup Invoke-allchecks issue - #64 (@SkiddieTech) + - Fixed shellcode stager - #76 (@Hubbl3) + - Fixed binary upload error - #55 (@Hubbl3) + - Fixed multi/bash error (@Cx01N) 1/14/2020 ------------ diff --git a/lib/common/empire.py b/lib/common/empire.py index b834ce654..86efdb247 100644 --- a/lib/common/empire.py +++ b/lib/common/empire.py @@ -15,7 +15,7 @@ from builtins import str from builtins import range -VERSION = "3.0.5 BC-Security Fork" +VERSION = "3.0.6 BC-Security Fork" from pydispatch import dispatcher