├── LICENSE ├── README.md ├── antivmdetect.py ├── requirements.txt └── vmdetect0.1.5.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Mikael Keri 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Antivmdetection 2 | 3 | ## Background 4 | 5 | A script to help you create templates, which you can use with VirtualBox to make VM detection harder. 6 | 7 | My first post on the subject was in 2012 and have after that been updated at random times. The blog format might have not been the best way of publishing the information and some people did make nice and "easy to apply" script based on the content. 8 | 9 | As a way to make it easier for me to add new content, I have decided to do the very same. 10 | 11 | The purpose of this script is to use available settings without modifying the VirtualBox base. There are people who do really neat things by patching Virtualbox. But that is out of the scoop for this script. I think this approach has some merits as it does not (hopefully) break with every new release of VirtualBox. 12 | Overtime I have also included "things" that are not directly VM related, but rather things that malware is using to fingerprint installations with, I hope you don't mind.. 13 | 14 | The main script will create the following files: 15 | 16 | * One shell script, that can be used as a template, to be used from the host OS and applied to the VM that you like to modify. 17 | * A dump of the DSDT, that is used in the template script above. 18 | * A Windows Powershell file to be used inside the guest, to handle the settings that is not possible to change from the host. This script will have to be run twice, one for the changes that requires reboot and the second time for the pesky things that resurface at reboot. 19 | 20 | ## Usage 21 | 22 | ## Generate script from host 23 | 24 | * Install dependencies `sudo apt install python3-pip libcdio-utils acpica-tools mesa-utils smartmontools` 25 | * Install Python modules: `sudo pip3 install -r requirements.txt` 26 | * Download the following Windows binaries and extract them in the antivmdetection directory : `wget https://download.sysinternals.com/files/VolumeId.zip https://www.nirsoft.net/utils/devmanview-x64.zip` (x64 version). 27 | * Create computer and user text files : `hostname > computer.lst`, `whoami > user.lst` . Modify if you want to use different machine names and users for the VMs (recommended is to fill the files with a long list of user and computer names) 28 | * Run python script as sudo `sudo python3 antivmdetect.py` 29 | * Make generated host script executable from current user `sudo chmod a+x xxxxx.sh` 30 | * If you do get the following message: "ACPI tables bigger than 64KB (VERR_TOO_MUCH_DATA)", this is due to a limitation in Virtualbox, for more context see this case: . Not verified to work, but might a good resource... 31 | 32 | ## Setup VM 33 | 34 | * Create the VM but don't start it, also exit the VirtualBox GUI. The shell script needs to be run before installation!. 35 | * Verify that "I/O APIC" is enabled (System > Motherboard tab). 36 | * Verify that "Paravirtualization Interface" is set to "None" (System > Acceleration tab). 37 | * Change CPU count to 2 or more if possible. 38 | * Set VM IP (File > Host Network Manager > Configure Adapter Manually > IPV4 adress). 39 | * The script expects that the storage layout to look like the following: + IDE: Primary master (Disk) and Primary slave (CD-ROM) + * ATA: Port 0 (Disk) and Port 1 (CD-ROM) 40 | * Run script as current user (because VMs are located in current user home dir) : `/bin/bash xxxxx.sh my-virtual-machine-name` 41 | * Install the Windows Operating System (Supports W7 and W10) 42 | 43 | ## Run script from inside the VM 44 | 45 | * Move the batch script (xxxx.ps1) to the newly installed guest. 46 | * Run the batch script inside the guest. Remember that most of the settings that gets modified, are reverted after each reboot. So make it run at boot if needed. 47 | * As of version 0.1.4, some applied settings will require a reboot. So run the batch script once, the guest will be rebooted. Then run the script once again to finalize the setup. 48 | * Before you apply the batch script inside the guest, please disable UAC (reboot required) otherwise you will not be able to modify the registry with the script. 49 | * For Windows 10 users: run the PS script as an administrator (right-click on the cmd.exe -> run as admin, navigate to the PS script and execute) 50 | * If applied correctly, a Pafish run will result in this (no need to modify Virtualbox). 51 | 52 | * Please note, that this script does other things that is not covered by Pafish (for example W10 artifacts) 53 | 54 | ![alt text](vmdetect0.1.5.png "VMDetect 1.5.x") 55 | 56 | ## Notes 57 | 58 | * When the antivmdetect script can't find any suitable values to use, it will comment these settings in the newly created script, with a "#". These needs manual review as they might have impact on what is displayed in the VM. 59 | 60 | ## Version History 61 | 62 | * 0.1.9: 63 |
Python3 compatible 64 |
First stab at trying to extract the correct disk, has been a source for headache for many. (Issue #35 (and a few others old issues), thanks @oaustin) 65 |
Improved the string handing in the shell script (Issue #35 and #36 and PR #44, thanks @oaustin, @dashjuvi and @corownik) 66 |
Added a link to a online DSDT resource (Issue #37, thanks @MasterCATZ) 67 |
Updated the README to make installations instructions more clear, thanks @jorants (issue #38) 68 |
Check if the DSDT dump is really created, thanks @nov3mb3r (Issue: #42) 69 |
Added a license notice. thanks @obilodeau (issue #43) 70 |
Code clean-up: removed RAID disk support due to lack of access to server hardware.. and a lot of other small improvements 71 | 72 | * 0.1.8: 73 |
Improved support for Windows 10 74 |
Merged markup fix from @bryant1410 (PR #14) 75 |
Solved an issue for people using macOS + VBox/VMWare Fusion to create the templates. 76 |
Creating the template from a virtual machine is not the best way regardless .. (issue #12 and possibly #15) 77 | 78 | * 0.1.7: 79 |
Windows 10 is now supported (feedback welcome) 80 |
Several new artifacts "corrected" for W10 installations 81 |
New dependency: mesa-utils 82 |
Merged bug fix from @Fullmetal5 (#10) 83 |
Misc code fix 84 |
Updated the readme 85 | 86 | * 0.1.6: 87 |
Added a pop-up after the second run, to make it more clear that you are good to go 88 |
Added a function that spawns a few instances of notepad, this feature will be extended in future versions 89 |
Reworked the RandomDate function, thanks to @Antelox for making me aware of the issue with the old one (#8) 90 |
Acpidump shipped with older versions of Ubuntu, does not support the "-s" switch. This is now handled with an error message. Thanks to @Antelox for this issue (#7) 91 |
Devmanview.exe was not removed after the second run, fixed 92 | 93 | * 0.1.5: 94 |
Added support for associating and de-associating (default disabled) file extensions. Reference: 95 |
Added support for user supplied clipboard buffer. If not present a random string will be generated. Fill the file with Honeytokens of your choice 96 |
Removed XP support 97 |
Converted the batch script sections to Powershell. Moved more logic to the guest script, in short there is less reason to create/re-generate the template often, as more items are randomized on the guest. 98 |
Added a function that randomizes the Desktop background image 99 |
Added a function that creates documents of "all" sorts on the guest 100 |
Added a function that creates documents of "all" sorts on the guest and moves them to the recycle bin 101 |
Randomizing the DigitalProductId in two more locations: 102 |
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Registration\DigitalProductId. 103 |
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey\DigitalProductId. 104 |
Use paravirtualization Interface: None (verified with VBox 5.1.4) - Check updated to reflect this change. I assume this change in VBox came about thanks to: TiTi87, thanks! 105 | 106 | * 0.1.4: 107 |
Fixed a bug for users of python-dmidecode 3.10.13-3, this one was all me.. 108 |
Added a function that randomizes VolumeID (new prerequisite: VolumeID.exe), this information is for example collected by Rovnix 109 |
Added a function that randomizes username and computername/hostname (new prerequisites: list of usernames and computernames) 110 |
First attempt to add information to the clipboard buffer, idea (command) came from a tweet by @shanselman . Will be improved in the next release 111 |
Updated the readme: new dependencies and new features that requires reboot 112 | 113 | * 0.1.3: 114 |
Copy and set the CPU brand string. 115 |
Check if an audio device is attached to the guest. Reference: 116 |
Check OS architecture vs DevManView binary. 117 |
Randomizing the ProductId in two more locations: 118 |
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Registration\ProductId. 119 |
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey\ProductId. 120 |
Purge the Windows product key from the registry (to prevent someone from stealing it...). 121 |
Edit the DigitalProductId (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId) to match the new ProductId. 122 | * 0.1.2: 123 |
Check if the Legacy paravirtualization interface is being used (Usage of the Legacy interface will mitigate the "cpuid feature" detection). 124 | * 0.1.1: 125 |
Check for CPU count (Less than 2 == alert). 126 |
Check for memory size (Less than 2GB == alert). 127 |
Check if the default IP/IP-range is being used for vboxnet0 (You can ignore the notification if you don't use it). 128 |
Randomizing the ProductId. 129 |
Merged PR #3 from r-sierra (Thanks for helping out! 130 |
Fixed a bug in the AcpiCreatorId (Thanks @Nadacsc for reporting it to me!). 131 |
Fixed a bug in the DmiBIOSReleaseDate parsing. 132 |
Fixed a bug in DmiBIOSReleaseDate, to handle both the "default" misspelled variant and the correctly spelled one (Thanks @WanpengQian for reporting it to me!). 133 |
The DevManView inclusion did not work as expected, It should be fixed in this release. 134 |
Supports SATA controller as well (Previously only IDE settings was modified) 135 |
Updated the readme 136 | * 0.1.0: 137 |
Resolved the WMI detection make famous by the HT. Added
DevManView.exe (your choice of architecture) to the prerequisites. 138 | * < 0.1.0 No version history kept prior to this, need to start somewhere I guess. 139 | 140 | /Mikael 141 | 142 | Feedback is always welcome! =) 143 | -------------------------------------------------------------------------------- /antivmdetect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Mikael,@nsmfoo - blog.prowling.nu 3 | 4 | # Tested on Ubuntu 20.04 LTS, MacOS 11.x, using several brands of computers and types..but there is no guarantee that it will work anyway.. 5 | # Prerequisites: see README.md 6 | 7 | # Import stuff 8 | import subprocess 9 | import netifaces 10 | import os.path 11 | import dmidecode 12 | import random 13 | import uuid 14 | import re 15 | import time 16 | import base64 17 | import sys 18 | 19 | # Welcome 20 | print('--- Generate VirtualBox templates to help thwart VM detection and more .. - Mikael, @nsmfoo ---') 21 | 22 | if not os.geteuid()==0: 23 | sys.exit("\n[*] You need to run this script as root\n") 24 | 25 | # Check dependencies 26 | dependencies = ["/usr/bin/cd-drive", "/usr/bin/acpidump", "DevManView.exe", "Volumeid.exe", "computer.lst", "user.lst", "/usr/bin/glxinfo", "/usr/sbin/smartctl"] 27 | for dep in dependencies: 28 | if not (os.path.exists(dep)): 29 | print('[WARNING] Dependencies are missing, please verify that you have installed: ', dep) 30 | exit() 31 | 32 | print('[*] Creating VirtualBox modifications ..') 33 | 34 | # Randomize serial 35 | def serial_randomize(start=0, string_length=10): 36 | rand = str(uuid.uuid4()) 37 | rand = rand.upper() 38 | rand = re.sub('-', '', rand) 39 | return rand[start:string_length] 40 | 41 | dmi_info = {} 42 | 43 | try: 44 | for v in dmidecode.get_by_type(0): 45 | if type(v) == dict and v['DMIType'] == 0: 46 | dmi_info['DmiBIOSVendor'] = "string:" + v['Vendor'] 47 | dmi_info['DmiBIOSVersion'] = "string:" + v['Version'].replace(" ", "") 48 | biosversion = v['BIOS Revision'] 49 | dmi_info['DmiBIOSReleaseDate'] = "string:" + v['Release Date'] 50 | except: 51 | # This typo is deliberate, as a previous version of py-dmidecode contained a typo 52 | dmi_info['DmiBIOSReleaseDate'] = "string:" + v['Relase Date'] 53 | 54 | try: 55 | dmi_info['DmiBIOSReleaseMajor'], dmi_info['DmiBIOSReleaseMinor'] = biosversion.split('.', 1) 56 | except: 57 | dmi_info['DmiBIOSReleaseMajor'] = '** No value to retrieve **' 58 | dmi_info['DmiBIOSReleaseMinor'] = '** No value to retrieve **' 59 | 60 | # python-dmidecode does not currently reveal all values .. this is plan B 61 | dmi_firmware = subprocess.getoutput("dmidecode t0") 62 | try: 63 | dmi_info['DmiBIOSFirmwareMajor'], dmi_info['DmiBIOSFirmwareMinor'] = re.search( 64 | "Firmware Revision: ([0-9A-Za-z. ]*)", dmi_firmware).group(1).split('.', 1) 65 | except: 66 | dmi_info['DmiBIOSFirmwareMajor'] = '** No value to retrieve **' 67 | dmi_info['DmiBIOSFirmwareMinor'] = '** No value to retrieve **' 68 | 69 | for v in dmidecode.get_by_type(2): 70 | if type(v) == dict and v['DMIType'] == 2: 71 | serial_number = v['Serial Number'] 72 | dmi_info['DmiBoardVersion'] = "string:" + v['Version'].replace(" ", "") 73 | dmi_info['DmiBoardProduct'] = "string:" + v['Product Name'].replace(" ", "") 74 | dmi_info['DmiBoardVendor'] = "string:" + v['Manufacturer'].replace(" ", "") 75 | 76 | # This is hopefully not the best solution .. 77 | try: 78 | s_number = [] 79 | if serial_number: 80 | # Get position 81 | if '/' in serial_number: 82 | for slash in re.finditer('/', serial_number): 83 | s_number.append(slash.start(0)) 84 | # Remove / from string 85 | new_serial = re.sub('/', '', serial_number) 86 | new_serial = serial_randomize(0, len(new_serial)) 87 | # Add / again 88 | for char in s_number: 89 | new_serial = new_serial[:char] + '/' + new_serial[char:] 90 | else: 91 | new_serial = serial_randomize(0, len(serial_number)) 92 | else: 93 | new_serial = "** No value to retrieve **" 94 | except: 95 | new_serial = "** No value to retrieve **" 96 | 97 | dmi_info['DmiBoardSerial'] = new_serial 98 | 99 | # python-dmidecode does not reveal all values .. this is plan B 100 | dmi_board = subprocess.getoutput("dmidecode -t2") 101 | try: 102 | asset_tag = re.search("Asset Tag: ([0-9A-Za-z ]*)", dmi_board).group(1) 103 | except: 104 | asset_tag = '** No value to retrieve **' 105 | 106 | dmi_info['DmiBoardAssetTag'] = "string:" + asset_tag 107 | 108 | try: 109 | loc_chassis = re.search("Location In Chassis: ([0-9A-Za-z ]*)", dmi_board).group(1) 110 | except: 111 | loc_chassis = '** No value to retrieve **' 112 | 113 | dmi_info['DmiBoardLocInChass'] = "string:" + loc_chassis.replace(" ", "") 114 | 115 | # Based on the list from https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0.pdf 116 | board_dict = {'Unknown': 1, 'Other': 2, 'Server Blade': 3, 'Connectivity Switch': 4, 'System Management Module': 5, 117 | 'Processor Module': 6, 'I/O Module': 7, 'Memory Module': 8, 'Daughter board': 9, 'Motherboard': 10, 118 | 'Processor/Memory Module': 11, 'Processor/IO Module': 12, 'Interconnect board': 13} 119 | try: 120 | board_type = re.search("Type: ([0-9A-Za-z ]+)", dmi_board).group(1) 121 | board_type = str(board_dict.get(board_type)) 122 | except: 123 | board_type = '** No value to retrieve **' 124 | 125 | dmi_info['DmiBoardBoardType'] = board_type 126 | 127 | for v in dmidecode.get_by_type(1): 128 | if type(v) == dict and v['DMIType'] == 1: 129 | dmi_info['DmiSystemSKU'] = v['SKU Number'] 130 | system_family = v['Family'] 131 | system_serial = v['Serial Number'] 132 | dmi_info['DmiSystemVersion'] = "string:" + v['Version'].replace(" ", "") 133 | dmi_info['DmiSystemProduct'] = "string:" + v['Product Name'].replace(" ", "") 134 | dmi_info['DmiSystemVendor'] = "string:" + v['Manufacturer'].replace(" ", "") 135 | 136 | if not system_family: 137 | dmi_info['DmiSystemFamily'] = "Not Specified" 138 | else: 139 | dmi_info['DmiSystemFamily'] = "string:" + system_family 140 | 141 | # Create a new UUID 142 | newuuid = str(uuid.uuid4()) 143 | dmi_info['DmiSystemUuid'] = newuuid.upper() 144 | # Create a new system serial number 145 | dmi_info['DmiSystemSerial'] = "string:" + (serial_randomize(0, len(system_serial))) 146 | 147 | for v in dmidecode.get_by_type(3): 148 | dmi_info['DmiChassisVendor'] = "string:" + v['Manufacturer'].replace(" ", "") 149 | chassi_serial = v['Serial Number'] 150 | dmi_info['DmiChassisVersion'] = "string:" + v['Version'].replace(" ", "") 151 | dmi_info['DmiChassisType'] = v['Type'] 152 | 153 | # Based on the list from https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0.pdf 154 | chassi_dict = {'Other': 1, 'Unknown': 2, 'Desktop': 3, 'Low Profile Desktop': 4, 'Pizza Box': 5, 'Mini Tower': 6, 155 | 'Tower': 7, 'Portable': 8, 'Laptop': 9, 'Notebook': 10, 'Hand Held': 11, 'Docking Station': 12, 156 | 'All in One': 13, 'Sub Notebook': 14, 'Space-saving': 15, 'Lunch Box': 16, 'Main Server Chassis': 17, 157 | 'Expansion Chassis': 18, 'SubChassis': 19, 'Bus Expansion Chassis': 20, 'Peripheral Chassis': 21, 'RAID Chassis': 22, 158 | 'Rack Mount Chassis': 23, 'Sealed-case PC': 24, 'Multi-system chassis': 25, 'Compact PCI': 26, 'Advanced TCA': 27, 159 | 'Blade': 28, 'Blade Enclosure': 29, 'Tablet': 30, 'Convertible': 31, 'Detachable': 32, 'IoT Gateway': 33, 160 | 'Embedded PC': 34, 'Mini PC': 35, 'Stick PC': 36} 161 | 162 | dmi_info['DmiChassisType'] = str(chassi_dict.get(dmi_info['DmiChassisType'])) 163 | 164 | # python-dmidecode does not reveal all values .. this is plan B 165 | chassi = subprocess.getoutput("dmidecode -t3") 166 | try: 167 | dmi_info['DmiChassisAssetTag'] = "string:" + re.search("Asset Tag: ([0-9A-Za-z ]*)", chassi).group(1) 168 | except: 169 | dmi_info['DmiChassisAssetTag'] = '** No value to retrieve **' 170 | 171 | # Create a new chassi serial number 172 | dmi_info['DmiChassisSerial'] = "string:" + (serial_randomize(0, len(chassi_serial))) 173 | 174 | for v in dmidecode.get_by_type(4): 175 | dmi_info['DmiProcVersion'] = "string:" + v['Version'].replace(" ", "") 176 | dmi_info['DmiProcManufacturer'] = "string:" + v['Manufacturer'].replace(" ", "") 177 | # OEM strings 178 | 179 | try: 180 | for v in dmidecode.get_by_type(11): 181 | oem_ver = v['Strings']['3'] 182 | oem_rev = v['Strings']['2'] 183 | except: 184 | pass 185 | try: 186 | dmi_info['DmiOEMVBoxVer'] = "string:" + oem_ver 187 | dmi_info['DmiOEMVBoxRev'] = "string:" + oem_rev 188 | except: 189 | dmi_info['DmiOEMVBoxVer'] = '** No value to retrieve **' 190 | dmi_info['DmiOEMVBoxRev'] = '** No value to retrieve **' 191 | 192 | # Write all data collected so far to file 193 | name_of_file = dmi_info['DmiSystemProduct'].replace(' ', '').replace('string:', '') 194 | if name_of_file: 195 | file_name = dmi_info['DmiSystemProduct'].replace(" ", "").replace("/", "_").replace(",", "_").replace('string:', '') + '.sh' 196 | else: 197 | file_name = dmi_info['DmiChassisType'] + '_' + dmi_info['DmiBoardProduct'].replace("string:", "") + '.sh' 198 | 199 | logfile = open(file_name, 'w+') 200 | logfile.write('#Script generated on: ' + time.strftime("%H:%M:%S") + '\n') 201 | bash = """ if [ $# -eq 0 ] 202 | then 203 | echo "[*] Please add vm name!" 204 | echo "[*] Available vms:" 205 | VBoxManage list vms | awk -F'"' {' print $2 '} | sed 's/"//g' 206 | exit 207 | fi """ 208 | logfile.write(bash + '\n') 209 | 210 | for k, v in sorted(dmi_info.items()): 211 | if '** No value to retrieve **' in v: 212 | logfile.write('# VBoxManage setextradata "$1" VBoxInternal/Devices/pcbios/0/Config/' + k + '\t' + v + '\n') 213 | else: 214 | logfile.write('VBoxManage setextradata "$1" VBoxInternal/Devices/pcbios/0/Config/' + k + '\t\'' + v + '\'\n') 215 | # Disk information 216 | disk_dmi = {} 217 | disk_name = subprocess.getoutput("df -P / | tail -n 1 | awk '/.*/ { print $1 }'") 218 | 219 | # Handle Ubuntu live-cd 220 | if '/cow' in disk_name: 221 | disk_name = "/dev/sdb" 222 | 223 | # Disk serial 224 | try: 225 | if os.path.exists(disk_name): 226 | disk_serial = subprocess.getoutput("smartctl -i " + disk_name + " | grep -o 'Serial Number: [A-Za-z0-9_\+\/ .\"-]*' | awk '{print $3}'") 227 | if 'SG_IO' in disk_serial: 228 | print('[WARNING] Unable to acquire the disk serial number! Will add one, but please try to run this script on another machine instead..') 229 | disk_serial = 'HUA721010KLA330' 230 | 231 | disk_dmi['SerialNumber'] = (serial_randomize(0, len(disk_serial))) 232 | 233 | if (len(disk_dmi['SerialNumber']) > 20): 234 | disk_dmi['SerialNumber'] = disk_dmi['SerialNumber'][:20] 235 | except OSError: 236 | print('Error reading system disk..') 237 | 238 | # Disk firmware rev 239 | try: 240 | if os.path.exists(disk_name): 241 | disk_fwrev = subprocess.getoutput("smartctl -i " + disk_name + " | grep -o 'Firmware Version: [A-Za-z0-9_\+\/ .\"-]*' | awk '{print $3}'") 242 | disk_dmi['FirmwareRevision'] = disk_fwrev 243 | if 'SG_IO' in disk_dmi['FirmwareRevision']: 244 | print('[WARNING] Unable to acquire the disk firmware revision! Will add one, but please try to run this script on another machine instead..') 245 | disk_dmi['FirmwareRevision'] = 'LMP07L3Q' 246 | disk_dmi['FirmwareRevision'] = (serial_randomize(0, len(disk_dmi['FirmwareRevision']))) 247 | except OSError: 248 | print('Error reading system disk..') 249 | 250 | # Disk model number 251 | try: 252 | if os.path.exists(disk_name): 253 | disk_modelno = subprocess.getoutput("smartctl -i " + disk_name + " | grep -o 'Model Family: [A-Za-z0-9_\+\/ .\"-]*' | awk '{print $3}'") 254 | disk_dmi['ModelNumber'] = disk_modelno 255 | 256 | if 'SG_IO' in disk_dmi['ModelNumber']: 257 | print('[WARNING] Unable to acquire the disk model number! Will add one, but please try to run this script on another machine instead..') 258 | disk_vendor = 'SAMSUNG' 259 | disk_vendor_part1 = 'F8E36628D278' 260 | disk_vendor_part1 = (serial_randomize(0, len(disk_vendor_part1))) 261 | disk_vendor_part2 = '611D3' 262 | disk_vendor_part2 = (serial_randomize(0, len(disk_vendor_part2))) 263 | disk_dmi['ModelNumber'] = (serial_randomize(0, len(disk_dmi['ModelNumber']))) 264 | disk_dmi['ModelNumber'] = disk_vendor + ' ' + disk_vendor_part1 + '-' + disk_vendor_part2 265 | except OSError: 266 | print('Error reading system disk..') 267 | 268 | logfile.write('controller=`VBoxManage showvminfo "$1" --machinereadable | grep SATA`\n') 269 | 270 | logfile.write('if [[ -z "$controller" ]]; then\n') 271 | for k, v in disk_dmi.items(): 272 | if '** No value to retrieve **' in v: 273 | logfile.write('# VBoxManage setextradata "$1" VBoxInternal/Devices/piix3ide/0/Config/PrimaryMaster/' + k + '\t' + v + '\n') 274 | else: 275 | logfile.write('VBoxManage setextradata "$1" VBoxInternal/Devices/piix3ide/0/Config/PrimaryMaster/' + k + '\t\'' + v + '\'\n') 276 | 277 | logfile.write('else\n') 278 | for k, v in disk_dmi.items(): 279 | if '** No value to retrieve **' in v: 280 | logfile.write('# VBoxManage setextradata "$1" VBoxInternal/Devices/ahci/0/Config/Port0/' + k + '\t' + v + '\n') 281 | else: 282 | logfile.write('VBoxManage setextradata "$1" VBoxInternal/Devices/ahci/0/Config/Port0/' + k + '\t\'' + v + '\'\n') 283 | logfile.write('fi\n') 284 | 285 | # CD-ROM information 286 | cdrom_dmi = {} 287 | if os.path.islink('/dev/cdrom'): 288 | # CD-ROM serial - No access to a computer with a CD-ROM to verify a switch to smartcrl, at the moment. 289 | cdrom_serial = subprocess.getoutput("hdparm -i /dev/cdrom | grep -o 'SerialNo=[A-Za-z0-9_\+\/ .\"-]*' | awk -F= '{print $2}'") 290 | if cdrom_serial: 291 | cdrom_dmi['ATAPISerialNumber'] = (serial_randomize(0, len(cdrom_serial))) 292 | else: 293 | cdrom_dmi['ATAPISerialNumber'] = "** No value to retrieve **" 294 | 295 | # CD-ROM firmeware rev 296 | cdrom_fwrev = subprocess.getoutput("cd-drive | grep Revision | grep ':' | awk {' print $3 \" \" $4'}") 297 | cdrom_dmi['ATAPIRevision'] = cdrom_fwrev.replace(" ", "") 298 | 299 | # CD-ROM Model numberA-Za-z0-9_\+\/ .\"- 300 | cdrom_modelno = subprocess.getoutput("cd-drive | grep Model | grep ':' | awk {' print $3 \" \" $4'}") 301 | cdrom_dmi['ATAPIProductId'] = cdrom_modelno 302 | 303 | # CD-ROM Vendor 304 | cdrom_vendor = subprocess.getoutput("cd-drive | grep Vendor | grep ':' | awk {' print $3 '}") 305 | cdrom_dmi['ATAPIVendorId'] = cdrom_vendor 306 | else: 307 | logfile.write('# No CD-ROM detected: ** No values to retrieve **\n') 308 | 309 | # And some more 310 | if os.path.islink('/dev/cdrom'): 311 | 312 | logfile.write('if [[ -z "$controller" ]]; then\n') 313 | 314 | for k, v in cdrom_dmi.items(): 315 | if '** No value to retrieve **' in v: 316 | logfile.write('# VBoxManage setextradata "$1" VBoxInternal/Devices/piix3ide/0/Config/PrimarySlave/' + k + '\t' + v + '\n') 317 | else: 318 | logfile.write('VBoxManage setextradata "$1" VBoxInternal/Devices/piix3ide/0/Config/PrimarySlave/' + k + '\t\'' + v + '\'\n') 319 | 320 | logfile.write('else\n') 321 | 322 | for k, v in cdrom_dmi.items(): 323 | if '** No value to retrieve **' in v: 324 | logfile.write('# VBoxManage setextradata "$1" VBoxInternal/Devices/ahci/0/Config/Port1/' + k + '\t' + v + '\n') 325 | else: 326 | logfile.write('VBoxManage setextradata "$1" VBoxInternal/Devices/ahci/0/Config/Port1/' + k + '\t\'' + v + '\'\n') 327 | logfile.write('fi\n') 328 | 329 | # Get and write DSDT image to file 330 | print('[*] Creating a DSDT file...') 331 | name_of_dsdt = dmi_info['DmiSystemProduct'].replace(' ', '').replace('string:', '') 332 | if name_of_dsdt: 333 | dsdt_name = 'DSDT_' + dmi_info['DmiSystemProduct'].replace(" ", "").replace("/", "_").replace("string:", "") + '.bin' 334 | os.system("dd if=/sys/firmware/acpi/tables/DSDT of=" + dsdt_name + " >/dev/null 2>&1") 335 | else: 336 | dsdt_name = 'DSDT_' + dmi_info['DmiChassisType'] + '_' + dmi_info['DmiBoardProduct'].replace("string:", "") + '.bin' 337 | os.system("dd if=/sys/firmware/acpi/tables/DSDT of=" + dsdt_name + " >/dev/null 2>&1") 338 | 339 | try: 340 | if os.path.isfile(dsdt_name): 341 | logfile.write('if [ ! -f "' + dsdt_name + '" ]; then echo "[WARNING] Unable to find the DSDT file!"; fi\t\n') 342 | logfile.write('VBoxManage setextradata "$1" "VBoxInternal/Devices/acpi/0/Config/CustomTable"\t "$PWD"/' + dsdt_name + '\n') 343 | print('[*] Finished: A DSDT dump has been created named:', dsdt_name) 344 | except: 345 | print('[WARNING] Unable to create the DSDT dump') 346 | pass 347 | 348 | acpi_dsdt = subprocess.getoutput('acpidump -s | grep DSDT | grep -o "\(([A-Za-z0-9].*)\)" | tr -d "()"') 349 | acpi_facp = subprocess.getoutput('acpidump -s | grep FACP | grep -o "\(([A-Za-z0-9].*)\)" | tr -d "()"') 350 | 351 | if "option requires" in acpi_dsdt: 352 | acpi_error = subprocess.getoutput("lsb_release -r | awk {' print $2 '}") 353 | print('The version of acpidump included in', acpi_error, 'is not supported') 354 | exit() 355 | else: 356 | acpi_list_dsdt = acpi_dsdt.split(' ') 357 | acpi_list_dsdt = list(filter(None, acpi_list_dsdt)) 358 | 359 | acpi_list_facp = acpi_facp.split(' ') 360 | acpi_list_facp = list(filter(None, acpi_list_facp)) 361 | 362 | # An attempt to solve some of the issues with the AcpiCreatorRev values, I blame the VBox team .. 363 | if isinstance(acpi_list_dsdt[5],str): 364 | acpi_list_dsdt[5] = re.sub("[^0-9]", "", acpi_list_dsdt[5]) 365 | 366 | logfile.write('VBoxManage setextradata "$1" VBoxInternal/Devices/acpi/0/Config/AcpiOemId\t\'' + acpi_list_dsdt[1] + '\'\n') 367 | logfile.write('VBoxManage setextradata "$1" VBoxInternal/Devices/acpi/0/Config/AcpiCreatorId\t\'' + acpi_list_dsdt[4] + '\'\n') 368 | logfile.write('VBoxManage setextradata "$1" VBoxInternal/Devices/acpi/0/Config/AcpiCreatorRev\t\'' + acpi_list_dsdt[5] + '\'\n') 369 | 370 | # Randomize MAC address, based on the host interface MAC 371 | find_int = netifaces.gateways()['default'][netifaces.AF_INET][1] 372 | macme = netifaces.ifaddresses(find_int)[netifaces.AF_LINK][0]['addr'] 373 | l = macme.split(':') 374 | mac_seed = l[0]+l[1]+l[2] 375 | 376 | pattern = re.compile("^([0-9A-Fa-f]{2}){5}([0-9A-Fa-f]{2})$") 377 | 378 | match = None 379 | while match is None: 380 | big_mac = mac_seed + "%02x:%02x:%02x" % ( 381 | random.randint(0, 255), 382 | random.randint(0, 255), 383 | random.randint(0, 255), 384 | ) 385 | 386 | le_big_mac = re.sub(':', '', big_mac) 387 | match = pattern.match(le_big_mac) 388 | 389 | logfile.write('VBoxManage modifyvm "$1" --macaddress1\t' + le_big_mac + '\n') 390 | 391 | # Copy and set the CPU brand string 392 | cpu_brand = subprocess.getoutput("cat /proc/cpuinfo | grep -m 1 'model name' | cut -d ':' -f2 | sed 's/^ *//'") 393 | 394 | if len(cpu_brand) < 47: 395 | cpu_brand = cpu_brand.ljust(47,' ') 396 | 397 | eax_values=('80000002', '80000003', '80000004') 398 | registers=('eax', 'ebx', 'ecx', 'edx') 399 | 400 | i=4 401 | while i<=47: 402 | for e in eax_values: 403 | for r in registers: 404 | k=i-4 405 | if len(cpu_brand[k:i]): 406 | rebrand = subprocess.getoutput("echo -n '" + cpu_brand[k:i] + "' |od -A n -t x4 | sed 's/ //'") 407 | logfile.write('VBoxManage setextradata "$1" VBoxInternal/CPUM/HostCPUID/' + e + '/' + r + ' 0x' +rebrand + '\t\n') 408 | i=i+4 409 | 410 | # Check the numbers of CPUs, should be 2 or more 411 | logfile.write('cpu_count=$(VBoxManage showvminfo --machinereadable "$1" | grep cpus=[0-9]* | sed "s/cpus=//")\t\n') 412 | logfile.write('if [ $cpu_count -lt "2" ]; then echo "[WARNING] CPU count is less than 2. Consider adding more!"; fi\t\n') 413 | 414 | # Check the set memory size. If it's less than 2GB notify user 415 | logfile.write('memory_size=$(VBoxManage showvminfo --machinereadable "$1" | grep memory=[0-9]* | sed "s/memory=//")\t\n') 416 | logfile.write('if [ $memory_size -lt "2048" ]; then echo "[WARNING] Memory size is 2GB or less. Consider adding more memory!"; fi\t\n') 417 | 418 | # Check if hostonlyifs IP address is the default 419 | logfile.write('net_used=$(VBoxManage showvminfo "$1" | grep NIC | grep -v disabled | grep -o "vboxnet.")\t\n') 420 | logfile.write('hostint_ip=$(VBoxManage list hostonlyifs | grep "$net_used\|IPAddress:" | sed -n \'2p\' | awk {\' print $2 \'} | grep \'192.168.56.1\')\t\n') 421 | logfile.write('if [ "$hostint_ip" == \'192.168.56.1\' ]; then echo "[WARNING] You are using the default IP/IP-range. Consider changing the IP and the range used!"; fi\t\n') 422 | 423 | # Check which paravirtualization interface is being used (Setting it to "none" will mitigate the "cpuid feature" check) 424 | logfile.write('virtualization_type=$(VBoxManage showvminfo --machinereadable "$1" | grep -i ^paravirtprovider | cut -d "=" -f2 | sed \'s/"//g\')\t\n') 425 | logfile.write('if [ ! $virtualization_type == \'none\' ]; then echo "[WARNING] Please switch paravirtualization interface to: None!"; fi\t\n') 426 | 427 | # Check if audio support is enabled 428 | logfile.write('audio=$(VBoxManage showvminfo --machinereadable "$1" | grep audio | cut -d "=" -f2 | sed \'s/"//g\' | head -1)\t\n') 429 | logfile.write('if [ $audio == \'none\' ]; then echo "[WARNING] Please consider adding an audio device!"; fi\t\n') 430 | 431 | # Check if you have the correct DevManview binary for the target architecture 432 | arc_devman = subprocess.getoutput("file -b DevManView.exe | grep -o '80386\|64' | sed 's/80386/32/'") 433 | logfile.write('arc_devman=' + arc_devman + '\t\n') 434 | logfile.write('devman_arc=$(VBoxManage showvminfo --machinereadable "$1" | grep ostype | cut -d "=" -f2 | grep -o "(.*)" | sed \'s/(//;s/)//;s/-bit//\')\t\n') 435 | logfile.write('if [ $devman_arc != $arc_devman ]; then echo "[WARNING] Please use the DevManView version that coresponds to the guest architecture: $devman_arc "; fi\t\n') 436 | 437 | # Done! 438 | logfile.close() 439 | 440 | print('[*] Finished: A template shell script has been created named:', file_name) 441 | 442 | # Check file size 443 | try: 444 | if os.path.getsize(dsdt_name) > 64000: 445 | print('[WARNING] Size of the DSDT file is too large (> 64k). Try to build the template from another computer') 446 | except: 447 | pass 448 | 449 | print('[*] Creating guest based modification file (to be run inside the guest)...') 450 | 451 | # Write all data to file 452 | name_of_ps1 = dmi_info['DmiSystemProduct'].replace(' ', '').replace('string:', '') 453 | if name_of_ps1: 454 | file_name = dmi_info['DmiSystemProduct'].replace(" ", "").replace("/", "_").replace('string:', '') + '.ps1' 455 | else: 456 | file_name = dmi_info['DmiChassisType'] + '_' + dmi_info['DmiBoardProduct'].replace('string:', '') + '.ps1' 457 | 458 | logfile = open(file_name, 'w+') 459 | 460 | # Tested on DELL, Lenovo clients and some "noname" boxes, running Windows natively 461 | if ('DELL' in acpi_list_dsdt[1] or 'INTEL' in acpi_list_dsdt[1]): 462 | manu = acpi_list_dsdt[1] + '__' 463 | else: 464 | manu = acpi_list_dsdt[1] 465 | 466 | # OS version - W7 or W10 467 | logfile.write('$version = (Get-WmiObject win32_operatingsystem).version\r\n') 468 | 469 | # DSDT 470 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\DSDT\VBOX__ -Destination HKLM:\HARDWARE\ACPI\DSDT\\' + manu + ' -Recurse\r\n') 471 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\DSDT\VBOX__ -Recurse\r\n') 472 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\DSDT\\' + manu + '\VBOXBIOS -Destination HKLM:\HARDWARE\ACPI\DSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___' + ' -Recurse\r\n') 473 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\DSDT\\' + manu + '\VBOXBIOS -Recurse\r\n') 474 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\DSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\00000002 -Destination HKLM:\HARDWARE\ACPI\DSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\' + acpi_list_dsdt[3] + ' -Recurse\r\n') 475 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\DSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\00000002 -Recurse\r\n') 476 | 477 | if 'INTEL' in acpi_list_dsdt[1]: 478 | manu = acpi_list_dsdt[1] + '_' 479 | else: 480 | manu = acpi_list_dsdt[1] 481 | 482 | # FADT 483 | logfile.write('if ($version -like \'10.0*\') {\r\n') 484 | logfile.write('$oddity = "HKLM:\HARDWARE\ACPI\FADT\\" + (Get-ChildItem "HKLM:\HARDWARE\ACPI\FADT" -Name)\r\n') 485 | logfile.write('if ($oddity -ne "HKLM:\HARDWARE\ACPI\FADT\\' + manu + '") {\r\n') 486 | logfile.write('Invoke-Expression ("Copy-Item -Path " + $oddity + " -Destination HKLM:\HARDWARE\ACPI\FADT\\' + manu + ' -Recurse")\r\n') 487 | logfile.write('Invoke-Expression ("Remove-Item -Path " + $oddity + " -Recurse")\r\n') 488 | logfile.write('}\r\n') 489 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\VBOXFACP -Destination HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\\' + acpi_list_facp[2] + '___ -Recurse\r\n') 490 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\VBOXFACP -Recurse\r\n') 491 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\\' + acpi_list_facp[2] + '___\\00000001 -Destination HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\\' + acpi_list_facp[2] + '___\\' + acpi_list_facp[3] + ' -Recurse\r\n') 492 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\\' + acpi_list_facp[2] + '___\\00000001 -Recurse\r\n') 493 | logfile.write('}else{\r\n') 494 | #Win7 495 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\VBOXFACP -Destination HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\\' + acpi_list_facp[2] + '___ -Recurse\r\n') 496 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\VBOXFACP -Recurse\r\n') 497 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\\' + acpi_list_facp[2] + '___\\00000001 -Destination HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\\' + acpi_list_facp[2] + '___\\' + acpi_list_facp[3] + ' -Recurse\r\n') 498 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\FADT\\' + manu + '\\' + acpi_list_facp[2] + '___\\00000001 -Recurse\r\n') 499 | logfile.write('}\r\n') 500 | 501 | # RSDT 502 | logfile.write('if ($version -like \'10.0*\') {\r\n') 503 | logfile.write('$noproblem = "HKLM:\HARDWARE\ACPI\RSDT\\" + (Get-ChildItem "HKLM:\HARDWARE\ACPI\RSDT" -Name)\r\n') 504 | logfile.write('if ($noproblem -ne "HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '") {\r\n') 505 | logfile.write('Invoke-Expression ("Copy-Item -Path " + $noproblem + " -Destination HKLM:\HARDWARE\ACPI\RSDT\\' + manu + ' -Recurse")\r\n') 506 | logfile.write('Invoke-Expression ("Remove-Item -Path " + $noproblem + " -Recurse")\r\n') 507 | logfile.write('}\r\n') 508 | logfile.write('$cinnamon = "HKLM:\HARDWARE\ACPI\RSDT\\" + (Get-ChildItem "HKLM:\HARDWARE\ACPI\RSDT" -Name)\r\n') 509 | logfile.write('$the_mero = "HKLM:\HARDWARE\ACPI\RSDT\\" + (Get-ChildItem "HKLM:\HARDWARE\ACPI\RSDT" -Name) + "\\" + (Get-ChildItem $cinnamon -Name)\r\n') 510 | logfile.write('Invoke-Expression ("Copy-Item -Path " + $the_mero + " -Destination HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___ -Recurse")\r\n') 511 | logfile.write('Invoke-Expression ("Remove-Item -Path " + $the_mero + " -Recurse")\r\n') 512 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\00000001 -Destination HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\' + acpi_list_dsdt[3] + ' -Recurse\r\n') 513 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\00000001 -Recurse\r\n') 514 | logfile.write('}else{\r\n') 515 | 516 | #Win7 517 | logfile.write('$check_exist = (Test-Path HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\00000001)\r\n') 518 | logfile.write('if ($check_exist) {\r\n') 519 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\00000001 -Destination HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\' + acpi_list_dsdt[3] + ' -Recurse\r\n') 520 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '___\\00000001 -Recurse\r\n') 521 | logfile.write('}else{\r\n') 522 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '\\00000001 -Destination HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '\\' + acpi_list_dsdt[3] + ' -Recurse\r\n') 523 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\RSDT\\' + manu + '\\' + acpi_list_dsdt[2] + '\\00000001 -Recurse\r\n') 524 | logfile.write('}}\r\n') 525 | 526 | # W10 specific settings: 527 | logfile.write('if ($version -like \'10.0*\') {\r\n') 528 | 529 | # SDDT .. very beta .. 530 | new_SDDT1 = subprocess.getoutput("sudo acpidump -s | grep SSDT | grep -o '\(([A-Za-z0-9].*)\)' | head -n 1 | awk {' print $2 '}") 531 | new_SDDT2 = subprocess.getoutput("sudo acpidump -s | grep SSDT | grep -o '\(([A-Za-z0-9].*)\)' | head -n 1 | awk {' print $3 '}") 532 | new_SDDT3 = subprocess.getoutput("sudo acpidump -s | grep SSDT | grep -o '\(([A-Za-z0-9].*)\)' | head -n 1 | awk {' print $4 '}") 533 | 534 | # Check if the key is present.. apparently it is not always the case? Feedback welcome 535 | logfile.write('$check_exist = (Test-Path HKLM:\HARDWARE\ACPI\SSDT)\r\n') 536 | logfile.write('if ($check_exist) {\r\n') 537 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\SSDT\VBOX__ -Destination HKLM:\HARDWARE\ACPI\SSDT\\' + new_SDDT1 + ' -Recurse\r\n') 538 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\SSDT\VBOX__ -Recurse\r\n') 539 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\SSDT\\' + new_SDDT1 + '\VBOXCPUT -Destination HKLM:\HARDWARE\ACPI\SSDT\\' + new_SDDT1 + '\\' + new_SDDT2 + '___ -Recurse\r\n') 540 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\SSDT\\' + new_SDDT1 + '\VBOXCPUT -Recurse\r\n') 541 | logfile.write('Copy-Item -Path HKLM:\HARDWARE\ACPI\SSDT\\' + new_SDDT1 + '\\' + new_SDDT2 + '___\\00000002 -Destination HKLM:\HARDWARE\ACPI\SSDT\\' + new_SDDT1 + '\\' + new_SDDT2 + '___\\' + new_SDDT3 + ' -Recurse\r\n') 542 | logfile.write('Remove-Item -Path HKLM:\HARDWARE\ACPI\SSDT\\' + new_SDDT1 + '\\' + new_SDDT2 + '___\\00000002 -Recurse\r\n') 543 | logfile.write('}\r\n}\r\n') 544 | 545 | # SystemBiosVersion - TODO: get real values 546 | logfile.write('New-ItemProperty -Path HKLM:\HARDWARE\DESCRIPTION\System -Name SystemBiosVersion -Value "'+ acpi_list_dsdt[1] + ' - ' + acpi_list_dsdt[0] + '" -PropertyType "String" -force\r\n') 547 | 548 | # VideoBiosVersion - TODO: get real values 549 | logfile.write('New-ItemProperty -Path HKLM:\HARDWARE\DESCRIPTION\System -Name VideoBiosVersion -Value "' + acpi_list_dsdt[0] + '" -PropertyType "String" -force\r\n') 550 | 551 | # SystemBiosDate 552 | d_month, d_day, d_year = dmi_info['DmiBIOSReleaseDate'].split('/') 553 | d_month = d_month.replace('string:','') 554 | if len(d_year) > 2: 555 | d_year = d_year[2:] 556 | logfile.write('New-ItemProperty -Path HKLM:\HARDWARE\DESCRIPTION\System -Name SystemBiosDate -Value "' + d_month + '/' + d_day + '/' + d_year + '" -PropertyType "String" -force\r\n') 557 | 558 | # OS Install Date (InstallDate) 559 | format = '%m/%d/%Y %I:%M %p' 560 | start = "1/1/2012 5:30 PM" 561 | end = time.strftime("%m/%d/%Y %I:%M %p") 562 | prop = random.random() 563 | stime = time.mktime(time.strptime(start, format)) 564 | etime = time.mktime(time.strptime(end, format)) 565 | ptime = stime + prop * (etime - stime) 566 | logfile.write('New-ItemProperty -Path \"HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" -Name InstallDate -Value "' + hex(int(ptime)) + '" -PropertyType "DWord" -force\r\n') 567 | logfile.write('New-ItemProperty -Path \"HKCU:\SOFTWARE\Microsoft\Internet Explorer\SQM\" -Name InstallDate -Value "' + hex(int(ptime)) + '" -PropertyType "DWord" -force\r\n') 568 | 569 | # MachineGuid 570 | machineGuid = str(uuid.uuid4()) 571 | logfile.write('New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Cryptography -Name MachineGuid -Value "' + machineGuid + '" -PropertyType "String" -force\r\n') 572 | 573 | # W10 specific settings: 574 | logfile.write('if ($version -like \'10.0*\') {\r\n') 575 | 576 | # DacType 577 | new_dactype1 = subprocess.getoutput("lspci | grep -i VGA | cut -d ':' -f3 | awk {' print $1 '}") 578 | new_dactype2 = subprocess.getoutput("lspci | grep -i VGA | cut -d ':' -f3 | awk {' print $2 '}") 579 | 580 | logfile.write('$DacType = ((Get-ItemProperty -path \'HKLM:\SYSTEM\CurrentControlSet\Control\Video\*\\0000\')."HardwareInformation.DacType")\r\n') 581 | logfile.write('if ($DacType -eq \'Oracle Corporation\') {\r\n') 582 | logfile.write('New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\Video\*\\0000 -Name HardwareInformation.DacType -Value "' + new_dactype1 + " " + new_dactype2 + '" -PropertyType "String" -force }\r\n') 583 | 584 | logfile.write('$DacType = ((Get-ItemProperty -path \'HKLM:\SYSTEM\ControlSet001\Control\Class\*\\0016\')."HardwareInformation.DacType")\r\n') 585 | logfile.write('if ($DacType -eq \'Oracle Corporation\') {\r\n') 586 | logfile.write('New-ItemProperty -Path HKLM:\SYSTEM\ControlSet001\Control\Class\*\\0016 -Name HardwareInformation.DacType -Value "' + new_dactype1 + " " + new_dactype2 + '" -PropertyType "String" -force }\r\n') 587 | 588 | # ChipType 589 | new_chiptype1 = subprocess.getoutput("glxinfo -B | grep 'OpenGL renderer string' | cut -d ':' -f2 | sed 's/Mesa DRI//' | awk {' print $1 '} ") 590 | new_chiptype2 = subprocess.getoutput("glxinfo -B | grep 'OpenGL renderer string' | cut -d ':' -f2 | sed 's/Mesa DRI//' | awk {' print $2 '} ") 591 | 592 | if 'Error: unable to open display' in new_chiptype1: 593 | print('[WARNING] Unable to retrieve correct information! You are probably using a server distribution (at least not in X). Will add some semi correct data ...') 594 | new_chiptype1 = subprocess.getoutput("lshw -c video | grep -i vendor: | awk ' { print $2 } '") 595 | new_chiptype2 = subprocess.getoutput("lshw -c video | grep -i vendor: | awk ' { print $3 } '") 596 | 597 | # Having access to only a limited amount of native Windows 10 installed hardware, I have at least noted that W10 reports Sandybridge/Ivybridge for systems that gxlinfo reports being equipped with Ivybridge. 598 | if 'Ivybridge' in new_chiptype2: 599 | new_chiptype2 = 'Sandybridge/Ivybridge' 600 | 601 | logfile.write('$ChipType = ((Get-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\Control\Video\*\\0000)."HardwareInformation.ChipType")\r\n') 602 | logfile.write('if ($ChipType -eq \'VirtualBox VESA BIOS\') {\r\n') 603 | logfile.write('New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\Video\*\\0000 -Name HardwareInformation.ChipType -Value "' + new_chiptype1 + " " + new_chiptype2 + '" -PropertyType "String" -force }\r\n') 604 | 605 | logfile.write('$ChipType = ((Get-ItemProperty -path HKLM:\SYSTEM\ControlSet001\Control\Class\*\\0016)."HardwareInformation.ChipType")\r\n') 606 | logfile.write('if ($ChipType -eq \'VirtualBox VESA BIOS\') {\r\n') 607 | logfile.write('New-ItemProperty -Path HKLM:\SYSTEM\ControlSet001\Control\Class\*\\0016 -Name HardwareInformation.ChipType -Value "' + new_chiptype1 + " " + new_chiptype2 + '" -PropertyType "String" -force }\r\n') 608 | 609 | # BiosString 610 | logfile.write('$BiosString = ((Get-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\Control\Video\*\\0000)."HardwareInformation.BiosString")\r\n') 611 | logfile.write('if ($BiosString -eq \'Oracle VM VirtualBox VBE Adapte\') {\r\n') 612 | logfile.write('New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\Video\*\\0000 -Name HardwareInformation.BiosString -Value "' + new_chiptype1 + " " + new_chiptype2 + '" -PropertyType "String" -force }\r\n') 613 | 614 | logfile.write('$BiosString = ((Get-ItemProperty -path HKLM:\SYSTEM\ControlSet001\Control\Class\*\\0016)."HardwareInformation.BiosString")\r\n') 615 | logfile.write('if ($BiosString -eq \'Oracle VM VirtualBox VBE Adapte\') {\r\n') 616 | logfile.write('New-ItemProperty -Path HKLM:\SYSTEM\ControlSet001\Control\Class\*\\0016 -Name HardwareInformation.BiosString -Value "' + new_chiptype1 + " " + new_chiptype2 + '" -PropertyType "String" -force }\r\n') 617 | 618 | logfile.write('}\r\n') 619 | 620 | # Requires a copy of the DevManView.exe for the target architecture. Reference: https://www.nirsoft.net/utils/device_manager_view.html 621 | with open("DevManView.exe", "rb") as file: 622 | data = file.read() 623 | s = base64.b64encode(data).decode("utf-8") 624 | 625 | logfile.write('$base64_devmanview = \'') 626 | logfile.write(s + '\'') 627 | 628 | DevManView = """\r\n 629 | [IO.File]::WriteAllBytes('DevManView.exe',[System.Convert]::FromBase64String($base64_devmanview))\r\n 630 | $devman = @'\r\n 631 | ./DevManView.exe /uninstall *"DEV_CAFE"* /use_wildcard\r\n 632 | '@\r\n 633 | Invoke-Expression -Command:$devman\r\n""" 634 | logfile.write(DevManView) 635 | 636 | # Second attempt to fill the clipbord buffer with something, will be evolved in future versions. Windows command courtesy of a tweet by @shanselman 637 | # Check if there is a user supplied list of things to populate the clipboard with 638 | if (os.path.exists("clipboard_buffer")): 639 | with open("clipboard_buffer", "rb") as file: 640 | data = file.read() 641 | s = base64.b64encode(data).decode("utf-8") 642 | 643 | logfile.write('$base64_clipboard = \'') 644 | logfile.write(s + '\'') 645 | 646 | clipper = """\r\n 647 | [IO.File]::WriteAllBytes("clipboard_buffer",[System.Convert]::FromBase64String($base64_clipboard))\r\n 648 | $clippy = Get-Random -InputObject (get-content clipboard_buffer)\r\n 649 | Invoke-Expression "echo $clippy | clip"\r\n 650 | Remove-Item clipboard_buffer\r\n 651 | """ 652 | logfile.write(clipper + '\r\n') 653 | else: 654 | print("[Info] Could not find a user supplied file called: clipboard_buffer, a random string will be generated instead") 655 | palinka = """\r\n 656 | [Reflection.Assembly]::LoadWithPartialName("System.Web")\r\n 657 | $length = Get-Random -minimum 5 -maximum 115\r\n 658 | $none = Get-Random -minimum 5 -maximum $length\r\n 659 | $clipboard = [System.Web.Security.Membership]::GeneratePassword($length, $none)\r\n 660 | Invoke-Expression 'echo $clipboard | clip'\r\n 661 | """ 662 | logfile.write(palinka) 663 | 664 | # Start notepad with random files so that the system looks more homely(?), could easily be extended to other applications 665 | langered = """\r\n 666 | $location = "$ENV:userprofile\Desktop", "$ENV:userprofile\Documents", "$ENV:homedrive", "$ENV:userprofile\Downloads", "$ENV:userprofile\Pictures"\r\n 667 | 668 | $notepad = @()\r\n 669 | foreach ($x in $location){\r\n 670 | Get-ChildItem $x | where {$_.extension -eq ".txt"} | % {\r\n 671 | $notepad += $_.FullName\r\n 672 | }\r\n 673 | }\r\n 674 | $notepad = $notepad | Sort-Object -unique {Get-Random}\r\n 675 | 676 | $a = 0\r\n 677 | foreach ($knackered in $notepad) {\r\n 678 | if ($a -le 3) {\r\n 679 | Start-Process "C:\windows\system32\\notepad.exe" -ArgumentList $knackered -WindowStyle Minimized\r\n 680 | $a++\r\n 681 | }\r\n 682 | }\r\n 683 | """ 684 | logfile.write(langered) 685 | 686 | ################################################################ 687 | # "First" boot changes, requires reboot in order to be finalized 688 | ################################################################ 689 | # Check if this has been done before .. 690 | waldo_check = """ 691 | if (Test-Path "kummerspeck") {\r\n 692 | Remove-Item "kummerspeck"\r\n 693 | Remove-Item "DevManView.exe"\r\n 694 | [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")\r\n 695 | [System.Windows.Forms.MessageBox]::Show("You are now ready to infected!")\r\n 696 | exit\r\n 697 | } \r\n""" 698 | logfile.write(waldo_check + '\r\n') 699 | 700 | # Microsoft Product ID (ProductId) 701 | serial = [5,3,7,5] 702 | o = [] 703 | for x in serial: 704 | o.append("%s" % ''.join(["%s" % random.randint(0, 9) for num in range(0, x)])) 705 | newProductId = "{0}-{1}-{2}-{3}".format(o[0], o[1], o[2], o[3]) 706 | 707 | logfile.write('New-ItemProperty -Path \"HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" -Name ProductId -Value "' + newProductId + '" -PropertyType "String" -force\r\n') 708 | logfile.write('New-ItemProperty -Path \"HKLM:\SOFTWARE\Microsoft\Internet Explorer\Registration\" -Name ProductId -Value "' + newProductId + '" -PropertyType "String" -force\r\n') 709 | logfile.write('New-ItemProperty -Path \"HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey\" -Name ProductId -Value "' + newProductId + '" -PropertyType "String" -force\r\n') 710 | 711 | # Clear the Product key from the registry (prevents people from stealing it) 712 | logfile.write('$slmgr="cscript $ENV:windir\system32\slmgr.vbs /cpky"\r\n') 713 | logfile.write('iex $slmgr\r\n') 714 | 715 | logfile.write('$newProductId = "' + newProductId + '"\r\n') 716 | 717 | prodId = """\r\n 718 | $newProductId = $newProductId.ToCharArray()\r\n 719 | 720 | $convert = ""\r\n 721 | foreach ($x in $newProductId) {\r\n 722 | $convert += $x -as [int]\r\n 723 | }\r\n 724 | $newNewProductId = $convert -split "(..)" | ? { $_ }\r\n 725 | 726 | $convertID = @()\r\n 727 | foreach ($x in $newNewProductId) {\r\n 728 | $convertID += [Convert]::ToString($x,16)\r\n 729 | }\r\n 730 | 731 | $data = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey" -Name DigitalProductId).DigitalProductId\r\n 732 | 733 | $convertData = ""\r\n 734 | foreach ($x in $data) {\r\n 735 | $convertData += [Convert]::ToString($x,16)\r\n 736 | }\r\n 737 | 738 | $con1 = $convertData.Substring(0,62)\r\n 739 | $con2 = $convertData.Substring(62)\r\n 740 | $con2 = $con2 -split "(..)" | ? { $_}\r\n 741 | $static = @("A4","00","00","00","03","00","00","00")\r\n 742 | 743 | # Finalize\r\n 744 | $hexDigitalProductId = $static + $convertID + $con2\r\n 745 | 746 | $hexHexDigitalProductId = @()\r\n 747 | foreach ($xxx in $hexDigitalProductId) {\r\n 748 | $hexHexDigitalProductId += "0x$xxx"\r\n 749 | }\r\n 750 | 751 | Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name DigitalProductId -Value ([byte[]] $hexHexDigitalProductId)\r\n 752 | Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Internet Explorer\Registration" -Name DigitalProductId -Value ([byte[]] $hexHexDigitalProductId)\r\n 753 | Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DefaultProductKey" -Name DigitalProductId -Value ([byte[]] $hexHexDigitalProductId)\r\n 754 | 755 | # Agree on the Volumeid EULA - Reference: https://peter.hahndorf.eu/blog/WorkAroundSysinternalsLicenseP.html\r\n 756 | $check_exist = (Test-Path HKCU:\Software\Sysinternals)\r\n 757 | if (-Not $check_exist) {\r\n 758 | New-Item -Path HKCU:\Software\Sysinternals\r\n 759 | New-Item -Path HKCU:\Software\Sysinternals\VolumeId\r\n 760 | New-ItemProperty -Path HKCU:\Software\Sysinternals\VolumeId -Name EulaAccepted -Value "1" -PropertyType "Dword" -force\r\n 761 | }\r\n 762 | """ 763 | logfile.write(prodId +'\r\n') 764 | 765 | # Requires a copy of the VolumeId.exe - Reference: https://technet.microsoft.com/en-us/sysinternals/bb897436.aspx 766 | with open("Volumeid.exe", "rb") as file: 767 | data = file.read() 768 | s = base64.b64encode(data).decode("utf-8") 769 | 770 | logfile.write('$base64_volumeid = \'') 771 | logfile.write(s) 772 | 773 | logfile.write("\'\r\n[IO.File]::WriteAllBytes('Volumeid.exe',[System.Convert]::FromBase64String($base64_volumeid))\r\n") 774 | 775 | # Requires a file with a list of "computer"(host) names - A start would be to use a list from this site: https://www.outpost9.com/files/WordLists.html 776 | with open("computer.lst", "rb") as file: 777 | data = file.read() 778 | s = base64.b64encode(data).decode("utf-8") 779 | 780 | logfile.write('$base64_computer = \'') 781 | logfile.write(s) 782 | 783 | logfile.write("\'\r\n[IO.File]::WriteAllBytes('computer.lst',[System.Convert]::FromBase64String($base64_computer))\r\n") 784 | 785 | # Requires a file with a list of "usernames" - A start would be to use a list from this site: https://www.outpost9.com/files/WordLists.html 786 | with open("user.lst", "rb") as file: 787 | data = file.read() 788 | s = base64.b64encode(data).decode("utf-8") 789 | 790 | logfile.write('$base64_user = \'') 791 | logfile.write(s) 792 | 793 | logfile.write("\'\r\n[IO.File]::WriteAllBytes('user.lst',[System.Convert]::FromBase64String($base64_user))\r\n") 794 | 795 | user_computer = """\r\n 796 | $result = ""\r\n 797 | $char_set = "ABCDEF0123456789".ToCharArray()\r\n 798 | for ($x = 0; $x -lt 8; $x++) {\r\n 799 | $result += $char_set | Get-Random\r\n 800 | }\r\n 801 | 802 | $volid1 = $result.Substring(0,4)\r\n 803 | $volid2 = $result.Substring(4)\r\n 804 | $weltschmerz = "c:"\r\n 805 | $dieweltschmerz = "$weltschmerz $volid1-$volid2"\r\n 806 | Invoke-Expression "./volumeid.exe $dieweltschmerz"\r\n 807 | 808 | $computer = Get-Random -InputObject (get-content computer.lst)\r\n 809 | (Get-WmiObject Win32_ComputerSystem).Rename($computer)\r\n 810 | 811 | $user = Get-Random -InputObject (get-content user.lst)\r\n 812 | $current_user = $ENV:username\r\n 813 | (Get-WmiObject Win32_UserAccount -Filter "Name='$current_user'").Rename($user)\r\n 814 | 815 | # Add waldo file\r\n 816 | New-Item kummerspeck -type file\r\n 817 | \r\n""" 818 | logfile.write(user_computer + '\r\n') 819 | 820 | # Chunk of Powershell code connected to the creation of random files and the randomization of the background image 821 | ps_blob = """ 822 | # Pop-up\r\n 823 | # Windows 10 (Enterprise..) does not ask for confirmation by default\r\n 824 | if ($version -notlike '10.0*') {\r\n 825 | [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")\r\n 826 | [System.Windows.Forms.MessageBox]::Show("Before you continue, please make sure that you have disabled 'Delete File confirmation dialog' (Right-click Recycle Bin -> Properties)")\r\n 827 | }\r\n 828 | # RandomDate function\r\n 829 | function RandomDate {\r\n 830 | $days = Get-Random -minimum 300 -maximum 2190\r\n 831 | $hours = Get-Random -minimum 5 -maximum 24\r\n 832 | $minutes = Get-Random -minimum 20 -maximum 60\r\n 833 | $seconds = Get-Random -minimum 12 -maximum 60\r\n 834 | return $days,$hours,$minutes,$seconds\r\n 835 | }\r\n 836 | 837 | # Generate files\r\n 838 | function GenFiles([string]$status) {\r\n 839 | $TimeStamp = RandomDate\r\n 840 | $ext = Get-Random -input ".pdf",".txt",".docx",".doc",".xls", ".xlsx",".zip",".png",".jpg", ".jpeg", ".gif", ".bmp", ".html", ".htm", ".ppt", ".pptx"\r\n 841 | $namely = Get-Random -InputObject (get-content computer.lst)\r\n 842 | 843 | if ($version -notlike '10.0*') {\r\n 844 | $location = Get-Random -input "$ENV:userprofile\Desktop\\", "$ENV:userprofile\Documents\\", "$ENV:homedrive\\", "$ENV:userprofile\Downloads\\", "$ENV:userprofile\Pictures\\"\r\n 845 | } else {\r\n 846 | $location = Get-Random -input "$ENV:userprofile\Desktop\\", "$ENV:userprofile\Documents\\", "$ENV:userprofile\Downloads\\", "$ENV:userprofile\Pictures\\"\r\n 847 | }\r\n 848 | $length = Get-Random -minimum 300 -maximum 4534350\r\n 849 | $buffer = New-Object Byte[] $length\r\n 850 | 851 | New-Item $location$namely$ext -type file -value $buffer\r\n 852 | Get-ChildItem $location$namely$ext | % {$_.CreationTime = ((get-date).AddDays(-$TimeStamp[0]).AddHours(-$TimeStamp[1]).AddMinutes(-$TimeStamp[2]).AddSeconds(-$TimeStamp[3])) }\r\n 853 | Get-ChildItem $location$namely$ext | % {$_.LastWriteTime = ((get-date).AddDays(-$TimeStamp[0]).AddHours(-$TimeStamp[1]).AddMinutes(-$TimeStamp[2]).AddSeconds(-$TimeStamp[3])) }\r\n 854 | 855 | if ($status -eq "delete"){\r\n 856 | # Now thrown them away!\r\n 857 | $shell = new-object -comobject "Shell.Application"\r\n 858 | $item = $shell.Namespace(0).ParseName("$location$namely$ext")\r\n 859 | $item.InvokeVerb("delete")\r\n 860 | }\r\n 861 | }\r\n 862 | 863 | # Generate files and then throw them away\r\n 864 | $amount = Get-Random -minimum 10 -maximum 30\r\n 865 | for ($x=0; $x -le $amount; $x++) {\r\n 866 | GenFiles delete\r\n 867 | }\r\n 868 | 869 | # Generate files, but these we keep\r\n 870 | $amount = Get-Random -minimum 15 -maximum 45\r\n 871 | for ($x=0; $x -le $amount; $x++) {\r\n 872 | GenFiles\r\n 873 | } 874 | # Set new background image (will only be visible after reboot)\r\n 875 | $image = Get-ChildItem -recurse c:\Windows\Web\Wallpaper -name -include *.jpg | Get-Random -Count 1\r\n 876 | Set-Itemproperty -path "HKCU:Control Panel\Desktop" -name WallPaper -value C:\Windows\Web\Wallpaper\$image\r\n """ 877 | 878 | logfile.write(ps_blob + '\r\n') 879 | 880 | # Associate file extensions. Reference: https://www.proofpoint.com/us/threat-insight/post/massive-adgholas-malvertising-campaigns-use-steganography-and-file-whitelisting-to-hide-in-plain-sight 881 | # Feel free to associate the file extensions with something else then Windows Media Player .. 882 | assocblob = """\r\n 883 | $assoc_ext = @('.divx=WMP11.AssocFile.WAV','.mkv=WMP11.AssocFile.WAV','.m4p=WMP11.AssocFile.WAV','.skype=WMP11.AssocFile.WAV','.flac=WMP11.AssocFile.WAV','.psd=WMP11.AssocFile.WAV','.torrent=WMP11.AssocFile.WAV')\r\n 884 | $cmd = 'cmd /c'\r\n 885 | $associ = 'assoc'\r\n 886 | 887 | foreach ($z in $assoc_ext) {\r\n 888 | Invoke-Expression $cmd$associ$z\r\n 889 | }\r\n 890 | """ 891 | logfile.write(assocblob + '\r\n') 892 | 893 | # De-associate file extensions. Reference: https://www.proofpoint.com/us/threat-insight/post/massive-adgholas-malvertising-campaigns-use-steganography-and-file-whitelisting-to-hide-in-plain-sight 894 | # Disabled by default in this version, enable if you wish 895 | #assocblob2 = """ 896 | #$assoc_remove = @('.py=','.saz=','.pcap=,'.chls=') 897 | #$cmd = 'cmd /c' 898 | #$associ 'assoc' 899 | #foreach ($z in $assoc_remove) { 900 | # Invoke-Expression $cmd$associ$z 901 | #} 902 | #""" 903 | #logfile.write(assocblob2 + '\r\n') 904 | 905 | # Sanitize 906 | logfile.write('Remove-Item Volumeid.exe, user.lst, computer.lst, DevManView.exe\r\n') 907 | logfile.write('Remove-Item -Path HKCU:\Software\Sysinternals\VolumeID -Recurse\r\n') 908 | logfile.write('Remove-Item -Path HKCU:\Software\Sysinternals -Recurse\r\n') 909 | # Reboot notification 910 | logfile.write('[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")\r\n') 911 | logfile.write('[System.Windows.Forms.MessageBox]::Show("The computer needs to reboot")\r\n') 912 | logfile.write('Restart-Computer\r\n') 913 | 914 | logfile.close() 915 | print('[*] Finished: A Powershell file has been created, named:', file_name) 916 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | py-dmidecode==0.0.2 2 | -------------------------------------------------------------------------------- /vmdetect0.1.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsmfoo/antivmdetection/8d7cf0ef8c5ebbdaec373e3e4fccf97b9cd4306c/vmdetect0.1.5.png --------------------------------------------------------------------------------