From 37fb2347d065b59ec033b57a63c420aeb6e1e986 Mon Sep 17 00:00:00 2001 From: man715 Date: Tue, 25 Aug 2020 13:00:12 -0700 Subject: [PATCH 1/5] Add the HyperV\.vagrant folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6580b03..5de5c2f 100755 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ inventory.yml inventory.yml.bak *.box manifest.xml +HyperV/.vagrant/* \ No newline at end of file From 85a5990b2ff8217bc24e5137c39f271456c69365 Mon Sep 17 00:00:00 2001 From: man715 Date: Tue, 25 Aug 2020 13:01:39 -0700 Subject: [PATCH 2/5] Copy the Splunk app to the temp directory of the VM before installing. --- Vagrant/scripts/install-windows_ta.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Vagrant/scripts/install-windows_ta.ps1 b/Vagrant/scripts/install-windows_ta.ps1 index 0493d1a..b9e80fe 100755 --- a/Vagrant/scripts/install-windows_ta.ps1 +++ b/Vagrant/scripts/install-windows_ta.ps1 @@ -9,7 +9,8 @@ If (Test-Path "C:\Program Files\SplunkUniversalForwarder\etc\apps\Splunk_TA_wind } # Install Windows TA (this only needs to be done on the WEF server) -$windowstaPath = "C:\vagrant\resources\splunk_forwarder\splunk-add-on-for-microsoft-windows_700.tgz" +Copy-Item -Path "C:\vagrant\resources\splunk_forwarder\splunk-add-on-for-microsoft-windows_700.tgz" -Destination $env:temp +$windowstaPath = $env:temp + "\splunk-add-on-for-microsoft-windows_700.tgz" $inputsPath = "C:\Program Files\SplunkUniversalForwarder\etc\apps\Splunk_TA_windows\local\inputs.conf" Write-Host "$('[{0:HH:mm}]' -f (Get-Date)) Installing the Windows TA" Start-Process -FilePath "C:\Program Files\SplunkUniversalForwarder\bin\splunk.exe" -ArgumentList "install app $windowstaPath -auth admin:changeme" -NoNewWindow From 53b0ec43a34241e039844c04a3a0531c95f7e79b Mon Sep 17 00:00:00 2001 From: man715 Date: Tue, 25 Aug 2020 13:03:34 -0700 Subject: [PATCH 3/5] Add the ability to use the hyperv provider. --- HyperV/README.md | 36 ++ HyperV/Vagrantfile | 221 +++++++++++ HyperV/bootstrap.sh | 498 ++++++++++++++++++++++++ HyperV/check-eth0-ip.sh | 18 + HyperV/fix-eth0-static-ip.sh | 31 ++ HyperV/fix-motd.sh | 4 + HyperV/hyperv-change-switch.ps1 | 5 + HyperV/hyperv-create-nat-switch.ps1 | 32 ++ HyperV/hyperv-remove-networkadapter.ps1 | 3 + HyperV/hyperv-set-static-ip.ps1 | 29 ++ HyperV/hyperv-set-switch.ps1 | 8 + 11 files changed, 885 insertions(+) create mode 100644 HyperV/README.md create mode 100644 HyperV/Vagrantfile create mode 100644 HyperV/bootstrap.sh create mode 100644 HyperV/check-eth0-ip.sh create mode 100644 HyperV/fix-eth0-static-ip.sh create mode 100644 HyperV/fix-motd.sh create mode 100644 HyperV/hyperv-change-switch.ps1 create mode 100644 HyperV/hyperv-create-nat-switch.ps1 create mode 100644 HyperV/hyperv-remove-networkadapter.ps1 create mode 100644 HyperV/hyperv-set-static-ip.ps1 create mode 100644 HyperV/hyperv-set-switch.ps1 diff --git a/HyperV/README.md b/HyperV/README.md new file mode 100644 index 0000000..b3e9fcb --- /dev/null +++ b/HyperV/README.md @@ -0,0 +1,36 @@ +# Detection Lab for Hyper-V +This hypervisor does not undergo the same level of weekly testing as what is found in the main part of Detectionlab. + +Hyper-V support is only in beta and needs more testing by more users to ensure its stability and usability. + +## Requirements +The version of Hyper-V will need to be compatible with Hyper-V VM configuration version 9.0. +You will need to be running one of the following operating systems: +* Windows 10 1809 or later +* Windows Server 2019 +* Windows Hyper-V Server 2019 +For a breakdown of what Operating Systems support which VM configuration versions please visit: (https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/deploy/upgrade-virtual-machine-version-in-hyper-v-on-windows-or-windows-server) + +This build also requires vagrant-reload. If you do not have it installed, you will be prompted to install it. + +## Known Issues Important! +Unfortunately, due to some issues with Vagrant and Microsoft, running DetectionLab with Hyper-V is not as easy as it is with other providers. You will need to do the following BEFORE trying to run `vagrant up`. +1) Patch Vagant +Vagrant does not play nice with Windows SMB share authentication. It uses cmdkey which is not properly implimented. More details about the issue can be found in this issue:(https://github.com/hashicorp/vagrant/issues/10661) + +To patch this, go find the mount_shared_folder.rb file and replace `"cmdkey /add:#{options[:smb_host]} /user:#{options[:smb_username]} /pass:\"#{options[:smb_password]}\""` with `"cmdkey '/add:\"#{options[:smb_host]}\"' '/user:\"#{options[:smb_username]}\"' '/pass:\"#{options[:smb_password]}\"'"` + +2) Windows will require you to enter an administrator username and password to be able to create and mount the SMB share. +This means the build will not be fully automated. One thing you can do is add `config.vm.synced_folder '../Vagrant', '/vagrant', smb_username: "username", smb_password: "password"` to the Vagrantfile on line 2. For security reasons, this is not a good idea as you will be storing your username and password in plaintext. +By not having this line added to the Vagrantfile you will be required to put in your username and password at least 2 times per machine. + +3) Selecting Virtual Switch +During the build you will also have to select the virtual switch you want to use for each server. This cannot be avoided. There is a option that can be used to force the network adapter to use a particular switch; however, using that option breaks this build process. +A really hacky workaround is, if you are using the smb_username and smb_password options, would be to press the option number corresponding with the virtual switch you want to use then enter four times after `vagrant up`. So if you know you want the virtual switch 1 `vagrant up` 1 enter 1 enter 1 enter 1 enter +Yes, I know hacky but it works. + +## How this build works +The majority of this build works the same as the VirtualBox build. The most notable difference is is on the Windows builds. There is a script that will create an internal virtual switch called "NATSwitch." Throughout the build process, a script will create a second network adapter and attach it to the NATSwitch on the VM being built. After the machine is built the original network adapter will be removed from the VM. + +## Note +This build will run two scripts on the host machine. It is advisable to always check any scripts that will be run on your machine before running them. \ No newline at end of file diff --git a/HyperV/Vagrantfile b/HyperV/Vagrantfile new file mode 100644 index 0000000..6d4d121 --- /dev/null +++ b/HyperV/Vagrantfile @@ -0,0 +1,221 @@ +Vagrant.configure("2") do |config| + config.vm.synced_folder '../Vagrant', '/vagrant' + config.vagrant.plugins = "vagrant-reload" + # Set up the Hyper-V switch + config.trigger.before :up do |trigger| + trigger.info = "Creating 'NATSwitch' Hyper-V switch if it does not exist..." + trigger.run = {privileged: "true", powershell_elevated_interactive: "true", path: "./hyperv-create-nat-switch.ps1"} + end + + config.vm.define "logger" do |cfg| + cfg.vm.box = "bento/ubuntu-18.04" + cfg.vm.hostname = "logger" + cfg.vm.boot_timeout = 600 + cfg.vm.provision :shell, path: "fix-eth0-static-ip.sh" + cfg.vm.provision "reload" + cfg.vm.provision :shell, path: "check-eth0-ip.sh" + cfg.vm.provision :shell, path: "../Vagrant/bootstrap.sh" + cfg.vm.provision :shell, path: "fix-motd.sh" + + + # Change the switch to the NATSwitch + cfg.trigger.before :reload do |trigger| + trigger.info = "Setting Hyper-V switch to 'NATSwitch' to allow for static IP..." + trigger.run = { + privileged: "true", + powershell_elevated_interactive: "true", + path: "./hyperv-change-switch.ps1" , + args: "-vmname logger" + } + end + + cfg.vm.provider "hyperv" do |h, override| + h.vmname = "logger" + h.memory = 4096 + h.cpus = 2 + h.ip_address_timeout = 60 + end + + end + + config.vm.define "dc" do |cfg| + + cfg.vm.box = "man715/Windows2016" + cfg.vm.hostname = "dc" + cfg.vm.boot_timeout = 600 + cfg.winrm.transport = :plaintext + cfg.vm.communicator = "winrm" + cfg.winrm.basic_auth_only = true + cfg.winrm.timeout = 300 + cfg.winrm.retry_limit = 20 + + # Create a new network adapter on the NATSwitch + cfg.trigger.before :reload do |trigger| + trigger.info = "Setting Hyper-V switch to 'NATSwitch' to allow for static IP..." + trigger.run = { + privileged: "true", + powershell_elevated_interactive: "true", + path: "./hyperv-set-switch.ps1", + args: "-vmname dc.windomain.local" + } + end + + # Remove the network adapter that was used to set up the box + cfg.trigger.after :up do |trigger| + trigger.info = "Removing the maintenance ethernet adapter" + trigger.run = { + privileged: "true", + powershell_elevated_interactive: "true", + path: "./hyperv-remove-networkadapter.ps1", + args: "-vmname dc.windomain.local" + } + end + + cfg.vm.provision "reload" + cfg.vm.provision "shell", path: "hyperv-set-static-ip.ps1", privileged: true, args: "-ip 192.168.38.102 -dns 8.8.8.8" + cfg.vm.provision "shell", path: "../Vagrant/scripts/provision.ps1", privileged: true + cfg.vm.provision "reload" + cfg.vm.provision "shell", path: "../Vagrant/scripts/provision.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/download_palantir_wef.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-utilities.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-redteam.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-choco-extras.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-osquery.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-sysinternals.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-velociraptor.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/configure-ou.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/configure-wef-gpo.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/configure-powershelllogging.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/configure-AuditingPolicyGPOs.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/configure-rdp-user-gpo.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/configure-disable-windows-defender-gpo.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-autorunstowineventlog.ps1", privileged: true + cfg.vm.provision "shell", inline: 'wevtutil el | Select-String -notmatch "Microsoft-Windows-LiveId" | Foreach-Object {wevtutil cl "$_"}', privileged: true + cfg.vm.provision "shell", inline: "Set-SmbServerConfiguration -AuditSmb1Access $true -Force", privileged: true + cfg.vm.provision "shell", inline: 'cscript c:\windows\system32\slmgr.vbs /dlv', privileged: true + + cfg.vm.provider "hyperv" do |h, override| + h.vmname = "dc.windomain.local" + h.memory = 4096 + h.cpus = 2 + h.ip_address_timeout = 600 + end + end + + config.vm.define "wef" do |cfg| + cfg.vm.box = "man715/Windows2016" + cfg.vm.hostname = "wef" + cfg.vm.boot_timeout = 600 + cfg.vm.communicator = "winrm" + cfg.winrm.basic_auth_only = true + cfg.winrm.timeout = 300 + cfg.winrm.retry_limit = 20 + + # Create a new network adapter on the NATSwitch + cfg.trigger.before :reload do |trigger| + trigger.info = "Setting Hyper-V switch to 'NATSwitch' to allow for static IP..." + trigger.run = { + privileged: "true", + powershell_elevated_interactive: "true", + path: "./hyperv-set-switch.ps1", + args: "-vmname wef.windomain.local" + } + end + + # Remove the network adapter that was used to set up the box + cfg.trigger.after :up do |trigger| + trigger.info = "Removing the maintenance ethernet adapter" + trigger.run = { + privileged: "true", + powershell_elevated_interactive: "true", + path: "./hyperv-remove-networkadapter.ps1", + args: "-vmname wef.windomain.local" + } + end + + cfg.vm.provision "reload" + cfg.vm.provision "shell", path: "hyperv-set-static-ip.ps1", privileged: true, args: "-ip 192.168.38.103 -dns 8.8.8.8" + cfg.vm.provision "shell", path: "../Vagrant/scripts/provision.ps1", privileged: true + cfg.vm.provision "reload" + cfg.vm.provision "shell", path: "../Vagrant/scripts/provision.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/download_palantir_wef.ps1", privileged: true + cfg.vm.provision "shell", inline: 'wevtutil el | Select-String -notmatch "Microsoft-Windows-LiveId" | Foreach-Object {wevtutil cl "$_"}', privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-wefsubscriptions.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-splunkuf.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-windows_ta.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-utilities.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-redteam.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-choco-extras.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-osquery.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-sysinternals.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-velociraptor.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/configure-pslogstranscriptsshare.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-autorunstowineventlog.ps1", privileged: true + cfg.vm.provision "shell", inline: "Set-SmbServerConfiguration -AuditSmb1Access $true -Force", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-microsoft-ata.ps1", privileged: true + cfg.vm.provision "shell", inline: 'cscript c:\windows\system32\slmgr.vbs /dlv', privileged: true + + cfg.vm.provider "hyperv" do |h, override| + h.vmname = "wef.windomain.local" + h.memory = 4096 + h.cpus = 2 + h.ip_address_timeout = 600 + end + end + + config.vm.define "win10" do |cfg| + cfg.vm.box = "man715/Windows10" + cfg.vm.hostname = "win10" + cfg.vm.boot_timeout = 600 + cfg.vm.communicator = "winrm" + cfg.winrm.basic_auth_only = true + cfg.winrm.timeout = 300 + cfg.winrm.retry_limit = 20 + + # Create a new network adapter on the NATSwitch + cfg.trigger.before :reload do |trigger| + trigger.info = "Setting Hyper-V switch to 'NATSwitch' to allow for static IP..." + trigger.run = { + privileged: "true", + powershell_elevated_interactive: "true", + path: "./hyperv-set-switch.ps1", + args: "-vmname win10.windomain.local" + } + end + + # Remove the network adapter that was used to set up the box + cfg.trigger.after :up do |trigger| + trigger.info = "Removing the maintenance ethernet adapter" + trigger.run = { + privileged: "true", + powershell_elevated_interactive: "true", + path: "./hyperv-remove-networkadapter.ps1", + args: "-vmname win10.windomain.local" + } + end + + cfg.vm.provision "reload" + cfg.vm.provision "shell", path: "hyperv-set-static-ip.ps1", privileged: true, args: "-ip 192.168.38.104 -dns 8.8.8.8" + cfg.vm.provision "shell", path: "../Vagrant/scripts/MakeWindows10GreatAgain.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/provision.ps1", privileged: true + cfg.vm.provision "reload" + cfg.vm.provision "shell", path: "../Vagrant/scripts/provision.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/download_palantir_wef.ps1", privileged: true + cfg.vm.provision "shell", inline: 'wevtutil el | Select-String -notmatch "Microsoft-Windows-LiveId" | Foreach-Object {wevtutil cl "$_"}', privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-utilities.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-redteam.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-choco-extras.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-osquery.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-sysinternals.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-velociraptor.ps1", privileged: true + cfg.vm.provision "shell", path: "../Vagrant/scripts/install-autorunstowineventlog.ps1", privileged: true + cfg.vm.provision "shell", inline: 'cscript c:\windows\system32\slmgr.vbs /dlv', privileged: true + + cfg.vm.provider "hyperv" do |h, override| + h.vmname = "win10.windomain.local" + h.memory = 4096 + h.cpus = 2 + h.ip_address_timeout = 600 + end + end +end diff --git a/HyperV/bootstrap.sh b/HyperV/bootstrap.sh new file mode 100644 index 0000000..59476a0 --- /dev/null +++ b/HyperV/bootstrap.sh @@ -0,0 +1,498 @@ +#! /bin/bash + +# Override existing DNS Settings using netplan, but don't do it for Terraform builds +if ! curl -s 169.254.169.254 --connect-timeout 2 >/dev/null; then + echo -e " eth0:\n dhcp4: true\n nameservers:\n addresses: [8.8.8.8,8.8.4.4]" >>/etc/netplan/01-netcfg.yaml + netplan apply +fi +sed -i 's/nameserver 127.0.0.53/nameserver 8.8.8.8/g' /etc/resolv.conf && chattr +i /etc/resolv.conf + +# Get a free Maxmind license here: https://www.maxmind.com/en/geolite2/signup +# Required for the ASNgen app to work: https://splunkbase.splunk.com/app/3531/ +export MAXMIND_LICENSE= +if [ -n "$MAXMIND_LICENSE" ]; then + echo "Note: You have not entered a MaxMind license key on line 5 of bootstrap.sh, so the ASNgen Splunk app may not work correctly." + echo "However, it is not required and everything else should function correctly." +fi + +export DEBIAN_FRONTEND=noninteractive +echo "apt-fast apt-fast/maxdownloads string 10" | debconf-set-selections +echo "apt-fast apt-fast/dlflag boolean true" | debconf-set-selections + +sed -i "2ideb mirror://mirrors.ubuntu.com/mirrors.txt bionic main restricted universe multiverse\ndeb mirror://mirrors.ubuntu.com/mirrors.txt bionic-updates main restricted universe multiverse\ndeb mirror://mirrors.ubuntu.com/mirrors.txt bionic-backports main restricted universe multiverse\ndeb mirror://mirrors.ubuntu.com/mirrors.txt bionic-security main restricted universe multiverse" /etc/apt/sources.list + +apt_install_prerequisites() { + echo "[$(date +%H:%M:%S)]: Adding apt repositories..." + # Add repository for apt-fast + add-apt-repository -y ppa:apt-fast/stable + # Add repository for yq + add-apt-repository -y ppa:rmescandon/yq + # Add repository for suricata + add-apt-repository -y ppa:oisf/suricata-stable + # Install prerequisites and useful tools + echo "[$(date +%H:%M:%S)]: Running apt-get clean..." + apt-get clean + echo "[$(date +%H:%M:%S)]: Running apt-get update..." + apt-get -qq update + apt-get -qq install -y apt-fast + echo "[$(date +%H:%M:%S)]: Running apt-fast install..." + apt-fast -qq install -y jq whois build-essential git unzip htop yq mysql-server redis-server python-pip +} + +modify_motd() { + echo "[$(date +%H:%M:%S)]: Updating the MOTD..." + # Force color terminal + sed -i 's/#force_color_prompt=yes/force_color_prompt=yes/g' /root/.bashrc + sed -i 's/#force_color_prompt=yes/force_color_prompt=yes/g' /home/vagrant/.bashrc + # Remove some stock Ubuntu MOTD content + chmod -x /etc/update-motd.d/10-help-text + # Copy the DetectionLab MOTD + cp /vagrant/resources/logger/20-detectionlab /etc/update-motd.d/ + chmod +x /etc/update-motd.d/20-detectionlab +} + +test_prerequisites() { + for package in jq whois build-essential git unzip yq mysql-server redis-server python-pip; do + echo "[$(date +%H:%M:%S)]: [TEST] Validating that $package is correctly installed..." + # Loop through each package using dpkg + if ! dpkg -S $package >/dev/null; then + # If which returns a non-zero return code, try to re-install the package + echo "[-] $package was not found. Attempting to reinstall." + apt-get -qq update && apt-get install -y $package + if ! which $package >/dev/null; then + # If the reinstall fails, give up + echo "[X] Unable to install $package even after a retry. Exiting." + exit 1 + fi + else + echo "[+] $package was successfully installed!" + fi + done +} + +install_splunk() { + # Check if Splunk is already installed + if [ -f "/opt/splunk/bin/splunk" ]; then + echo "[$(date +%H:%M:%S)]: Splunk is already installed" + else + echo "[$(date +%H:%M:%S)]: Installing Splunk..." + # Get download.splunk.com into the DNS cache. Sometimes resolution randomly fails during wget below + dig @8.8.8.8 download.splunk.com >/dev/null + dig @8.8.8.8 splunk.com >/dev/null + dig @8.8.8.8 www.splunk.com >/dev/null + + # Try to resolve the latest version of Splunk by parsing the HTML on the downloads page + echo "[$(date +%H:%M:%S)]: Attempting to autoresolve the latest version of Splunk..." + LATEST_SPLUNK=$(curl https://www.splunk.com/en_us/download/splunk-enterprise.html | grep -i deb | grep -Eo "data-link=\"................................................................................................................................" | cut -d '"' -f 2) + # Sanity check what was returned from the auto-parse attempt + if [[ "$(echo "$LATEST_SPLUNK" | grep -c "^https:")" -eq 1 ]] && [[ "$(echo "$LATEST_SPLUNK" | grep -c "\.deb$")" -eq 1 ]]; then + echo "[$(date +%H:%M:%S)]: The URL to the latest Splunk version was automatically resolved as: $LATEST_SPLUNK" + echo "[$(date +%H:%M:%S)]: Attempting to download..." + wget --progress=bar:force -P /opt "$LATEST_SPLUNK" + else + echo "[$(date +%H:%M:%S)]: Unable to auto-resolve the latest Splunk version. Falling back to hardcoded URL..." + # Download Hardcoded Splunk + wget --progress=bar:force -O /opt/splunk-8.0.2-a7f645ddaf91-linux-2.6-amd64.deb 'https://download.splunk.com/products/splunk/releases/8.0.2/linux/splunk-8.0.2-a7f645ddaf91-linux-2.6-amd64.deb&wget=true' + fi + if ! ls /opt/splunk*.deb 1>/dev/null 2>&1; then + echo "Something went wrong while trying to download Splunk. This script cannot continue. Exiting." + exit 1 + fi + if ! dpkg -i /opt/splunk*.deb >/dev/null; then + echo "Something went wrong while trying to install Splunk. This script cannot continue. Exiting." + exit 1 + fi + + /opt/splunk/bin/splunk start --accept-license --answer-yes --no-prompt --seed-passwd changeme + /opt/splunk/bin/splunk add index wineventlog -auth 'admin:changeme' + /opt/splunk/bin/splunk add index osquery -auth 'admin:changeme' + /opt/splunk/bin/splunk add index osquery-status -auth 'admin:changeme' + /opt/splunk/bin/splunk add index sysmon -auth 'admin:changeme' + /opt/splunk/bin/splunk add index powershell -auth 'admin:changeme' + /opt/splunk/bin/splunk add index zeek -auth 'admin:changeme' + /opt/splunk/bin/splunk add index suricata -auth 'admin:changeme' + /opt/splunk/bin/splunk add index threathunting -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_forwarder/splunk-add-on-for-microsoft-windows_700.tgz -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_server/splunk-add-on-for-microsoft-sysmon_1062.tgz -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_server/asn-lookup-generator_110.tgz -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_server/lookup-file-editor_331.tgz -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_server/splunk-add-on-for-zeek-aka-bro_400.tgz -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_server/force-directed-app-for-splunk_200.tgz -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_server/punchcard-custom-visualization_130.tgz -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_server/sankey-diagram-custom-visualization_130.tgz -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_server/link-analysis-app-for-splunk_161.tgz -auth 'admin:changeme' + /opt/splunk/bin/splunk install app /vagrant/resources/splunk_server/threathunting_144.tgz -auth 'admin:changeme' + + # Install the Maxmind license key for the ASNgen App + if [ -n "$MAXMIND_LICENSE" ]; then + mkdir /opt/splunk/etc/apps/TA-asngen/local + cp /opt/splunk/etc/apps/TA-asngen/default/asngen.conf /opt/splunk/etc/apps/TA-asngen/local/asngen.conf + sed -i "s/license_key =/license_key = $MAXMIND_LICENSE/g" /opt/splunk/etc/apps/TA-asngen/local/asngen.conf + fi + + # Replace the props.conf for Sysmon TA and Windows TA + # Removed all the 'rename = xmlwineventlog' directives + # I know youre not supposed to modify files in "default", + # but for some reason adding them to "local" wasnt working + cp /vagrant/resources/splunk_server/windows_ta_props.conf /opt/splunk/etc/apps/Splunk_TA_windows/default/props.conf + cp /vagrant/resources/splunk_server/sysmon_ta_props.conf /opt/splunk/etc/apps/TA-microsoft-sysmon/default/props.conf + + # Add custom Macro definitions for ThreatHunting App + cp /vagrant/resources/splunk_server/macros.conf /opt/splunk/etc/apps/ThreatHunting/default/macros.conf + # Fix props.conf in ThreatHunting App + sed -i 's/EVAL-host_fqdn = Computer/EVAL-host_fqdn = ComputerName/g' /opt/splunk/etc/apps/ThreatHunting/default/props.conf + # Fix Windows TA macros + mkdir /opt/splunk/etc/apps/Splunk_TA_windows/local + cp /opt/splunk/etc/apps/Splunk_TA_windows/default/macros.conf /opt/splunk/etc/apps/Splunk_TA_windows/local + sed -i 's/wineventlog_windows/wineventlog/g' /opt/splunk/etc/apps/Splunk_TA_windows/local/macros.conf + # Fix Force Directed App until 2.0.1 is released (https://answers.splunk.com/answers/668959/invalid-key-in-stanza-default-value-light.html#answer-669418) + rm /opt/splunk/etc/apps/force_directed_viz/default/savedsearches.conf + + # Add a Splunk TCP input on port 9997 + echo -e "[splunktcp://9997]\nconnection_host = ip" >/opt/splunk/etc/apps/search/local/inputs.conf + # Add props.conf and transforms.conf + cp /vagrant/resources/splunk_server/props.conf /opt/splunk/etc/apps/search/local/ + cp /vagrant/resources/splunk_server/transforms.conf /opt/splunk/etc/apps/search/local/ + cp /opt/splunk/etc/system/default/limits.conf /opt/splunk/etc/system/local/limits.conf + # Bump the memtable limits to allow for the ASN lookup table + sed -i.bak 's/max_memtable_bytes = 10000000/max_memtable_bytes = 30000000/g' /opt/splunk/etc/system/local/limits.conf + + # Skip Splunk Tour and Change Password Dialog + echo "[$(date +%H:%M:%S)]: Disabling the Splunk tour prompt..." + touch /opt/splunk/etc/.ui_login + mkdir -p /opt/splunk/etc/users/admin/search/local + echo -e "[search-tour]\nviewed = 1" >/opt/splunk/etc/system/local/ui-tour.conf + # Source: https://answers.splunk.com/answers/660728/how-to-disable-the-modal-pop-up-help-us-to-improve.html + if [ ! -d "/opt/splunk/etc/users/admin/user-prefs/local" ]; then + mkdir -p "/opt/splunk/etc/users/admin/user-prefs/local" + fi + echo '[general] +render_version_messages = 1 +dismissedInstrumentationOptInVersion = 4 +notification_python_3_impact = false +display.page.home.dashboardId = /servicesNS/nobody/search/data/ui/views/logger_dashboard' >/opt/splunk/etc/users/admin/user-prefs/local/user-prefs.conf + # Enable SSL Login for Splunk + echo -e "[settings]\nenableSplunkWebSSL = true" >/opt/splunk/etc/system/local/web.conf + # Copy over the Logger Dashboard + if [ ! -d "/opt/splunk/etc/apps/search/local/data/ui/views" ]; then + mkdir -p "/opt/splunk/etc/apps/search/local/data/ui/views" + fi + cp /vagrant/resources/splunk_server/logger_dashboard.xml /opt/splunk/etc/apps/search/local/data/ui/views || echo "Unable to find dashboard" + # Reboot Splunk to make changes take effect + /opt/splunk/bin/splunk restart + /opt/splunk/bin/splunk enable boot-start + fi +} + +download_palantir_osquery_config() { + if [ -f /opt/osquery-configuration ]; then + echo "[$(date +%H:%M:%S)]: osquery configs have already been downloaded" + else + # Import Palantir osquery configs into Fleet + echo "[$(date +%H:%M:%S)]: Downloading Palantir osquery configs..." + cd /opt && git clone https://github.com/palantir/osquery-configuration.git + fi +} + +install_fleet_import_osquery_config() { + if [ -f "/opt/fleet" ]; then + echo "[$(date +%H:%M:%S)]: Fleet is already installed" + else + cd /opt || exit 1 + + echo "[$(date +%H:%M:%S)]: Installing Fleet..." + echo -e "\n127.0.0.1 kolide" >>/etc/hosts + echo -e "\n127.0.0.1 logger" >>/etc/hosts + + # Set MySQL username and password, create kolide database + mysql -uroot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'kolide';" + mysql -uroot -pkolide -e "create database kolide;" + + # Always download the latest release of Fleet + curl -s https://api.github.com/repos/kolide/fleet/releases/latest | grep 'https://github.com' | grep "/fleet.zip" | cut -d ':' -f 2,3 | tr -d '"' | wget --progress=bar:force -i - + unzip fleet.zip -d fleet + cp fleet/linux/fleetctl /usr/local/bin/fleetctl && chmod +x /usr/local/bin/fleetctl + cp fleet/linux/fleet /usr/local/bin/fleet && chmod +x /usr/local/bin/fleet + + # Prepare the DB + fleet prepare db --mysql_address=127.0.0.1:3306 --mysql_database=kolide --mysql_username=root --mysql_password=kolide + + # Copy over the certs and service file + cp /vagrant/resources/fleet/server.* /opt/fleet/ + cp /vagrant/resources/fleet/fleet.service /etc/systemd/system/fleet.service + + mkdir /var/log/fleet + + /bin/systemctl enable fleet.service + /bin/systemctl start fleet.service + + echo "[$(date +%H:%M:%S)]: Waiting for fleet service to start..." + while true; do + result=$(curl --silent -k https://127.0.0.1:8412) + if echo "$result" | grep -q setup; then break; fi + sleep 1 + done + + fleetctl config set --address https://192.168.38.105:8412 + fleetctl config set --tls-skip-verify true + fleetctl setup --email admin@detectionlab.network --username admin --password 'admin123#' --org-name DetectionLab + fleetctl login --email admin@detectionlab.network --password 'admin123#' + + # Set the enrollment secret to match what we deploy to Windows hosts + mysql -uroot --password=kolide -e 'use kolide; update enroll_secrets set secret = "enrollmentsecret" where active=1;' + echo "Updated enrollment secret" + + # Change the query invervals to reflect a lab environment + # Every hour -> Every 3 minutes + # Every 24 hours -> Every 15 minutes + sed -i 's/interval: 3600/interval: 180/g' osquery-configuration/Fleet/Endpoints/MacOS/osquery.yaml + sed -i 's/interval: 3600/interval: 180/g' osquery-configuration/Fleet/Endpoints/Windows/osquery.yaml + sed -i 's/interval: 28800/interval: 900/g' osquery-configuration/Fleet/Endpoints/MacOS/osquery.yaml + sed -i 's/interval: 28800/interval: 900/g' osquery-configuration/Fleet/Endpoints/Windows/osquery.yaml + + # Don't log osquery INFO messages + # Fix snapshot event formatting + fleetctl get options > /tmp/options.yaml + /usr/bin/yq w -i /tmp/options.yaml 'spec.config.options.enroll_secret' 'enrollmentsecret' + /usr/bin/yq w -i /tmp/options.yaml 'spec.config.options.logger_snapshot_event_type' 'true' + # Fleet 3.0 requires the "kind" to be "options" instead of "option" + sed -i 's/kind: option/kind: options/g' /tmp/options.yaml + fleetctl apply -f /tmp/options.yaml + + # Use fleetctl to import YAML files + fleetctl apply -f osquery-configuration/Fleet/Endpoints/MacOS/osquery.yaml + fleetctl apply -f osquery-configuration/Fleet/Endpoints/Windows/osquery.yaml + for pack in osquery-configuration/Fleet/Endpoints/packs/*.yaml; do + fleetctl apply -f "$pack" + done + + # Add Splunk monitors for Fleet + # Files must exist before splunk will add a monitor + touch /var/log/fleet/osquery_result + touch /var/log/fleet/osquery_status + /opt/splunk/bin/splunk add monitor "/var/log/fleet/osquery_result" -index osquery -sourcetype 'osquery:json' -auth 'admin:changeme' + /opt/splunk/bin/splunk add monitor "/var/log/fleet/osquery_status" -index osquery-status -sourcetype 'osquery:status' -auth 'admin:changeme' + fi +} + +install_zeek() { + echo "[$(date +%H:%M:%S)]: Installing Zeek..." + # Environment variables + NODECFG=/opt/zeek/etc/node.cfg + sh -c "echo 'deb http://download.opensuse.org/repositories/security:/zeek/xUbuntu_18.04/ /' > /etc/apt/sources.list.d/security:zeek.list" + wget -nv https://download.opensuse.org/repositories/security:zeek/xUbuntu_18.04/Release.key -O /tmp/Release.key + apt-key add - /dev/null + # Update APT repositories + apt-get -qq -ym update + # Install tools to build and configure Zeek + apt-get -qq -ym install zeek crudini + export PATH=$PATH:/opt/zeek/bin + pip install zkg==2.1.1 + zkg refresh + zkg autoconfig + zkg install --force salesforce/ja3 + # Load Zeek scripts + echo ' + @load protocols/ftp/software + @load protocols/smtp/software + @load protocols/ssh/software + @load protocols/http/software + @load tuning/json-logs + @load policy/integration/collective-intel + @load policy/frameworks/intel/do_notice + @load frameworks/intel/seen + @load frameworks/intel/do_notice + @load frameworks/files/hash-all-files + @load base/protocols/smb + @load policy/protocols/conn/vlan-logging + @load policy/protocols/conn/mac-logging + @load ja3 + + redef Intel::read_files += { + "/opt/zeek/etc/intel.dat" + }; + ' >>/opt/zeek/share/zeek/site/local.zeek + + # Configure Zeek + crudini --del $NODECFG zeek + crudini --set $NODECFG manager type manager + crudini --set $NODECFG manager host localhost + crudini --set $NODECFG proxy type proxy + crudini --set $NODECFG proxy host localhost + + # Setup $CPUS numbers of Zeek workers + crudini --set $NODECFG worker-eth0 type worker + crudini --set $NODECFG worker-eth0 host localhost + crudini --set $NODECFG worker-eth0 interface eth0 + crudini --set $NODECFG worker-eth0 lb_method pf_ring + crudini --set $NODECFG worker-eth0 lb_procs "$(nproc)" + + # Setup Zeek to run at boot + cp /vagrant/resources/zeek/zeek.service /lib/systemd/system/zeek.service + systemctl enable zeek + systemctl start zeek + + # Configure the Splunk inputs + mkdir -p /opt/splunk/etc/apps/Splunk_TA_bro/local && touch /opt/splunk/etc/apps/Splunk_TA_bro/local/inputs.conf + crudini --set /opt/splunk/etc/apps/Splunk_TA_bro/local/inputs.conf monitor:///opt/zeek/spool/manager index zeek + crudini --set /opt/splunk/etc/apps/Splunk_TA_bro/local/inputs.conf monitor:///opt/zeek/spool/manager sourcetype bro:json + crudini --set /opt/splunk/etc/apps/Splunk_TA_bro/local/inputs.conf monitor:///opt/zeek/spool/manager whitelist '.*\.log$' + crudini --set /opt/splunk/etc/apps/Splunk_TA_bro/local/inputs.conf monitor:///opt/zeek/spool/manager blacklist '.*(communication|stderr)\.log$' + crudini --set /opt/splunk/etc/apps/Splunk_TA_bro/local/inputs.conf monitor:///opt/zeek/spool/manager disabled 0 + + # Ensure permissions are correct and restart splunk + chown -R splunk:splunk /opt/splunk/etc/apps/Splunk_TA_bro + /opt/splunk/bin/splunk restart + + # Verify that Zeek is running + if ! pgrep -f zeek >/dev/null; then + echo "Zeek attempted to start but is not running. Exiting" + exit 1 + fi +} + +install_velociraptor() { + echo "[$(date +%H:%M:%S)]: Installing Velociraptor..." + if [ ! -d "/opt/velociraptor" ]; then + mkdir /opt/velociraptor + fi + echo "[$(date +%H:%M:%S)]: Attempting to determine the URL for the latest release of Velociraptor" + LATEST_VELOCIRAPTOR_LINUX_URL=$(curl -sL https://github.com/Velocidex/velociraptor/releases/latest | grep 'linux-amd64' | grep -Eo "/(?[^\"]+)" | grep amd | sed 's#^#https://github.com#g') + echo "[$(date +%H:%M:%S)]: The URL for the latest release was extracted as $LATEST_VELOCIRAPTOR_LINUX_URL" + echo "[$(date +%H:%M:%S)]: Attempting to download..." + #wget -P /opt/velociraptor --progress=bar:force "$LATEST_VELOCIRAPTOR_LINUX_URL" + # Harcoding until the release after v0.4.7 + wget -P /opt/velociraptor --progress=bar:force "https://github.com/Velocidex/velociraptor/releases/download/v0.4.7/velociraptor-v0.4.7-1-linux-amd64" + if [ "$(file /opt/velociraptor/velociraptor*linux-amd64 | grep -c 'ELF 64-bit LSB executable')" -eq 1 ]; then + echo "[$(date +%H:%M:%S)]: Velociraptor successfully downloaded!" + else + echo "[$(date +%H:%M:%S)]: Failed to download the latest version of Velociraptor. Please open a DetectionLab issue on Github." + return + fi + + cd /opt/velociraptor || exit 1 + mv velociraptor-*-linux-amd64 velociraptor + chmod +x velociraptor + cp /vagrant/resources/velociraptor/server.config.yaml /opt/velociraptor + echo "[$(date +%H:%M:%S)]: Creating Velociraptor dpkg..." + ./velociraptor --config /opt/velociraptor/server.config.yaml debian server + echo "[$(date +%H:%M:%S)]: Installing the dpkg..." + if dpkg -i velociraptor_*_server.deb >/dev/null; then + echo "[$(date +%H:%M:%S)]: Installation complete!" + else + echo "[$(date +%H:%M:%S)]: Failed to install the dpkg" + return + fi +} + +install_suricata() { + # Run iwr -Uri testmyids.com -UserAgent "BlackSun" in Powershell to generate test alerts from Windows + echo "[$(date +%H:%M:%S)]: Installing Suricata..." + + # Install suricata + apt-get -qq -y install suricata crudini + test_suricata_prerequisites + # Install suricata-update + cd /opt || exit 1 + git clone https://github.com/OISF/suricata-update.git + cd /opt/suricata-update || exit 1 + pip install pyyaml + python setup.py install + + cp /vagrant/resources/suricata/suricata.yaml /etc/suricata/suricata.yaml + crudini --set --format=sh /etc/default/suricata '' iface eth0 + # update suricata signature sources + suricata-update update-sources + # disable protocol decode as it is duplicative of Zeek + echo re:protocol-command-decode >>/etc/suricata/disable.conf + # enable et-open and attackdetection sources + suricata-update enable-source et/open + suricata-update enable-source ptresearch/attackdetection + + # Configure the Splunk inputs + mkdir -p /opt/splunk/etc/apps/SplunkLightForwarder/local && touch /opt/splunk/etc/apps/SplunkLightForwarder/local/inputs.conf + crudini --set /opt/splunk/etc/apps/SplunkLightForwarder/local/inputs.conf monitor:///var/log/suricata index suricata + crudini --set /opt/splunk/etc/apps/SplunkLightForwarder/local/inputs.conf monitor:///var/log/suricata sourcetype suricata:json + crudini --set /opt/splunk/etc/apps/SplunkLightForwarder/local/inputs.conf monitor:///var/log/suricata whitelist 'eve.json' + crudini --set /opt/splunk/etc/apps/SplunkLightForwarder/local/inputs.conf monitor:///var/log/suricata disabled 0 + crudini --set /opt/splunk/etc/apps/SplunkLightForwarder/local/props.conf json_suricata TRUNCATE 0 + + # Update suricata and restart + suricata-update + service suricata stop + service suricata start + sleep 3 + + # Verify that Suricata is running + if ! pgrep -f suricata >/dev/null; then + echo "Suricata attempted to start but is not running. Exiting" + exit 1 + fi +} + +test_suricata_prerequisites() { + for package in suricata crudini; do + echo "[$(date +%H:%M:%S)]: [TEST] Validating that $package is correctly installed..." + # Loop through each package using dpkg + if ! dpkg -S $package >/dev/null; then + # If which returns a non-zero return code, try to re-install the package + echo "[-] $package was not found. Attempting to reinstall." + apt-get clean && apt-get -qq update && apt-get install -y $package + if ! which $package >/dev/null; then + # If the reinstall fails, give up + echo "[X] Unable to install $package even after a retry. Exiting." + exit 1 + fi + else + echo "[+] $package was successfully installed!" + fi + done +} + +install_guacamole() { + echo "[$(date +%H:%M:%S)]: Installing Guacamole..." + cd /opt || exit 1 + apt-get -qq install -y libcairo2-dev libjpeg62-dev libpng-dev libossp-uuid-dev libfreerdp-dev libpango1.0-dev libssh2-1-dev libssh-dev tomcat8 tomcat8-admin tomcat8-user + wget --progress=bar:force "http://apache.org/dyn/closer.cgi?action=download&filename=guacamole/1.0.0/source/guacamole-server-1.0.0.tar.gz" -O guacamole-server-1.0.0.tar.gz + tar -xf guacamole-server-1.0.0.tar.gz && cd guacamole-server-1.0.0 || echo "[-] Unable to find the Guacamole folder." + ./configure &>/dev/null && make --quiet &>/dev/null && make --quiet install &>/dev/null || echo "[-] An error occurred while installing Guacamole." + ldconfig + cd /var/lib/tomcat8/webapps || echo "[-] Unable to find the tomcat8/webapps folder." + wget --progress=bar:force "http://apache.org/dyn/closer.cgi?action=download&filename=guacamole/1.0.0/binary/guacamole-1.0.0.war" -O guacamole.war + mkdir /etc/guacamole + mkdir /usr/share/tomcat8/.guacamole + cp /vagrant/resources/guacamole/user-mapping.xml /etc/guacamole/ + cp /vagrant/resources/guacamole/guacamole.properties /etc/guacamole/ + cp /vagrant/resources/guacamole/guacd.service /lib/systemd/system + sudo ln -s /etc/guacamole/guacamole.properties /usr/share/tomcat8/.guacamole/ + sudo ln -s /etc/guacamole/user-mapping.xml /usr/share/tomcat8/.guacamole/ + systemctl enable guacd + systemctl enable tomcat8 + systemctl start guacd + systemctl start tomcat8 +} + +postinstall_tasks() { + # Include Splunk and Zeek in the PATH + echo export PATH="$PATH:/opt/splunk/bin:/opt/zeek/bin" >>~/.bashrc + echo "export SPLUNK_HOME=/opt/splunk" >>~/.bashrc + # Ping DetectionLab server for usage statistics + curl -s -A "DetectionLab-logger" "https:/ping.detectionlab.network/logger" +} + +main() { + apt_install_prerequisites + modify_motd + test_prerequisites + install_splunk + download_palantir_osquery_config + install_fleet_import_osquery_config + install_velociraptor + install_suricata + install_zeek + install_guacamole + postinstall_tasks +} + +main +exit 0 diff --git a/HyperV/check-eth0-ip.sh b/HyperV/check-eth0-ip.sh new file mode 100644 index 0000000..b796a48 --- /dev/null +++ b/HyperV/check-eth0-ip.sh @@ -0,0 +1,18 @@ +check_eth0_ip() { + ETH1_IP=$(ip -4 addr show eth1 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1) + if [ "$ETH1_IP" != "192.168.38.105" ]; then + echo "Incorrect IP Address settings detected. Attempting to fix." + ifdown eth1 + ip addr flush dev eth1 + ifup eth1 + ETH1_IP=$(ifconfig eth1 | grep 'inet addr' | cut -d ':' -f 2 | cut -d ' ' -f 1) + if [ "$ETH1_IP" == "192.168.38.105" ]; then + echo "[$(date +%H:%M:%S)]: The static IP has been fixed and set to 192.168.38.105" + else + echo "[$(date +%H:%M:%S)]: Failed to fix the broken static IP for eth1. Exiting because this will cause problems with other VMs." + exit 1 + fi + fi +} + +check_eth0_ip \ No newline at end of file diff --git a/HyperV/fix-eth0-static-ip.sh b/HyperV/fix-eth0-static-ip.sh new file mode 100644 index 0000000..0c0169a --- /dev/null +++ b/HyperV/fix-eth0-static-ip.sh @@ -0,0 +1,31 @@ +fix_eth0_static_ip() { + # There's a fun issue where dhclient keeps messing with eth0 despite the fact + # that eth0 has a static IP set. We workaround this by setting a static DHCP lease. + echo -e 'interface "eth0" { + send host-name = gethostname(); + send dhcp-requested-address 192.168.38.105; + }' >>/etc/dhcp/dhclient.conf + netplan apply + # Set the ip address on eth0 and rename the adapter to eth1 + ETH0_IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') + if [ "$ETH0_IP" != "192.168.38.105" ]; then + MAC=$(ip a | grep "link/ether" | cut -d ' ' -f 6) + cat > /etc/netplan/01-netcfg.yaml << EOL +network: + ethernets: + eth0: + match: + macaddress: $MAC + dhcp4: no + addresses: [192.168.38.105/24] + gateway4: 192.168.38.1 + nameservers: + addresses: [8.8.8.8,8.8.4.4] + set-name: eth1 + version: 2 + renderer: networkd +EOL + fi +} + +fix_eth0_static_ip \ No newline at end of file diff --git a/HyperV/fix-motd.sh b/HyperV/fix-motd.sh new file mode 100644 index 0000000..bc485e1 --- /dev/null +++ b/HyperV/fix-motd.sh @@ -0,0 +1,4 @@ +#! /bin/sh +# Fix the motd script +cp /etc/update-motd.d/20-detectionlab . +tr -d '\15\32' < 20-detectionlab > /etc/update-motd.d/20-detectionlab \ No newline at end of file diff --git a/HyperV/hyperv-change-switch.ps1 b/HyperV/hyperv-change-switch.ps1 new file mode 100644 index 0000000..66f15a2 --- /dev/null +++ b/HyperV/hyperv-change-switch.ps1 @@ -0,0 +1,5 @@ +# See: https://www.thomasmaurer.ch/2016/01/change-hyper-v-vm-switch-of-virtual-machines-using-powershell/ +# https://superuser.com/questions/1354658/hyperv-static-ip-with-vagrant#:~:text=%20HyperV%20-%20Static%20Ip%20with%20Vagrant%20,static%20IP%20address%20will%20be%20set...%20More%20 + +param ([String] $vmname) +Get-VM "$vmname" | Get-VMNetworkAdapter | Connect-VMNetworkAdapter -SwitchName "NATSwitch" diff --git a/HyperV/hyperv-create-nat-switch.ps1 b/HyperV/hyperv-create-nat-switch.ps1 new file mode 100644 index 0000000..94650da --- /dev/null +++ b/HyperV/hyperv-create-nat-switch.ps1 @@ -0,0 +1,32 @@ +# See: https://www.petri.com/using-nat-virtual-switch-hyper-v + +If ("NATSwitch" -in (Get-VMSwitch | Select-Object -ExpandProperty Name) -eq $FALSE) { + 'Creating Internal-only switch named "NATSwitch" on Windows Hyper-V host...' + + New-VMSwitch -SwitchName "NATSwitch" -SwitchType Internal + + New-NetIPAddress -IPAddress 192.168.38.1 -PrefixLength 24 -InterfaceAlias "vEthernet (NATSwitch)" + + New-NetNAT -Name "NATNetwork" -InternalIPInterfaceAddressPrefix 192.168.38.0/24 +} +else { + '"NATSwitch" for static IP configuration already exists; skipping' +} + +If ("192.168.38.1" -in (Get-NetIPAddress | Select-Object -ExpandProperty IPAddress) -eq $FALSE) { + 'Registering new IP address 192.168.38.1 on Windows Hyper-V host...' + + New-NetIPAddress -IPAddress 192.168.38.1 -PrefixLength 24 -InterfaceAlias "vEthernet (NATSwitch)" +} +else { + '"192.168.38.1" for static IP configuration already registered; skipping' +} + +If ("192.168.38.0/24" -in (Get-NetNAT | Select-Object -ExpandProperty InternalIPInterfaceAddressPrefix) -eq $FALSE) { + 'Registering new NAT adapter for 192.168.38.0/24 on Windows Hyper-V host...' + + New-NetNAT -Name "NATNetwork" -InternalIPInterfaceAddressPrefix 192.168.38.0/24 +} +else { + '"192.168.38.0/24" for static IP configuration already registered; skipping' +} \ No newline at end of file diff --git a/HyperV/hyperv-remove-networkadapter.ps1 b/HyperV/hyperv-remove-networkadapter.ps1 new file mode 100644 index 0000000..c05ee4b --- /dev/null +++ b/HyperV/hyperv-remove-networkadapter.ps1 @@ -0,0 +1,3 @@ +param ([String] $vmname) + +Remove-VMNetworkAdapter -VMName $vmname -Name "Network Adapter" \ No newline at end of file diff --git a/HyperV/hyperv-set-static-ip.ps1 b/HyperV/hyperv-set-static-ip.ps1 new file mode 100644 index 0000000..33c2f15 --- /dev/null +++ b/HyperV/hyperv-set-static-ip.ps1 @@ -0,0 +1,29 @@ +# Source: https://github.com/StefanScherer/adfs + +param ([String] $ip, [String] $dns) + +Write-Host "$('[{0:HH:mm}]' -f (Get-Date))" +Write-Host "Setting IP address and DNS information." +Write-Host "If this step times out, it's because vagrant is connecting to the VM on the wrong interface" +Write-Host "See https://github.com/clong/DetectionLab/issues/114 for more information" + +$subnet = $ip -replace "\.\d+$", "" +$name = (Get-NetIPAddress -AddressFamily IPv4 ` + | Where-Object -FilterScript { ($_.IPAddress).StartsWith("169") } ` + ).InterfaceAlias +if (!$name) { + $name = (Get-NetIPAddress -AddressFamily IPv4 ` + | Where-Object -FilterScript { ($_.IPAddress).StartsWith("192.168.38") } ` + ).InterfaceAlias +} +if ($name) { + Write-Host "Set IP address to $ip of interface $name" + & netsh.exe int ip set address $name static $ip 255.255.255.0 "$subnet.1" + Write-Host "Set DNS server address to $dns of interface $name" + & netsh.exe interface ipv4 add dnsserver $name address=192.168.38.102 index=1 + if ($dns) { + & netsh.exe interface ipv4 add dnsserver $name address=$dns index=2 + } +} else { + Write-Error "Could not find a interface with subnet $subnet.xx" +} diff --git a/HyperV/hyperv-set-switch.ps1 b/HyperV/hyperv-set-switch.ps1 new file mode 100644 index 0000000..a2055ba --- /dev/null +++ b/HyperV/hyperv-set-switch.ps1 @@ -0,0 +1,8 @@ +# See: https://www.thomasmaurer.ch/2016/01/change-hyper-v-vm-switch-of-virtual-machines-using-powershell/ +param ([String] $vmname) +# Get-VM $vmname | Get-VMNetworkAdapter | Connect-VMNetworkAdapter -SwitchName "NATSwitch" +if (((Get-VMNetworkAdapter -VMName $vmname).Name).Contains("NATAdapter")){ + Write-Host "The NATAdapter already exits" +} else { + Add-VMNetworkAdapter -VMName $vmname -SwitchName "NATSwitch" -Name NATAdapter -DeviceNaming On +} From 3d28a9c7ed83d1ba1c8f770db80c1a37c1373628 Mon Sep 17 00:00:00 2001 From: Arron Patton Date: Tue, 25 Aug 2020 14:11:08 -0600 Subject: [PATCH 4/5] Update README.md Update formatting and spelling. --- HyperV/README.md | 59 ++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/HyperV/README.md b/HyperV/README.md index b3e9fcb..61244ad 100644 --- a/HyperV/README.md +++ b/HyperV/README.md @@ -1,36 +1,41 @@ -# Detection Lab for Hyper-V -This hypervisor does not undergo the same level of weekly testing as what is found in the main part of Detectionlab. +# Detection Lab for Hyper-V -Hyper-V support is only in beta and needs more testing by more users to ensure its stability and usability. +This hypervisor does not undergo the same level of weekly testing as what is found in the main part of Detectionlab. +Hyper-V support is only in beta and needs more testing by more users to ensure its stability and usability. -## Requirements -The version of Hyper-V will need to be compatible with Hyper-V VM configuration version 9.0. -You will need to be running one of the following operating systems: -* Windows 10 1809 or later -* Windows Server 2019 -* Windows Hyper-V Server 2019 -For a breakdown of what Operating Systems support which VM configuration versions please visit: (https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/deploy/upgrade-virtual-machine-version-in-hyper-v-on-windows-or-windows-server) +## Requirements -This build also requires vagrant-reload. If you do not have it installed, you will be prompted to install it. +The version of Hyper-V will need to be compatible with Hyper-V VM configuration version 9.0. +You will need to be running one of the following operating systems: +* Windows 10 1809 or later +* Windows Server 2019 +* Windows Hyper-V Server 2019 -## Known Issues Important! -Unfortunately, due to some issues with Vagrant and Microsoft, running DetectionLab with Hyper-V is not as easy as it is with other providers. You will need to do the following BEFORE trying to run `vagrant up`. -1) Patch Vagant -Vagrant does not play nice with Windows SMB share authentication. It uses cmdkey which is not properly implimented. More details about the issue can be found in this issue:(https://github.com/hashicorp/vagrant/issues/10661) +For a breakdown of what Operating Systems support which VM configuration versions please visit: (https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/deploy/upgrade-virtual-machine-version-in-hyper-v-on-windows-or-windows-server) +This build also requires vagrant-reload. If you do not have it installed, you will be prompted to install it. -To patch this, go find the mount_shared_folder.rb file and replace `"cmdkey /add:#{options[:smb_host]} /user:#{options[:smb_username]} /pass:\"#{options[:smb_password]}\""` with `"cmdkey '/add:\"#{options[:smb_host]}\"' '/user:\"#{options[:smb_username]}\"' '/pass:\"#{options[:smb_password]}\"'"` +## Known Issues Important! -2) Windows will require you to enter an administrator username and password to be able to create and mount the SMB share. -This means the build will not be fully automated. One thing you can do is add `config.vm.synced_folder '../Vagrant', '/vagrant', smb_username: "username", smb_password: "password"` to the Vagrantfile on line 2. For security reasons, this is not a good idea as you will be storing your username and password in plaintext. -By not having this line added to the Vagrantfile you will be required to put in your username and password at least 2 times per machine. +Unfortunately, due to some issues with Vagrant and Microsoft, running DetectionLab with Hyper-V is not as easy as it is with other providers. You will need to do the following BEFORE trying to run `vagrant up`. +1) Patch Vagant +Vagrant does not play nice with Windows SMB share authentication. It uses cmdkey which is not properly implemented. More details about the issue can be found in this issue:(https://github.com/hashicorp/vagrant/issues/10661) +To patch this, go find the mount_shared_folder.rb file and replace `"cmdkey /add:#{options[:smb_host]} /user:#{options[:smb_username]} /pass:\"#{options[:smb_password]}\""` with `"cmdkey '/add:\"#{options[:smb_host]}\"' '/user:\"#{options[:smb_username]}\"' '/pass:\"#{options[:smb_password]}\"'"` -3) Selecting Virtual Switch -During the build you will also have to select the virtual switch you want to use for each server. This cannot be avoided. There is a option that can be used to force the network adapter to use a particular switch; however, using that option breaks this build process. -A really hacky workaround is, if you are using the smb_username and smb_password options, would be to press the option number corresponding with the virtual switch you want to use then enter four times after `vagrant up`. So if you know you want the virtual switch 1 `vagrant up` 1 enter 1 enter 1 enter 1 enter -Yes, I know hacky but it works. +2) Windows will require you to enter an administrator username and password to be able to create and mount the SMB share. +This means the build will not be fully automated. One thing you can do is add `config.vm.synced_folder '../Vagrant', '/vagrant', smb_username: "username", smb_password: "password"` to the Vagrantfile on line 2. For security reasons, this is not a good idea as you will be storing your username and password in plaintext. +By not having this line added to the Vagrantfile you will be required to put in your username and password at least 2 times per machine. -## How this build works -The majority of this build works the same as the VirtualBox build. The most notable difference is is on the Windows builds. There is a script that will create an internal virtual switch called "NATSwitch." Throughout the build process, a script will create a second network adapter and attach it to the NATSwitch on the VM being built. After the machine is built the original network adapter will be removed from the VM. +3) Selecting Virtual Switch +During the build you will also have to select the virtual switch you want to use for each server. This cannot be avoided. There is a option that can be used to force the network adapter to use a particular switch; however, using that option breaks this build process. -## Note -This build will run two scripts on the host machine. It is advisable to always check any scripts that will be run on your machine before running them. \ No newline at end of file +A really hacky workaround is, if you are using the smb_username and smb_password options, would be to press the option number corresponding with the virtual switch you want to use then enter four times after `vagrant up`. So, if you know you want the virtual switch 1 `vagrant up` 1 enter 1 enter 1 enter 1 enter + +Yes, I know hacky but it works. + +## How this build works + +The majority of this build works the same as the VirtualBox build. The most notable difference is on the Windows builds. There is a script that will create an internal virtual switch called "NATSwitch." Throughout the build process, a script will create a second network adapter and attach it to the NATSwitch on the VM being built. After the machine is built the original network adapter will be removed from the VM. + +## Note + +This build will run two scripts on the host machine. It is advisable to always check any scripts that will be run on your machine before running them. From 1076565d34c88b6a99ac580c5e72153abb41840e Mon Sep 17 00:00:00 2001 From: Arron Patton Date: Tue, 25 Aug 2020 15:24:33 -0600 Subject: [PATCH 5/5] Update README.md --- HyperV/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HyperV/README.md b/HyperV/README.md index 61244ad..0db29fe 100644 --- a/HyperV/README.md +++ b/HyperV/README.md @@ -1,6 +1,6 @@ # Detection Lab for Hyper-V -This hypervisor does not undergo the same level of weekly testing as what is found in the main part of Detectionlab. +This build does not undergo the same level of weekly testing as what is found in the main part of Detectionlab. Hyper-V support is only in beta and needs more testing by more users to ensure its stability and usability. ## Requirements