mirror of
https://github.com/wietze/Invoke-ArgFuscator
synced 2026-06-08 18:17:29 +00:00
149 lines
7.8 KiB
PowerShell
149 lines
7.8 KiB
PowerShell
using module "..\Types\Modifier.psm1"
|
|
using module "..\Types\Token.psm1"
|
|
using module "..\Types\Argument.psm1"
|
|
|
|
class ReorderArgs : Modifier {
|
|
[float]$Probability;
|
|
|
|
[boolean]$CombineShortForm;
|
|
[boolean]$RandomiseOrder;
|
|
[boolean]$SwapLongShortForm;
|
|
[boolean]$InsertRedundantShortforms;
|
|
|
|
ReorderArgs([Token[]]$InputCommandTokens, [string[]]$AppliesTo, [Argument[]]$Arguments, [float]$Probability, [bool]$CombineShortForm, [bool]$RandomiseOrder, [bool]$SwapLongShortForm, [bool]$InsertRedundantShortforms) : base($InputCommandTokens, $AppliesTo, $Arguments, $Probability) {
|
|
$this.CombineShortForm = $CombineShortForm;
|
|
$this.RandomiseOrder = $RandomiseOrder;
|
|
$this.SwapLongShortForm = $SwapLongShortForm;
|
|
$this.InsertRedundantShortforms = $InsertRedundantShortforms;
|
|
}
|
|
|
|
[void]GenerateOutput() {
|
|
if ($this.RandomiseOrder) {
|
|
# 1. Get the objects that match the condition
|
|
$matching = $this.InputCommandTokens.Where({ $this.AppliesTo.Contains($_.Type) -and (-not $_.HasValue) })
|
|
|
|
# 2. Extract their TokenContent as an array of char[]
|
|
$tokenArrays = @()
|
|
$matching | ForEach-Object { $tokenArrays += , $_.TokenContent }
|
|
|
|
# 3. Create an array of indices and shuffle them
|
|
$indices = 0..($tokenArrays.Count - 1) | Sort-Object { Get-Random }
|
|
|
|
# 4. Assign the shuffled arrays back to the matching objects
|
|
$i = 0
|
|
$matching | ForEach-Object { $_.TokenContent = $tokenArrays[$indices[$i++]] }
|
|
}
|
|
|
|
if ($this.SwapLongShortForm -and ($null -ne $this.Arguments)) {
|
|
foreach ($Token in $This.InputCommandTokens) {
|
|
$t = [Argument]::GetArgumentDetails($This.Arguments, $Token.TokenContent)
|
|
if (($null -ne $t) -and [Modifier]::CoinFlip($this.Probability)) {
|
|
$Token.TokenContent = [Modifier]::ChooseRandom($t.Arguments)
|
|
}
|
|
}
|
|
}
|
|
|
|
$IsMergeable = { param($Token) $this.AppliesTo.Contains($Token.Type) -and $Token.ToString() -match '^-[^-]$' -and !$Token.HasValue }
|
|
$IsValueMergeable = { param($Token) $this.AppliesTo.Contains($Token.Type) -and $Token.ToString() -match '^-[^-]$' -and $Token.HasValue }
|
|
|
|
$redundants = $this.Arguments | Where-Object { $_.Redundant -eq $true -and $_.ValueCount -eq 0 } | ForEach-Object { $_.Arguments | Where-Object { $_ -match '^-\S$' } | ForEach-Object { $_[1] } }
|
|
|
|
|
|
if ($this.CombineShortForm) {
|
|
$arg_i = -1;
|
|
foreach ($Token in $This.InputCommandTokens) {
|
|
$arg_i += 1;
|
|
# Check if this is one of the mergeable tokens, and with probability merge it
|
|
if ($IsMergeable.Invoke($Token)) {
|
|
# Create brand new token with the found one, plus all upcoming ones
|
|
$NewTokenContent = [System.Collections.ArrayList]@($Token.TokenContent);
|
|
|
|
# Add redundant characters
|
|
if($redundants.Count -gt 0){
|
|
for ($i = 0; $true; $i = $i + 1) {
|
|
if ($This.InsertRedundantShortforms -and [Modifier]::CoinFlip($This.Probability * [Math]::Pow(0.9, $i))) {
|
|
$NewTokenContent.Add([Modifier]::ChooseRandom($redundants))
|
|
}
|
|
else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
# Find all upcoming mergable tokens
|
|
$candidates = ($This.InputCommandTokens | Select-Object -Skip ($arg_i + 1)).Where({ $IsMergeable.Invoke($_) -and [Modifier]::CoinFlip($This.Probability) });
|
|
if ($candidates.Count -ne 0) {
|
|
$candidates | ForEach-Object {
|
|
$NewTokenContent.addRange(@($_.TokenContent | Select-Object -Skip 1));
|
|
$_.TokenContent = @(); #// Ensures token is 'removed'
|
|
}
|
|
}
|
|
|
|
# Randomise order
|
|
if ($this.RandomiseOrder -and [Modifier]::CommonOptionChars -contains $NewTokenContent[0] ) {
|
|
$NewTokenContent = [System.Collections.ArrayList]@($NewTokenContent[0]) + ([System.Collections.ArrayList]@($NewTokenContent | Select-Object -Skip 1) | Sort-Object { Get-Random })
|
|
$NewTokenContent = [System.Collections.ArrayList]$NewTokenContent;
|
|
}
|
|
|
|
# Find short-form arguments that DO have a value; we can pick at most one, and only add them to the end.
|
|
$valueCandidates = ($This.InputCommandTokens | Select-Object -Skip ($arg_i + 1) -SkipLast 1 | ForEach-Object { $j = ($arg_i + 2); } { [System.Tuple]::Create($_, $This.InputCommandTokens[$j++]) } ).Where({ $IsValueMergeable.Invoke($_[0]) -and [Modifier]::CoinFlip($This.Probability) })
|
|
|
|
if ($valueCandidates.Length -gt 0) {
|
|
$valueCandidate = [Modifier]::ChooseRandom($valueCandidates)
|
|
$NewTokenContent.AddRange(@($valueCandidate[0].TokenContent | Select-Object -Skip 1))
|
|
$valueCandidate[0].TokenContent = @();
|
|
$NewTokenContent.AddRange(@($valueCandidate[1].TokenContent))
|
|
$valueCandidate[1].TokenContent = @();
|
|
}
|
|
|
|
# Update current token
|
|
$Token.TokenContent = $NewTokenContent;
|
|
} elseif ($IsValueMergeable.Invoke($Token)){
|
|
|
|
# Create new, empty token
|
|
$NewTokenContent = [System.Collections.ArrayList]@($Token.TokenContent[0]);
|
|
|
|
# Add redundant characters
|
|
if($redundants.Count -gt 0){
|
|
for ($i = 0; $true; $i = $i + 1) {
|
|
if ($This.InsertRedundantShortforms -and [Modifier]::CoinFlip($This.Probability * [Math]::Pow(0.9, $i))) {
|
|
$NewTokenContent.Add([Modifier]::ChooseRandom($redundants))
|
|
}
|
|
else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
$NewTokenContent.Add($Token.TokenContent[1])
|
|
$Token.TokenContent = $NewTokenContent
|
|
}
|
|
}
|
|
|
|
# Second pass: merge left-over short-form arguments that have a value
|
|
$i = 0;
|
|
foreach ($Token in $This.InputCommandTokens) {
|
|
# Check if this is one of the mergeable tokens, and with probability merge it
|
|
if ($IsValueMergeable.Invoke($Token) -and (($i + 1) -lt $This.InputCommandTokens.Length) -and [Modifier]::CoinFlip($This.Probability)) {
|
|
$NewTokenContent = @($Token.TokenContent);
|
|
# Add redundant characters
|
|
if($redundants.Count -gt 0){
|
|
for ($j = 0; $true; $j = $j + 1) {
|
|
if ($This.InsertRedundantShortforms -and [Modifier]::CoinFlip($This.Probability * [Math]::Pow(0.9, $j))) {
|
|
$NewTokenContent = @($NewTokenContent[0]) + @([Modifier]::ChooseRandom($redundants)) + @($NewTokenContent[1..($NewTokenContent.Count - 1)])
|
|
}
|
|
else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
$NewTokenContent = @($NewTokenContent) + @($This.InputCommandTokens[$i + 1].TokenContent);
|
|
$this.InputCommandTokens[$i + 1].TokenContent = @();
|
|
$Token.TokenContent = $NewTokenContent;
|
|
}
|
|
$i += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|