Spaces:
Sleeping
Sleeping
Upload 11 files
Browse files- Obfus/LICENSE +21 -0
- Obfus/example/test.ps1 +44 -0
- Obfus/example/test_hard.ps1 +100 -0
- Obfus/main.ps1 +456 -0
- Obfus/util/MBA_OBF/mixed_boolean_arithmetic.ps1 +0 -0
- Obfus/util/commands/commands.ps1 +168 -0
- Obfus/util/commands/function_names.ps1 +16 -0
- Obfus/util/final/encodeOutput.ps1 +93 -0
- Obfus/util/numbers/obfuscate_numbers.ps1 +32 -0
- Obfus/util/strings/strings.ps1 +233 -0
- Obfus/util/variables/variables.ps1 +79 -0
Obfus/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2024 K.Dot
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
Obfus/example/test.ps1
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function Hello-World {
|
2 |
+
Write-Host "Hello, World!"
|
3 |
+
}
|
4 |
+
|
5 |
+
function Xor-Encrypt {
|
6 |
+
param (
|
7 |
+
[string] $string,
|
8 |
+
[string] $key
|
9 |
+
)
|
10 |
+
|
11 |
+
$keyLength = $key.Length
|
12 |
+
$stringLength = $string.Length
|
13 |
+
$encryptedString = ""
|
14 |
+
|
15 |
+
for ($i = 0; $i -lt $stringLength; $i++) {
|
16 |
+
$encryptedString += [char]($string[$i] -bxor $key[$i % $keyLength])
|
17 |
+
}
|
18 |
+
|
19 |
+
return $encryptedString
|
20 |
+
}
|
21 |
+
|
22 |
+
function Xor-Decrypt {
|
23 |
+
param (
|
24 |
+
[string] $string,
|
25 |
+
[string] $key
|
26 |
+
)
|
27 |
+
|
28 |
+
$keyLength = $key.Length
|
29 |
+
$stringLength = $string.Length
|
30 |
+
$decryptedString = ""
|
31 |
+
|
32 |
+
for ($i = 0; $i -lt $stringLength; $i++) {
|
33 |
+
$decryptedString += [char]($string[$i] -bxor $key[$i % $keyLength])
|
34 |
+
}
|
35 |
+
|
36 |
+
return $decryptedString
|
37 |
+
}
|
38 |
+
|
39 |
+
Hello-World
|
40 |
+
$encrypted = Xor-Encrypt -string "Hello, World!" -key "key"
|
41 |
+
Write-Host $encrypted
|
42 |
+
$decrypted = Xor-Decrypt -string $encrypted -key "key"
|
43 |
+
Write-Host $decrypted
|
44 |
+
|
Obfus/example/test_hard.ps1
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Add-Type -AssemblyName "System.IO.Compression"
|
2 |
+
|
3 |
+
$compressionTypes = 'Gzip', 'Deflate'
|
4 |
+
$method = ""
|
5 |
+
$decode_command = @"
|
6 |
+
function Decode-Code(`$compressedBytes, `$compressionPick) {
|
7 |
+
[System.IO.MemoryStream] `$input1 = New-Object System.IO.MemoryStream
|
8 |
+
`$input1.Write(`$compressedBytes, 0, `$compressedBytes.Length)
|
9 |
+
`$input1.Seek(0, [IO.SeekOrigin]::Begin)
|
10 |
+
|
11 |
+
`$compressionStream = $null
|
12 |
+
`$reader = $null
|
13 |
+
`$decompressedData = $null
|
14 |
+
|
15 |
+
if (`$compressionPick -eq 'Gzip') {
|
16 |
+
`$compressionStream = New-Object System.IO.Compression.GzipStream `$input1, ([IO.Compression.CompressionMode]::Decompress)
|
17 |
+
} elseif (`$compressionPick -eq 'Deflate') {
|
18 |
+
`$compressionStream = New-Object System.IO.Compression.DeflateStream `$input1, ([IO.Compression.CompressionMode]::Decompress)
|
19 |
+
}
|
20 |
+
|
21 |
+
`$reader = New-Object System.IO.StreamReader `$compressionStream
|
22 |
+
`$decompressedData = `$reader.ReadToEnd()
|
23 |
+
|
24 |
+
`$reader.Close()
|
25 |
+
`$compressionStream.Close()
|
26 |
+
|
27 |
+
`$input1.Close()
|
28 |
+
return `$decompressedData
|
29 |
+
}
|
30 |
+
"@
|
31 |
+
|
32 |
+
function Read-And-Interpret-Script($scriptPath) {
|
33 |
+
$scriptContent = [System.IO.File]::ReadAllBytes($scriptPath)
|
34 |
+
|
35 |
+
$compressionPick = $compressionTypes | Get-Random
|
36 |
+
|
37 |
+
$encodedScriptContent = Encode-Code -code $scriptContent -compressionPick $compressionPick
|
38 |
+
Write-Host "Encoded Script Content:"
|
39 |
+
Write-Host $encodedScriptContent
|
40 |
+
|
41 |
+
$decodedScriptContent = Decode-Code -compressedBytes $encodedScriptContent -compressionPick $compressionPick
|
42 |
+
|
43 |
+
Write-Host "Decoded Script Content:"
|
44 |
+
Write-Host $decodedScriptContent[1]
|
45 |
+
}
|
46 |
+
|
47 |
+
function Obfuscate-Code($code) {
|
48 |
+
$obfuscatedCode = $code
|
49 |
+
return $obfuscatedCode
|
50 |
+
}
|
51 |
+
|
52 |
+
function Encode-Code($code, $compressionPick) {
|
53 |
+
[System.IO.MemoryStream] $output = New-Object System.IO.MemoryStream
|
54 |
+
$compressionStream = $null
|
55 |
+
|
56 |
+
if ($compressionPick -eq 'Gzip') {
|
57 |
+
$compressionStream = New-Object System.IO.Compression.GzipStream $output, ([IO.Compression.CompressionMode]::Compress)
|
58 |
+
} elseif ($compressionPick -eq 'Deflate') {
|
59 |
+
$compressionStream = New-Object System.IO.Compression.DeflateStream $output, ([IO.Compression.CompressionMode]::Compress)
|
60 |
+
}
|
61 |
+
|
62 |
+
$compressionStream.Write($code, 0, $code.Length)
|
63 |
+
$compressionStream.Close()
|
64 |
+
$compressedBytes = $output.ToArray()
|
65 |
+
|
66 |
+
$output.Close()
|
67 |
+
return $compressedBytes
|
68 |
+
}
|
69 |
+
|
70 |
+
function Decode-Code($compressedBytes, $compressionPick) {
|
71 |
+
[System.IO.MemoryStream] $input1 = New-Object System.IO.MemoryStream
|
72 |
+
$input1.Write($compressedBytes, 0, $compressedBytes.Length)
|
73 |
+
$input1.Seek(0, [IO.SeekOrigin]::Begin)
|
74 |
+
|
75 |
+
$compressionStream = $null
|
76 |
+
$reader = $null
|
77 |
+
$decompressedData = $null
|
78 |
+
|
79 |
+
if ($compressionPick -eq 'Gzip') {
|
80 |
+
$compressionStream = New-Object System.IO.Compression.GzipStream $input1, ([IO.Compression.CompressionMode]::Decompress)
|
81 |
+
} elseif ($compressionPick -eq 'Deflate') {
|
82 |
+
$compressionStream = New-Object System.IO.Compression.DeflateStream $input1, ([IO.Compression.CompressionMode]::Decompress)
|
83 |
+
}
|
84 |
+
|
85 |
+
$reader = New-Object System.IO.StreamReader $compressionStream
|
86 |
+
$decompressedData = $reader.ReadToEnd()
|
87 |
+
|
88 |
+
$reader.Close()
|
89 |
+
$compressionStream.Close()
|
90 |
+
|
91 |
+
$input1.Close()
|
92 |
+
return $decompressedData
|
93 |
+
}
|
94 |
+
|
95 |
+
|
96 |
+
|
97 |
+
|
98 |
+
|
99 |
+
$scriptPath = "example\test.ps1"
|
100 |
+
Read-And-Interpret-Script -scriptPath $scriptPath
|
Obfus/main.ps1
ADDED
@@ -0,0 +1,456 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#python import type shi
|
2 |
+
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
|
3 |
+
|
4 |
+
. "$scriptPath\util\strings\strings.ps1"
|
5 |
+
. "$scriptPath\util\variables\variables.ps1"
|
6 |
+
. "$scriptPath\util\commands\commands.ps1"
|
7 |
+
. "$scriptPath\util\commands\function_names.ps1"
|
8 |
+
. "$scriptPath\util\final\encodeOutput.ps1"
|
9 |
+
. "$scriptPath\util\numbers\obfuscate_numbers.ps1"
|
10 |
+
|
11 |
+
$global:pass_number = 1
|
12 |
+
|
13 |
+
$times = 2
|
14 |
+
$verbose = $false
|
15 |
+
$verbose_out_file = $true
|
16 |
+
|
17 |
+
if ($verbose_out_file) {
|
18 |
+
#redirect standard output when we need the verbose in a file
|
19 |
+
$VerbosePreference = "Continue"
|
20 |
+
$date_and_time = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
|
21 |
+
$VerboseOutput = "obfuscate$date_and_time.log"
|
22 |
+
Start-Transcript -Path $VerboseOutput
|
23 |
+
}
|
24 |
+
|
25 |
+
# this is EXTREMELY NEEDED because the Get-Command function is so utterly slow.
|
26 |
+
$CommandTypeCache = @{}
|
27 |
+
|
28 |
+
$functionNamesIgnore = @("CheckValidationResult")
|
29 |
+
|
30 |
+
$built_in_aliases = @('foreach', 'where', 'clc', 'cli', 'clp', 'clv', 'cpi', 'cvpa', 'dbp', 'ebp', 'epal',
|
31 |
+
'epcsv', 'fl', 'ft', 'fw', 'gal', 'gbp', 'gc', 'gci', 'gcm', 'gdr', 'gcs', 'ghy', 'gi', 'gl', 'gm', 'gmo', 'gp',
|
32 |
+
'gpv', 'gps', 'group', 'gu', 'gv', 'iex', 'ihy', 'ii', 'ipmo', 'ipal', 'ipcsv', 'measure', 'mi', 'mp', 'nal',
|
33 |
+
'ndr', 'ni', 'nv', 'nmo', 'oh', 'rbp', 'rdr', 'ri', 'rni', 'rnp', 'rp', 'rmo', 'rv', 'gerr', 'rvpa', 'sal',
|
34 |
+
'sbp', 'select', 'si', 'sl', 'sp', 'saps', 'spps', 'sv', 'irm', 'iwr', 'ac', 'clear', 'compare', 'cpp', 'diff',
|
35 |
+
'gsv', 'sleep', 'sort', 'start', 'sasv', 'spsv', 'tee', 'write', 'cat', 'cp', 'ls', 'man', 'mount', 'mv', 'ps',
|
36 |
+
'rm', 'rmdir', 'cnsn', 'dnsn', 'ogv', 'shcm', 'cd', 'dir', 'echo', 'fc', 'kill', 'pwd', 'type', 'h', 'history',
|
37 |
+
'md', 'popd', 'pushd', 'r', 'cls', 'chdir', 'copy', 'del', 'erase', 'move', 'rd', 'ren', 'set', 'icm', 'clhy',
|
38 |
+
'gjb', 'rcjb', 'rjb', 'sajb', 'spjb', 'wjb', 'nsn', 'gsn', 'rsn', 'etsn', 'rcsn', 'exsn', 'sls')
|
39 |
+
|
40 |
+
function ObfuscateCode($code) {
|
41 |
+
$code_copy = $code
|
42 |
+
$functionReplacementMap = @{}
|
43 |
+
$variableReplacementMap = @{}
|
44 |
+
$parameterReplacementMap = @{}
|
45 |
+
$stringReplacementMap = @{}
|
46 |
+
$numberReplacementMap = @{}
|
47 |
+
|
48 |
+
$comments = [System.Management.Automation.PSParser]::Tokenize($code_copy, [ref]$null) | Where-Object { $_.Type -eq "Comment" }
|
49 |
+
foreach ($comment in $comments) {
|
50 |
+
$code_copy = $code_copy.Replace($comment.Content, "")
|
51 |
+
}
|
52 |
+
|
53 |
+
# first pass - handle everything except barewords
|
54 |
+
$ast = [System.Management.Automation.Language.Parser]::ParseInput($code_copy, [ref]$null, [ref]$null)
|
55 |
+
|
56 |
+
# get all function definitions
|
57 |
+
$functionDefinitions = $ast.FindAll({ param([System.Management.Automation.Language.Ast] $Ast)
|
58 |
+
$Ast -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true)
|
59 |
+
|
60 |
+
# get all command calls
|
61 |
+
$allCommandCalls = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.CommandAst] }, $true)
|
62 |
+
|
63 |
+
# get all variable expressions
|
64 |
+
$variableExpressions = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.VariableExpressionAst] }, $true)
|
65 |
+
|
66 |
+
$stringAsts = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.StringConstantExpressionAst] -and ($args[0].StringConstantType -eq "DoubleQuoted" -or $args[0].StringConstantType -eq "SingleQuoted") }, $true)
|
67 |
+
|
68 |
+
$numberAsts = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.ConstantExpressionAst] -and $args[0].StaticType.Name -eq "Int32" }, $true)
|
69 |
+
|
70 |
+
# Process function definitions and create replacement map
|
71 |
+
foreach ($func in $functionDefinitions) {
|
72 |
+
if (-not $functionReplacementMap.ContainsKey($func.Name)) {
|
73 |
+
$functionReplacementMap[$func.Name] = ObfuscateFunctionNames $func.Name
|
74 |
+
}
|
75 |
+
|
76 |
+
# handle parameters in function definition
|
77 |
+
if ($func.Parameters) {
|
78 |
+
foreach ($param in $func.Parameters) {
|
79 |
+
$paramName = $param.Name.VariablePath.UserPath
|
80 |
+
if (-not $parameterReplacementMap.ContainsKey($paramName)) {
|
81 |
+
$newParamName = ObfuscateVariables $paramName $true
|
82 |
+
$parameterReplacementMap[$paramName] = $newParamName.TrimStart('$')
|
83 |
+
$variableReplacementMap[$paramName] = $newParamName
|
84 |
+
}
|
85 |
+
}
|
86 |
+
}
|
87 |
+
if ($func.Body.ParamBlock) {
|
88 |
+
foreach ($param in $func.Body.ParamBlock.Parameters) {
|
89 |
+
$paramName = $param.Name.VariablePath.UserPath
|
90 |
+
if (-not $parameterReplacementMap.ContainsKey($paramName)) {
|
91 |
+
$newParamName = ObfuscateVariables $paramName $true
|
92 |
+
$parameterReplacementMap[$paramName] = $newParamName.TrimStart('$')
|
93 |
+
$variableReplacementMap[$paramName] = $newParamName
|
94 |
+
}
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
# process regular variables
|
100 |
+
foreach ($var in $variableExpressions) {
|
101 |
+
$varName = $var.VariablePath.UserPath
|
102 |
+
if (-not $variableReplacementMap.ContainsKey($varName) -and -not $parameterReplacementMap.ContainsKey($varName)) {
|
103 |
+
$variableReplacementMap[$varName] = ObfuscateVariables $var.Extent.Text
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
$allReplacements = @()
|
108 |
+
|
109 |
+
# add function definitions with improved handling
|
110 |
+
foreach ($func in $functionDefinitions) {
|
111 |
+
if ($func.Name -in $functionNamesIgnore) { continue }
|
112 |
+
|
113 |
+
$functionKeyword = "function "
|
114 |
+
$fullStartOffset = $func.Extent.StartOffset
|
115 |
+
$nameStartOffset = $func.Extent.StartOffset
|
116 |
+
|
117 |
+
# find actual start of function name by checking for the keyword
|
118 |
+
if ($func.Extent.Text.TrimStart().StartsWith($functionKeyword)) {
|
119 |
+
$nameStartOffset = $fullStartOffset + $func.Extent.Text.IndexOf($functionKeyword) + $functionKeyword.Length
|
120 |
+
}
|
121 |
+
|
122 |
+
$allReplacements += @{
|
123 |
+
StartOffset = $nameStartOffset
|
124 |
+
Length = $func.Name.Length
|
125 |
+
OriginalName = $func.Name
|
126 |
+
Text = $func.Name
|
127 |
+
Type = "Function"
|
128 |
+
RequiresKeyword = $true # new flag to indicate this needs special handling
|
129 |
+
FullStartOffset = $fullStartOffset
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
# add function calls and parameters with improved validation
|
134 |
+
foreach ($call in $allCommandCalls) {
|
135 |
+
$commandName = $call.CommandElements[0].Extent.Text
|
136 |
+
|
137 |
+
if ($commandName -in $functionNamesIgnore) { continue }
|
138 |
+
|
139 |
+
if ($functionReplacementMap.ContainsKey($commandName)) {
|
140 |
+
# verify the replacement exists and is valid
|
141 |
+
$newName = $functionReplacementMap[$commandName]
|
142 |
+
$allReplacements += @{
|
143 |
+
StartOffset = $call.CommandElements[0].Extent.StartOffset
|
144 |
+
Length = $commandName.Length
|
145 |
+
OriginalName = $commandName
|
146 |
+
Text = $commandName
|
147 |
+
Type = "Function"
|
148 |
+
RequiresKeyword = $false # function calls don't need the keyword
|
149 |
+
}
|
150 |
+
|
151 |
+
# process parameters
|
152 |
+
for ($i = 1; $i -lt $call.CommandElements.Count; $i++) {
|
153 |
+
$element = $call.CommandElements[$i]
|
154 |
+
if ($element.Extent.Text.StartsWith('-')) {
|
155 |
+
$paramName = $element.Extent.Text.TrimStart('-')
|
156 |
+
if ($parameterReplacementMap.ContainsKey($paramName)) {
|
157 |
+
$allReplacements += @{
|
158 |
+
StartOffset = $element.Extent.StartOffset
|
159 |
+
Length = $element.Extent.Text.Length
|
160 |
+
OriginalName = $paramName
|
161 |
+
Text = "-" + $paramName
|
162 |
+
Type = "ParameterName"
|
163 |
+
}
|
164 |
+
}
|
165 |
+
}
|
166 |
+
}
|
167 |
+
}
|
168 |
+
}
|
169 |
+
|
170 |
+
# add variables
|
171 |
+
foreach ($var in $variableExpressions) {
|
172 |
+
$varName = $var.VariablePath.UserPath
|
173 |
+
$parent = $var.Parent
|
174 |
+
$isParameterName = $false
|
175 |
+
while ($parent) {
|
176 |
+
if ($parent -is [System.Management.Automation.Language.CommandAst]) {
|
177 |
+
$isParameterName = $parent.CommandElements | Where-Object { $_.Extent.Text -eq "-$($var.Extent.Text)" }
|
178 |
+
if ($isParameterName) { break }
|
179 |
+
}
|
180 |
+
$parent = $parent.Parent
|
181 |
+
}
|
182 |
+
|
183 |
+
if (-not $isParameterName) {
|
184 |
+
$allReplacements += @{
|
185 |
+
StartOffset = $var.Extent.StartOffset
|
186 |
+
Length = $var.Extent.Text.Length
|
187 |
+
OriginalName = $varName
|
188 |
+
Text = $var.Extent.Text
|
189 |
+
Type = "Variable"
|
190 |
+
}
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
# add strings
|
195 |
+
foreach ($string in $stringAsts) {
|
196 |
+
$stringText = $string.Extent.Text
|
197 |
+
|
198 |
+
# handle empty strings
|
199 |
+
if ([string]::IsNullOrWhiteSpace($stringText) -or $stringText -eq '""' -or $stringText -eq "''") {
|
200 |
+
$allReplacements += @{
|
201 |
+
StartOffset = $string.Extent.StartOffset
|
202 |
+
Length = $string.Extent.Text.Length
|
203 |
+
OriginalName = $stringText
|
204 |
+
Text = $string.Extent.Text
|
205 |
+
Type = "EmptyString"
|
206 |
+
NewName = '[string]::Empty'
|
207 |
+
}
|
208 |
+
continue
|
209 |
+
}
|
210 |
+
|
211 |
+
# check to see if string only contains single or double quotes inside. (if example: "''" or "''''") if the string is empty then just keep going.
|
212 |
+
if ($stringText -match "^['""]+$") {
|
213 |
+
$allReplacements += @{
|
214 |
+
StartOffset = $string.Extent.StartOffset
|
215 |
+
Length = $string.Extent.Text.Length
|
216 |
+
OriginalName = $stringText
|
217 |
+
Text = $string.Extent.Text
|
218 |
+
Type = "EmptyString"
|
219 |
+
NewName = '[string]::Empty'
|
220 |
+
}
|
221 |
+
continue
|
222 |
+
}
|
223 |
+
|
224 |
+
# handle normal strings
|
225 |
+
if ($string.Extent.Text.Length -lt 3) { continue }
|
226 |
+
if (-not $stringReplacementMap.ContainsKey($stringText)) {
|
227 |
+
$stringReplacementMap[$stringText] = ObfuscateString $stringText
|
228 |
+
}
|
229 |
+
|
230 |
+
$allReplacements += @{
|
231 |
+
StartOffset = $string.Extent.StartOffset
|
232 |
+
Length = $string.Extent.Text.Length
|
233 |
+
OriginalName = $stringText
|
234 |
+
Text = $string.Extent.Text
|
235 |
+
Type = "String"
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
# first pass replacements
|
240 |
+
$allReplacements = $allReplacements | Sort-Object { $_.StartOffset } -Descending
|
241 |
+
|
242 |
+
foreach ($replacement in $allReplacements) {
|
243 |
+
$newName = switch ($replacement.Type) {
|
244 |
+
"Function" { $functionReplacementMap[$replacement.OriginalName] }
|
245 |
+
"ParameterName" { "-" + $parameterReplacementMap[$replacement.OriginalName] }
|
246 |
+
"Variable" { $variableReplacementMap[$replacement.OriginalName] }
|
247 |
+
"String" { $stringReplacementMap[$replacement.OriginalName] }
|
248 |
+
"EmptyString" { $replacement.NewName }
|
249 |
+
}
|
250 |
+
|
251 |
+
Write-Host "First Pass - Replacing '$($replacement.Text)' at position $($replacement.StartOffset) with '$newName' (Type: $($replacement.Type))"
|
252 |
+
|
253 |
+
$code_copy = Replace-TextAtPosition -SourceText $code_copy `
|
254 |
+
-StartPosition $replacement.StartOffset `
|
255 |
+
-Length $replacement.Length `
|
256 |
+
-ReplacementText $newName
|
257 |
+
}
|
258 |
+
|
259 |
+
$newAst = [System.Management.Automation.Language.Parser]::ParseInput($code_copy, [ref]$null, [ref]$null)
|
260 |
+
$barewordAsts = $newAst.FindAll({ ($args[0] -is [System.Management.Automation.Language.StringConstantExpressionAst] -and $args[0].StringConstantType -eq "BareWord") -or ($args[0] -is [System.Management.Automation.Language.TypeExpressionAst]) }, $true)
|
261 |
+
$bareword_Commands = $newAst.FindAll({ $args[0] -is [System.Management.Automation.Language.CommandAst] }, $true)
|
262 |
+
$numberAsts = $newAst.FindAll({ $args[0] -is [System.Management.Automation.Language.ConstantExpressionAst] -and $args[0].StaticType.Name -eq "Int32" }, $true)
|
263 |
+
|
264 |
+
$barewordReplacements = @()
|
265 |
+
$numberReplacements = @()
|
266 |
+
|
267 |
+
foreach ($bareword in $barewordAsts) {
|
268 |
+
if ($bareword.Extent.Text.Length -lt 3) { continue }
|
269 |
+
if ($functionReplacementMap.ContainsKey($bareword.Extent.Text)) { continue }
|
270 |
+
|
271 |
+
# check parent to see if this is a command
|
272 |
+
$isCommandFirst = $false
|
273 |
+
if ($bareword.Parent -is [System.Management.Automation.Language.CommandAst]) {
|
274 |
+
# check if its the first bareword (the actual command)
|
275 |
+
$commandElements = $bareword.Parent.CommandElements
|
276 |
+
$isCommandFirst = $commandElements[0].Extent.Text -eq $bareword.Extent.Text
|
277 |
+
|
278 |
+
# if not then skip
|
279 |
+
if (-not $isCommandFirst) {
|
280 |
+
continue
|
281 |
+
}
|
282 |
+
}
|
283 |
+
|
284 |
+
# get command type information
|
285 |
+
$commandInfo = Get-CommandType -CommandName $bareword.Extent.Text
|
286 |
+
|
287 |
+
# generate a new random replacement for each instance
|
288 |
+
# pass the command info to ObfuscateCommandTypes
|
289 |
+
$newBarewordName = ObfuscateCommandTypes -CommandText $bareword.Extent.Text -CommandInfo $commandInfo -RealBearWord $isCommandFirst
|
290 |
+
|
291 |
+
$barewordReplacements += @{
|
292 |
+
StartOffset = $bareword.Extent.StartOffset
|
293 |
+
Length = $bareword.Extent.Text.Length
|
294 |
+
OriginalName = $bareword.Extent.Text
|
295 |
+
Text = $bareword.Extent.Text
|
296 |
+
NewName = $newBarewordName
|
297 |
+
Type = "Bareword"
|
298 |
+
CommandType = $commandInfo.Type
|
299 |
+
IsBuiltIn = $commandInfo.IsBuiltIn
|
300 |
+
}
|
301 |
+
}
|
302 |
+
|
303 |
+
# too many numbers lol
|
304 |
+
if ($global:pass_number -lt 2) {
|
305 |
+
foreach ($number in $numberAsts) {
|
306 |
+
$numberText = $number.Extent.Text
|
307 |
+
if ($numberReplacementMap.ContainsKey($numberText)) { continue }
|
308 |
+
|
309 |
+
$newNumber = ObfuscateNumbers $numberText
|
310 |
+
$numberReplacements += @{
|
311 |
+
StartOffset = $number.Extent.StartOffset
|
312 |
+
Length = $number.Extent.Text.Length
|
313 |
+
OriginalName = $numberText
|
314 |
+
Text = $numberText
|
315 |
+
NewName = $newNumber
|
316 |
+
Type = "Number"
|
317 |
+
}
|
318 |
+
}
|
319 |
+
}
|
320 |
+
|
321 |
+
|
322 |
+
$allReplacements = @()
|
323 |
+
|
324 |
+
foreach ($replacement in $barewordReplacements) {
|
325 |
+
$allReplacements += $replacement
|
326 |
+
}
|
327 |
+
|
328 |
+
foreach ($replacement in $numberReplacements) {
|
329 |
+
$allReplacements += $replacement
|
330 |
+
}
|
331 |
+
|
332 |
+
$allReplacements = $allReplacements | Sort-Object { $_.StartOffset } -Descending
|
333 |
+
|
334 |
+
|
335 |
+
foreach ($replacement in $allReplacements) {
|
336 |
+
$newName = switch ($replacement.Type) {
|
337 |
+
"Bareword" { $replacement.NewName }
|
338 |
+
"Number" { $replacement.NewName }
|
339 |
+
}
|
340 |
+
|
341 |
+
Write-Host "Second Pass - Replacing '$($replacement.Text)' at position $($replacement.StartOffset) with '$newName' (Type: $($replacement.Type))"
|
342 |
+
|
343 |
+
$code_copy = Replace-TextAtPosition -SourceText $code_copy `
|
344 |
+
-StartPosition $replacement.StartOffset `
|
345 |
+
-Length $replacement.Length `
|
346 |
+
-ReplacementText $newName
|
347 |
+
}
|
348 |
+
|
349 |
+
return $code_copy
|
350 |
+
}
|
351 |
+
|
352 |
+
function Replace-TextAtPosition {
|
353 |
+
param(
|
354 |
+
[string]$SourceText,
|
355 |
+
[int]$StartPosition,
|
356 |
+
[int]$Length,
|
357 |
+
[string]$ReplacementText
|
358 |
+
)
|
359 |
+
|
360 |
+
try {
|
361 |
+
$before = $SourceText.Substring(0, $StartPosition)
|
362 |
+
$after = $SourceText.Substring($StartPosition + $Length)
|
363 |
+
return $before + $ReplacementText + $after
|
364 |
+
}
|
365 |
+
catch {
|
366 |
+
Write-Host "Error in Replace-TextAtPosition:"
|
367 |
+
Write-Host "Source length: $($SourceText.Length)"
|
368 |
+
Write-Host "Start: $StartPosition"
|
369 |
+
Write-Host "Length: $Length"
|
370 |
+
Write-Host "Replacement: $ReplacementText"
|
371 |
+
throw $_
|
372 |
+
}
|
373 |
+
}
|
374 |
+
|
375 |
+
function Encrypt-Payload($string_payload) {
|
376 |
+
$placeholder_code = @"
|
377 |
+
function Create-AesManagedObject(`$key, `$IV, `$mode) {`$aesManaged = New-Object "System.Security.Cryptography.AesManaged";if (`$mode="CBC") { `$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC }elseif (`$mode="CFB") {`$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CFB}elseif (`$mode="CTS") {`$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CTS}elseif (`$mode="ECB") {`$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::ECB}elseif (`$mode="OFB"){`$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::OFB};`$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7;`$aesManaged.BlockSize = 128;`$aesManaged.KeySize = 256;if (`$IV) {if (`$IV.getType().Name -eq "String") {`$aesManaged.IV = [System.Convert]::FromBase64String(`$IV)}else {`$aesManaged.IV = `$IV}};if (`$key) {if (`$key.getType().Name -eq "String") {`$aesManaged.Key = [System.Convert]::FromBase64String(`$key)}else {`$aesManaged.Key = `$key}};return `$aesManaged};function Decrypt-String(`$key, `$encryptedStringWithIV) {`$bytes = [System.Convert]::FromBase64String(`$encryptedStringWithIV);`$IV = `$bytes[0..15];`$aesManaged = Create-AesManagedObject `$key `$IV;`$decryptor = `$aesManaged.CreateDecryptor();;`$unencryptedData = `$decryptor.TransformFinalBlock(`$bytes, 16, `$bytes.Length - 16);;`$aesManaged.Dispose();return [System.Text.Encoding]::UTF8.GetString(`$unencryptedData).Trim([char]0)};iex(Decrypt-String "YOUR_KEY_HERE" "YOUR_ENCRYPTED_STRING_HERE")
|
378 |
+
"@
|
379 |
+
$key = Create-AesKey
|
380 |
+
$encryptedString = Encrypt-String $key $string_payload
|
381 |
+
$new_code1 = $placeholder_code -replace "YOUR_KEY_HERE", $key
|
382 |
+
$final_code = $new_code1 -replace "YOUR_ENCRYPTED_STRING_HERE", $encryptedString
|
383 |
+
return $final_code
|
384 |
+
}
|
385 |
+
|
386 |
+
function Get-CommandType {
|
387 |
+
param(
|
388 |
+
[string]$CommandName
|
389 |
+
)
|
390 |
+
|
391 |
+
# simple cache because Get-Command is slow ash
|
392 |
+
if ($CommandTypeCache.ContainsKey($CommandName)) {
|
393 |
+
return $CommandTypeCache[$CommandName]
|
394 |
+
}
|
395 |
+
|
396 |
+
$command = Get-Command -Name $CommandName -ErrorAction Ignore
|
397 |
+
|
398 |
+
$result = if ($command) {
|
399 |
+
@{
|
400 |
+
IsBuiltIn = $true
|
401 |
+
Type = $command.CommandType
|
402 |
+
Name = $CommandName
|
403 |
+
}
|
404 |
+
} else {
|
405 |
+
@{
|
406 |
+
IsBuiltIn = $false
|
407 |
+
Type = "Unknown"
|
408 |
+
Name = $CommandName
|
409 |
+
}
|
410 |
+
}
|
411 |
+
|
412 |
+
# cache the result for future calls
|
413 |
+
$CommandTypeCache[$CommandName] = $result
|
414 |
+
return $result
|
415 |
+
}
|
416 |
+
|
417 |
+
function Main($payload) {
|
418 |
+
$obfuscatedCode = ObfuscateCode $payload
|
419 |
+
if ($times -ne 0) {
|
420 |
+
$totalSteps = ($times * 2) + 1
|
421 |
+
$currentStep = 0
|
422 |
+
while ($times -ne 1) {
|
423 |
+
$global:pass_number++
|
424 |
+
$times = $times - 1
|
425 |
+
$obfuscatedCode = Encrypt-Payload $obfuscatedCode
|
426 |
+
$currentStep++
|
427 |
+
Write-Progress -Activity "Obfuscating Code" -Status "Encrypting Payload" -PercentComplete (($currentStep / $totalSteps) * 100)
|
428 |
+
$obfuscatedCode = ObfuscateCode $obfuscatedCode
|
429 |
+
$currentStep++
|
430 |
+
Write-Progress -Activity "Obfuscating Code" -Status "Obfuscating Code" -PercentComplete (($currentStep / $totalSteps) * 100)
|
431 |
+
}
|
432 |
+
}
|
433 |
+
|
434 |
+
Write-Progress -Activity "Obfuscating Code" -Status "Completed" -PercentComplete 100 -Completed
|
435 |
+
return $obfuscatedCode
|
436 |
+
}
|
437 |
+
|
438 |
+
function Get-FileLocation {
|
439 |
+
while ($true) {
|
440 |
+
$file_location = Read-Host "Enter the file location -> "
|
441 |
+
if ((Test-Path $file_location) -and $file_location -like "*.ps1") {
|
442 |
+
return $file_location
|
443 |
+
} else {
|
444 |
+
Write-Host "File not found or not a .ps1 file: $file_location"
|
445 |
+
}
|
446 |
+
}
|
447 |
+
}
|
448 |
+
|
449 |
+
$location_good = Get-FileLocation
|
450 |
+
|
451 |
+
$stuff = Get-Content $location_good -Raw
|
452 |
+
|
453 |
+
$obfuscatedCode = Main $stuff
|
454 |
+
|
455 |
+
$out_file = $location_good -replace ".ps1", "_obf.ps1"
|
456 |
+
$obfuscatedCode | Out-File $out_file -Force
|
Obfus/util/MBA_OBF/mixed_boolean_arithmetic.ps1
ADDED
File without changes
|
Obfus/util/commands/commands.ps1
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
$printables = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
2 |
+
$banned = "abefnrtvABEFNRTV"
|
3 |
+
|
4 |
+
function ObfuscateCommandTypes {
|
5 |
+
param(
|
6 |
+
[string]$CommandText,
|
7 |
+
[hashtable]$CommandInfo,
|
8 |
+
[bool]$RealBearWord = $false
|
9 |
+
)
|
10 |
+
|
11 |
+
if ($RealBearWord) {
|
12 |
+
return DotObfuscateBareWord $CommandText
|
13 |
+
}
|
14 |
+
|
15 |
+
if ($CommandInfo.IsBuiltIn) {
|
16 |
+
switch ($CommandInfo.Type) {
|
17 |
+
"Cmdlet" {
|
18 |
+
$verb, $noun = $CommandText -split '-'
|
19 |
+
if ($noun) {
|
20 |
+
if ($verbose) {
|
21 |
+
Write-Host $CommandText NOUN
|
22 |
+
}
|
23 |
+
return DotObfuscateBareWord $CommandText
|
24 |
+
}
|
25 |
+
if ($verbose) {
|
26 |
+
Write-Host $CommandText VERB
|
27 |
+
}
|
28 |
+
return DotObfuscateBareWord $CommandText
|
29 |
+
}
|
30 |
+
"BuiltinAlias" {
|
31 |
+
return DotObfuscateBareWord $CommandText
|
32 |
+
}
|
33 |
+
"Function" {
|
34 |
+
if ($verbose) {
|
35 |
+
Write-Host $CommandText FUNCTION
|
36 |
+
}
|
37 |
+
return DotObfuscateBareWord $CommandText
|
38 |
+
}
|
39 |
+
"Alias" {
|
40 |
+
return RandomUpercaseCharacters $CommandText
|
41 |
+
}
|
42 |
+
default {
|
43 |
+
return RandomUpercaseCharacters $CommandText
|
44 |
+
}
|
45 |
+
}
|
46 |
+
}
|
47 |
+
else {
|
48 |
+
if ($verbose) {
|
49 |
+
Write-Host $CommandText CUSTOM
|
50 |
+
}
|
51 |
+
return RandomUpercaseCharacters $CommandText
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
function Get-RandomString {
|
56 |
+
$length = Get-Random -Minimum 8 -Maximum 16
|
57 |
+
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
58 |
+
return -join ((1..$length) | ForEach-Object { $chars[(Get-Random -Maximum $chars.Length)] })
|
59 |
+
}
|
60 |
+
|
61 |
+
function RandomUpercaseCharacters($string) {
|
62 |
+
$string = $string -split ""
|
63 |
+
for ($i = 0; $i -lt $string.Length; $i++) {
|
64 |
+
if ($i -gt 0 -and $string[$i - 1] -eq '`' -and $printables.Contains($string[$i])) {
|
65 |
+
continue
|
66 |
+
}
|
67 |
+
|
68 |
+
if ($printables.Contains($string[$i]) -and ($string[$i] -ne "")) {
|
69 |
+
$random = Get-Random -Minimum 0 -Maximum 2
|
70 |
+
if ($random -eq 0) {
|
71 |
+
$string[$i] = $string[$i].ToUpper()
|
72 |
+
}
|
73 |
+
else {
|
74 |
+
$string[$i] = $string[$i].ToLower()
|
75 |
+
}
|
76 |
+
}
|
77 |
+
}
|
78 |
+
return $string -join ''
|
79 |
+
}
|
80 |
+
|
81 |
+
function ObfuscateMethodsGood($string) {
|
82 |
+
$last = $false
|
83 |
+
$first = $true
|
84 |
+
$out_str = ""
|
85 |
+
if ($string.Contains("KDOT!?!_")) {
|
86 |
+
return $string
|
87 |
+
}
|
88 |
+
$string = $string -split ""
|
89 |
+
$string | ForEach-Object {
|
90 |
+
if (($first -eq $true) -and ($_ -ne "")) {
|
91 |
+
$out_str += $_
|
92 |
+
$first = $false
|
93 |
+
}
|
94 |
+
else {
|
95 |
+
if ($_ -ne "") {
|
96 |
+
$random = Get-Random -Minimum 0 -Maximum 3
|
97 |
+
if (($random -eq 0) -and ($last -eq $false)) {
|
98 |
+
$out_str += "`'$_`'"
|
99 |
+
$last = $true
|
100 |
+
}
|
101 |
+
elseif (($random -eq 1) -and ($last -eq $false) -and ($printables.Contains($_)) -and ($_ -ne "") -and (!($banned.Contains($_)))) {
|
102 |
+
$out_str += "``$_"
|
103 |
+
$last = $true
|
104 |
+
}
|
105 |
+
else {
|
106 |
+
$out_str += $_
|
107 |
+
$last = $false
|
108 |
+
}
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
112 |
+
return $out_str
|
113 |
+
}
|
114 |
+
|
115 |
+
function DotObfuscateBareWord($string) {
|
116 |
+
$split_str = $string -split ""
|
117 |
+
$map = @()
|
118 |
+
# get the char value for each char in the string
|
119 |
+
$split_str | ForEach-Object {
|
120 |
+
if ($_ -ne "") {
|
121 |
+
$map += [int][char]$_
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
$out_str = ".("
|
126 |
+
|
127 |
+
$map | ForEach-Object {
|
128 |
+
if ($global:pass_number -lt 2) {
|
129 |
+
$obfuscated = AddOrSubtractRandomEQ $_
|
130 |
+
$out_str += "[char]($obfuscated)+"
|
131 |
+
} else {
|
132 |
+
$out_str += "[char]($_)+"
|
133 |
+
}
|
134 |
+
|
135 |
+
}
|
136 |
+
$out_str = $out_str.Substring(0, $out_str.Length - 1)
|
137 |
+
$out_str += ")"
|
138 |
+
return $out_str
|
139 |
+
}
|
140 |
+
|
141 |
+
function AddOrSubtractRandomEQ($number_to_obf) {
|
142 |
+
#get 3 random numbers
|
143 |
+
$number1 = Get-Random -Minimum 1 -Maximum 10000
|
144 |
+
$number2 = Get-Random -Minimum 1 -Maximum 10000
|
145 |
+
$number3 = Get-Random -Minimum 1 -Maximum 10000
|
146 |
+
|
147 |
+
$signs = @('+', '-')
|
148 |
+
|
149 |
+
$num1_sign = Get-Random -Minimum 0 -Maximum 2
|
150 |
+
$num2_sign = Get-Random -Minimum 0 -Maximum 2
|
151 |
+
$num3_sign = Get-Random -Minimum 0 -Maximum 2
|
152 |
+
|
153 |
+
$sign1 = $signs[$num1_sign]
|
154 |
+
$sign2 = $signs[$num2_sign]
|
155 |
+
$sign3 = $signs[$num3_sign]
|
156 |
+
|
157 |
+
$opposite_sign1 = $signs[1 - $num1_sign]
|
158 |
+
$opposite_sign2 = $signs[1 - $num2_sign]
|
159 |
+
$opposite_sign3 = $signs[1 - $num3_sign]
|
160 |
+
|
161 |
+
$final_number = "$number_to_obf $sign1 $number1 $sign2 $number2 $sign3 $number3"
|
162 |
+
$out_final = Invoke-Expression $final_number
|
163 |
+
|
164 |
+
$new_problem = "$out_final $opposite_sign1 $number1 $opposite_sign2 $number2 $opposite_sign3 $number3"
|
165 |
+
return "($new_problem)"
|
166 |
+
}
|
167 |
+
|
168 |
+
#ObfuscateMethodsGood "KDOT_frslwSZslJ"
|
Obfus/util/commands/function_names.ps1
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Define characters for function name generation
|
2 |
+
$characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
3 |
+
|
4 |
+
function Create_Random_String {
|
5 |
+
$string = $characters[(Get-Random -Minimum 26 -Maximum $characters.Length)]
|
6 |
+
|
7 |
+
for ($i = 0; $i -lt 15; $i++) {
|
8 |
+
$string += $characters[(Get-Random -Minimum 0 -Maximum $characters.Length)]
|
9 |
+
}
|
10 |
+
return $string
|
11 |
+
}
|
12 |
+
|
13 |
+
function ObfuscateFunctionNames($name) {
|
14 |
+
$newName = Create_Random_String
|
15 |
+
return $newName
|
16 |
+
}
|
Obfus/util/final/encodeOutput.ps1
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Taken from https://gist.github.com/ctigeek/2a56648b923d198a6e60
|
2 |
+
|
3 |
+
function Create-AesManagedObject($key, $IV, $mode) {
|
4 |
+
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
|
5 |
+
|
6 |
+
if ($mode="CBC") { $aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC }
|
7 |
+
elseif ($mode="CFB") {$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CFB}
|
8 |
+
elseif ($mode="CTS") {$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CTS}
|
9 |
+
elseif ($mode="ECB") {$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::ECB}
|
10 |
+
elseif ($mode="OFB"){$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::OFB}
|
11 |
+
|
12 |
+
|
13 |
+
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
|
14 |
+
$aesManaged.BlockSize = 128
|
15 |
+
$aesManaged.KeySize = 256
|
16 |
+
if ($IV) {
|
17 |
+
if ($IV.getType().Name -eq "String") {
|
18 |
+
$aesManaged.IV = [System.Convert]::FromBase64String($IV)
|
19 |
+
}
|
20 |
+
else {
|
21 |
+
$aesManaged.IV = $IV
|
22 |
+
}
|
23 |
+
}
|
24 |
+
if ($key) {
|
25 |
+
if ($key.getType().Name -eq "String") {
|
26 |
+
$aesManaged.Key = [System.Convert]::FromBase64String($key)
|
27 |
+
}
|
28 |
+
else {
|
29 |
+
$aesManaged.Key = $key
|
30 |
+
}
|
31 |
+
}
|
32 |
+
return $aesManaged
|
33 |
+
}
|
34 |
+
|
35 |
+
function Create-AesKey() {
|
36 |
+
$aesManaged = Create-AesManagedObject
|
37 |
+
$aesManaged.GenerateKey()
|
38 |
+
return [System.Convert]::ToBase64String($aesManaged.Key)
|
39 |
+
}
|
40 |
+
|
41 |
+
function Encrypt-String($key, $plaintext) {
|
42 |
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($plaintext)
|
43 |
+
$aesManaged = Create-AesManagedObject $key
|
44 |
+
$encryptor = $aesManaged.CreateEncryptor()
|
45 |
+
$encryptedData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length)
|
46 |
+
[byte[]] $fullData = $aesManaged.IV + $encryptedData
|
47 |
+
return [System.Convert]::ToBase64String($fullData)
|
48 |
+
}
|
49 |
+
|
50 |
+
function Decrypt-String($key, $encryptedStringWithIV) {r
|
51 |
+
$bytes = [System.Convert]::FromBase64String($encryptedStringWithIV)
|
52 |
+
$IV = $bytes[0..15]
|
53 |
+
$aesManaged = Create-AesManagedObject $key $IV
|
54 |
+
$decryptor = $aesManaged.CreateDecryptor();
|
55 |
+
$unencryptedData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16)
|
56 |
+
$aesManaged.Dispose()
|
57 |
+
return [System.Text.Encoding]::UTF8.GetString($unencryptedData).Trim([char]0)
|
58 |
+
}
|
59 |
+
|
60 |
+
#$key = Create-AesKey
|
61 |
+
#
|
62 |
+
#
|
63 |
+
#$plaintext = "This is a test string"
|
64 |
+
#$mode = "OFB"
|
65 |
+
#"== Powershell AES $mode Encyption=="
|
66 |
+
#"`nKey: "+$key
|
67 |
+
#
|
68 |
+
#$encryptedString = Encrypt-String $key $plaintext
|
69 |
+
#
|
70 |
+
#$bytes = [System.Convert]::FromBase64String($encryptedString)
|
71 |
+
#
|
72 |
+
#$IV = $bytes[0..15]
|
73 |
+
#"Salt: " + [System.Convert]::ToHexString($IV)
|
74 |
+
#"Salt: " + [System.Convert]::ToBase64String($IV)
|
75 |
+
#
|
76 |
+
#$plain = Decrypt-String $key $encryptedString
|
77 |
+
#
|
78 |
+
#"`nEncrypted: "+$encryptedString
|
79 |
+
#
|
80 |
+
#"Decrypted: "+$plain
|
81 |
+
|
82 |
+
function Encrypt-Payload($string_payload) {
|
83 |
+
$placeholder_code = @"
|
84 |
+
function Decrypt-String(`$key, `$encryptedStringWithIV) {`$bytes = [System.Convert]::FromBase64String(`$encryptedStringWithIV);`$IV = `$bytes[0..15];`$aesManaged = Create-AesManagedObject `$key `$IV;`$decryptor = `$aesManaged.CreateDecryptor();;`$unencryptedData = `$decryptor.TransformFinalBlock(`$bytes, 16, `$bytes.Length - 16);;`$aesManaged.Dispose();return [System.Text.Encoding]::UTF8.GetString(`$unencryptedData).Trim([char]0)};iex(Decrypt-String "YOUR_KEY_HERE" "YOUR_ENCRYPTED_STRING_HERE")
|
85 |
+
"@
|
86 |
+
$key = Create-AesKey
|
87 |
+
$encryptedString = Encrypt-String $key $string_payload
|
88 |
+
$placeholder_code -replace "YOUR_KEY_HERE", $key
|
89 |
+
$placeholder_code -replace "YOUR_ENCRYPTED_STRING_HERE", $encryptedString
|
90 |
+
return $placeholder_code
|
91 |
+
}
|
92 |
+
|
93 |
+
$placeholder_code -replace "YOUR_KEY_HERE" | Out-Null
|
Obfus/util/numbers/obfuscate_numbers.ps1
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function ObfuscateNumbers($number) {
|
2 |
+
$number_to_obf = $number
|
3 |
+
$obf_number = AddOrSubtractRandomEQ $number_to_obf
|
4 |
+
return $obf_number
|
5 |
+
}
|
6 |
+
|
7 |
+
function AddOrSubtractRandomEQ($number_to_obf) {
|
8 |
+
#get 3 random numbers
|
9 |
+
$number1 = Get-Random -Minimum 1 -Maximum 10000
|
10 |
+
$number2 = Get-Random -Minimum 1 -Maximum 10000
|
11 |
+
$number3 = Get-Random -Minimum 1 -Maximum 10000
|
12 |
+
|
13 |
+
$signs = @('+', '-')
|
14 |
+
|
15 |
+
$num1_sign = Get-Random -Minimum 0 -Maximum 2
|
16 |
+
$num2_sign = Get-Random -Minimum 0 -Maximum 2
|
17 |
+
$num3_sign = Get-Random -Minimum 0 -Maximum 2
|
18 |
+
|
19 |
+
$sign1 = $signs[$num1_sign]
|
20 |
+
$sign2 = $signs[$num2_sign]
|
21 |
+
$sign3 = $signs[$num3_sign]
|
22 |
+
|
23 |
+
$opposite_sign1 = $signs[1 - $num1_sign]
|
24 |
+
$opposite_sign2 = $signs[1 - $num2_sign]
|
25 |
+
$opposite_sign3 = $signs[1 - $num3_sign]
|
26 |
+
|
27 |
+
$final_number = "$number_to_obf $sign1 $number1 $sign2 $number2 $sign3 $number3"
|
28 |
+
$out_final = Invoke-Expression $final_number
|
29 |
+
|
30 |
+
$new_problem = "$out_final $opposite_sign1 $number1 $opposite_sign2 $number2 $opposite_sign3 $number3"
|
31 |
+
return "($new_problem)"
|
32 |
+
}
|
Obfus/util/strings/strings.ps1
ADDED
@@ -0,0 +1,233 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#TODO add env var obf
|
2 |
+
$split_string_verbose = $false
|
3 |
+
|
4 |
+
function ObfuscateString($string) {
|
5 |
+
$splitting = $true
|
6 |
+
if ($string.Length -lt 4) {
|
7 |
+
$splitting = $false
|
8 |
+
}
|
9 |
+
if ($string.StartsWith("'") -and $string.EndsWith("'")) {
|
10 |
+
$string = $string.Substring(1, $string.Length - 2)
|
11 |
+
}
|
12 |
+
if ($string.StartsWith('"') -and $string.EndsWith('"')) {
|
13 |
+
$string = $string.Substring(1, $string.Length - 2)
|
14 |
+
}
|
15 |
+
$string = $string -replace "`'", "`'`'"
|
16 |
+
if ($string -eq "") {
|
17 |
+
return "''"
|
18 |
+
}
|
19 |
+
$out_content = ""
|
20 |
+
|
21 |
+
if ($splitting -eq $false) {
|
22 |
+
$string_pieces = @($string)
|
23 |
+
} else {
|
24 |
+
try {
|
25 |
+
[string[]]$string_pieces = SplitStrings $string
|
26 |
+
}
|
27 |
+
catch {
|
28 |
+
Write-Host "Error splitting string: $string"
|
29 |
+
Read-Host "Press enter to exit..."
|
30 |
+
exit 1
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
for ($i = 0; $i -lt $string_pieces.Count; $i++) {
|
35 |
+
$small_string = $string_pieces[$i]
|
36 |
+
$obfuscationFunctions = @(
|
37 |
+
#"ObfuscateStringReverse",
|
38 |
+
"ObfuscateBase64String",
|
39 |
+
#"ObfuscateReplaceString",
|
40 |
+
"ObfuscateHexString",
|
41 |
+
"ObfuscateByteArrayString",
|
42 |
+
"ObfuscateMixedString"
|
43 |
+
)
|
44 |
+
$random = Get-Random -Minimum 0 -Maximum $obfuscationFunctions.Length
|
45 |
+
$obfuscationFunction = $obfuscationFunctions[$random]
|
46 |
+
$out_content2 = & $obfuscationFunction $small_string
|
47 |
+
|
48 |
+
if ($i -lt ($string_pieces.Count - 1)) {
|
49 |
+
$out_content += "$out_content2 + "
|
50 |
+
} else {
|
51 |
+
$out_content += $out_content2
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
return "($out_content)"
|
56 |
+
}
|
57 |
+
|
58 |
+
function ObfuscateStringReverse($string) {
|
59 |
+
#WORKING
|
60 |
+
$split_string = $string -split ""
|
61 |
+
[array]::Reverse($split_string)
|
62 |
+
$reversed_string = $split_string -join ''
|
63 |
+
$command = "('$reversed_string'[-1..-$($reversed_string.Length)] -join '')"
|
64 |
+
return $command
|
65 |
+
}
|
66 |
+
|
67 |
+
function ObfuscateBase64String($string) {
|
68 |
+
#WORKING
|
69 |
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($string)
|
70 |
+
$encoded = [System.Convert]::ToBase64String($bytes)
|
71 |
+
$command = "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('$encoded'))"
|
72 |
+
return $command
|
73 |
+
}
|
74 |
+
|
75 |
+
function ObfuscateByteArrayString($string) {
|
76 |
+
#WORKING
|
77 |
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($string)
|
78 |
+
$good_bytes = "(" + ($bytes -join ', ') + ")"
|
79 |
+
$command = "[System.Text.Encoding]::UTF8.GetString($good_bytes)"
|
80 |
+
return $command
|
81 |
+
}
|
82 |
+
|
83 |
+
function ObfuscateHexString($string) {
|
84 |
+
if ([string]::IsNullOrEmpty($string)) {
|
85 |
+
return "''"
|
86 |
+
}
|
87 |
+
|
88 |
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($string)
|
89 |
+
$hexString = $bytes | ForEach-Object { "0x{0:x2}" -f $_ }
|
90 |
+
$hexString = "($($hexString -join ', '))"
|
91 |
+
$command = "[System.Text.Encoding]::UTF8.GetString($hexString)"
|
92 |
+
return $command
|
93 |
+
}
|
94 |
+
|
95 |
+
function ObfuscateMixedString($string) {
|
96 |
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($string)
|
97 |
+
$hexArray = $bytes | ForEach-Object { "0x{0:x2}" -f $_ }
|
98 |
+
|
99 |
+
if ($bytes.Length -eq 1) {
|
100 |
+
$byteArrayString = $bytes[0]
|
101 |
+
} else {
|
102 |
+
$mixedArray = for ($i = 0; $i -lt $bytes.Length; $i++) {
|
103 |
+
if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) {
|
104 |
+
$bytes[$i]
|
105 |
+
} else {
|
106 |
+
$hexArray[$i]
|
107 |
+
}
|
108 |
+
}
|
109 |
+
$byteArrayString = "(" + ($mixedArray -join ', ') + ")"
|
110 |
+
}
|
111 |
+
|
112 |
+
$command = "[System.Text.Encoding]::UTF8.GetString($byteArrayString)"
|
113 |
+
return $command
|
114 |
+
}
|
115 |
+
|
116 |
+
function SplitStrings {
|
117 |
+
param (
|
118 |
+
[string]$string
|
119 |
+
)
|
120 |
+
|
121 |
+
$string_length = $string.Length
|
122 |
+
if ($string_length -lt 2) {
|
123 |
+
return @($string)
|
124 |
+
}
|
125 |
+
|
126 |
+
# array to store chunks
|
127 |
+
$result = @()
|
128 |
+
$i = 0
|
129 |
+
|
130 |
+
while ($i -lt $string_length) {
|
131 |
+
if ($string_length -lt 10) {
|
132 |
+
$chunk_length = Get-Random -Minimum 2 -Maximum 5
|
133 |
+
} elseif ($string_length -lt 50) {
|
134 |
+
$chunk_length = Get-Random -Minimum 15 -Maximum 25
|
135 |
+
} elseif ($string_length -lt 100) {
|
136 |
+
$chunk_length = Get-Random -Minimum 24 -Maximum 50
|
137 |
+
} elseif ($string_length -lt 200) {
|
138 |
+
$chunk_length = Get-Random -Minimum 50 -Maximum 100
|
139 |
+
} elseif ($string_length -lt 500) {
|
140 |
+
$chunk_length = Get-Random -Minimum 75 -Maximum 200
|
141 |
+
} elseif ($string_length -lt 1000) {
|
142 |
+
$chunk_length = Get-Random -Minimum 100 -Maximum 300
|
143 |
+
} else {
|
144 |
+
$chunk_length = Get-Random -Minimum 200 -Maximum 500
|
145 |
+
}
|
146 |
+
|
147 |
+
# make sure we got the remaining string length
|
148 |
+
$length = [Math]::Min($chunk_length, $string_length - $i)
|
149 |
+
|
150 |
+
# add it to the chunk array
|
151 |
+
$result += $string.Substring($i, $length)
|
152 |
+
|
153 |
+
# move the index forward of how far we've gone.
|
154 |
+
$i += $length
|
155 |
+
|
156 |
+
if ($split_string_verbose) {
|
157 |
+
Write-Host "Chunk: $($result[-1])"
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
#pretty print the chunks
|
162 |
+
if ($split_string_verbose) {
|
163 |
+
Write-Host "Chunks: $($result -join ', ')"
|
164 |
+
}
|
165 |
+
|
166 |
+
return $result
|
167 |
+
}
|
168 |
+
|
169 |
+
function ObfuscateReplaceString($string) {
|
170 |
+
#BROKEN
|
171 |
+
$split_str = SplitStrings $string
|
172 |
+
$replaces_amount = $split_str.Length
|
173 |
+
|
174 |
+
$set_dict = @{}
|
175 |
+
|
176 |
+
for ($i = 0; $i -lt $replaces_amount; $i++) {
|
177 |
+
$set_dict[$i] = $split_str[$i]
|
178 |
+
}
|
179 |
+
|
180 |
+
$shuffled_key_locations = @()
|
181 |
+
for ($i = 0; $i -lt $replaces_amount; $i++) {
|
182 |
+
$shuffled_key_locations += $i
|
183 |
+
}
|
184 |
+
|
185 |
+
#this is the order we will put the keys in the string.
|
186 |
+
$shuffled_keys = $shuffled_key_locations | Sort-Object {Get-Random}
|
187 |
+
|
188 |
+
$format_string = ""
|
189 |
+
$arguments = @()
|
190 |
+
|
191 |
+
#make the output look like "{1}{0}{2}" -f "b", "a", "c"
|
192 |
+
for ($i = 0; $i -lt $shuffled_keys.Length; $i++) {
|
193 |
+
$format_string += "{$($shuffled_keys[$i])}"
|
194 |
+
$arguments += $set_dict[$i]
|
195 |
+
}
|
196 |
+
|
197 |
+
$format_string = '"' + $format_string + '"'
|
198 |
+
$arguments = '"' + ($arguments -join '", "') + '"'
|
199 |
+
|
200 |
+
$command = "($format_string -f $arguments)"
|
201 |
+
|
202 |
+
Write-Host "Obfuscated: $command"
|
203 |
+
Write-Host $shuffled_key_locations
|
204 |
+
Write-Host $shuffled_keys
|
205 |
+
Write-Host $format_string
|
206 |
+
Write-Host $arguments
|
207 |
+
|
208 |
+
return $command
|
209 |
+
}
|
210 |
+
|
211 |
+
function make_random_string($length) {
|
212 |
+
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
213 |
+
return -join ((1..$length) | ForEach-Object { $chars[(Get-Random -Maximum $chars.Length)] })
|
214 |
+
}
|
215 |
+
|
216 |
+
## Test the obfuscation
|
217 |
+
#for ($i = 0; $i -lt 1000; $i++) {
|
218 |
+
# $length = Get-Random -Minimum 1 -Maximum 10
|
219 |
+
# $string = make_random_string $length
|
220 |
+
# $obfuscated_string = ObfuscateReplaceString $string
|
221 |
+
# $deobfuscated_string = Invoke-Expression $obfuscated_string
|
222 |
+
#
|
223 |
+
# if ($string -ne $deobfuscated_string) {
|
224 |
+
# Write-Host "-------------------------------------"
|
225 |
+
# Write-Host "$string"
|
226 |
+
# Write-Host "$deobfuscated_string"
|
227 |
+
# Write-Host "Failed to deobfuscate string: $string"
|
228 |
+
# Write-Host "Obfuscated: $obfuscated_string"
|
229 |
+
# Write-Host "Deobfuscated: $deobfuscated_string"
|
230 |
+
# Write-Host "Press Enter to continue..."
|
231 |
+
# Read-Host
|
232 |
+
# }
|
233 |
+
#}
|
Obfus/util/variables/variables.ps1
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
$bad_vars2 = @('$_', '$ignore', '$PSScriptRoot', '$global', '$MyInvocation', '$local', '`$', '$args', '$ErrorActionPreference', '$ProgressPreference', '$PROFILE')
|
2 |
+
$good_chars = "cdghijklmopqsuwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
3 |
+
|
4 |
+
function ObfuscateVariables($variable_good, $parameter) {
|
5 |
+
$lower_var = $variable_good.ToLower()
|
6 |
+
switch ($lower_var) {
|
7 |
+
'$true' { return ObfuscateTrue }
|
8 |
+
'$false' { return ObfuscateFalse }
|
9 |
+
'$null' { return ObfuscateNull }
|
10 |
+
}
|
11 |
+
|
12 |
+
foreach ($bad_var in $bad_vars2) {
|
13 |
+
if ($lower_var -contains $bad_var) {
|
14 |
+
return $variable_good
|
15 |
+
}
|
16 |
+
}
|
17 |
+
$var = MakeRandomVariableName 10
|
18 |
+
$new_var_final = RandomChangeVar $var $parameter
|
19 |
+
Write-Host "Obfuscating variable: $variable_good to $new_var_final"
|
20 |
+
return $new_var_final
|
21 |
+
}
|
22 |
+
|
23 |
+
function MakeRandomVariableName($length) {
|
24 |
+
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
25 |
+
$name = "`$KDOT"
|
26 |
+
for ($i = 0; $i -lt $length; $i++) {
|
27 |
+
$name += $chars[(Get-Random -Minimum 0 -Maximum $chars.Length)]
|
28 |
+
}
|
29 |
+
return $name
|
30 |
+
}
|
31 |
+
|
32 |
+
function RandomChangeVar($variable, $parameter) {
|
33 |
+
# if the variable is in good_chars, do random capitalization and randomly add a ` in front.
|
34 |
+
$ticks = Get-Random -Minimum 0 -Maximum 2
|
35 |
+
if ($parameter -eq $true) {
|
36 |
+
$ticks = 999
|
37 |
+
}
|
38 |
+
$variable = $variable -split ""
|
39 |
+
for ($i = 0; $i -lt $variable.Length; $i++) {
|
40 |
+
if ($i -gt 0 -and $variable[$i - 1] -eq '`' -and $good_chars.Contains($variable[$i])) {
|
41 |
+
continue
|
42 |
+
}
|
43 |
+
|
44 |
+
if ($good_chars.Contains($variable[$i]) -and ($variable[$i] -ne "")) {
|
45 |
+
$random = Get-Random -Minimum 0 -Maximum 2
|
46 |
+
$random2 = Get-Random -Minimum 0 -Maximum 2
|
47 |
+
if ($random -eq 0) {
|
48 |
+
$variable[$i] = $variable[$i].ToUpper()
|
49 |
+
} else {
|
50 |
+
$variable[$i] = $variable[$i].ToLower()
|
51 |
+
}
|
52 |
+
|
53 |
+
if (($random2 -eq 0) -and ($ticks -eq 0)) {
|
54 |
+
$variable[$i] = "``" + $variable[$i]
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
58 |
+
$variable = $variable -join ''
|
59 |
+
if ($ticks -eq 0) {
|
60 |
+
#insert a { at the beginning after the first character and a } at the end
|
61 |
+
$variable = $variable.Insert(1, "{")
|
62 |
+
$variable += "}"
|
63 |
+
}
|
64 |
+
return $variable
|
65 |
+
}
|
66 |
+
|
67 |
+
function ObfuscateTrue {
|
68 |
+
return '$true'
|
69 |
+
}
|
70 |
+
|
71 |
+
function ObfuscateFalse {
|
72 |
+
return '$false'
|
73 |
+
}
|
74 |
+
|
75 |
+
function ObfuscateNull {
|
76 |
+
return '$null'
|
77 |
+
}
|
78 |
+
|
79 |
+
#ObfuscateVariables '$this_is_a_test'
|