Implementing FilePathTransformer, URLTransformer, Regex modifiers

Also updating CharacterInsertion and Sed
This commit is contained in:
Wietze
2024-02-17 15:49:06 +00:00
parent 36d4df012f
commit 84bf4e85f4
8 changed files with 223 additions and 25 deletions
+5 -2
View File
@@ -4,6 +4,9 @@ using module "Modifiers\CharacterInsertion.psm1"
using module "Modifiers\RandomCase.psm1"
using module "Modifiers\OptionCharSubstitution.psm1"
using module "Modifiers\Sed.psm1"
using module "Modifiers\FilePathTransformer.psm1"
using module "Modifiers\UrlTransformer.psm1"
using module "Modifiers\Regex.psm1"
param (
[Parameter(Mandatory = $true)][string]$InputFile,
@@ -27,7 +30,7 @@ function Parse-Json {
foreach ($modifier_params in $JSONData.modifiers.PSObject.Properties) {
$ModifierName = $modifier_params.Name;
$ModifierName = $modifier_params.Name -replace "^(?i)regex$","RegularExpression"; # Regex is a reserved name, hence this rename for the Modifier class
$Modifier = ($ModifierName -as [type])
if ($null -eq $Modifier) {
@@ -64,7 +67,7 @@ function Parse-Json {
# Show final result
$Output = $tokens[0]
if($Tokens.length -gt 0){
if($Tokens.Count -gt 1){
ForEach ($Index in (1..($Tokens.Count - 1))) {
$Output = -join ($Output, $(if (($Tokens[$Index - 1].Type -eq "argument" -or $Tokens[$Index - 1].Type -eq "value") -and ($Tokens[$Index - 1].TokenContent[-1] -eq "=")) { "" } else { " " }), ($Tokens[$Index].ToString()))
}
+22 -16
View File
@@ -4,28 +4,34 @@ using module "..\Types\Token.psm1"
class CharacterInsertion : Modifier {
[float]$Probability;
[char[]]$Characters;
[int]$Offset;
CharacterInsertion([Token[]]$InputCommandTokens, [string[]]$ExcludedTypes, [float]$Probability, [string[]]$Characters) : base($InputCommandTokens, $ExcludedTypes) {
CharacterInsertion([Token[]]$InputCommandTokens, [string[]]$ExcludedTypes, [float]$Probability, [string[]]$Characters, [int]$Offset) : base($InputCommandTokens, $ExcludedTypes) {
$this.Probability = $Probability;
$this.Characters = $Characters;
$this.Offset = $Offset;
}
[void]GenerateOutput(){
foreach($Token in $this.InputCommandTokens){
$NewTokenContent = [System.Collections.ArrayList]@();
foreach($Char in $Token.TokenContent){
$NewTokenContent.Add($Char);
$i = 0;
if(!$this.ExcludedTypes.Contains($Token.Type) -and [Modifier]::CoinFlip($this.Probability)){
do {
$chosen = [Modifier]::ChooseRandom($this.Characters)
$NewTokenContent.Add($chosen);
$i++;
} while ([Modifier]::CoinFlip($this.Probability * [Math]::Pow(0.9, $i)));
}
}
[void]GenerateOutput() {
foreach ($Token in $this.InputCommandTokens) {
if (!$this.ExcludedTypes.Contains($Token.Type)) {
$NewTokenContent = [System.Collections.ArrayList]@();
$Token.TokenContent | Select-Object -First $this.Offset | ForEach-Object { $NewTokenContent.Add($_) }
$Token.TokenContent = $NewTokenContent;
foreach ($Char in ($Token.TokenContent | Select-Object -Skip $this.Offset)) {
$NewTokenContent.Add($Char);
$i = 0;
if ([Modifier]::CoinFlip($this.Probability)) {
do {
$chosen = [Modifier]::ChooseRandom($this.Characters)
$NewTokenContent.Add($chosen);
$i++;
} while ([Modifier]::CoinFlip($this.Probability * [Math]::Pow(0.9, $i)));
}
}
$Token.TokenContent = $NewTokenContent;
}
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using module "..\Types\Modifier.psm1"
using module "..\Types\Token.psm1"
class FilePathTransformer : Modifier {
[float]$Probability;
[boolean]$PathTraversal;
[boolean]$SubstituteSlashes;
[boolean]$ExtraSlashes;
$keywords = @("debug", "system32", "compile", "winsxs", "temp", "update")
FilePathTransformer([Token[]]$InputCommandTokens, [string[]]$ExcludedTypes, [float]$Probability, [boolean]$PathTraversal, [boolean]$SubstituteSlashes, [boolean]$ExtraSlashes) : base($InputCommandTokens, $ExcludedTypes) {
$this.Probability = $Probability;
$this.PathTraversal = $PathTraversal;
$this.SubstituteSlashes = $SubstituteSlashes;
$this.ExtraSlashes = $ExtraSlashes;
}
[void]GenerateOutput() {
foreach ($Token in $this.InputCommandTokens) {
$NewTokenContent = $Token.ToString();
if (!$this.ExcludedTypes.Contains($Token.Type)) {
# Path Traversal
if ($this.PathTraversal) {
$NewTokenContent = [regex]::replace($NewTokenContent, "([^\\/])([\\/])([^\\/])", {
$slash = $args[0].groups[2].value;
if ([Modifier]::CoinFlip($this.Probability)) {
$subpath = $slash + [Modifier]::ChooseRandom($this.Keywords) + $slash + ".." + $slash;
return $args[0].groups[1].value + $subpath + $args[0].groups[3].value;
}
return $args[0].groups[0].value;
});
}
# Substitute slashes
if ($this.SubstituteSlashes) {
$NewTokenContent = [regex]::replace($NewTokenContent, "[/\\]", {
if ([Modifier]::CoinFlip($this.Probability)) {
if ($args[0].value -eq "/") {
return "\\"
}
return "/"
}
return $args[0].value;
});
}
# Extra slashes
if ($this.ExtraSlashes) {
$NewTokenContent = [regex]::replace($NewTokenContent, "([^\\/])([\\/])([^\\/])", {
$slash = $args[0].groups[2].value;
if ([Modifier]::CoinFlip($this.Probability)) {
$extra_slashes = $slash * [Modifier]::ChooseRandom($(2, 3, 4));
return $args[0].groups[1].value + $extra_slashes + $args[0].groups[3].value;
}
return $args[0].groups[0].value;
});
}
$Token.TokenContent = $NewTokenContent;
}
}
}
}
-3
View File
@@ -18,6 +18,3 @@ class OptionCharSubstitution : Modifier {
}
}
}
+47
View File
@@ -0,0 +1,47 @@
using module "..\Types\Modifier.psm1"
using module "..\Types\Token.psm1"
# 'Regex' is taken, hence 'RegularExpression'
class RegularExpression : Modifier {
[float]$Probability;
[string]$RegexMatch;
[string]$RegexReplace;
RegularExpression([Token[]]$InputCommandTokens, [string[]]$ExcludedTypes, [float]$Probability, [string]$RegexMatch, [string]$RegexReplace, [boolean]$CaseSensitive) : base($InputCommandTokens, $ExcludedTypes) {
$this.Probability = $Probability;
$this.RegexMatch = $RegexMatch;
if(!$CaseSensitive){
$this.RegexMatch = "(?i)"+ $this.RegexMatch;
}
$this.RegexReplace = $RegexReplace;
}
[void]GenerateOutput() {
foreach ($Token in $this.InputCommandTokens) {
$NewTokenContent = $Token.ToString();
if (!$this.ExcludedTypes.Contains($Token.Type) -and [Modifier]::CoinFlip($this.Probability)) {
$this.RegexReplace = [regex]::replace($this.RegexReplace, "\`$(\d+)\[(\d+):(\d+(?:-x?(?:\d+)?)?)\]", {
[int]$rIndex = $args[0].groups[1].value
[int]$start = $args[0].groups[2].value
[string]$end = $args[0].groups[3].value
if($NewTokenContent -match $this.RegexMatch){
$match = $Matches[$rIndex]
if($end.IndexOf('-') -ge 0){
$ids = $end.split('-')
if($ids[1] -eq ''){$ids[1] = $match.length;}
[int]$end = Get-Random -Minimum ([int]($ids[0])) -Maximum ([int]($ids[1]));
}
return $match.substring($start, $end);
}
return $args[0].value;
});
$this.RegexMatch = $this.RegexMatch -replace "`$RANDOM",(-join((65..90) + (97..122)|Get-Random -Count (Get-Random -minimum 1 -Maximum 20)|ForEach-Object {[char]$_}))
$NewTokenContent = [regex]::replace($NewTokenContent, $this.RegexMatch, $this.RegexReplace)
$Token.TokenContent = $NewTokenContent;
}
}
}
}
+2 -2
View File
@@ -25,9 +25,9 @@ class Sed : Modifier {
while ($Instance -ge 0) {
$Replacement = [Modifier]::ChooseRandom($Match.Replace);
if ([Modifier]::CoinFlip($this.Probability)) {
$NewTokenContent = $NewTokenContent.Substring(0, $instance) + $Replacement + $NewTOkenContent.substring($instance + $match.Find.length);
$NewTokenContent = $NewTokenContent.Substring(0, $instance) + $Replacement + $NewTokenContent.substring($instance + $match.Find.length);
}
$instance = $NewTokenContent.IndexOf($Match.Find, $instance + $Replacement.Length);
$instance = $NewTokenContent.IndexOf($Match.Find, [math]::Min($instance + $Replacement.Length, $NewTokenContent.Length));
}
}
$Token.TokenContent = $NewTokenContent.ToCharArray()
+82
View File
@@ -0,0 +1,82 @@
using module "..\Types\Modifier.psm1"
using module "..\Types\Token.psm1"
class UrlTransformer : Modifier {
[float]$Probability;
[boolean]$LeaveOutProtocol;
[boolean]$LeaveOutDoubleSlashes;
[boolean]$SubstituteSlashes;
[boolean]$IpToHex;
[boolean]$PathTraversal;
$keywords = @("debug", "system32", "compile", "winsxs", "temp", "update")
UrlTransformer([Token[]]$InputCommandTokens, [string[]]$ExcludedTypes, [float]$Probability, [boolean]$LeaveOutProtocol, [boolean]$LeaveOutDoubleSlashes, [boolean]$SubstituteSlashes, [boolean]$IpToHex, [boolean]$PathTraversal) : base($InputCommandTokens, $ExcludedTypes) {
$this.Probability = $Probability;
$this.LeaveOutProtocol = $LeaveOutProtocol;
$this.SubstituteSlashes = $SubstituteSlashes;
$this.IpToHex = $IpToHex;
$this.PathTraversal = $PathTraversal;
}
[void]GenerateOutput() {
foreach ($Token in $this.InputCommandTokens) {
$NewTokenContent = $Token.ToString();
if (!$this.ExcludedTypes.Contains($Token.Type)) {
# Leave out protocol
if ($this.LeaveOutProtocol -and [Modifier]::CoinFlip($this.Probability)) {
$NewTokenContent = [regex]::replace($NewTokenContent, "\w+:\/\/", "://");
}
# Path Traversal
if ($this.PathTraversal) {
[int]$i = 0;
do {
$NewTokenContent = [regex]::replace($NewTokenContent, "([^/])([/])([^/])", {
$slash = $args[0].groups[2].value;
if ([Modifier]::CoinFlip($this.Probability)) {
$subpath = $slash + [Modifier]::ChooseRandom($this.Keywords) + $slash + ".." + $slash;
return $args[0].groups[1].value + $subpath + $args[0].groups[3].value;
}
return $args[0].groups[0].value;
});
$i++;
} while ([Modifier]::CoinFlip($this.Probability * [Math]::Pow(0.9, $i)));
}
# Change double slashes
if ($this.LeaveOutDoubleSlashes -and [Modifier]::CoinFlip($this.Probability)) {
$NewTokenContent = [regex]::replace($NewTokenContent, "\:\/\/", ":/");
}
# Substitute slashes
if ($this.SubstituteSlashes) {
$NewTokenContent = [regex]::replace($NewTokenContent, "\/+", {
if ([Modifier]::CoinFlip($this.Probability)) {
return "\" * $args[0].value.length;
}
return $args[0].value;
});
}
# IP Transform
if ($this.IpToHex -and [Modifier]::CoinFlip($this.Probability)) {
$NewTokenContent = [regex]::replace($NewTokenContent, "(?:[0-9]{1,3}\.){3}[0-9]{1,3}", {
$ints = $args[0].value.split('.');
[array]::reverse($ints);
[int]$decimal = 0;
$ints | foreach { $i = 0 } { $decimal += ([int]$_ * [Math]::Pow(256, $i++)) };
if ([Modifier]::CoinFlip(0.5)) {
return $decimal;
}
else {
return '0x{0:x}'-f $decimal;
}
})
}
$Token.TokenContent = $NewTokenContent;
}
}
}
}
+2 -2
View File
@@ -13,8 +13,8 @@ class SedStatement {
[int32]StringIndex([string]$Content){
if($this.CaseInsensitive){
return $Content.ToUpper().IndexOf($This.Find.ToUpper());
return $Content.ToUpper().IndexOf($this.Find.ToUpper());
}
return $Content.IndexOf($This.Find);
return $Content.IndexOf($this.Find);
}
}