AV
AV
com/t3l3machus/PowerShell-Obfuscation-Bible
t3l3machus / PowerShell-Obfuscation-Bible
PowerShell-Obfuscation-Bible Public
1 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
A collection of techniques,
t3l3machus Update R… ca7cfa9 · 2 months ago 97 Commits
examples and a little bit of theory
for manually obfuscating
LICENSE.md Create LICENSE.md 10 months ago PowerShell scripts to achieve AV
evasion, compiled for educational
README.md Update README.md 2 months ago
purposes. The contents of this
repository are the result of personal
README MIT license research, including reading
materials online and conducting
trial-and-error attempts in labs and
# redteam # offensivesecurity
A collection of techniques, examples and a little bit of theory for manually obfuscating PowerShell
Readme scripts to
bypass signature-based detection, compiled for educational purposes. The contents of this repository
MIT licenseare the
result of personal research, including reading materials online and conducting trial-and-error attempts in labs
Activity
and pentests. You should not take anything for granted.
627 stars
YouTube video presentation: youtube.com/watch?v=tGFdmAh_lXE 11 watching
74 forks
Disclaimer: Usage of the techniques and concepts described in this repository for gaining unauthorized
Report
access to systems that you do not have permission to test is illegal. You are responsible for yourrepository
actions.
Don't be evil.
Sponsor this project
Table of Contents
https://www.buymeacoffee.com/…
2 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
1. Entropy
https://ko-fi.com/t3l3machus
2. Identify Detection Triggers
3. Rename Objects https://github.com/sponsors/t3l3…
Entropy
The scientific term entropy , which is generally defined as the measure of randomness or disorder of a
system is important in AV evasion. This is because, malware often contains code that is highly randomized,
encrypted and/or encoded (obfuscated) to make it difficult to analyze and therefore detect. As one of various
methods, Anti-virus products use entropy analysis to identify potentially malicious files and payloads.
It is important to understand this concept because, when obfuscating code, you should keep in mind the
entropy variance created by the changes you choose to make. Breaking signatures is easy, but if you don't
pay attention to the entropy level, sophisticated AV/EDRs will see through it.
A principle to keep in mind: The greater the entropy, the more likely the data is obfuscated or encrypted,
3 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
and the more probable the file/payload is malicious. Fortunately, there are ways to lower it.
Claude E. Shannon introduced a formula in his 1948 paper A Mathematical Theory of Communication which
can be used to measure the entropy in a set of data. Here's a simple Python implementation of the Shannon
Entropy you can use to measure the entropy of the payloads you develop:
#!/bin/python3
# Usage: python3 entropy.py <file>
def entropy(string):
"Calculates the Shannon entropy of a UTF-8 encoded string"
return entropy
f = open(sys.argv[1], 'rb')
content = f.read()
f.close()
print(entropy(content))
You can also use this online Shannon Entropy calculator or Microsoft's Sigcheck.exe with the -a option.
4 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
A great tool to identify such triggers is AMSItrigger. Here's a usage example with a file containing a malicious
script. The red area signifies the part that obfuscation should be applied:
You could also identify triggers manually by executing a script chunk by chunk.
Rename Objects
When obfuscating scripts, it should be a priority to replace variable/class/function names with random ones.
That way, in combination with other techniques, you will be able to bypass detection easily. But you should
keep in mind the entropy of the payloads you develop. Take in consideration the following standard reverse
shell script that is generally detected by most if not all AVs:
5 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
In this version, all variable names have been substituted with 32 chars long random names. I also replaced
(pwd).Path with $(gl) . The payload has a Shannon entropy of 4.96 . At the time of writing this, it is not
detected by MS Defender and a banch of other products:
6 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
This variation also has all variable names replaced but this time with names consisting of x number of 'f'
characters, which results in a significant drop of the payload's entropy. I replaced (pwd).Path with $(gl)
here as well. Again, at the time of writing, it is not detected by MS Defender. The payload has a Shannon
entropy of 0.76 .
Both of these variations bypass common AVs, but the second one has a lower entropy and will probably
have a better chance when processed by EDRs and other sophisticated anti-malware engines. I am not
saying that the better performance of the second payload variation in this example is certainly because of the
7 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
entropy level (I can't really know that, it could have been the length or both or who knows what), but it is an
important aspect to have in mind when obfuscating stuff and this example is meant to underline that
concept.
You can use the script below to randomize the names of variables in a PowerShell script. The script is not
perfect! If you run it against large, complex PowerShell scripts it might break their functionality by replacing
stuff it shouldn't. Use it with caution and be mindful.
#!/bin/python3
#
# This script is an example. It is not perfect and you should use it with caution.
# Source: https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
# Usage: python3 randomize-variables.py <path/to/powershell/script>
import re
from sys import argv
from uuid import uuid4
def get_file_content(path):
f = open(path, 'r')
content = f.read()
f.close()
return content
def main():
payload = get_file_content(argv[1])
used_var_names = []
8 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
while True:
new_var_name = uuid4().hex
else:
used_var_names.append(new_var_name)
break
print(payload + '\n')
main()
Boolean typecast of literally anything that is not 0 or Null or an empty string , will return True :
9 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
[bool]1254
[bool]0x12AE
[bool][convert]::ToInt32("111011", 2) # Converts a string to int from base 2 (binary)
![bool]$null
![bool]$False
[bool]"Any non empty string"
[bool](-12354893) # Boolean typecast of a negative number
[bool](12 + (3 * 6))
[bool](Get-ChildItem -Path Env: | Where-Object {$_.Name -eq "username"})
[bool]@(0x01BE)
[bool][System.Collections.ArrayList]
[bool][System.Collections.CaseInsensitiveComparer]
[bool][System.Collections.Hashtable]
[bool][bool]
[bool][char]
[bool][int]
[bool][string]
[bool][double]
[bool][short]
[bool][decimal]
[bool][byte]
[bool][timespan]
[bool][datetime]
10 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
$x = [System.Data.AcceptRejectRule].Assembly.GlobalAssemblyCache
$x = [System.TimeZoneInfo+AdjustmentRule].IsAnsiClass
$x = [mailaddress].IsAutoLayout
$x = [ValidateCount].IsVisible
You can mix all this stuff and weird things up by composing hideous ways to state True or False :
[bool](![bool]$null)
[System.Collections.CaseInsensitiveComparer] -ne [bool][datetime]'2023-01-01'
[bool]$(Get-LocalGroupMember Administrators)
!!!![bool][bool][bool][bool][bool][bool]
i''ex "pwd"
i''e''x "pwd"
i''e''x'' "pwd"
ie''x'' "pwd"
iex'' "pwd"
i""e''x"" "pwd"
ie""x'' "pwd"
11 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
i''ex "p''wd"
i''e''x "p''w''d"
i''e''x'' "p''w''d''"
ie''x'' "pw''d`"`""
iex'' "p`"`"w`"`"d`"`""
i""e''x"" "p`"`"w`"`"d''"
ie""x'' "p`"`"w''d`"`""
cmd /c "who^am^i"
Get-Command Technique
A really cool trick my friend and mighty haxor Karol Musolff (@kmusolff) showed me. You can use Get-
Command (or gcm ) to retrieve the name (string) of any command, including all of the non-PowerShell files in
the Path environment variable ( $env:Path ) by using wildcards. You can then run them as jobs with the &
operator. For example, the following line:
12 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
Or even better, this one, that has a lower Shannon entropy value:
Substitute Loops
There are certain loops that can be substituted with other loop types or functions. For example, a While
($True){ # some code } loop can be substituted with the following:
An infinite For loop
A Do-While loop
A Do-Until loop
13 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
A recursive function
function runToInfinity {
# do something;
runToInfinity;
}
Append Junk
Add/Remove parameters
You can try adding parameters to a cmdlet. For example, the following line:
iex "whoami"
14 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
$virus = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b64));
iex $virus;
Substitute Commands
You can always look for commands or even whole code blocks in a script that you can substitute with
components that have the same/similar functionality. In the following classic reverse shell script, the pwd
command is used to retrieve the current working directory and reconstruct the shell's prompt value:
The (pwd).Path part can be replaced by the following weird, unorthodox little script and although it even
includes pwd it does serve our purpose of breaking the signature while maintaining the functionality of the
script:
There are of course simpler substitutes for pwd like gl , get-location and cmd.exe /c chdir that could do
the trick, especially in combination with other techniques.
15 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
$x = 'echo malware';
iex $x;
$x = 'echo malware';
iex @"
$x
"@
Reverse Strings
Concatenation
Pretty straightforward and classic:
16 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
'xxxmalwarexxx'.Substring(3,7)
[System.Text.Encoding]::Default.GetString([System.Convert]::FromBase64String("bWFsd2FyZQ=="))
"$([char]([byte]0x6d)+[char]([byte]0x61)+[char]([byte]0x6c)+[char]([byte]0x77)+[char]
([byte]0x61)+[char]([byte]0x72)+[char]([byte]0x65))"
17 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
Appending Comments
Obfuscating a script by appending comments here and there might actually do the trick on its own.
for example, a reverse shell command could be obfuscated like this:
Modified (appended <# Suspendisse imperdiet lacus eu tellus pellentesque suscipit #> in
various places)
This will not only work, but also lower the payload's Shannon entropy value (given that you don't use
complex random comments).
Removing Comments
18 of 20 2/6/2024, 3:05 AM
t3l3machus/PowerShell-Obfuscation-Bible: A collection of techniques, examples and a little bi... https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
There are malware-ish strings that will trigger AMSI immediately and it should be a priority to replace them,
when obfuscating scripts. Check this out:
Just by typing the string 'invoke-mimikatz' in the terminal AMSI is having a stroke (the script is not even
present / loaded). These strings may be found in comments as well, so it's a good idea to remove them,
especially from FOS resources you grab from the internet (e.g. Invoke-Mimikatz.ps1 from GitHub).
*It's generally a good idea to remove comments. This was just an example.
20 of 20 2/6/2024, 3:05 AM