# dridex/qbot vbs decoder (#constunt)
# tested with scripts from:
# dridex
# https://app.any.run/tasks/c25c082c-7712-4e62-80f1-bdea4d1e6953/
# https://app.any.run/tasks/7d36a639-0b2a-41a2-8053-cfd703f8f115/
# qbot
# https://app.any.run/tasks/a7db0dc7-97e3-4dcb-b3f5-1be72c0de814/
# does not decode the EXE, just the other strings in the script
# v0.6 added generic identification of function/offset
# v0.7 changed decoder function name detection to include qbot, fix extra ) on cint/clng
# v0.8 added steps to remove redundant functions/const
cls
$raw_script = gc 'something_evil.vbs'
$entry = "([\w]*)\(array\("
$offset = "function ([\w]*)\(.*\)-([\d]{2})\)"
$rx_consts = "const (\w{1,2})=(\d{2,3}):"
$pairs = @()
# remove null functions
$null_func = "iF False ThEn :dim [\w]*:End iF:"
($raw_script | Select-String -Pattern $null_func -AllMatches | % {$_.matches.value} | % {$raw_script = $raw_script -Replace $_, ''})
# get array name and decode offset
$arrayname = (($raw_script | Select-String -Pattern $entry | % {$_.matches}).groups[1]).value
$offset = [int](($raw_script | Select-String -Pattern $offset | % {$_.matches}).groups[2]).value
# extract code table
$raw_script | Select-String -Pattern $rx_consts -AllMatches | % {$_.matches} | % {$pairs += ($_.groups[1].value + " " + [char]($_.groups[2].value - $offset))}
$pairs = $pairs | sort
# remove const
$rx_consts2 = "const (\w{1,3})=(\d{2,3}):"
($raw_script | Select-String -Pattern $rx_consts2 -AllMatches | % {$_.matches.value} | % {$raw_script = $raw_script -Replace $_, ''})
# find encoded blocks
$arrays = (($raw_script -split "\(array(\([a-z0-9,]*\))\)") -match "^\([a-z][0-9]?(,[a-z][0-9]?)*\)$" ) | sort -Unique -Descending
# decode
$arrays | % {
$to_Replace = $_
$original = $_
$pairs | % {
$var1 = ($_[0,1] -replace ' ', '') -join ''
$var2 = $_[-1]
$to_Replace = $to_Replace -replace "\($var1\)", "($var2)"
$to_Replace = $to_Replace -replace ",$var1\)", ",$var2 )"
}
$pairs | % {
$var1 = ($_[0,1] -replace ' ', '') -join ''
$var2 = $_[-1]
$to_Replace = $to_Replace -replace "\($var1,", "($var2"
$to_Replace = $to_Replace -replace "$var1,", "$var2"
}
$raw_script = $raw_script.Replace($original, $to_Replace)
}
# tidy up
$raw_script = $raw_script -replace "$arrayname\(array\([ ]*([^\)]*) *\)\)", '"$1"'
$raw_script = $raw_script -replace 'cint\("([\d)]*)[ ]*"\)', '$1'
$raw_script = $raw_script -replace 'clng\("([\d)]*)[ ]*"\)', '$1'
# remove more redundant functions
$redun_func = 'FuNCtiON [\w]*\(\) : dim [\w]* : [\w]*="[\w]* " : End FuNctiOn :'
($raw_script | Select-String -Pattern $redun_func -AllMatches | % {$_.matches.value} | % {$raw_script = $raw_script.Replace($_, '')})
# split lines (needs work)
$raw_script = $raw_script.Replace(':',"`n")
$raw_script
Comments