├── assets ├── vbscrambler_header.png └── vbscrambler_help.png ├── LICENSE ├── .github └── workflows │ └── python-publish.yml ├── README.md └── VBScrambler.py /assets/vbscrambler_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobby-tablez/VBScrambler/HEAD/assets/vbscrambler_header.png -------------------------------------------------------------------------------- /assets/vbscrambler_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobby-tablez/VBScrambler/HEAD/assets/vbscrambler_help.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Bobby-Tablez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.x' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI }} 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VBScrambler - A Python-Based Multi-Language Code Obfuscator 2 | ![header image_vbscrambler](https://raw.githubusercontent.com/bobby-tablez/VBScrambler/main/assets/vbscrambler_header.png) 3 | 4 | [![PyPI Version](https://img.shields.io/pypi/v/VBScrambler)](https://pypi.org/project/VBScrambler/) 5 | [![PyPI Downloads](https://static.pepy.tech/badge/vbscrambler)](https://pepy.tech/projects/vbscrambler) 6 | 7 | VBScrambler is a Python based code obfuscator supporting both VBScript and JavaScript. It takes code as input (either file or inline) and provides obfuscated one-liner output. The obfuscation works by performing a byte shift on the supplied code, then inserting it into a randomly generated deobfuscation script which reverses the byte shift and executes the original code. 8 | 9 | The shift works similar to ROT13 with a randomly supplied shift value ranging from -5 to 7. Larger numbers tend to prevent the generated script from executing, producing errors. Other errors can occur when copying generated code from console, as special characters, especially in Linux, may not copy correctly. 10 | 11 | ### Optional arguments: 12 | - `-l, --language` Specify language: `vbscript`/`vbs` or `javascript`/`js` (default: vbscript) 13 | - `-c, --content` Supply inline code to obfuscate (This must be the last argument supplied) 14 | - `-f, --file` Supply a file to obfuscate (supports multi-line) 15 | - `-o, --output` Save generated output to file 16 | - `-s, --shift` Manually specify a shift value 17 | 18 | If no argument is provided, the script will prompt the user for code to obfuscate. 19 | 20 | ![help image_vbscrambler](https://raw.githubusercontent.com/bobby-tablez/VBScrambler/main/assets/vbscrambler_help.png) 21 | 22 | ### Installation 23 | Requires Python v3.8+ 24 | Either download and execute VBScrambler.py file manually on Windows or Linux, or install and run via pypi package: 25 | 26 | `pip install VBScrambler` 27 | 28 | ### Example: 29 | Obfuscating the following VBScript using the command: `python3 VBScrambler.py -s 5 -f ps.vbs` 30 | ```VBScript 31 | Dim shell,command 32 | command = "powershell.exe -nologo -command ""New-Item C:\text\vbstest.txt -Force""" 33 | Set shell = CreateObject("WScript.Shell") 34 | shell.Run command,0 35 | ``` 36 | Generates the following VBScript code: 37 | ```VBScript 38 | lgwi = "":for i = 1 to 163: lgwi = lgwi + chr(Asc(mid("Inr%xmjqq1htrrfsihtrrfsi%B%'ut|jwxmjqq3j}j%2stqtlt%2htrrfsi%''Sj|2Nyjr%H?ayj}ya{gxyjxy3y}y%2Ktwhj'''Xjy%xmjqq%B%HwjfyjTgojhy-'\Xhwnuy3Xmjqq'.xmjqq3Wzs%htrrfsi15",i,1)) - (5)):Next:Execute lgwi: 39 | ``` 40 | 41 | ### Example: JavaScript 42 | Obfuscating the following JavaScript using the command: `python3 VBScrambler.py -l javascript -s 3 -c console.log("Hello World");` 43 | ```JavaScript 44 | console.log("Hello World"); 45 | ``` 46 | Generates the following JavaScript code: 47 | ```JavaScript 48 | var kpqw="";for(var i=0;i<"frqvroh1orj+#Khoor#Zruog#,>".length;i++){kpqw+=String.fromCharCode("frqvroh1orj+#Khoor#Zruog#,>".charCodeAt(i)-3);}eval(kpqw); 49 | ``` 50 | 51 | #### Errors and issues 52 | After extensively testing various VBScripts, I've discovered that certain scritps will produce errors with specific shift number combinations (typically 1 out of 10) when using the default provided range. If you encounter an error, try either adjusting the shfit number manually, or simply run it again to get a potentially new value. 53 | 54 | Another issue occurs in Linux more often than in Windows where the console doesn't properly print the shifted ASCII characters properly, thus copying the printed code could skip some characters. If you run into this, use the `-o` option to print to a file and use a text editor such as Sublime which handles special characters well. 55 | 56 | **DISCLAIMER: Use at your own risk, for educational and demonstration purposes only!** 57 | -------------------------------------------------------------------------------- /VBScrambler.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import random 3 | import string 4 | 5 | banner = r""" 6 | ____ ______________ _________ ___. .__ 7 | \ \ / /\______ \ / _____/ ____ _______ _____ _____ \_ |__ | | ____ _______ 8 | \ Y / | | _/ \_____ \ _/ ___\\_ __ \\__ \ / \ | __ \ | | _/ __ \\_ __ \ 9 | \ / | | \ / \\ \___ | | \/ / __ \_| Y Y \| \_\ \| |__\ ___/ | | \/ 10 | \___/ |______ //_______ / \___ >|__| (____ /|__|_| /|___ /|____/ \___ >|__| 11 | \/ \/ \/ \/ \/ \/ \/ 12 | VBScrambler by GH: @Bobby-Tablez 13 | https://github.com/bobby-tablez/VBScrambler 14 | 15 | """ 16 | print(banner) 17 | 18 | def scramble_vbscript(code, shift_num): 19 | obfuscated = ''.join(chr(ord(v) + shift_num) for v in code) 20 | code_len = len(obfuscated) 21 | 22 | # Fix double quotes if they're generated after the shift 23 | final_code = obfuscated.replace('"', '""') 24 | 25 | # Randomize variable name 26 | var_name = ''.join(random.choices(string.ascii_letters, k=4)) 27 | 28 | # Generate the output 29 | result = (var_name + r' = "":for i = 1 to ' + f"{code_len}" + ": " + var_name + 30 | f" = {var_name} + chr(Asc(mid(\"{final_code}\",i,1)) - ({shift_num})):Next:Execute " + var_name + ":") 31 | 32 | return result 33 | 34 | def scramble_javascript(code, shift_num): 35 | obfuscated = ''.join(chr(ord(v) + shift_num) for v in code) 36 | 37 | # Escape special characters for JavaScript string 38 | final_code = (obfuscated 39 | .replace('\\', '\\\\') 40 | .replace('"', '\\"') 41 | .replace('\n', '\\n') 42 | .replace('\r', '\\r') 43 | .replace('\t', '\\t')) 44 | 45 | # Randomize variable name 46 | var_name = ''.join(random.choices(string.ascii_letters, k=4)) 47 | 48 | # Generate the output with JavaScript deobfuscation 49 | result = (f"var {var_name}=\"\";for(var i=0;i<\"{final_code}\".length;i++)" + 50 | f"{{{var_name}+=String.fromCharCode(\"{final_code}\".charCodeAt(i)-{shift_num});}}eval({var_name});") 51 | 52 | return result 53 | 54 | def main(): 55 | 56 | parser = argparse.ArgumentParser(description="VBScrambler - Multi-language code obfuscator") 57 | parser.add_argument("-c", "--content", nargs=argparse.REMAINDER, help="Inline code to obfuscate.", default=[], required=False) 58 | parser.add_argument("-f", "--file", type=str, help="File to obfuscate.", required=False) 59 | parser.add_argument("-o", "--output", type=str, help="Output file to save the scrambled code to", required=False) 60 | parser.add_argument("-s", "--shift", type=int, help="Manually set the ROT/Shift number", required=False) 61 | parser.add_argument("-l", "--language", type=str, choices=['vbscript', 'javascript', 'vbs', 'js'], 62 | default='vbscript', help="Language to obfuscate (vbscript/vbs or javascript/js)") 63 | 64 | args = parser.parse_args() 65 | 66 | # Normalize language input 67 | language = args.language.lower() 68 | if language in ['vbs', 'vbscript']: 69 | language = 'vbscript' 70 | elif language in ['js', 'javascript']: 71 | language = 'javascript' 72 | 73 | # Handle the various input types 74 | if args.content: 75 | code = ' '.join(args.content) 76 | elif args.file: 77 | try: 78 | with open(args.file, 'r') as file: 79 | code = file.read() 80 | except FileNotFoundError: 81 | print(f"Error: The file '{args.file}' does not exist.") 82 | return 83 | else: 84 | prompt = "Provide a VBScript one-liner (Mind your quotes!):" if language == 'vbscript' else "Provide JavaScript code to obfuscate:" 85 | code = input(prompt) 86 | 87 | if args.shift: 88 | shift_num = args.shift 89 | else: 90 | shift_num = random.randint(-5, 7) # Define range for byte shifts. This range seems to work well with most scripts. Increasing this could break the generated script 91 | 92 | # Scramble based on language 93 | if language == 'vbscript': 94 | result = scramble_vbscript(code, shift_num) 95 | else: 96 | result = scramble_javascript(code, shift_num) 97 | 98 | # Either save output as a file, or print it based on parameters used 99 | if args.output: 100 | try: 101 | with open(args.output, 'w', encoding='utf-8') as file: 102 | file.write(result) 103 | print(f"\nContent saved to {args.output}\n") 104 | except IOError as e: 105 | print(f"\nError writing to file: {e}\n") 106 | else: 107 | print(f"\n{result}\n") 108 | 109 | if __name__ == "__main__": 110 | main() 111 | --------------------------------------------------------------------------------