From 21add55b94fb3ba15ac4f486fb3a256ac6982382 Mon Sep 17 00:00:00 2001 From: svieg Date: Sun, 21 Aug 2016 16:06:09 -0400 Subject: [PATCH 01/30] Deleted the customization commands to make them functions. --- malboxes/malboxes.py | 113 +++++++++++++------------------------------ 1 file changed, 34 insertions(+), 79 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index e66dc54..885d10b 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -88,53 +88,6 @@ def init_parser(): 'Ex: Cryptolocker_XYZ.') parser_spin.set_defaults(func=spin) - # reg command - parser_reg = subparsers.add_parser('registry', - help='Modifies a registry key.') - parser_reg.add_argument('profile', help='Name of the profile to modify.') - parser_reg.add_argument('modtype', - help='Modification type (add, delete or modify).') - parser_reg.add_argument('key', help='Location of the key to modify.') - parser_reg.add_argument('name', help='Name of the key.') - parser_reg.add_argument('value', help='Value of the key.') - parser_reg.add_argument('valuetype', - help='Type of the value of the key: ' - 'DWORD for integer, String for string.') - parser_reg.set_defaults(func=reg) - - # dir command - parser_dir = subparsers.add_parser('directory', - help='Modifies a directory.') - parser_dir.add_argument('profile', - help='Name of the profile to modify.') - parser_dir.add_argument('modtype', - help='Modification type (delete or add).') - parser_dir.add_argument('dirpath', - help='Path of the directory to modify.') - parser_dir.set_defaults(func=directory) - - # wallpaper command - - # package command - parser_package = subparsers.add_parser('package', - help='Adds package to install.') - parser_package.add_argument('profile', - help='Name of the profile to modify.') - parser_package.add_argument('package', - help='Name of the package to install.') - parser_package.set_defaults(func=package) - - # document command - parser_document = subparsers.add_parser('document', - help='Adds a file') - parser_document.add_argument('profile', - help='Name of the profile to modify.') - parser_document.add_argument('modtype', - help='Modification type (delete or add).') - parser_document.add_argument('docpath', - help='Path of the file to add.') - parser_document.set_defaults(func=document) - # no command parser.set_defaults(func=default) @@ -419,6 +372,11 @@ def append_to_script(filename, line): with open(filename, 'a') as f: f.write(line) +def customize(parser, args): + """ + Converts the customization profile to a powershell script. + """ + def add_to_user_scripts(profile): """ Adds the modified script to the user scripts file.""" @@ -437,24 +395,23 @@ def add_to_user_scripts(profile): f.write(line) -def reg(parser, args): +def reg(profile, modtype, key, name, value, valuetype): """ Adds a registry key modification to a profile with PowerShell commands. """ - if args.modtype == "add": + if modtype == "add": command = "New-ItemProperty" line = "{} -Path {} -Name {} -Value {} -PropertyType {}\r\n".format( - command, args.key, args.name, args.value, args.valuetype) + command, key, name, value, valuetype) print("Adding: " + line) - elif args.modtype == "modify": + elif modtype == "modify": command = "Set-ItemProperty" line = "{0} -Path {1} -Name {2} -Value {3}\r\n".format( - command, args.key, args.name, args.value) + command, key, name, value) print("Adding: " + line) - elif args.modtype == "delete": + elif modtype == "delete": command = "Remove-ItemProperty" - line = "{0} -Path {1} -Name {2}\r\n".format( - command, args.key, args.name) + line = "{0} -Path {1} -Name {2}\r\n".format(command, key, name) print("Adding: " + line) else: print("Registry modification type invalid.") @@ -468,66 +425,64 @@ def reg(parser, args): add_to_user_scripts(args.profile) -def directory(parser, args): +def directory(profile, modtype, dirpath): """ Adds the directory manipulation commands to the profile.""" - if args.modtype == "add": + if modtype == "add": command = "New-Item" - line = "{0} -Path {1} -Type directory\r\n".format(command, - args.dirpath) - print("Adding directory: {}".format(args.dirpath)) + line = "{0} -Path {1} -Type directory\r\n".format(command, dirpath) + print("Adding directory: {}".format(dirpath)) elif args.modtype == "delete": command = "Remove-Item" - line = "{0} -Path {1}\r\n".format( - command, args.dirpath) - print("Removing directory: {}".format(args.dirpath)) + line = "{0} -Path {1}\r\n".format(command, dirpath) + print("Removing directory: {}".format(dirpath)) else: print("Directory modification type invalid.") print("Valid ones are: add, delete.") filename = os.path.join(DIRS.user_config_dir, "scripts", "user", - "windows", "{}.ps1".format(args.profile)) + "windows", "{}.ps1".format(profile)) append_to_script(filename, line) """ Adds the modified script to the user scripts.""" - add_to_user_scripts(args.profile) + add_to_user_scripts(profile) -def package(parser, args): +def package(profile, package): """ Adds a package to install with Chocolatey.""" - line = "cinst {} -y\r\n".format(args.package) - print("Adding Chocolatey package: {}".format(args.package)) + line = "cinst {} -y\r\n".format(package) + print("Adding Chocolatey package: {}".format(package)) filename = os.path.join(DIRS.user_config_dir, "scripts", "user", - "windows", "{}.ps1".format(args.profile)) + "windows", "{}.ps1".format(profile)) append_to_script(filename, line) """ Adds the modified script to the user scripts.""" - add_to_user_scripts(args.profile) + add_to_user_scripts(profile) -def document(parser, args): +def document(profile, modtype, docpath): """ Adds the file manipulation commands to the profile.""" - if args.modtype == "add": + if modtype == "add": command = "New-Item" - line = "{0} -Path {1}\r\n".format(command, args.docpath) - print("Adding file: {}".format(args.docpath)) - elif args.modtype == "delete": + line = "{0} -Path {1}\r\n".format(command, docpath) + print("Adding file: {}".format(docpath)) + elif modtype == "delete": command = "Remove-Item" line = "{0} -Path {1}\r\n".format( - command, args.docpath) - print("Removing file: {}".format(args.docpath)) + command, docpath) + print("Removing file: {}".format(docpath)) else: print("Directory modification type invalid.") print("Valid ones are: add, delete.") filename = os.path.join(DIRS.user_config_dir, "scripts", "user", "windows", - "{}.ps1".format(args.profile)) + "{}.ps1".format(profile)) append_to_script(filename, line) """ Adds the modified script to the user scripts.""" - add_to_user_scripts(args.profile) + add_to_user_scripts(profile) def main(): From 84a0795615c78fe9670dbb081c9c8a9470448ccf Mon Sep 17 00:00:00 2001 From: svieg Date: Sun, 21 Aug 2016 16:06:57 -0400 Subject: [PATCH 02/30] Deleted useless Ansible config file. --- ansible-inventory | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 ansible-inventory diff --git a/ansible-inventory b/ansible-inventory deleted file mode 100644 index 7b0069b..0000000 --- a/ansible-inventory +++ /dev/null @@ -1,2 +0,0 @@ -analyst ansible_port=5985 ansible_host=192.168.1.71 ansible_connection=winrm ansible_winrm_server_cert_validation=ignore ansible_user=vagrant ansible_password=vagrant -#analyst ansible_host=192.168.1.72 ansible_user=vagrant ansible_password=vagrant From a8d92034efc59fe96b5f9a3ff449168457090275 Mon Sep 17 00:00:00 2001 From: svieg Date: Thu, 15 Sep 2016 00:03:33 -0400 Subject: [PATCH 03/30] Changed custom profile format for smtg simpler. Bugfixes. --- malboxes/malboxes.py | 59 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index 885d10b..6c4bfe4 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -34,7 +34,7 @@ from jinja2 import Environment, FileSystemLoader from jsmin import jsmin -from malboxes._version import __version__ +#from malboxes._version import __version__ DIRS = AppDirs("malboxes") DEBUG = False @@ -54,7 +54,7 @@ def init_parser(): description="Vagrant box builder " "and config generator for malware analysis.") parser.add_argument('-V', '--version', action='version', - version='%(prog)s ' + __version__) + version='%(prog)s ' + "0.1") parser.add_argument('-d', '--debug', action='store_true', help="Debug mode") subparsers = parser.add_subparsers() @@ -188,6 +188,14 @@ def load_config(config_file, profile): return config +def load_customization(customization_filename): + """Loads the customization file, minifies it and returns the content.""" + customization = {} + with open(customization_filename, 'r') as customization_file: + config = json.loads(jsmin(customization_file.read())) + return customization + + def _get_os_type(config): """OS Type is extracted from profile json config""" return config['builders'][0]['guest_os_type'].lower() @@ -306,6 +314,8 @@ def build(parser, args): print("Generating configuration files...") config, packer_tmpl = prepare_config(args.profile) prepare_autounattend(config) + if "customization_file" in config.keys(): + prepare_customization(args.profile, config["customization_profile"]) print("Configuration files are ready") if not args.skip_packer_build: @@ -372,11 +382,36 @@ def append_to_script(filename, line): with open(filename, 'a') as f: f.write(line) -def customize(parser, args): + +def prepare_customization(profile, customization_filename): """ - Converts the customization profile to a powershell script. + Converts the customization file to a powershell script. """ - + customization = load_customization(customization_filename) + for i in range(len(customization["registry"])): + registry(profile, + customization["registry"][i]["modtype"], + customization["registry"][i]["key"], + customization["registry"][i]["name"], + customization["registry"][i]["value"], + customization["registry"][i]["valuetype"], + ) + for i in range(len(customization["directory"])): + directory(profile, + customization["directory"][i]["filetype"], + customization["directory"][i]["dirpath"] + ) + for i in range(len(customization["document"])): + directory(profile, + customization["document"][i]["modtype"], + customization["document"][i]["docpath"] + ) + for i in range(len(customization["package"])): + print("YAAA") + package(profile, + customization["package"][i] + ) + def add_to_user_scripts(profile): """ Adds the modified script to the user scripts file.""" @@ -395,7 +430,7 @@ def add_to_user_scripts(profile): f.write(line) -def reg(profile, modtype, key, name, value, valuetype): +def registry(profile, modtype, key, name, value, valuetype): """ Adds a registry key modification to a profile with PowerShell commands. """ @@ -418,11 +453,11 @@ def reg(profile, modtype, key, name, value, valuetype): print("Valid ones are: add, delete and modify.") filename = os.path.join(DIRS.user_config_dir, "scripts", "user", - "windows", "{}.ps1".format(args.profile)) + "windows", "{}.ps1".format(profile)) append_to_script(filename, line) """ Adds the modified script to the user scripts.""" - add_to_user_scripts(args.profile) + add_to_user_scripts(profile) def directory(profile, modtype, dirpath): @@ -431,7 +466,7 @@ def directory(profile, modtype, dirpath): command = "New-Item" line = "{0} -Path {1} -Type directory\r\n".format(command, dirpath) print("Adding directory: {}".format(dirpath)) - elif args.modtype == "delete": + elif modtype == "delete": command = "Remove-Item" line = "{0} -Path {1}\r\n".format(command, dirpath) print("Removing directory: {}".format(dirpath)) @@ -447,10 +482,10 @@ def directory(profile, modtype, dirpath): add_to_user_scripts(profile) -def package(profile, package): +def package(profile, package_name): """ Adds a package to install with Chocolatey.""" - line = "cinst {} -y\r\n".format(package) - print("Adding Chocolatey package: {}".format(package)) + line = "cinst {} -y\r\n".format(package_name) + print("Adding Chocolatey package: {}".format(package_name)) filename = os.path.join(DIRS.user_config_dir, "scripts", "user", "windows", "{}.ps1".format(profile)) From f046e25d9ba5225f79b0b998b4ddac72d4cfd5f8 Mon Sep 17 00:00:00 2001 From: svieg Date: Sat, 24 Dec 2016 13:12:43 -0500 Subject: [PATCH 04/30] Using config dir now. Config_dir added as a variable in config dict. --- malboxes/malboxes.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index 7340a6a..d265105 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -199,10 +199,12 @@ def load_config(config_file, profile): config['cache_dir'] = DIRS.user_cache_dir.replace('\\', '/') config['dir'] = resource_filename(__name__, "").replace('\\', '/') config['profile_name'] = profile + config['config_dir'] = DIRS.user_config_dir.replace('\\', '/') return config def load_customization(customization_filename): + #filename = os.path.join(DIRS.user_cache_dir.replace('\\', '/'), "scripts", "user", """Loads the customization file, minifies it and returns the content.""" customization = {} with open(customization_filename, 'r') as customization_file: @@ -328,8 +330,8 @@ def build(parser, args): print("Generating configuration files...") config, packer_tmpl = prepare_config(args.profile) prepare_autounattend(config) - if "customization_file" in config.keys(): - prepare_customization(args.profile, config["customization_profile"]) + if "customization_profile" in config.keys(): + prepare_customization(args.profile, config) _prepare_vagrantfile(config, "box_win.rb", create_cachefd('box_win.rb')) print("Configuration files are ready") @@ -394,11 +396,11 @@ def append_to_script(filename, line): f.write(line) -def prepare_customization(profile, customization_filename): +def prepare_customization(profile, config): """ Converts the customization file to a powershell script. """ - customization = load_customization(customization_filename) + customization = load_customization(profile) for i in range(len(customization["registry"])): registry(profile, customization["registry"][i]["modtype"], @@ -413,12 +415,11 @@ def prepare_customization(profile, customization_filename): customization["directory"][i]["dirpath"] ) for i in range(len(customization["document"])): - directory(profile, + document(profile, customization["document"][i]["modtype"], customization["document"][i]["docpath"] ) for i in range(len(customization["package"])): - print("YAAA") package(profile, customization["package"][i] ) @@ -463,8 +464,8 @@ def registry(profile, modtype, key, name, value, valuetype): print("Registry modification type invalid.") print("Valid ones are: add, delete and modify.") - filename = os.path.join(DIRS.user_config_dir, "scripts", "user", - "windows", "{}.ps1".format(profile)) + filename = os.path.join(DIRS.user_cache_dir.replace('\\', '/'), "scripts", "user", + "{}.ps1".format(profile)) append_to_script(filename, line) """ Adds the modified script to the user scripts.""" @@ -544,4 +545,5 @@ def main(): if __name__ == "__main__": - main() + print(prepare_config("win10_64_analyst")) + #main() From 39ca36c5a1689c893332ac71839c4169cefe536c Mon Sep 17 00:00:00 2001 From: svieg Date: Thu, 26 Jan 2017 14:56:20 -0500 Subject: [PATCH 05/30] Customization profiles now work with json in {{ config_dir }}/customization --- malboxes/malboxes.py | 98 +++++++------------ .../snippets/provision_powershell.json | 1 + 2 files changed, 36 insertions(+), 63 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index d265105..ecfb67e 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -187,12 +187,12 @@ def prepare_config(profile): return config, packer_tmpl -def load_config(config_file, profile): +def load_config(config_filename, profile): """Loads the minified JSON config. Returns a dict.""" config = {} - with open(config_file, 'r') as f: + with open(config_filename, 'r') as config_file: # minify then load as JSON - config = json.loads(jsmin(f.read())) + config = json.loads(jsmin(config_file.read())) # add packer required variables # Note: Backslashes are replaced with forward slashes (Packer on Windows) @@ -203,8 +203,13 @@ def load_config(config_file, profile): return config -def load_customization(customization_filename): - #filename = os.path.join(DIRS.user_cache_dir.replace('\\', '/'), "scripts", "user", +def load_customization(customization_profile): + customization_filename = os.path.join( + DIRS.user_config_dir.replace('\\', '/'), + "customization", + customization_profile, + ".js") + """Loads the customization file, minifies it and returns the content.""" customization = {} with open(customization_filename, 'r') as customization_file: @@ -331,7 +336,7 @@ def build(parser, args): config, packer_tmpl = prepare_config(args.profile) prepare_autounattend(config) if "customization_profile" in config.keys(): - prepare_customization(args.profile, config) + prepare_customization(config["customization_profile"]) _prepare_vagrantfile(config, "box_win.rb", create_cachefd('box_win.rb')) print("Configuration files are ready") @@ -391,18 +396,16 @@ def spin(parser, args): def append_to_script(filename, line): - """ Appends a line to a file.""" - with open(filename, 'a') as f: - f.write(line) + """ Appends a line to a script.""" + with open(filename, 'a') as script: + script.write(line) -def prepare_customization(profile, config): - """ - Converts the customization file to a powershell script. - """ - customization = load_customization(profile) +def prepare_customization(customization_profile): + """Converts the customization file to a powershell script.""" + customization = load_customization(customization_profile) for i in range(len(customization["registry"])): - registry(profile, + registry(customization_profile, customization["registry"][i]["modtype"], customization["registry"][i]["key"], customization["registry"][i]["name"], @@ -410,39 +413,22 @@ def prepare_customization(profile, config): customization["registry"][i]["valuetype"], ) for i in range(len(customization["directory"])): - directory(profile, + directory(customization_profile, customization["directory"][i]["filetype"], customization["directory"][i]["dirpath"] ) for i in range(len(customization["document"])): - document(profile, - customization["document"][i]["modtype"], - customization["document"][i]["docpath"] - ) + document(customization_profile, + customization["document"][i]["modtype"], + customization["document"][i]["docpath"] + ) for i in range(len(customization["package"])): - package(profile, + package(customization_profile, customization["package"][i] ) -def add_to_user_scripts(profile): - """ Adds the modified script to the user scripts file.""" - """ File names for the user scripts file and the script to be added.""" - filename = os.path.join(DIRS.user_config_dir, "scripts", "windows", - "user_scripts.ps1") - line = "{}.ps1".format(profile) - - """ Check content of the user scripts file.""" - with open(filename, "r") as f: - content = f.read() - - """ If script isnt present, add it.""" - if content.find(line) == -1: - with open(filename, "a") as f: - f.write(line) - - -def registry(profile, modtype, key, name, value, valuetype): +def registry(customization_profile, modtype, key, name, value, valuetype): """ Adds a registry key modification to a profile with PowerShell commands. """ @@ -464,15 +450,12 @@ def registry(profile, modtype, key, name, value, valuetype): print("Registry modification type invalid.") print("Valid ones are: add, delete and modify.") - filename = os.path.join(DIRS.user_cache_dir.replace('\\', '/'), "scripts", "user", - "{}.ps1".format(profile)) + filename = os.path.join(DIRS.user_config_dir.replace('\\', '/'), "scripts", "user", + "{}.ps1".format(customization_profile)) append_to_script(filename, line) - """ Adds the modified script to the user scripts.""" - add_to_user_scripts(profile) - -def directory(profile, modtype, dirpath): +def directory(customization_profile, modtype, dirpath): """ Adds the directory manipulation commands to the profile.""" if modtype == "add": command = "New-Item" @@ -487,27 +470,21 @@ def directory(profile, modtype, dirpath): print("Valid ones are: add, delete.") filename = os.path.join(DIRS.user_config_dir, "scripts", "user", - "windows", "{}.ps1".format(profile)) + "{}.ps1".format(customization_profile)) append_to_script(filename, line) - """ Adds the modified script to the user scripts.""" - add_to_user_scripts(profile) - -def package(profile, package_name): +def package(customization_profile, package_name): """ Adds a package to install with Chocolatey.""" line = "cinst {} -y\r\n".format(package_name) print("Adding Chocolatey package: {}".format(package_name)) filename = os.path.join(DIRS.user_config_dir, "scripts", "user", - "windows", "{}.ps1".format(profile)) + "{}.ps1".format(customization_profile)) append_to_script(filename, line) - """ Adds the modified script to the user scripts.""" - add_to_user_scripts(profile) - -def document(profile, modtype, docpath): +def document(customization_profile, modtype, docpath): """ Adds the file manipulation commands to the profile.""" if modtype == "add": command = "New-Item" @@ -522,15 +499,11 @@ def document(profile, modtype, docpath): print("Directory modification type invalid.") print("Valid ones are: add, delete.") - filename = os.path.join(DIRS.user_config_dir, - "scripts", "user", "windows", - "{}.ps1".format(profile)) + filename = os.path.join(DIRS.user_config_dir, "scripts", "user", + "{}.ps1".format(customization_profile)) append_to_script(filename, line) - """ Adds the modified script to the user scripts.""" - add_to_user_scripts(profile) - def main(): global DEBUG @@ -545,5 +518,4 @@ def main(): if __name__ == "__main__": - print(prepare_config("win10_64_analyst")) - #main() + main() diff --git a/malboxes/profiles/snippets/provision_powershell.json b/malboxes/profiles/snippets/provision_powershell.json index eb8b4d3..762ff02 100644 --- a/malboxes/profiles/snippets/provision_powershell.json +++ b/malboxes/profiles/snippets/provision_powershell.json @@ -3,6 +3,7 @@ "scripts": [ {% if not windows_updates == "true" %}"{{ dir }}/scripts/windows/disable_auto-updates.ps1",{% endif %} {% if not windows_defender == "true" %}"{{ dir }}/scripts/windows/disable_defender.ps1",{% endif %} + {% if customization_profile %}"{{ config_dir }}/scripts/user/{{ customization_profile }}.ps1",{% endif %} "{{ dir }}/scripts/windows/vmtools.ps1", "{{ dir }}/scripts/windows/malware_analysis.ps1", "{{ dir }}/scripts/windows/installtools.ps1" From 8bf6767ef6b3a7f26708785fdb0983b53b9314aa Mon Sep 17 00:00:00 2001 From: svieg Date: Mon, 6 Feb 2017 10:29:39 -0500 Subject: [PATCH 06/30] Changed the order of provision_powershell scripts to make chocolatey available to the customization scripts. --- .pylintrc | 2 - malboxes/malboxes.py | 59 ++++++++++--------- .../snippets/provision_powershell.json | 6 +- 3 files changed, 35 insertions(+), 32 deletions(-) delete mode 100644 .pylintrc diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index 748fe71..0000000 --- a/.pylintrc +++ /dev/null @@ -1,2 +0,0 @@ -[BASIC] -errors-only=True diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index 11e9c41..cd0836e 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -207,13 +207,11 @@ def load_customization(customization_profile): customization_filename = os.path.join( DIRS.user_config_dir.replace('\\', '/'), "customization", - customization_profile, - ".js") + "{}.js".format(customization_profile)) """Loads the customization file, minifies it and returns the content.""" - customization = {} with open(customization_filename, 'r') as customization_file: - config = json.loads(jsmin(customization_file.read())) + customization = json.loads(jsmin(customization_file.read())) return customization @@ -412,28 +410,35 @@ def append_to_script(filename, line): def prepare_customization(customization_profile): """Converts the customization file to a powershell script.""" customization = load_customization(customization_profile) - for i in range(len(customization["registry"])): - registry(customization_profile, - customization["registry"][i]["modtype"], - customization["registry"][i]["key"], - customization["registry"][i]["name"], - customization["registry"][i]["value"], - customization["registry"][i]["valuetype"], - ) - for i in range(len(customization["directory"])): - directory(customization_profile, - customization["directory"][i]["filetype"], - customization["directory"][i]["dirpath"] - ) - for i in range(len(customization["document"])): - document(customization_profile, - customization["document"][i]["modtype"], - customization["document"][i]["docpath"] - ) - for i in range(len(customization["package"])): - package(customization_profile, - customization["package"][i] - ) + + if "registry" in customization: + for i in range(len(customization["registry"])): + registry(customization_profile, + customization["registry"][i]["modtype"], + customization["registry"][i]["key"], + customization["registry"][i]["name"], + customization["registry"][i]["value"], + customization["registry"][i]["valuetype"], + ) + + if "directory" in customization: + for i in range(len(customization["directory"])): + directory(customization_profile, + customization["directory"][i]["filetype"], + customization["directory"][i]["dirpath"] + ) + if "document" in customization: + for i in range(len(customization["document"])): + document(customization_profile, + customization["document"][i]["modtype"], + customization["document"][i]["docpath"] + ) + + if "package" in customization: + for i in range(len(customization["package"])): + package(customization_profile, + customization["package"][i]["package"] + ) def registry(customization_profile, modtype, key, name, value, valuetype): @@ -484,7 +489,7 @@ def directory(customization_profile, modtype, dirpath): def package(customization_profile, package_name): """ Adds a package to install with Chocolatey.""" - line = "cinst {} -y\r\n".format(package_name) + line = "choco install {} -y\r\n".format(package_name) print("Adding Chocolatey package: {}".format(package_name)) filename = os.path.join(DIRS.user_config_dir, "scripts", "user", diff --git a/malboxes/profiles/snippets/provision_powershell.json b/malboxes/profiles/snippets/provision_powershell.json index 3af32c1..2b1ca71 100644 --- a/malboxes/profiles/snippets/provision_powershell.json +++ b/malboxes/profiles/snippets/provision_powershell.json @@ -3,10 +3,10 @@ "scripts": [ {% if not windows_updates == "true" %}"{{ dir }}/scripts/windows/disable_auto-updates.ps1",{% endif %} {% if not windows_defender == "true" %}"{{ dir }}/scripts/windows/disable_defender.ps1",{% endif %} - {% if customization_profile %}"{{ config_dir }}/scripts/user/{{ customization_profile }}.ps1",{% endif %} "{{ dir }}/scripts/windows/vmtools.ps1", - "{{ dir }}/scripts/windows/malware_analysis.ps1", - "{{ dir }}/scripts/windows/installtools.ps1" + "{{ dir }}/scripts/windows/installtools.ps1", + {% if customization_profile %}"{{ config_dir }}/scripts/user/{{ customization_profile }}.ps1",{% endif %} + "{{ dir }}/scripts/windows/malware_analysis.ps1" ] } {% if choco_packages %}, From 3836686fb02012355cc5bf94603c4ee6036d85c7 Mon Sep 17 00:00:00 2001 From: svieg Date: Mon, 6 Feb 2017 10:41:12 -0500 Subject: [PATCH 07/30] Re-added the pylintrc. --- .pylintrc | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .pylintrc diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..1f624bd --- /dev/null +++ b/.pylintrc @@ -0,0 +1,2 @@ +-[BASIC] +-errors-only=True From 60eff1d35a7efd457e55009e0d61226a4aafcbc6 Mon Sep 17 00:00:00 2001 From: svieg Date: Mon, 6 Feb 2017 10:55:28 -0500 Subject: [PATCH 08/30] Fixed the .pylintrc --- .pylintrc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 1f624bd..748fe71 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,2 +1,2 @@ --[BASIC] --errors-only=True +[BASIC] +errors-only=True From 1a85ac65c519ccd7d74ffea023b6c15a4b0926e4 Mon Sep 17 00:00:00 2001 From: svieg Date: Mon, 6 Feb 2017 10:56:00 -0500 Subject: [PATCH 09/30] Switched from python to python3 for Ubuntu compat. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5415f31..7044863 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ test: pylint malboxes ./tests/config_example_valid.sh - python -m unittest discover + python3 -m unittest discover pkg_clean: rm -r build/ dist/ malboxes.egg-info/ From f31cc5fa29ff61ef75b160b19201acc3c9d6763b Mon Sep 17 00:00:00 2001 From: "hugo.genesse" Date: Mon, 20 Feb 2017 11:14:26 -0800 Subject: [PATCH 10/30] Now automatically makes the missing customization dirs and fixed some typos/bugs --- malboxes/malboxes.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index cd0836e..58a084b 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -43,6 +43,8 @@ def initialize(): # create appdata directories if they don't exist if not os.path.exists(DIRS.user_config_dir): os.makedirs(DIRS.user_config_dir) + os.makedirs(os.path.join(DIRS.user_config_dir, "customization")) + os.makedirs(os.path.join(DIRS.user_config_dir, "scripts", "user")) if not os.path.exists(DIRS.user_cache_dir): os.makedirs(DIRS.user_cache_dir) @@ -424,7 +426,7 @@ def prepare_customization(customization_profile): if "directory" in customization: for i in range(len(customization["directory"])): directory(customization_profile, - customization["directory"][i]["filetype"], + customization["directory"][i]["modtype"], customization["directory"][i]["dirpath"] ) if "document" in customization: @@ -463,7 +465,7 @@ def registry(customization_profile, modtype, key, name, value, valuetype): print("Registry modification type invalid.") print("Valid ones are: add, delete and modify.") - filename = os.path.join(DIRS.user_config_dir.replace('\\', '/'), "scripts", "user", + filename = os.path.join(DIRS.user_config_dir, "scripts", "user", "{}.ps1".format(customization_profile)) append_to_script(filename, line) From 1aac11f32e8c5939309a196d0735950e885d46b0 Mon Sep 17 00:00:00 2001 From: "hugo.genesse" Date: Fri, 28 Apr 2017 21:22:57 -0700 Subject: [PATCH 11/30] Removed useless commands from the readme. --- README.adoc | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/README.adoc b/README.adoc index 6272e60..8beeae9 100644 --- a/README.adoc +++ b/README.adoc @@ -125,38 +125,6 @@ For example: malboxes spin win7_32_analyst 20160519.cryptolocker.xyz -//// -FIXME: not sure we are going to keep this interface so commented for now - -=== Customization - -You can modify (add, modify or delete) registry keys, directories and files like this: - -Registry keys: - - malboxes registry - -Example: - - malboxes registry win10_64_analyst add HKCU:\Software Malboxes IsAwesome String - -Directories and files: - - malboxes directory - -Example: - - malboxes directory BadAPT57 delete C:\Windows\System32 - -You can add packages to install that are specific to the profile: - - malboxes package - -Example: - - malboxes package RansomwareThatINeedRevengeOn chrome -//// - == More information === Videos From 682f3ad1b94dba103a4f4d6fbfbceaf254540191 Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 00:25:30 -0400 Subject: [PATCH 12/30] Moved the creation of the cached dir fo ps1 script for profiles --- malboxes/malboxes.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index daef995..d4a988b 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -43,8 +43,6 @@ def initialize(): # create appdata directories if they don't exist if not os.path.exists(DIRS.user_config_dir): os.makedirs(DIRS.user_config_dir) - os.makedirs(os.path.join(DIRS.user_config_dir, "customization")) - os.makedirs(os.path.join(DIRS.user_config_dir, "scripts", "user")) profile_dir = os.path.join(DIRS.user_config_dir, "customization") @@ -54,6 +52,11 @@ def initialize(): if not os.path.exists(DIRS.user_cache_dir): os.makedirs(DIRS.user_cache_dir) + cache_profile_dir = os.path.join(DIRS.user_cache_dir, "scripts", "user") + + if not (os.path.exists(cache_profile_dir)): + os.makedirs(cache_profile_dir) + return init_parser() def init_parser(): @@ -484,7 +487,7 @@ def registry(customization_profile, reg_mod): print("Registry modification type invalid.") print("Valid ones are: add, delete and modify.") - filename = os.path.join(DIRS.user_config_dir, "scripts", "user", + filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", "{}.ps1".format(customization_profile)) append_to_script(filename, line) @@ -503,7 +506,7 @@ def directory(customization_profile, modtype, dirpath): print("Directory modification type invalid.") print("Valid ones are: add, delete.") - filename = os.path.join(DIRS.user_config_dir, "scripts", "user", + filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", "{}.ps1".format(customization_profile)) append_to_script(filename, line) @@ -513,7 +516,7 @@ def package(customization_profile, package_name): line = "choco install {} -y\r\n".format(package_name) print("Adding Chocolatey package: {}".format(package_name)) - filename = os.path.join(DIRS.user_config_dir, "scripts", "user", + filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", "{}.ps1".format(customization_profile)) append_to_script(filename, line) @@ -533,7 +536,7 @@ def document(customization_profile, modtype, docpath): print("Directory modification type invalid.") print("Valid ones are: add, delete.") - filename = os.path.join(DIRS.user_config_dir, "scripts", "user", + filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", "{}.ps1".format(customization_profile)) append_to_script(filename, line) From 1048de481b2990f37662e6f751daf6a736b6421e Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 00:28:53 -0400 Subject: [PATCH 13/30] Use of the cached dir for the powershell provisioning. --- malboxes/profiles/snippets/provision_powershell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/malboxes/profiles/snippets/provision_powershell.json b/malboxes/profiles/snippets/provision_powershell.json index 2b1ca71..56f7e5f 100644 --- a/malboxes/profiles/snippets/provision_powershell.json +++ b/malboxes/profiles/snippets/provision_powershell.json @@ -5,7 +5,7 @@ {% if not windows_defender == "true" %}"{{ dir }}/scripts/windows/disable_defender.ps1",{% endif %} "{{ dir }}/scripts/windows/vmtools.ps1", "{{ dir }}/scripts/windows/installtools.ps1", - {% if customization_profile %}"{{ config_dir }}/scripts/user/{{ customization_profile }}.ps1",{% endif %} + "{{ cache_dir }}/scripts/user/{{ customization_profile }}.ps1", "{{ dir }}/scripts/windows/malware_analysis.ps1" ] } From bcf9dbfd6cd3b0332d63a7e48502c26868d11854 Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 00:44:14 -0400 Subject: [PATCH 14/30] Added the profile with the cached dir in the windows 7 powershell snippet --- malboxes/profiles/snippets/provision_powershell_win7.json | 1 + 1 file changed, 1 insertion(+) diff --git a/malboxes/profiles/snippets/provision_powershell_win7.json b/malboxes/profiles/snippets/provision_powershell_win7.json index 1346a1b..39a503c 100644 --- a/malboxes/profiles/snippets/provision_powershell_win7.json +++ b/malboxes/profiles/snippets/provision_powershell_win7.json @@ -5,6 +5,7 @@ {% if not windows_updates == "true" %}"{{ dir }}/scripts/windows/disable_auto-updates.ps1",{% endif %} {% if not windows_defender == "true" %}"{{ dir }}/scripts/windows/disable_defender.ps1",{% endif %} "{{ dir }}/scripts/windows/vmtools.ps1", + "{{ cache_dir }}/scripts/user/{{ customization_profile }}.ps1", "{{ dir }}/scripts/windows/malware_analysis.ps1" ] }, From c443c0e05f7c67a441a56af6dbee96115150918d Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 00:44:41 -0400 Subject: [PATCH 15/30] Added the default profile. --- malboxes/profile-example.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 malboxes/profile-example.js diff --git a/malboxes/profile-example.js b/malboxes/profile-example.js new file mode 100644 index 0000000..aa7e97a --- /dev/null +++ b/malboxes/profile-example.js @@ -0,0 +1,20 @@ +{ + + "package": [{"package": "thunderbird"}], + "document": [{"modtype": "add", "docpath": "C:\\Malboxes"}], + "directory": [{"modtype": "add", "dirpath": "C:\\mlbxs\\"}], + "registry": [ + {"modtype": "add", "key": "HKLM:\\Hardware\\Description\\System", "value": "04/04/04", "name": "SystemBiosDate", "valuetype": "String"}, + {"modtype": "add", "key": "HKLM:\\Hardware\\Description\\System", "value": "Hardware Version 0.0 PARTTBLX", "name": "SystemBiosDate", "valuetype": "String"}, + {"modtype": "delete", "key": "HKLM:\\HARDWARE\\ACPI\\DSDT\\VBOX__"}, + {"modtype": "delete", "key": "HKLM:\\HARDWARE\\ACPI\\FADT\\VBOX__"}, + {"modtype": "delete", "key": "HKLM:\\HARDWARE\\ACPI\\RSDT\\VBOX__"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxGuest"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxMouse"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxService"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxSF"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxVideo"}, + {"modtype": "add", "key": "HKLM:\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "value": "Malboxes", "name": "Identifier", "valuetype": "String"}] + + +} From 42863043a236d40caad2619a372b781ca0156147 Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 09:19:14 -0400 Subject: [PATCH 16/30] Fix config to cache when user doesn't specify a profile. --- malboxes/malboxes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index 19bb90d..5fc2d80 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -437,7 +437,7 @@ def prepare_customization(config): if "customization_profile" in config.keys(): customization_profile = config["customization_profile"] else: - profile_file = os.path.join(DIRS.user_config_dir, "customization", 'profile.js') + profile_file = os.path.join(DIRS.user_cache_dir, "customization", 'profile.js') if not os.path.isfile(profile_file): shutil.copy(resource_filename(__name__, 'profile-example.js'), profile_file) From a3d7bd9f71583f572bbb19d2bcb9efa3e9a0f8b1 Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 09:22:10 -0400 Subject: [PATCH 17/30] Revert to config --- malboxes/malboxes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index 5fc2d80..19bb90d 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -437,7 +437,7 @@ def prepare_customization(config): if "customization_profile" in config.keys(): customization_profile = config["customization_profile"] else: - profile_file = os.path.join(DIRS.user_cache_dir, "customization", 'profile.js') + profile_file = os.path.join(DIRS.user_config_dir, "customization", 'profile.js') if not os.path.isfile(profile_file): shutil.copy(resource_filename(__name__, 'profile-example.js'), profile_file) From 7a1c5db574a45c55a2df483f2a1ba8ccde17d9fb Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 10:11:26 -0400 Subject: [PATCH 18/30] The profile is prepared just before creating the packer template --- malboxes/malboxes.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index 19bb90d..a338f34 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -182,15 +182,12 @@ def prepare_config(profile): [1]: https://plus.google.com/+DouglasCrockfordEsq/posts/RK8qyGVaGSr """ - # if config does not exist, copy default one - config_file = os.path.join(DIRS.user_config_dir, 'config.js') - if not os.path.isfile(config_file): - print("Default configuration doesn't exist. Populating one: {}" - .format(config_file)) - shutil.copy(resource_filename(__name__, 'config-example.js'), - config_file) + config = load_config(profile) + + profile_config = prepare_customization(profile) - config = load_config(config_file, profile) + # profile_config might contain a profile not in the config file + config.update(profile_config) packer_tmpl = prepare_packer_template(config, profile) @@ -201,10 +198,19 @@ def prepare_config(profile): return config, packer_tmpl -def load_config(config_filename, profile): +def load_config(profile): """Loads the minified JSON config. Returns a dict.""" + + # if config does not exist, copy default one + config_file = os.path.join(DIRS.user_config_dir, 'config.js') + if not os.path.isfile(config_file): + print("Default configuration doesn't exist. Populating one: {}" + .format(config_file)) + shutil.copy(resource_filename(__name__, 'config-example.js'), + config_file) + config = {} - with open(config_filename, 'r') as config_file: + with open(config_file, 'r') as config_file: # minify then load as JSON config = json.loads(jsmin(config_file.read())) @@ -365,7 +371,6 @@ def build(parser, args): print("Generating configuration files...") config, packer_tmpl = prepare_config(args.profile) prepare_autounattend(config) - prepare_customization(config) _prepare_vagrantfile(config, "box_win.rb", create_cachefd('box_win.rb')) print("Configuration files are ready") @@ -431,9 +436,11 @@ def append_to_script(filename, line): script.write(line) -def prepare_customization(config): +def prepare_customization(profile): """Converts the customization file to a powershell script.""" + config = load_config(profile) + if "customization_profile" in config.keys(): customization_profile = config["customization_profile"] else: @@ -442,6 +449,7 @@ def prepare_customization(config): shutil.copy(resource_filename(__name__, 'profile-example.js'), profile_file) customization_profile = "profile" + config["customization_profile"] = "profile" customization = load_customization(customization_profile) @@ -469,6 +477,7 @@ def prepare_customization(config): package(customization_profile, package_mod["package"] ) + return config def registry(customization_profile, reg_mod): From f9684ad2adb1a7221ab3833dcf94149e55162763 Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 10:23:12 -0400 Subject: [PATCH 19/30] Changed the template test to the new load_config prototype --- tests/test_packer_templates.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_packer_templates.py b/tests/test_packer_templates.py index 43099f8..b7cc458 100755 --- a/tests/test_packer_templates.py +++ b/tests/test_packer_templates.py @@ -42,8 +42,7 @@ def test_packer_template_rendering(self): # process profile profile_name = os.path.basename(profile) - config = load_config('malboxes/config-example.js', - re.match('(.*).json$', profile_name).group(1)) + config = load_config(re.match('(.*).json$', profile_name).group(1)) try: template = self.env.get_template(os.path.basename(profile_name)) From 340ccddd420d70effe11b3e657e7592344784392 Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Fri, 21 Jul 2017 10:44:52 -0400 Subject: [PATCH 20/30] Fixed configuration loading --- malboxes/malboxes.py | 28 +++++++++++++--------------- tests/test_packer_templates.py | 3 ++- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index a338f34..f602588 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -182,9 +182,17 @@ def prepare_config(profile): [1]: https://plus.google.com/+DouglasCrockfordEsq/posts/RK8qyGVaGSr """ - config = load_config(profile) + # if config does not exist, copy default one + config_file = os.path.join(DIRS.user_config_dir, 'config.js') + if not os.path.isfile(config_file): + print("Default configuration doesn't exist. Populating one: {}" + .format(config_file)) + shutil.copy(resource_filename(__name__, 'config-example.js'), + config_file) - profile_config = prepare_customization(profile) + config = load_config(config_file, profile) + + profile_config = prepare_customization(profile, config) # profile_config might contain a profile not in the config file config.update(profile_config) @@ -198,19 +206,11 @@ def prepare_config(profile): return config, packer_tmpl -def load_config(profile): +def load_config(config_filename, profile): """Loads the minified JSON config. Returns a dict.""" - # if config does not exist, copy default one - config_file = os.path.join(DIRS.user_config_dir, 'config.js') - if not os.path.isfile(config_file): - print("Default configuration doesn't exist. Populating one: {}" - .format(config_file)) - shutil.copy(resource_filename(__name__, 'config-example.js'), - config_file) - config = {} - with open(config_file, 'r') as config_file: + with open(config_filename, 'r') as config_file: # minify then load as JSON config = json.loads(jsmin(config_file.read())) @@ -436,11 +436,9 @@ def append_to_script(filename, line): script.write(line) -def prepare_customization(profile): +def prepare_customization(profile, config): """Converts the customization file to a powershell script.""" - config = load_config(profile) - if "customization_profile" in config.keys(): customization_profile = config["customization_profile"] else: diff --git a/tests/test_packer_templates.py b/tests/test_packer_templates.py index b7cc458..43099f8 100755 --- a/tests/test_packer_templates.py +++ b/tests/test_packer_templates.py @@ -42,7 +42,8 @@ def test_packer_template_rendering(self): # process profile profile_name = os.path.basename(profile) - config = load_config(re.match('(.*).json$', profile_name).group(1)) + config = load_config('malboxes/config-example.js', + re.match('(.*).json$', profile_name).group(1)) try: template = self.env.get_template(os.path.basename(profile_name)) From cebe97779d7aa64ff56671b90d894bbef1a78483 Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 11:39:46 -0400 Subject: [PATCH 21/30] Changed ref to profile to template and customization to profile --- malboxes/malboxes.py | 146 +++++++++--------- .../snippets/builder_kvm_windows.json | 27 ++++ .../snippets/builder_virtualbox_windows.json | 0 .../snippets/ida_remote_32.json | 0 .../snippets/ida_remote_64.json | 0 .../snippets/postprocessor_vagrant.json | 2 +- .../snippets/provision_powershell.json | 2 +- .../snippets/provision_powershell_win7.json | 2 +- .../snippets/tools.json | 0 .../win10_32_analyst.json | 0 .../win10_64_analyst.json | 0 .../win7_32_analyst.json | 0 .../win7_64_analyst.json | 0 13 files changed, 103 insertions(+), 76 deletions(-) create mode 100644 malboxes/templates/snippets/builder_kvm_windows.json rename malboxes/{profiles => templates}/snippets/builder_virtualbox_windows.json (100%) rename malboxes/{profiles => templates}/snippets/ida_remote_32.json (100%) rename malboxes/{profiles => templates}/snippets/ida_remote_64.json (100%) rename malboxes/{profiles => templates}/snippets/postprocessor_vagrant.json (69%) rename malboxes/{profiles => templates}/snippets/provision_powershell.json (90%) rename malboxes/{profiles => templates}/snippets/provision_powershell_win7.json (93%) rename malboxes/{profiles => templates}/snippets/tools.json (100%) rename malboxes/{profiles => templates}/win10_32_analyst.json (100%) rename malboxes/{profiles => templates}/win10_64_analyst.json (100%) rename malboxes/{profiles => templates}/win7_32_analyst.json (100%) rename malboxes/{profiles => templates}/win7_64_analyst.json (100%) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index f602588..0b857aa 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -44,7 +44,7 @@ def initialize(): if not os.path.exists(DIRS.user_config_dir): os.makedirs(DIRS.user_config_dir) - profile_dir = os.path.join(DIRS.user_config_dir, "customization") + profile_dir = os.path.join(DIRS.user_config_dir, "profiles") if not os.path.exists(profile_dir): os.makedirs(profile_dir) @@ -52,10 +52,10 @@ def initialize(): if not os.path.exists(DIRS.user_cache_dir): os.makedirs(DIRS.user_cache_dir) - cache_profile_dir = os.path.join(DIRS.user_cache_dir, "scripts", "user") + cache_scripts_dir = os.path.join(DIRS.user_cache_dir, "scripts", "user") - if not (os.path.exists(cache_profile_dir)): - os.makedirs(cache_profile_dir) + if not (os.path.exists(cache_scripts_dir)): + os.makedirs(cache_scripts_dir) return init_parser() @@ -71,16 +71,16 @@ def init_parser(): # list command parser_list = subparsers.add_parser('list', - help="Lists available profiles.") - parser_list.set_defaults(func=list_profiles) + help="Lists available templates.") + parser_list.set_defaults(func=list_templates) # build command parser_build = subparsers.add_parser('build', help="Builds a Vagrant box based on " - "a given profile.") - parser_build.add_argument('profile', help='Name of the profile to build. ' + "a given template.") + parser_build.add_argument('template', help='Name of the template to build. ' 'Use list command to view ' - 'available profiles.') + 'available templates.') parser_build.add_argument('--force', action='store_true', help='Force the build to happen. Overwrites ' 'pre-existing builds or vagrant boxes.') @@ -95,8 +95,8 @@ def init_parser(): # spin command parser_spin = subparsers.add_parser('spin', help="Creates a Vagrantfile for " - "your profile / Vagrant box.") - parser_spin.add_argument('profile', help='Name of the profile to spin.') + "your template / Vagrant box.") + parser_spin.add_argument('template', help='Name of the template to spin.') parser_spin.add_argument('name', help='Name of the target VM. ' 'Must be unique on your system. ' 'Ex: Cryptolocker_XYZ.') @@ -132,16 +132,16 @@ def prepare_packer_template(config, template_name): it into a temporary location where packer later expects it. Uses jinja2 template syntax to generate the resulting JSON file. - Templates are in profiles/ and snippets in profiles/snippets/. + Templates are in templates/ and snippets in templates/snippets/. """ try: - profile_fd = resource_stream(__name__, - 'profiles/{}.json'.format(template_name)) + template_fd = resource_stream(__name__, + 'templates/{}.json'.format(template_name)) except FileNotFoundError: - print("Profile doesn't exist: {}".format(template_name)) + print("Template doesn't exist: {}".format(template_name)) sys.exit(2) - filepath = resource_filename(__name__, 'profiles/') + filepath = resource_filename(__name__, 'templates/') env = Environment(loader=FileSystemLoader(filepath), autoescape=False, trim_blocks=True, lstrip_blocks=True) template = env.get_template("{}.json".format(template_name)) @@ -167,9 +167,9 @@ def _prepare_vagrantfile(config, source, fd_dest): fd_dest.close() -def prepare_config(profile): +def prepare_config(template): """ - Prepares Malboxes configuration and merge with Packer profile configuration + Prepares Malboxes configuration and merge with Packer template configuration Packer uses a configuration in JSON so we decided to go with JSON as well. However since we have features that should be easily "toggled" by our users @@ -178,7 +178,7 @@ def prepare_config(profile): gives a nice suggestion here[1] that I will follow. In a nutshell, our configuration is Javascript, which when minified gives - JSON and then it gets merged with the selected profile. + JSON and then it gets merged with the selected template. [1]: https://plus.google.com/+DouglasCrockfordEsq/posts/RK8qyGVaGSr """ @@ -190,23 +190,23 @@ def prepare_config(profile): shutil.copy(resource_filename(__name__, 'config-example.js'), config_file) - config = load_config(config_file, profile) + config = load_config(config_file, template) - profile_config = prepare_customization(profile, config) + profile_config = prepare_profile(template, config) # profile_config might contain a profile not in the config file config.update(profile_config) - packer_tmpl = prepare_packer_template(config, profile) + packer_tmpl = prepare_packer_template(config, template) - # merge/update with profile config + # merge/update with template config with open(packer_tmpl, 'r') as f: config.update(json.loads(f.read())) return config, packer_tmpl -def load_config(config_filename, profile): +def load_config(config_filename, template): """Loads the minified JSON config. Returns a dict.""" config = {} @@ -218,25 +218,25 @@ def load_config(config_filename, profile): # Note: Backslashes are replaced with forward slashes (Packer on Windows) config['cache_dir'] = DIRS.user_cache_dir.replace('\\', '/') config['dir'] = resource_filename(__name__, "").replace('\\', '/') - config['profile_name'] = profile + config['template_name'] = template config['config_dir'] = DIRS.user_config_dir.replace('\\', '/') return config -def load_customization(customization_profile): - customization_filename = os.path.join( +def load_profile(profile_name): + filename = os.path.join( DIRS.user_config_dir.replace('\\', '/'), - "customization", - "{}.js".format(customization_profile)) + "profiles", + "{}.js".format(profile_name)) - """Loads the customization file, minifies it and returns the content.""" - with open(customization_filename, 'r') as customization_file: - customization = json.loads(jsmin(customization_file.read())) - return customization + """Loads the profile, minifies it and returns the content.""" + with open(filename, 'r') as profile_file: + profile = json.loads(jsmin(profile_file.read())) + return profile def _get_os_type(config): - """OS Type is extracted from profile json config""" + """OS Type is extracted from template json config""" return config['builders'][0]['guest_os_type'].lower() @@ -333,9 +333,9 @@ def add_box(config, args): box = config['post-processors'][0]['output'] box = os.path.join(DIRS.user_cache_dir, box) - box = box.replace('{{user `name`}}', args.profile) + box = box.replace('{{user `name`}}', args.template) - flags = ['--name={}'.format(args.profile)] + flags = ['--name={}'.format(args.template)] if args.force: flags.append('--force') @@ -352,16 +352,16 @@ def add_box(config, args): def default(parser, args): parser.print_help() print("\n") - list_profiles(parser, args) + list_templates(parser, args) sys.exit(1) -def list_profiles(parser, args): - print("supported profiles:\n") +def list_templates(parser, args): + print("supported templates:\n") - filepath = resource_filename(__name__, "profiles/") + filepath = resource_filename(__name__, "templates/") for f in sorted(glob.glob(os.path.join(filepath, '*.json'))): - m = re.search(r'profiles[\/\\](.*).json$', f) + m = re.search(r'templates[\/\\](.*).json$', f) print(m.group(1)) print() @@ -369,7 +369,7 @@ def list_profiles(parser, args): def build(parser, args): print("Generating configuration files...") - config, packer_tmpl = prepare_config(args.profile) + config, packer_tmpl = prepare_config(args.template) prepare_autounattend(config) _prepare_vagrantfile(config, "box_win.rb", create_cachefd('box_win.rb')) print("Configuration files are ready") @@ -407,7 +407,7 @@ def build(parser, args): You can re-use this base box several times by using `malboxes spin`. Each VM will be independent of each other. ===============================================================""") - .format(args.profile, DIRS.user_cache_dir)) + .format(args.template, DIRS.user_cache_dir)) def spin(parser, args): @@ -418,9 +418,9 @@ def spin(parser, args): print("Vagrantfile already exists. Please move it away. Exiting...") sys.exit(5) - config, _ = prepare_config(args.profile) + config, _ = prepare_config(args.template) - config['profile'] = args.profile + config['template'] = args.template config['name'] = args.name print("Creating a Vagrantfile") @@ -436,49 +436,49 @@ def append_to_script(filename, line): script.write(line) -def prepare_customization(profile, config): - """Converts the customization file to a powershell script.""" +def prepare_profile(template, config): + """Converts the profile to a powershell script.""" - if "customization_profile" in config.keys(): - customization_profile = config["customization_profile"] + if "profile" in config.keys(): + profile_name = config["profile"] else: - profile_file = os.path.join(DIRS.user_config_dir, "customization", 'profile.js') + profile_file = os.path.join(DIRS.user_config_dir, "profiles", 'profile.js') if not os.path.isfile(profile_file): shutil.copy(resource_filename(__name__, 'profile-example.js'), profile_file) - customization_profile = "profile" - config["customization_profile"] = "profile" + profile_name = "profile" + config["profile"] = "profile" - customization = load_customization(customization_profile) + profile = load_profile(profile_name) - if "registry" in customization: - for reg_mod in customization["registry"]: - registry(customization_profile, + if "registry" in profile: + for reg_mod in profile["registry"]: + registry(profile_name, reg_mod ) - if "directory" in customization: - for dir_mod in customization["directory"]: - directory(customization_profile, + if "directory" in profile: + for dir_mod in profile["directory"]: + directory(profile_name, dir_mod["modtype"], dir_mod["dirpath"] ) - if "document" in customization: - for doc_mod in customization["document"]: - document(customization_profile, + if "document" in profile: + for doc_mod in profile["document"]: + document(profile_name, doc_mod["modtype"], doc_mod["docpath"] ) - if "package" in customization: - for package_mod in customization["package"]: - package(customization_profile, + if "package" in profile: + for package_mod in profile["package"]: + package(profile_name, package_mod["package"] ) return config -def registry(customization_profile, reg_mod): +def registry(profile_name, reg_mod): """ Adds a registry key modification to a profile with PowerShell commands. """ @@ -508,11 +508,11 @@ def registry(customization_profile, reg_mod): print("Valid ones are: add, delete and modify.") filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", - "{}.ps1".format(customization_profile)) + "{}.ps1".format(profile_name)) append_to_script(filename, line) -def directory(customization_profile, modtype, dirpath): +def directory(profile_name, modtype, dirpath): """ Adds the directory manipulation commands to the profile.""" if modtype == "add": command = "New-Item" @@ -527,21 +527,21 @@ def directory(customization_profile, modtype, dirpath): print("Valid ones are: add, delete.") filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", - "{}.ps1".format(customization_profile)) + "{}.ps1".format(profile_name)) append_to_script(filename, line) -def package(customization_profile, package_name): +def package(profile_name, package_name): """ Adds a package to install with Chocolatey.""" line = "choco install {} -y\r\n".format(package_name) print("Adding Chocolatey package: {}".format(package_name)) filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", - "{}.ps1".format(customization_profile)) + "{}.ps1".format(profile_name)) append_to_script(filename, line) -def document(customization_profile, modtype, docpath): +def document(profile_name, modtype, docpath): """ Adds the file manipulation commands to the profile.""" if modtype == "add": command = "New-Item" @@ -557,7 +557,7 @@ def document(customization_profile, modtype, docpath): print("Valid ones are: add, delete.") filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", - "{}.ps1".format(customization_profile)) + "{}.ps1".format(profile_name)) append_to_script(filename, line) diff --git a/malboxes/templates/snippets/builder_kvm_windows.json b/malboxes/templates/snippets/builder_kvm_windows.json new file mode 100644 index 0000000..be5c574 --- /dev/null +++ b/malboxes/templates/snippets/builder_kvm_windows.json @@ -0,0 +1,27 @@ + "type": "qemu", + "format":"qcow2", + "accelerator": "kvm", + + "disk_size": "{{ disk_size }}", + "disk_interface":"virtio", + + "shutdown_command": "shutdown /s /t 10 /f", + "boot_wait": "10s", + + "floppy_files": [ + "floppy/drivers/virtio-win-0.1.117/viostor/w10/amd64/*", + "floppy/drivers/virtio-win-0.1.117/NetKVM/w10/amd64/*", + "floppy/common/*", + "floppy/windows-10-enterprise//*" + ], + + "communicator": "winrm", + + "winrm_username": "{{ username }}", + "winrm_password": "{{ password }}", + "winrm_timeout": "30m", + + "qemuargs": [ + [ "-m", "4048M" ], + [ "-cpu", "Westmere" ] + ] diff --git a/malboxes/profiles/snippets/builder_virtualbox_windows.json b/malboxes/templates/snippets/builder_virtualbox_windows.json similarity index 100% rename from malboxes/profiles/snippets/builder_virtualbox_windows.json rename to malboxes/templates/snippets/builder_virtualbox_windows.json diff --git a/malboxes/profiles/snippets/ida_remote_32.json b/malboxes/templates/snippets/ida_remote_32.json similarity index 100% rename from malboxes/profiles/snippets/ida_remote_32.json rename to malboxes/templates/snippets/ida_remote_32.json diff --git a/malboxes/profiles/snippets/ida_remote_64.json b/malboxes/templates/snippets/ida_remote_64.json similarity index 100% rename from malboxes/profiles/snippets/ida_remote_64.json rename to malboxes/templates/snippets/ida_remote_64.json diff --git a/malboxes/profiles/snippets/postprocessor_vagrant.json b/malboxes/templates/snippets/postprocessor_vagrant.json similarity index 69% rename from malboxes/profiles/snippets/postprocessor_vagrant.json rename to malboxes/templates/snippets/postprocessor_vagrant.json index 68f8749..8e9abad 100644 --- a/malboxes/profiles/snippets/postprocessor_vagrant.json +++ b/malboxes/templates/snippets/postprocessor_vagrant.json @@ -1,5 +1,5 @@ "post-processors": [{ "type": "vagrant", - "output": "boxes/{{ profile_name }}.box", + "output": "boxes/{{ template_name }}.box", "vagrantfile_template": "{{ cache_dir }}/box_win.rb" }] diff --git a/malboxes/profiles/snippets/provision_powershell.json b/malboxes/templates/snippets/provision_powershell.json similarity index 90% rename from malboxes/profiles/snippets/provision_powershell.json rename to malboxes/templates/snippets/provision_powershell.json index 56f7e5f..7cdf32c 100644 --- a/malboxes/profiles/snippets/provision_powershell.json +++ b/malboxes/templates/snippets/provision_powershell.json @@ -5,7 +5,7 @@ {% if not windows_defender == "true" %}"{{ dir }}/scripts/windows/disable_defender.ps1",{% endif %} "{{ dir }}/scripts/windows/vmtools.ps1", "{{ dir }}/scripts/windows/installtools.ps1", - "{{ cache_dir }}/scripts/user/{{ customization_profile }}.ps1", + "{{ cache_dir }}/scripts/user/{{ profile }}.ps1", "{{ dir }}/scripts/windows/malware_analysis.ps1" ] } diff --git a/malboxes/profiles/snippets/provision_powershell_win7.json b/malboxes/templates/snippets/provision_powershell_win7.json similarity index 93% rename from malboxes/profiles/snippets/provision_powershell_win7.json rename to malboxes/templates/snippets/provision_powershell_win7.json index 39a503c..a37afad 100644 --- a/malboxes/profiles/snippets/provision_powershell_win7.json +++ b/malboxes/templates/snippets/provision_powershell_win7.json @@ -5,7 +5,7 @@ {% if not windows_updates == "true" %}"{{ dir }}/scripts/windows/disable_auto-updates.ps1",{% endif %} {% if not windows_defender == "true" %}"{{ dir }}/scripts/windows/disable_defender.ps1",{% endif %} "{{ dir }}/scripts/windows/vmtools.ps1", - "{{ cache_dir }}/scripts/user/{{ customization_profile }}.ps1", + "{{ cache_dir }}/scripts/user/{{ profile }}.ps1", "{{ dir }}/scripts/windows/malware_analysis.ps1" ] }, diff --git a/malboxes/profiles/snippets/tools.json b/malboxes/templates/snippets/tools.json similarity index 100% rename from malboxes/profiles/snippets/tools.json rename to malboxes/templates/snippets/tools.json diff --git a/malboxes/profiles/win10_32_analyst.json b/malboxes/templates/win10_32_analyst.json similarity index 100% rename from malboxes/profiles/win10_32_analyst.json rename to malboxes/templates/win10_32_analyst.json diff --git a/malboxes/profiles/win10_64_analyst.json b/malboxes/templates/win10_64_analyst.json similarity index 100% rename from malboxes/profiles/win10_64_analyst.json rename to malboxes/templates/win10_64_analyst.json diff --git a/malboxes/profiles/win7_32_analyst.json b/malboxes/templates/win7_32_analyst.json similarity index 100% rename from malboxes/profiles/win7_32_analyst.json rename to malboxes/templates/win7_32_analyst.json diff --git a/malboxes/profiles/win7_64_analyst.json b/malboxes/templates/win7_64_analyst.json similarity index 100% rename from malboxes/profiles/win7_64_analyst.json rename to malboxes/templates/win7_64_analyst.json From ba5b4e46a147b35170ec63cf7c5e613823a69969 Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 11:40:22 -0400 Subject: [PATCH 22/30] Write to script instead of append --- malboxes/malboxes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index 0b857aa..f764110 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -432,7 +432,7 @@ def spin(parser, args): def append_to_script(filename, line): """ Appends a line to a script.""" - with open(filename, 'a') as script: + with open(filename, 'w') as script: script.write(line) From b575914b082dc2d3d8fa11784d41508dda11f03d Mon Sep 17 00:00:00 2001 From: Hugo Genesse Date: Fri, 21 Jul 2017 11:41:05 -0400 Subject: [PATCH 23/30] Vagrantfile now refers to template_name instead of profile --- malboxes/vagrantfiles/analyst_single.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/malboxes/vagrantfiles/analyst_single.rb b/malboxes/vagrantfiles/analyst_single.rb index 9f83099..ef1bd59 100644 --- a/malboxes/vagrantfiles/analyst_single.rb +++ b/malboxes/vagrantfiles/analyst_single.rb @@ -3,7 +3,7 @@ ENV['VAGRANT_DEFAULT_PROVIDER'] = 'virtualbox' Vagrant.configure(2) do |config| - config.vm.box = "{{ profile }}" + config.vm.box = "{{ template_name }}" config.vm.provider "virtualbox" do |vb| vb.name = "{{ name }}" vb.gui = true From 30c0e5f95d48ae9dde4eeba6d80718d0a44c2376 Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Fri, 21 Jul 2017 18:55:35 -0400 Subject: [PATCH 24/30] Revert "Write to script instead of append" This reverts commit ba5b4e46a147b35170ec63cf7c5e613823a69969. --- malboxes/malboxes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index f764110..0b857aa 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -432,7 +432,7 @@ def spin(parser, args): def append_to_script(filename, line): """ Appends a line to a script.""" - with open(filename, 'w') as script: + with open(filename, 'a') as script: script.write(line) From 97295359a28d7177c11d4ce4b730e3d6158a3c71 Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Fri, 21 Jul 2017 19:25:26 -0400 Subject: [PATCH 25/30] Fixed some problems with profiles and misc improvements - using existing cache facilities - added a -Name to registry deletion (avoid build stalling) - Fixed cache file append bug (via using existing create_cachefd) --- malboxes/malboxes.py | 65 ++++++------------- malboxes/profile-example.js | 19 +++--- .../snippets/provision_powershell.json | 2 +- .../snippets/provision_powershell_win7.json | 2 +- 4 files changed, 31 insertions(+), 57 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index 0b857aa..2520754 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -430,10 +430,6 @@ def spin(parser, args): "and issue a `vagrant up` to get started with your VM.") -def append_to_script(filename, line): - """ Appends a line to a script.""" - with open(filename, 'a') as script: - script.write(line) def prepare_profile(template, config): @@ -451,34 +447,29 @@ def prepare_profile(template, config): profile = load_profile(profile_name) + fd = create_cachefd('profile-{}.ps1'.format(profile_name)) + if "registry" in profile: for reg_mod in profile["registry"]: - registry(profile_name, - reg_mod - ) + registry(profile_name, reg_mod, fd) if "directory" in profile: for dir_mod in profile["directory"]: - directory(profile_name, - dir_mod["modtype"], - dir_mod["dirpath"] - ) + directory(profile_name, dir_mod["modtype"], dir_mod["dirpath"], fd) + if "document" in profile: for doc_mod in profile["document"]: - document(profile_name, - doc_mod["modtype"], - doc_mod["docpath"] - ) + document(profile_name, doc_mod["modtype"], doc_mod["docpath"], fd) if "package" in profile: for package_mod in profile["package"]: - package(profile_name, - package_mod["package"] - ) + package(profile_name, package_mod["package"], fd) + + fd.close() return config -def registry(profile_name, reg_mod): +def registry(profile_name, reg_mod, fd): """ Adds a registry key modification to a profile with PowerShell commands. """ @@ -487,32 +478,25 @@ def registry(profile_name, reg_mod): line = "{} -Path {} -Name {} -Value {} -PropertyType {}\r\n".format( command, reg_mod["key"], reg_mod["name"], reg_mod["value"], reg_mod["valuetype"]) - print("Adding: " + line) elif reg_mod["modtype"] == "modify": command = "Set-ItemProperty" line = "{0} -Path {1} -Name {2} -Value {3}\r\n".format( command, reg_mod["key"], reg_mod["name"], reg_mod["value"]) - print("Adding: " + line) elif reg_mod["modtype"] == "delete": command = "Remove-ItemProperty" - if "name" in reg_mod.keys(): - line = "{0} -Path {1} -Name {2}\r\n".format( - command, reg_mod["key"], reg_mod["name"]) - else: - line = "{0} -Path {1}\r\n".format( - command, reg_mod["key"]) - print("Adding: " + line) + line = "{0} -Path {1} -Name {2}\r\n".format(command, reg_mod["key"], + reg_mod["name"]) else: print("Registry modification type invalid.") print("Valid ones are: add, delete and modify.") + return - filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", - "{}.ps1".format(profile_name)) - append_to_script(filename, line) + print("Adding: " + line, end='') + fd.write(line) -def directory(profile_name, modtype, dirpath): +def directory(profile_name, modtype, dirpath, fd): """ Adds the directory manipulation commands to the profile.""" if modtype == "add": command = "New-Item" @@ -526,22 +510,18 @@ def directory(profile_name, modtype, dirpath): print("Directory modification type invalid.") print("Valid ones are: add, delete.") - filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", - "{}.ps1".format(profile_name)) - append_to_script(filename, line) + fd.write(line) -def package(profile_name, package_name): +def package(profile_name, package_name, fd): """ Adds a package to install with Chocolatey.""" line = "choco install {} -y\r\n".format(package_name) print("Adding Chocolatey package: {}".format(package_name)) - filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", - "{}.ps1".format(profile_name)) - append_to_script(filename, line) + fd.write(line) -def document(profile_name, modtype, docpath): +def document(profile_name, modtype, docpath, fd): """ Adds the file manipulation commands to the profile.""" if modtype == "add": command = "New-Item" @@ -556,10 +536,7 @@ def document(profile_name, modtype, docpath): print("Directory modification type invalid.") print("Valid ones are: add, delete.") - filename = os.path.join(DIRS.user_cache_dir, "scripts", "user", - "{}.ps1".format(profile_name)) - - append_to_script(filename, line) + fd.write(line) def main(): diff --git a/malboxes/profile-example.js b/malboxes/profile-example.js index aa7e97a..539b113 100644 --- a/malboxes/profile-example.js +++ b/malboxes/profile-example.js @@ -1,20 +1,17 @@ { - "package": [{"package": "thunderbird"}], "document": [{"modtype": "add", "docpath": "C:\\Malboxes"}], "directory": [{"modtype": "add", "dirpath": "C:\\mlbxs\\"}], "registry": [ {"modtype": "add", "key": "HKLM:\\Hardware\\Description\\System", "value": "04/04/04", "name": "SystemBiosDate", "valuetype": "String"}, {"modtype": "add", "key": "HKLM:\\Hardware\\Description\\System", "value": "Hardware Version 0.0 PARTTBLX", "name": "SystemBiosDate", "valuetype": "String"}, - {"modtype": "delete", "key": "HKLM:\\HARDWARE\\ACPI\\DSDT\\VBOX__"}, - {"modtype": "delete", "key": "HKLM:\\HARDWARE\\ACPI\\FADT\\VBOX__"}, - {"modtype": "delete", "key": "HKLM:\\HARDWARE\\ACPI\\RSDT\\VBOX__"}, - {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxGuest"}, - {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxMouse"}, - {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxService"}, - {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxSF"}, - {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services\\VBoxVideo"}, + {"modtype": "delete", "key": "HKLM:\\HARDWARE\\ACPI\\DSDT", "name": "VBOX__"}, + {"modtype": "delete", "key": "HKLM:\\HARDWARE\\ACPI\\FADT", "name": "VBOX__"}, + {"modtype": "delete", "key": "HKLM:\\HARDWARE\\ACPI\\RSDT", "name": "VBOX__"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services", "name": "VBoxGuest"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services", "name": "VBoxMouse"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services", "name": "VBoxService"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services", "name": "VBoxSF"}, + {"modtype": "delete", "key": "HKLM:\\SYSTEM\\ControlSet001\\Services", "name": "VBoxVideo"}, {"modtype": "add", "key": "HKLM:\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "value": "Malboxes", "name": "Identifier", "valuetype": "String"}] - - } diff --git a/malboxes/templates/snippets/provision_powershell.json b/malboxes/templates/snippets/provision_powershell.json index 7cdf32c..df6535c 100644 --- a/malboxes/templates/snippets/provision_powershell.json +++ b/malboxes/templates/snippets/provision_powershell.json @@ -5,7 +5,7 @@ {% if not windows_defender == "true" %}"{{ dir }}/scripts/windows/disable_defender.ps1",{% endif %} "{{ dir }}/scripts/windows/vmtools.ps1", "{{ dir }}/scripts/windows/installtools.ps1", - "{{ cache_dir }}/scripts/user/{{ profile }}.ps1", + "{{ cache_dir }}/profile-{{ profile }}.ps1", "{{ dir }}/scripts/windows/malware_analysis.ps1" ] } diff --git a/malboxes/templates/snippets/provision_powershell_win7.json b/malboxes/templates/snippets/provision_powershell_win7.json index a37afad..94f3945 100644 --- a/malboxes/templates/snippets/provision_powershell_win7.json +++ b/malboxes/templates/snippets/provision_powershell_win7.json @@ -5,7 +5,7 @@ {% if not windows_updates == "true" %}"{{ dir }}/scripts/windows/disable_auto-updates.ps1",{% endif %} {% if not windows_defender == "true" %}"{{ dir }}/scripts/windows/disable_defender.ps1",{% endif %} "{{ dir }}/scripts/windows/vmtools.ps1", - "{{ cache_dir }}/scripts/user/{{ profile }}.ps1", + "{{ cache_dir }}/profile-{{ profile }}.ps1", "{{ dir }}/scripts/windows/malware_analysis.ps1" ] }, From a9a60393a34e1cdd3d85faf6ff5e531e1ac1726e Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Fri, 21 Jul 2017 19:31:41 -0400 Subject: [PATCH 26/30] Migrated tests from profiles/ to templates/ (removed erroneous file) --- .../snippets/builder_kvm_windows.json | 27 ------------------- tests/test_packer_templates.py | 4 +-- 2 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 malboxes/templates/snippets/builder_kvm_windows.json diff --git a/malboxes/templates/snippets/builder_kvm_windows.json b/malboxes/templates/snippets/builder_kvm_windows.json deleted file mode 100644 index be5c574..0000000 --- a/malboxes/templates/snippets/builder_kvm_windows.json +++ /dev/null @@ -1,27 +0,0 @@ - "type": "qemu", - "format":"qcow2", - "accelerator": "kvm", - - "disk_size": "{{ disk_size }}", - "disk_interface":"virtio", - - "shutdown_command": "shutdown /s /t 10 /f", - "boot_wait": "10s", - - "floppy_files": [ - "floppy/drivers/virtio-win-0.1.117/viostor/w10/amd64/*", - "floppy/drivers/virtio-win-0.1.117/NetKVM/w10/amd64/*", - "floppy/common/*", - "floppy/windows-10-enterprise//*" - ], - - "communicator": "winrm", - - "winrm_username": "{{ username }}", - "winrm_password": "{{ password }}", - "winrm_timeout": "30m", - - "qemuargs": [ - [ "-m", "4048M" ], - [ "-cpu", "Westmere" ] - ] diff --git a/tests/test_packer_templates.py b/tests/test_packer_templates.py index 43099f8..f4e0f37 100755 --- a/tests/test_packer_templates.py +++ b/tests/test_packer_templates.py @@ -33,11 +33,11 @@ class PackerTemplateTestCase(unittest.TestCase): def setUp(self): - self.env = Environment(loader=FileSystemLoader('malboxes/profiles/'), + self.env = Environment(loader=FileSystemLoader('malboxes/templates/'), autoescape=False) def test_packer_template_rendering(self): - for profile in glob.glob("malboxes/profiles/*.json"): + for profile in glob.glob("malboxes/templates/*.json"): print("Processing file {}".format(profile)) # process profile From 556a7114779680f831d489d6b744a3af684f87b5 Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Sat, 22 Jul 2017 14:25:28 -0400 Subject: [PATCH 27/30] Enclosing arguments in double quotes and added -ItemType to document --- malboxes/malboxes.py | 22 +++++++++++----------- malboxes/profile-example.js | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/malboxes/malboxes.py b/malboxes/malboxes.py index 2520754..212c47b 100755 --- a/malboxes/malboxes.py +++ b/malboxes/malboxes.py @@ -475,18 +475,19 @@ def registry(profile_name, reg_mod, fd): """ if reg_mod["modtype"] == "add": command = "New-ItemProperty" - line = "{} -Path {} -Name {} -Value {} -PropertyType {}\r\n".format( - command, reg_mod["key"], reg_mod["name"], - reg_mod["value"], reg_mod["valuetype"]) + line = '{} -Path "{}" -Name "{}" -Value "{}" -PropertyType "{}"\r\n' \ + .format(command, reg_mod["key"], reg_mod["name"], reg_mod["value"], + reg_mod["valuetype"]) elif reg_mod["modtype"] == "modify": command = "Set-ItemProperty" - line = "{0} -Path {1} -Name {2} -Value {3}\r\n".format( + line = '{0} -Path "{1}" -Name "{2}" -Value "{3}"\r\n'.format( command, reg_mod["key"], reg_mod["name"], reg_mod["value"]) elif reg_mod["modtype"] == "delete": command = "Remove-ItemProperty" - line = "{0} -Path {1} -Name {2}\r\n".format(command, reg_mod["key"], - reg_mod["name"]) + line = '{0} -Path "{1}" -Name "{2}"\r\n'.format(command, + reg_mod["key"], + reg_mod["name"]) else: print("Registry modification type invalid.") print("Valid ones are: add, delete and modify.") @@ -500,11 +501,11 @@ def directory(profile_name, modtype, dirpath, fd): """ Adds the directory manipulation commands to the profile.""" if modtype == "add": command = "New-Item" - line = "{0} -Path {1} -Type directory\r\n".format(command, dirpath) + line = '{0} -Path "{1}" -Type directory\r\n'.format(command, dirpath) print("Adding directory: {}".format(dirpath)) elif modtype == "delete": command = "Remove-Item" - line = "{0} -Path {1}\r\n".format(command, dirpath) + line = '{0} -Path "{1}"\r\n'.format(command, dirpath) print("Removing directory: {}".format(dirpath)) else: print("Directory modification type invalid.") @@ -525,12 +526,11 @@ def document(profile_name, modtype, docpath, fd): """ Adds the file manipulation commands to the profile.""" if modtype == "add": command = "New-Item" - line = "{0} -Path {1}\r\n".format(command, docpath) + line = '{0} -Path "{1}" -ItemType file\r\n'.format(command, docpath) print("Adding file: {}".format(docpath)) elif modtype == "delete": command = "Remove-Item" - line = "{0} -Path {1}\r\n".format( - command, docpath) + line = '{0} -Path "{1}"\r\n'.format(command, docpath) print("Removing file: {}".format(docpath)) else: print("Directory modification type invalid.") diff --git a/malboxes/profile-example.js b/malboxes/profile-example.js index 539b113..53ddd78 100644 --- a/malboxes/profile-example.js +++ b/malboxes/profile-example.js @@ -1,6 +1,6 @@ { "package": [{"package": "thunderbird"}], - "document": [{"modtype": "add", "docpath": "C:\\Malboxes"}], + "document": [{"modtype": "add", "docpath": "C:\\Test.doc"}], "directory": [{"modtype": "add", "dirpath": "C:\\mlbxs\\"}], "registry": [ {"modtype": "add", "key": "HKLM:\\Hardware\\Description\\System", "value": "04/04/04", "name": "SystemBiosDate", "valuetype": "String"}, From 536226a5d16924dc97a759c8c0aa053351530190 Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Mon, 24 Jul 2017 11:07:31 -0400 Subject: [PATCH 28/30] doc: profiles -> templates --- README.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 1f156f4..076a3f4 100644 --- a/README.adoc +++ b/README.adoc @@ -100,9 +100,9 @@ re-use the same box several times per sample analysis. Run: - malboxes build + malboxes build