## VisualBasicObfuscator (obsoleted)
### NOTICE: This repository is now obsoleted.
I'm working on releasing my second, way more reliable and advanced Visual Basic obfuscator that I have been using for a few years by now. This obfuscator therefore becomes outdated and will be no longer maintained.
---
### Intro
Visual Basic Code universal Obfuscator intended to be used during penetration testing assignments.
To be used mainly to avoid AV and mail filters detections as well as Blue Teams inspection tasks.
Here is a sample **VirusTotal.com** scan against malicious Word document with embedded [RobustPentestMacro](https://github.com/mgeeky/RobustPentestMacro) geared up with _Empire_-generated powershell stager:
No obfuscation | Obfuscated
--- | ---
[15 / 58](https://www.virustotal.com/#/file/d45af91e7a46cedc0aaa68a79eea48f19f47cdf2202e8347e61c178d987e2dcd/detection) | [9 / 58](https://www.virustotal.com/#/file/ea2e812c62543946f9f175b4183db2555d69673307bb046138b41e7fa9f63b91/detection)
- In case of _Non-obfuscated_ sample, the AV software has flagged the file with certain malicious-macro statement.
- As of obfuscated sample we've been left with _obfuscated_ flag.
There is still a huge area of improvement in testing which obfuscation techniques trigger what patterns, and work towards reducing such detection rate.
---
### FEATURES
- Able to extract HTML/HTA/<script> contents
- Able to obfuscate arrays of numbers and characters
- Obfuscating strings via Bit Shuffling and base64 encoding (_as described in D.Knuth's vol.4a chapter 7.1.3_). This method produces smaller in size results (approx. 66% smaller resulting scripts)
- Merging long concatenated lines into variables appendings to avoid maximum number of continuing lines (24)
- Junk insertion, smart enough to avoid breaking syntax outside of routines
- Sensitive to quote escapes within strings, detecting consecutive lines concatenation
- Variables, Globals, Constants, function names, function parameters names randomization
- Comments, indents and blank lines removal,
```
usage: obfuscate.py [-h] [-o OUTPUT] [-N | -g GARBAGE | -G | -C]
[-m MIN_VAR_LEN] [-r RESERVED] [-v | -q]
input_file
Attempts to obfuscate an input visual basic script in order to prevent curious
eyes from reading over it.
positional arguments:
input_file Visual Basic script to be obfuscated.
optional arguments:
-h, --help show this help message and exit
-o OUTPUT, --output OUTPUT
Output file. Default: stdout
-N, --normalize Don't perform obfuscation, do only code normalization
(like long strings transformation).
-g GARBAGE, --garbage GARBAGE
Percent of garbage to append to the obfuscated code.
Default: 12%.
-G, --no-garbage Don't append any garbage.
-C, --no-colors Dont use colors.
-m MIN_VAR_LEN, --min-var-len MIN_VAR_LEN
Minimum length of variable to include in name
obfuscation. Too short value may break the original
script. Default: 5.
-r RESERVED, --reserved RESERVED
Reserved word/name that should not be obfuscated (in
case some name has to be in original script cause it
may break it otherwise). Repeat the option for more
words.
-v, --verbose Verbose output.
-q, --quiet No unnecessary output.
```
---
## Obfuscation example
**Original form**
```
Const MY_CONSTANTS = "Some super const"
Dim AnotherVariable As String
Sub MyTestSub(ByVal arg1 As String)
' The below real-world used query contains nested quotes/apostrophes
' That could confuse `removeComments` routine
Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 " _
& "WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' " _
& "AND TargetInstance.SystemUpTime >= 200 AND " _
& "TargetInstance.SystemUpTime < 320"
Dim arr As Variant
arr = Array(1, 2, 3, 4, 5, 6) ' This is an inline comment
Dim var1, var2
var1 = "Testing Short string"
var2 = "short"
'
' This is a comment
'
Dim longString
longString = "1. this is some very long string concatenated."
longString = longString + "2. this is some very long string concatenated."
longString = longString + "3. this is some very long string concatenated."
longString = longString + "4. this is some very long string concatenated."
longString = longString + "5. this is some very long string concatenated." _
& "6. this is some very long string concatenated." _
& "7. this is some very long string concatenated." _
& "8. this is some very long string concatenated." _
& "9. this is some very long string concatenated."
Dim somecondition As Boolean
somecondition = False
If somecondition <> False Then
Exit Sub
End If
MsgBox ("Test1(Constant): " & MY_CONSTANTS)
MsgBox ("Test2(Query): " & Query)
MsgBox ("Test3(var1 + var2): " & var1 & var2)
MsgBox ("Test4(longString): " & longString)
MsgBox ("Test5(Array's contents): " & Join(arr, ","))
End Sub
Sub test()
MyTestSub (0)
End Sub
```
---
**Obfuscated form**:
Invocation - we have to specify that the macro is named `test` and therefore this Sub name shall not be mangled:
```
bash $ ./obfuscate.py -r test -v demo.vbs
```
Output (mind that _Constants_ contents cannot be anyhow obfuscated, as they have to be known at compile time):
```
Const MY_CONSTANTS="Some super const"
Dim H5AyJRiT As String
Sub LdzqEiHkpovt(ByVal arg1 As String)
K8fqa=onOrpZJSZL("Aq0oV8IwZBFohAVdSO6+TJjg8124pPFV0K9zUbqn0FD4q9xWwLr1VWiukEpQooxWoBBRCQ==") _
& onOrpZJSZL("EuqkUgCucEii6dFXmODzXbik8VU4hYBYaI3RSep3F0yIoVRf2qdRXaC8cF2g4sBVMLVhXSrsnVOC9+9aoK/cFw==") _
& onOrpZJSZL("EKhhEYinVF5gsvxV4rD0V6ptPFGgvXNeoPMiXbCp8hGyU1YDoBQQQg==") _
& onOrpZJSZL("iKdUXmCy/FXisPRXqm08UaC9c16g8yJdsKnyEahC1go=")
Dim arr As Variant
arr=Array(3256/3256,293-291,-1964+1967,-2979+2983,1678-1673,342-336)
Dim var1,var2
var1=onOrpZJSZL(Chr(Int("&H69"))&Chr(&H4f)&Chr(Int("&H50"))&Chr(Int("&H51"))&"X"&Chr(55)&Chr(Int("&H69"))&Chr(Int("111"))&Chr(Int("56"))&Chr(Int("120"))&Chr(&H47)&Chr(&H61)&Chr(&H36)&Chr(-209+289)&Chr(Int("120"))&Chr(Int("&H53"))&Chr(113)&Chr(Int("&H4f"))&Chr(76)&"Q"&Chr(Int("84"))&Chr(114)&"q"&Chr(&H74)&Chr(88)&Chr(70)&Chr(-2196+2285)&Chr(Int("&H3d")))
var2=Chr(Int("115"))&Chr(Int("104"))&Chr(111)&"r"&Chr(1900-1784)
Dim oAQ96qYI As String
oAQ96qYI=Chr(&H4c)&Chr(56)&Chr(Int("&H79"))&Chr(112)&Chr(111)&Chr(76)&Chr(Int("48"))&Chr(Int("&H50"))&Chr(78645/749)&Chr(&H45)&Chr(&H49)&Chr(110)&Chr(Int("78"))&Chr(Int("97"))&Chr(2431-2328)&Chr(&H52)&Chr(-1842+1955)&Chr(3538-3458)&"7"&Chr(Int("104"))&Chr(121)
Dim ChtxGWGe As String
ChtxGWGe=Chr(1513-1429)&Chr(80)&Chr(Int("69"))&Chr(121)&Chr(Int("122"))&Chr(&H41)&Chr(Int("&H73"))&Chr(Int("&H31"))&Chr(Int("&H76"))&"l"&"k"&Chr(Int("&H33"))&Chr(Int("67"))&Chr(&H42)&Chr(51)&Chr(&H78)&Chr(&H37)&Chr(&H71)&Chr(878-766)&Chr(2660-2571)&Chr(Int("71"))&Chr(Int("&H58"))&Chr(77)&Chr(113)&Chr(78276/1186)
Dim E1X9VVBEe
E1X9VVBEe=onOrpZJSZL("sEBxR7ih0higdXdQsqvyEernUFv4iNxVquLwTLqtXFboid1Uoq1wXKKvUlw=")
E1X9VVBEe=E1X9VVBEe+onOrpZJSZL("skBRR7ih0higdXdQsqvyEernUFv4iNxVquLwTLqtXFboid1Uoq1wXKKvUlw=")
E1X9VVBEe=E1X9VVBEe+onOrpZJSZL("skBxR7ih0higdXdQsqvyEernUFv4iNxVquLwTLqtXFboid1Uoq1wXKKvUlw=")
E1X9VVBEe=E1X9VVBEe+onOrpZJSZL("sEJRR7ih0higdXdQsqvyEernUFv4iNxVquLwTLqtXFboid1Uoq1wXKKvUlw=")
E1X9VVBEe=E1X9VVBEe+onOrpZJSZL("sEJxR7ih0higdXdQsqvyEernUFv4iNxVquLwTLqtXFboid1Uoq1wXKKvUlw=") _
& onOrpZJSZL("skJRR7ih0higdXdQsqvyEernUFv4iNxVquLwTLqtXFboid1Uoq1wXKKvUlw=") _
& onOrpZJSZL("skJxR7ih0higdXdQsqvyEernUFv4iNxVquLwTLqtXFboid1Uoq1wXKKvUlw=") _
& onOrpZJSZL("sEBTR7ih0higdXdQsqvyEernUFv4iNxVquLwTLqtXFboid1Uoq1wXKKvUlw=") _
& onOrpZJSZL("sEBzR7ih0higdXdQsqvyEernUFv4iNxVquL