19 Commits
Author SHA1 Message Date
Jake OtteandClaude Opus 5 9d232aa480 Fix expiry check from #2 and rework dump/list output
PR #2 added ticket end/renew reporting and expired-ticket skipping. Three
bugs came with it:

* klistwinrm.py called time.time() without importing time -- every dump
  died with NameError on the first ticket.
* The skip was nested inside `if info["renew_till"]:`. parse_time() returns
  0 for an absent field, so non-renewable tickets were never checked and
  expired ones got written anyway -- the exact case the PR set out to catch.
* parse_time() tags klist's "(local)" wallclock as UTC, so its values are
  target-local wallclock, not true epochs. Comparing them to time.time()
  skewed every check by the UTC offset: valid tickets dropped west of UTC,
  expired ones kept east of it.

Expiry now keys off end_time via now_ticket_frame(), which builds "now" in
the same frame parse_time() uses, so no time import is needed. A ticket past
end_time but still within renew_till is written rather than dropped, since
the ccache can be renewed.

Output follows PRTremote's convention: [*]/[X] markers, dot-aligned kv rows,
unmarked list rows, and a closing summary with the KRB5CCNAME hint. Skipped
expired tickets are counted so "0 ccaches written" explains itself instead of
just exiting 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 13:03:03 -04:00
Jake Otte 63910dc6ae Merge pull request #2 from absolomb/main
Update dumping behavior to display ticket end and renewal time and skip expired tickets
2026-08-06 12:56:52 -04:00
Ryan McFarland 49e556bb5c Update klistwinrm.py 2026-07-29 09:27:33 -05:00
Ryan McFarland 22bae36471 Update klistremote.py 2026-07-29 09:27:03 -05:00
Ryan McFarland b2a91b3d69 Update klistremote.py 2026-07-29 09:23:52 -05:00
Ryan McFarland 6b89258e4a Update klistwinrm.py 2026-07-29 09:23:05 -05:00
Jake OtteandClaude Opus 4.8 555afcf89a Credential Guard keys are unexportable: refuse instead of emitting a bad key
The previous commit assumed the CG KerberosKeyWithMetadata blob held a
cleartext key at offset 28 and exported it. It does not: both opaque
regions in the blob are 48 bytes (a 32-byte secret block-aligned +
padding), i.e. the session key is wrapped/encrypted. Under Credential
Guard the key lives in the secure kernel (VTL1) and the unwrap key never
leaves it, so the cleartext key cannot be recovered offline. Feeding the
wrapped bytes into a ccache produced KRB_AP_ERR_BAD_INTEGRITY.

Stop extracting offset-28 bytes on the CG path. Instead detect the CG
layout and refuse with a clear message (klist2ccache exits non-zero;
klistremote/klistwinrm skip the account) so the failure is loud rather
than a plausible-looking but unusable ccache. Non-CG SYSTEM blobs and
raw-key paths are unchanged. README updated to explain the limitation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 15:50:49 -04:00
Jake OtteandClaude Opus 4.8 6e351234fa Auto-detect Credential Guard KerberosKeyWithMetadata blobs
Under Credential Guard, klist emits the session key as a marshalled
KerberosKeyWithMetadata blob: self-size@0, typename-length@8,
typename-offset@12 pointing at the literal "KerberosKeyWithMetadata",
key payload@28, then the typename + metadata tail.

The old parser read the etype from offset 8, which in the CG blob is the
typename length (23 == 0x17, colliding with RC4) rather than the real
etype. That yielded a wrong key type and a truncated 16-byte key,
producing tickets that failed with BAD_INTEGRITY.

Detect the CG layout by checking that the offset-8/12 fields frame the
embedded "KerberosKeyWithMetadata" string, and in that case take the
etype from the "KeyType 0x.." header line instead of offset 8. Legacy
SYSTEM metadata blobs and raw-key paths are unchanged. Applied to all
three tools; prints a notice when the CG path triggers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 15:42:34 -04:00
Jake OtteandClaude Sonnet 4.6 c4d392e0eb Add klistwinrm.py, requirements.txt, and --computer flag
- klistwinrm.py: new tool that lists/dumps Kerberos TGTs via WinRM
  instead of Task Scheduler + SMB; supports all auth types (NTLM,
  PTH, Kerberos, AES key, keytab) plus -ssl/-port options
- requirements.txt: pywinrm + impacket deps; requests-ntlm2 noted for PTH
- klistremote.py + klistwinrm.py: add --computer flag to include
  machine account sessions (Kerberos:Network, e.g. HOSTNAME$)
- README: document all three tools with usage examples and auth matrix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 15:02:21 -04:00
Jake Otte 32eb0e18a4 Merge pull request #1 from Pebl3/main
Handle KerberosKeyWithMetadata blob in session key field
2026-05-08 10:40:15 -07:00
Pebl3 2620b5e430 Refactor key handling in klistremote.py 2026-04-29 23:12:15 -04:00
Pebl3 036efcf4bf Refactor key handling in klist2ccache.py 2026-04-29 23:11:54 -04:00
Jake Otte 2b64bae278 readme 2026-03-12 22:34:17 -04:00
Jake Otte f06d2dfb43 Named pipes 2026-03-12 22:26:41 -04:00
Jake Otte e97c454e3f Update README.md 2026-03-10 17:22:20 -04:00
Jake Otte 7722ffc356 Add files via upload 2026-03-10 17:09:34 -04:00
Jake Otte 97909ae126 Enhance README with klist2ccache.py output example
Added example output for klist2ccache.py usage.
2026-03-06 23:24:53 -05:00
Jake Otte f4233065f3 Remove TGT dumping section from README
Removed section on dumping TGTs with klist from README.
2026-03-06 23:19:44 -05:00
Jake Otte dbdb000dc0 Add files via upload 2026-03-06 23:19:13 -05:00