From 0d90dc7d995a234f568e68ed152fb11f9dcad49c Mon Sep 17 00:00:00 2001 From: "hugo.genesse" Date: Sun, 22 May 2016 21:08:34 -0700 Subject: [PATCH 1/8] Deleted WinPcap from tools (was not able to install). --- scripts/windows/installtools.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/windows/installtools.ps1 b/scripts/windows/installtools.ps1 index 56e842a..e7c7738 100644 --- a/scripts/windows/installtools.ps1 +++ b/scripts/windows/installtools.ps1 @@ -8,7 +8,6 @@ cinst windbg -y cinst autohotkey -y $env:Path = "$($env:Path)C:\Program Files\AutoHotkey;" -cinst winpcap -y cinst wireshark -y -i cinst 7zip -y cinst putty -y From 3f6f795bbe792f856cb6b7c903a89fff5742ff76 Mon Sep 17 00:00:00 2001 From: "hugo.genesse" Date: Mon, 23 May 2016 02:50:04 -0700 Subject: [PATCH 2/8] Refactored reg, dir, doc, pkg commands to get rid of code duplcation and git tree problems. --- malboxes.py | 96 ++++++++++++++++++++++++----------------------------- 1 file changed, 43 insertions(+), 53 deletions(-) diff --git a/malboxes.py b/malboxes.py index 20057b6..919afde 100755 --- a/malboxes.py +++ b/malboxes.py @@ -7,6 +7,10 @@ # Copyright (C) 2016 GoSecure Inc. # All rights reserved. # +# Hugo Genesse +# Copyright (C) 2016. +# All rights reserved. +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -274,6 +278,28 @@ def spin(parser, args): print("Vagrantfile generated. You can move it in your analysis directory " "and issue a `vagrant up` to get started with your VM.") +def append_to_script(filename, line): + """ Appends a line to a file.""" + f = open(filename, 'a') + f.write(line) + f.close() + +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("scripts", "windows", "user_scripts.ps1") + line = "{}.ps1".format(profile) + + """ Check content of the user scripts file.""" + f = open(filename, "r") + content = f.read() + f.close() + + """ If script isnt present, add it.""" + if content.find(line) == -1: + f = open(filename, "a") + f.write(line) + f.close() def reg(parser, args): """ @@ -298,21 +324,11 @@ def reg(parser, args): print("Registry modification type invalid.") print("Valid ones are: add, delete and modify.") - filename = os.path.join("scripts","windows", "{}.ps1".format(args.profile)) - f = open(filename, "a") - f.write(line) - f.close() - - """ Add the script to the profile.""" - config = load_config(args.profile) - provisioners_list = config["provisioners"][0]["scripts"] - """ If the script is not already in the profile.""" - if filename not in provisioners_list: - provisioners_list.append(fiString) - f = open(os.path.join("profiles","{}.json".format(args.profile)), "w") - json.dump(config, f, sort_keys=True, indent=4, separators=(',', ': ')) - f.close() + filename = os.path.join("scripts","user","windows", "{}.ps1".format(args.profile)) + append_to_script(filename, line) + """ Adds the modified script to the user scripts.""" + add_to_user_scripts(args.profile) def directory(parser, args): """ Adds the directory manipulation commands to the profile.""" @@ -329,39 +345,22 @@ def directory(parser, args): print("Directory modification type invalid.") print("Valid ones are: add, delete.") - filename = os.path.join("scripts","windows","{}.ps1".format(args.profile)) - f = open(filename, "a") - f.write(line) - f.close() + filename = os.path.join("scripts","user","windows", "{}.ps1".format(args.profile)) + append_to_script(filename, line) - """ Add the script to the profile.""" - config = load_config(args.profile) - provisioners_list = config["provisioners"][0]["scripts"] - """ If the script is not already in the profile.""" - if filename not in provisioners_list: - provisioners_list.append(filename) - f = open(os.path.join("profiles","{}.json".format(args.profile)), "w") - json.dump(config, f, sort_keys=True, indent=4, separators=(',', ': ')) - f.close() + """ Adds the modified script to the user scripts.""" + add_to_user_scripts(args.profile) def package(parser, args): """ Adds a package to install with Chocolatey.""" line = "cinst {} -y\r\n".format(args.package) print("Adding Chocolatey package: {}".format(args.package)) - filename = os.path.join("scripts","windows","{}.ps1".format(args.profile)) - f = open(filename, "a") - f.write(line) - f.close() + + filename = os.path.join("scripts","user","windows", "{}.ps1".format(args.profile)) + append_to_script(filename, line) - """ Add the script to the profile.""" - config = load_config(args.profile) - provisioners_list = config["provisioners"][0]["scripts"] - """ If the script is not already in the profile.""" - if filename not in provisioners_list: - provisioners_list.append(filename) - f = open(os.path.join("profiles","{}.json".format(args.profile)), "w") - json.dump(config, f, sort_keys=True, indent=4, separators=(',', ': ')) - f.close() + """ Adds the modified script to the user scripts.""" + add_to_user_scripts(args.profile) def document(parser, args): """ Adds the file manipulation commands to the profile.""" @@ -378,20 +377,11 @@ def document(parser, args): print("Directory modification type invalid.") print("Valid ones are: add, delete.") - filename = os.path.join("scripts","windows","{}.ps1".format(args.profile)) - f = open(filename, "a") - f.write(line) - f.close() + filename = os.path.join("scripts","user","windows", "{}.ps1".format(args.profile)) + append_to_script(filename, line) - """ Add the script to the profile.""" - config = load_config(args.profile) - provisioners_list = config["provisioners"][0]["scripts"] - """ If the script is not already in the profile.""" - if filename not in provisioners_list: - provisioners_list.append(filename) - f = open(os.path.join("profiles","{}.json".format(args.profile)), "w") - json.dump(config, f, sort_keys=True, indent=4, separators=(',', ': ')) - f.close() + """ Adds the modified script to the user scripts.""" + add_to_user_scripts(args.profile) if __name__ == "__main__": From b25b975ad63739204d6afe4d4019fac6e570d378 Mon Sep 17 00:00:00 2001 From: "hugo.genesse" Date: Tue, 7 Jun 2016 01:42:17 -0700 Subject: [PATCH 3/8] Added middle-script not to fuck up the git tree. --- profiles/win10_64_analyst.json | 1 + 1 file changed, 1 insertion(+) diff --git a/profiles/win10_64_analyst.json b/profiles/win10_64_analyst.json index 8614cde..b6efc7b 100644 --- a/profiles/win10_64_analyst.json +++ b/profiles/win10_64_analyst.json @@ -51,6 +51,7 @@ "scripts/windows/vmtools.ps1", "scripts/windows/enablerdp.ps1", "scripts/windows/installtools.ps1" + "scripts/windows/userscripts.ps1" ] }] } From cc57b66e9e7dbef00c84b5c6c7e68285ee2e6ab3 Mon Sep 17 00:00:00 2001 From: "hugo.genesse" Date: Tue, 7 Jun 2016 02:36:05 -0700 Subject: [PATCH 4/8] Fixed PEP8 issues. --- malboxes.py | 189 ++++++++++++++++++++++++++++------------------------ 1 file changed, 101 insertions(+), 88 deletions(-) diff --git a/malboxes.py b/malboxes.py index 919afde..3dc2346 100755 --- a/malboxes.py +++ b/malboxes.py @@ -36,77 +36,78 @@ def initialize(): - parser = argparse.ArgumentParser(description= - "Vagrant box builder and config generator for malware analysis.") + parser = argparse.ArgumentParser( + description="Vagrant box builder " + "and config generator for malware analysis.") subparsers = parser.add_subparsers() # list command - parser_list = subparsers.add_parser('list', help= - "Lists available profiles.") + parser_list = subparsers.add_parser('list', + help="Lists available profiles.") parser_list.set_defaults(func=list_profiles) # build command parser_build = subparsers.add_parser('build', - help="Builds a Vagrant box based on a given profile.") + help="Builds a Vagrant box based on " + "a given profile.") parser_build.add_argument('profile', help='Name of the profile to build. ' - 'Use list command to view available profiles.') + 'Use list command to view ' + 'available profiles.') parser_build.set_defaults(func=build) # spin command - parser_spin = subparsers.add_parser('spin', help= - "Creates a Vagrantfile for your profile / Vagrant box.") + 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.') parser_spin.add_argument('name', help='Name of the target VM. ' - 'Must be unique on your system. Ex: Cryptolocker_XYZ.') + 'Must be unique on your system. ' + '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= - 'The 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 = 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 = 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 = 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('docpath', help= - 'Path of the file to add with the filename. Ex: C:\Document.txt') + # 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('docpath', + help='Path of the file to add.') parser_document.set_defaults(func=document) # no command @@ -138,7 +139,7 @@ def load_config(profile): """ Config is in JSON since we can re-use the same in both malboxes and packer """ - profile_file = os.path.join('profiles','{}.json'.format(profile)) + profile_file = os.path.join('profiles', '{}.json'.format(profile)) # validate if profile is present if not os.path.isfile(profile_file): print("Profile doesn't exist") @@ -175,7 +176,7 @@ def cleanup(): def run_foreground(command): p = subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT) try: for line in iter(p.stdout.readline, b''): print(line.rstrip().decode('utf-8')) @@ -228,7 +229,7 @@ def default(parser, args): def list_profiles(parser, args): print("supported profiles:\n") - for f in sorted(glob.glob(os.path.join('profiles','*.json'))): + for f in sorted(glob.glob(os.path.join('profiles', '*.json'))): m = re.search(r'^profiles[\/\\](.*).json$', f) print(m.group(1)) print() @@ -240,7 +241,8 @@ def build(parser, args): print("Generating configuration files...") prepare_autounattend(config) print("Configuration files are ready") - ret = run_packer(os.path.join('profiles','{}.json'.format(args.profile))) + ret = run_packer(os.path.join('profiles', + '{}.json'.format(args.profile))) if ret != 0: print("Packer failed. Build failed. Exiting...") sys.exit(3) @@ -252,7 +254,7 @@ def build(parser, args): print("A base box was imported into your local Vagrant box repository") print("You can re-use this base box several times by using the " - "following statement in your Vagrantfile:") + "following statement in your Vagrantfile:") print('config.vm.box = "{}"'.format(args.profile)) @@ -273,33 +275,33 @@ def spin(parser, args): config['profile'] = args.profile config['name'] = args.name - f = open("Vagrantfile", 'w') - f.write(template.render(config)) + with open("Vagrantfile", 'w') as f: + f.write(template.render(config)) print("Vagrantfile generated. You can move it in your analysis directory " - "and issue a `vagrant up` to get started with your VM.") + "and issue a `vagrant up` to get started with your VM.") + def append_to_script(filename, line): - """ Appends a line to a file.""" - f = open(filename, 'a') - f.write(line) - f.close() + """ Appends a line to a file.""" + with open(filename, 'a') as f: + f.write(line) + 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("scripts", "windows", "user_scripts.ps1") - line = "{}.ps1".format(profile) - - """ Check content of the user scripts file.""" - f = open(filename, "r") - content = f.read() - f.close() - - """ If script isnt present, add it.""" - if content.find(line) == -1: - f = open(filename, "a") - f.write(line) - f.close() + """ 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("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 reg(parser, args): """ @@ -307,8 +309,9 @@ def reg(parser, args): """ if args.modtype == "add": command = "New-ItemProperty" - line = "{0} -Path {1} -Name {2} -Value {3} -PropertyType {4}\r\n".format( - command, args.key, args.name, args.value, args.valuetype) + line = "{0} -Path {1} -Name {2} -Value {3} " + + "-PropertyType {4}\r\n".format(command, args.key, args.name, + args.value, args.valuetype) print("Adding: " + line) elif args.modtype == "modify": command = "Set-ItemProperty" @@ -324,17 +327,20 @@ def reg(parser, args): print("Registry modification type invalid.") print("Valid ones are: add, delete and modify.") - filename = os.path.join("scripts","user","windows", "{}.ps1".format(args.profile)) + filename = os.path.join("scripts", "user", + "windows", "{}.ps1".format(args.profile)) append_to_script(filename, line) - """ Adds the modified script to the user scripts.""" - add_to_user_scripts(args.profile) + """ Adds the modified script to the user scripts.""" + add_to_user_scripts(args.profile) + def directory(parser, args): """ Adds the directory manipulation commands to the profile.""" if args.modtype == "add": command = "New-Item" - line = "{0} -Path {1} -Type directory\r\n".format(command, args.dirpath) + line = "{0} -Path {1} -Type directory\r\n".format(command, + args.dirpath) print("Adding directory: {}".format(args.dirpath)) elif args.modtype == "delete": command = "Remove-Item" @@ -345,22 +351,26 @@ def directory(parser, args): print("Directory modification type invalid.") print("Valid ones are: add, delete.") - filename = os.path.join("scripts","user","windows", "{}.ps1".format(args.profile)) + filename = os.path.join("scripts", "user", + "windows", "{}.ps1".format(args.profile)) append_to_script(filename, line) - """ Adds the modified script to the user scripts.""" - add_to_user_scripts(args.profile) + """ Adds the modified script to the user scripts.""" + add_to_user_scripts(args.profile) + def package(parser, args): """ Adds a package to install with Chocolatey.""" line = "cinst {} -y\r\n".format(args.package) print("Adding Chocolatey package: {}".format(args.package)) - - filename = os.path.join("scripts","user","windows", "{}.ps1".format(args.profile)) + + filename = os.path.join("scripts", "user", + "windows", "{}.ps1".format(args.profile)) append_to_script(filename, line) - """ Adds the modified script to the user scripts.""" - add_to_user_scripts(args.profile) + """ Adds the modified script to the user scripts.""" + add_to_user_scripts(args.profile) + def document(parser, args): """ Adds the file manipulation commands to the profile.""" @@ -377,11 +387,14 @@ def document(parser, args): print("Directory modification type invalid.") print("Valid ones are: add, delete.") - filename = os.path.join("scripts","user","windows", "{}.ps1".format(args.profile)) + filename = os.path.join( + "scripts", "user", "windows", + "{}.ps1".format(args.profile)) + append_to_script(filename, line) - """ Adds the modified script to the user scripts.""" - add_to_user_scripts(args.profile) + """ Adds the modified script to the user scripts.""" + add_to_user_scripts(args.profile) if __name__ == "__main__": From b1484b5ad8f8f7d32b723f03bb0de08bcae1e029 Mon Sep 17 00:00:00 2001 From: "hugo.genesse" Date: Tue, 7 Jun 2016 02:47:18 -0700 Subject: [PATCH 5/8] Bugfix on format string. Line 312 to check for PEP8. --- malboxes.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/malboxes.py b/malboxes.py index 3dc2346..80ddf70 100755 --- a/malboxes.py +++ b/malboxes.py @@ -309,9 +309,7 @@ def reg(parser, args): """ if args.modtype == "add": command = "New-ItemProperty" - line = "{0} -Path {1} -Name {2} -Value {3} " + - "-PropertyType {4}\r\n".format(command, args.key, args.name, - args.value, args.valuetype) + line = "{} -Path {} -Name {} -Value {} -PropertyType {}\r\n".format(command, args.key, args.name, args.value, args.valuetype) print("Adding: " + line) elif args.modtype == "modify": command = "Set-ItemProperty" From b5ee316539fb1608d033515b2474fb157851ae70 Mon Sep 17 00:00:00 2001 From: svieg Date: Wed, 8 Jun 2016 02:37:52 -0400 Subject: [PATCH 6/8] Fixed a few bugs. Users scripts logic needs rework. --- malboxes.py | 10 ++++++---- profiles/win10_64_analyst.json | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/malboxes.py b/malboxes.py index 80ddf70..a59330c 100755 --- a/malboxes.py +++ b/malboxes.py @@ -106,6 +106,8 @@ def initialize(): 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) @@ -374,13 +376,13 @@ def document(parser, args): """ Adds the file manipulation commands to the profile.""" if args.modtype == "add": command = "New-Item" - line = "{0} -Path {1}\r\n".format(command, args.dirpath) - print("Adding file: {}".format(args.dirpath)) + line = "{0} -Path {1}\r\n".format(command, args.docpath) + print("Adding file: {}".format(args.docpath)) elif args.modtype == "delete": command = "Remove-Item" line = "{0} -Path {1}\r\n".format( - command, args.dirpath) - print("Removing file: {}".format(args.dirpath)) + command, args.docpath) + print("Removing file: {}".format(args.docpath)) else: print("Directory modification type invalid.") print("Valid ones are: add, delete.") diff --git a/profiles/win10_64_analyst.json b/profiles/win10_64_analyst.json index b6efc7b..23cea04 100644 --- a/profiles/win10_64_analyst.json +++ b/profiles/win10_64_analyst.json @@ -50,8 +50,8 @@ "scripts": [ "scripts/windows/vmtools.ps1", "scripts/windows/enablerdp.ps1", - "scripts/windows/installtools.ps1" - "scripts/windows/userscripts.ps1" + "scripts/windows/installtools.ps1", + "scripts/windows/user_scripts.ps1" ] }] } From a9174541a13eeec431f29a29334ed324a5c1d719 Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Wed, 8 Jun 2016 09:03:45 -0400 Subject: [PATCH 7/8] Fixed Hugo's copyright statement --- malboxes.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/malboxes.py b/malboxes.py index a59330c..fc10a5e 100755 --- a/malboxes.py +++ b/malboxes.py @@ -4,11 +4,9 @@ # https://github.com/gosecure/malboxes # # Olivier Bilodeau -# Copyright (C) 2016 GoSecure Inc. -# All rights reserved. -# # Hugo Genesse -# Copyright (C) 2016. +# Copyright (C) 2016 GoSecure Inc. +# Copyright (C) 2016 Hugo Genesse # All rights reserved. # # This program is free software: you can redistribute it and/or modify From 18f0ee37fce905055595e0844d6c20fbcb669643 Mon Sep 17 00:00:00 2001 From: svieg Date: Sat, 18 Jun 2016 02:33:44 -0400 Subject: [PATCH 8/8] Fixed two lines for styling so we are done with those kind of changes for now. --- malboxes.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/malboxes.py b/malboxes.py index 9762d6d..5cc3c7c 100755 --- a/malboxes.py +++ b/malboxes.py @@ -105,7 +105,7 @@ def initialize(): parser_document.add_argument('profile', help='Name of the profile to modify.') parser_document.add_argument('modtype', - help='Modification type (delete or add).') + help='Modification type (delete or add).') parser_document.add_argument('docpath', help='Path of the file to add.') parser_document.set_defaults(func=document) @@ -309,7 +309,8 @@ def reg(parser, args): """ if args.modtype == "add": command = "New-ItemProperty" - line = "{} -Path {} -Name {} -Value {} -PropertyType {}\r\n".format(command, args.key, args.name, args.value, args.valuetype) + line = "{} -Path {} -Name {} -Value {} -PropertyType {}\r\n".format( + command, args.key, args.name, args.value, args.valuetype) print("Adding: " + line) elif args.modtype == "modify": command = "Set-ItemProperty"