Skip to content

Instantly share code, notes, and snippets.

@purplemonkeymad
Created June 26, 2022 22:15
Show Gist options
  • Select an option

  • Save purplemonkeymad/097c1db89541c066c2358035df4048a5 to your computer and use it in GitHub Desktop.

Select an option

Save purplemonkeymad/097c1db89541c066c2358035df4048a5 to your computer and use it in GitHub Desktop.
Basic Regex brute forcer
class RegExExpandedValues {
<# wet with class as it keeps stuff together and I can put a bit of code in it.
I extend to other types might use inheritance at some point. shrug #>
$OriginalString
$ValueList
<# I can't be bothered to fill it out right now, feel free.#>
static [hashtable]$SlashCodes = @{
[char]'d' = 0..9 | ForEach-Object { "$_" }
[char]'-' = '-'
}
# the order of these or terms means we should always match in a logical way.
static [regex]$TermMatcher = [regex]'\[.+?\]|\\.|.'
static [regex]$CharGroupMatcher = [regex]'\\.|.\-.|.'
RegExExpandedValues ([string] $StartingString) {
$term = $StartingString
$this.OriginalString = $term
$this.ValueList = switch ($term[0]) {
'\' {
if ([RegExExpandedValues]::SlashCodes[$term[1]]) {
[RegExExpandedValues]::SlashCodes[$term[1]]
}
else {
Write-Error "Expected value after backslash got unknown value or no value. : $_ " -ErrorAction Stop
throw
}
}
'[' {
$InnerTerms = $term.Trim('[]')
[RegExExpandedValues]::CharGroupMatcher.Matches($InnerTerms).Value | ForEach-Object {
<# kinda undry but whatever. #>
if ($_[0] -eq '\') {
if ([RegExExpandedValues]::SlashCodes[$_[1]]) {
[RegExExpandedValues]::SlashCodes[$_[1]]
}
else {
Write-Error "Expected value after backslash got unknown value or no value in char grouping. : $_ " -ErrorAction Stop
throw
}
}
elseif ($_[1] -eq '-') {
([int][char]$_[0])..([int][char]$_[2]) | ForEach-Object { [char]$_ }
}
else {
$_
}
}
}
Default { $_ }
}
}
}
function Get-RegExTerms {
param([Parameter(Mandatory)][regex]$RegularExpression)
begin {
}
end {
$parser = [RegExExpandedValues]::TermMatcher
$parser.Matches($RegularExpression.ToString()).Value | ForEach-Object {
$term = $_
[RegExExpandedValues]::new($term)
}
}
}
function Get-RegExBruteStats {
param([Parameter(Mandatory)][regex]$RegularExpression)
end {
$TermList = Get-RegExTerms $RegularExpression
$accumulator = [bigint]::One
$TermList | ForEach-Object {
$exp = [bigint]$_.ValueList.count
$accumulator = [bigint]::Multiply($accumulator, $exp)
}
$byteSize = [bigint]::Multiply($accumulator, $TermList.count)
$FileSize = [bigint]::Multiply($accumulator, ($TermList.count + 2))
[pscustomobject]@{
StringLength = $TermList.count
Combinations = $accumulator
CombinationsSI = $accumulator.ToString('E')
ByteSize = $byteSize
FileSizeWin = $FileSize
FileSizeWinGB = $FileSize / 1GB
}
}
}
function Get-RegExBruteCombination {
param (
[Parameter(Mandatory)][regex]$RegularExpression
)
# use a nested recusion function
<# This limits us to about 3.8k term regexs. This includes single chars as a term.
Could combine conseutive combination terms to deduce the stack depth?#>
$RegExTermList = Get-RegExTerms $RegularExpression
function nestedGenerator {
<# the function can access the parent scope so using an index here should prevent any
need to copy the array around.#>
Param([int]$ListIndex, [string]$StringSoFar)
if ($ListIndex -ge $RegExTermList.count) {
Write-Error "Overran index, check code." -ErrorAction Stop
return
}
if ($ListIndex -eq ($RegExTermList.count -1)) {
# no recurse
$ListItem = $RegExTermList[$ListIndex]
foreach ( $Value in $ListItem.ValueList) {
$StringSoFar + $Value
}
return
}
# time to nest
$ListItem = $RegExTermList[$ListIndex]
foreach ( $Value in $ListItem.ValueList ) {
$newStringSoFar = $StringSoFar + $Value
nestedGenerator -ListIndex ($ListIndex + 1) -StringSoFar $newStringSoFar
}
}
nestedGenerator -ListIndex 0 -StringSoFar ""
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment