1use vmi_core::{Va, VmiError, VmiState, VmiVa, driver::VmiRead};
2
3use super::{
4 super::{WindowsLuid, WindowsSid, WindowsSidAndAttributes},
5 FromWindowsObject, WindowsObject, WindowsObjectTypeKind,
6};
7use crate::{ArchAdapter, WindowsOs, offset};
8
9pub struct WindowsToken<'a, Driver>
22where
23 Driver: VmiRead,
24 Driver::Architecture: ArchAdapter<Driver>,
25{
26 vmi: VmiState<'a, WindowsOs<Driver>>,
28
29 va: Va,
31}
32
33impl<'a, Driver> From<WindowsToken<'a, Driver>> for WindowsObject<'a, Driver>
34where
35 Driver: VmiRead,
36 Driver::Architecture: ArchAdapter<Driver>,
37{
38 fn from(value: WindowsToken<'a, Driver>) -> Self {
39 Self::new(value.vmi, value.va)
40 }
41}
42
43impl<'a, Driver> FromWindowsObject<'a, Driver> for WindowsToken<'a, Driver>
44where
45 Driver: VmiRead,
46 Driver::Architecture: ArchAdapter<Driver>,
47{
48 fn from_object(object: WindowsObject<'a, Driver>) -> Result<Option<Self>, VmiError> {
49 match object.type_kind()? {
50 Some(WindowsObjectTypeKind::Token) => Ok(Some(Self::new(object.vmi, object.va))),
51 _ => Ok(None),
52 }
53 }
54}
55
56impl<Driver> VmiVa for WindowsToken<'_, Driver>
57where
58 Driver: VmiRead,
59 Driver::Architecture: ArchAdapter<Driver>,
60{
61 fn va(&self) -> Va {
62 self.va
63 }
64}
65
66bitflags::bitflags! {
67 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
69 pub struct WindowsTokenFlags: u32 {
70 const HAS_TRAVERSE_PRIVILEGE = 0x0000_0001;
72
73 const HAS_BACKUP_PRIVILEGE = 0x0000_0002;
75
76 const HAS_RESTORE_PRIVILEGE = 0x0000_0004;
78
79 const WRITE_RESTRICTED = 0x0000_0008;
81
82 const IS_RESTRICTED = 0x0000_0010;
84
85 const SESSION_NOT_REFERENCED = 0x0000_0020;
87
88 const SANDBOX_INERT = 0x0000_0040;
90
91 const HAS_IMPERSONATE_PRIVILEGE = 0x0000_0080;
93
94 const SE_BACKUP_PRIVILEGES_CHECKED = 0x0000_0100;
96
97 const VIRTUALIZE_ALLOWED = 0x0000_0200;
99
100 const VIRTUALIZE_ENABLED = 0x0000_0400;
102
103 const IS_FILTERED = 0x0000_0800;
105
106 const UIACCESS = 0x0000_1000;
108
109 const NOT_LOW = 0x0000_2000;
111
112 const LOWBOX = 0x0000_4000;
114
115 const HAS_OWN_CLAIM_ATTRIBUTES = 0x0000_8000;
117
118 const PRIVATE_NAMESPACE = 0x0001_0000;
120
121 const DO_NOT_USE_GLOBAL_ATTRIBS_FOR_QUERY = 0x0002_0000;
123
124 const SPECIAL_ENCRYPTED_OPEN = 0x0004_0000;
126
127 const NO_CHILD_PROCESS = 0x0008_0000;
129
130 const NO_CHILD_PROCESS_UNLESS_SECURE = 0x0010_0000;
132
133 const AUDIT_NO_CHILD_PROCESS = 0x0020_0000;
135
136 const ENFORCE_REDIRECTION_TRUST = 0x0040_0000;
138
139 const AUDIT_REDIRECTION_TRUST = 0x0080_0000;
141
142 const LEARNING_MODE_LOGGING = 0x0100_0000;
144
145 const PERMISSIVE_LEARNING_MODE = 0x0300_0000;
149
150 const SYSTEM_MANAGED_ADMIN_FULL_TOKEN = 0x0800_0000;
152 }
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub enum WindowsTokenType {
162 Primary,
164
165 Impersonation,
167
168 Unknown(u32),
170}
171
172impl From<u32> for WindowsTokenType {
173 fn from(value: u32) -> Self {
175 match value {
176 1 => Self::Primary,
177 2 => Self::Impersonation,
178 _ => Self::Unknown(value),
179 }
180 }
181}
182
183#[derive(Debug, Clone, Copy, PartialEq, Eq)]
189pub enum WindowsImpersonationLevel {
190 Anonymous,
192
193 Identification,
195
196 Impersonation,
198
199 Delegation,
201
202 Unknown(u32),
204}
205
206impl From<u32> for WindowsImpersonationLevel {
207 fn from(value: u32) -> Self {
208 match value {
209 0 => Self::Anonymous,
210 1 => Self::Identification,
211 2 => Self::Impersonation,
212 3 => Self::Delegation,
213 _ => Self::Unknown(value),
214 }
215 }
216}
217
218pub struct WindowsTokenSource<'a, Driver>
224where
225 Driver: VmiRead,
226 Driver::Architecture: ArchAdapter<Driver>,
227{
228 vmi: VmiState<'a, WindowsOs<Driver>>,
230
231 va: Va,
233}
234
235impl<Driver> VmiVa for WindowsTokenSource<'_, Driver>
236where
237 Driver: VmiRead,
238 Driver::Architecture: ArchAdapter<Driver>,
239{
240 fn va(&self) -> Va {
241 self.va
242 }
243}
244
245impl<'a, Driver> WindowsTokenSource<'a, Driver>
246where
247 Driver: VmiRead,
248 Driver::Architecture: ArchAdapter<Driver>,
249{
250 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
252 Self { vmi, va }
253 }
254
255 pub fn name_bytes(&self) -> Result<[u8; 8], VmiError> {
261 let TOKEN_SOURCE = offset!(self.vmi, _TOKEN_SOURCE);
262 debug_assert_eq!(TOKEN_SOURCE.SourceName.size(), 8);
263
264 let mut bytes = [0; 8];
265 self.vmi
266 .read(self.va + TOKEN_SOURCE.SourceName.offset(), &mut bytes)?;
267
268 Ok(bytes)
269 }
270
271 pub fn name(&self) -> Result<String, VmiError> {
277 let bytes = self.name_bytes()?;
278
279 let end = bytes
280 .iter()
281 .position(|byte| *byte == 0)
282 .unwrap_or(bytes.len());
283
284 Ok(String::from_utf8_lossy(&bytes[..end])
285 .trim_end()
286 .to_string())
287 }
288
289 pub fn identifier(&self) -> Result<WindowsLuid, VmiError> {
295 let TOKEN_SOURCE = offset!(self.vmi, _TOKEN_SOURCE);
296
297 let raw = self
298 .vmi
299 .read_u64(self.va + TOKEN_SOURCE.SourceIdentifier.offset())?;
300
301 Ok(WindowsLuid::from(raw))
302 }
303}
304
305#[derive(Copy, Clone, Eq, PartialEq, Hash)]
310pub struct WindowsPrivilege(u32);
311
312impl WindowsPrivilege {
313 pub const CREATE_TOKEN: Self = Self(2);
315
316 pub const ASSIGNPRIMARYTOKEN: Self = Self(3);
318
319 pub const LOCK_MEMORY: Self = Self(4);
321
322 pub const INCREASE_QUOTA: Self = Self(5);
324
325 pub const MACHINE_ACCOUNT: Self = Self(6);
327
328 pub const TCB: Self = Self(7);
330
331 pub const SECURITY: Self = Self(8);
333
334 pub const TAKE_OWNERSHIP: Self = Self(9);
336
337 pub const LOAD_DRIVER: Self = Self(10);
339
340 pub const SYSTEM_PROFILE: Self = Self(11);
342
343 pub const SYSTEMTIME: Self = Self(12);
345
346 pub const PROF_SINGLE_PROCESS: Self = Self(13);
348
349 pub const INC_BASE_PRIORITY: Self = Self(14);
351
352 pub const CREATE_PAGEFILE: Self = Self(15);
354
355 pub const CREATE_PERMANENT: Self = Self(16);
357
358 pub const BACKUP: Self = Self(17);
360
361 pub const RESTORE: Self = Self(18);
363
364 pub const SHUTDOWN: Self = Self(19);
366
367 pub const DEBUG: Self = Self(20);
369
370 pub const AUDIT: Self = Self(21);
372
373 pub const SYSTEM_ENVIRONMENT: Self = Self(22);
375
376 pub const CHANGE_NOTIFY: Self = Self(23);
378
379 pub const REMOTE_SHUTDOWN: Self = Self(24);
381
382 pub const UNDOCK: Self = Self(25);
384
385 pub const SYNC_AGENT: Self = Self(26);
387
388 pub const ENABLE_DELEGATION: Self = Self(27);
390
391 pub const MANAGE_VOLUME: Self = Self(28);
393
394 pub const IMPERSONATE: Self = Self(29);
396
397 pub const CREATE_GLOBAL: Self = Self(30);
399
400 pub const TRUSTED_CREDMAN_ACCESS: Self = Self(31);
402
403 pub const RELABEL: Self = Self(32);
405
406 pub const INC_WORKING_SET: Self = Self(33);
408
409 pub const TIME_ZONE: Self = Self(34);
411
412 pub const CREATE_SYMBOLIC_LINK: Self = Self(35);
414
415 pub const DELEGATE_SESSION_USER_IMPERSONATE: Self = Self(36);
417
418 pub const fn new(low_part: u32) -> Self {
420 Self(low_part)
421 }
422
423 pub const fn low_part(self) -> u32 {
425 self.0
426 }
427
428 pub const fn mask(self) -> u64 {
430 1 << self.0
431 }
432
433 pub const fn name(self) -> Option<&'static str> {
435 match self.0 {
436 2 => Some("SeCreateTokenPrivilege"),
437 3 => Some("SeAssignPrimaryTokenPrivilege"),
438 4 => Some("SeLockMemoryPrivilege"),
439 5 => Some("SeIncreaseQuotaPrivilege"),
440 6 => Some("SeMachineAccountPrivilege"),
441 7 => Some("SeTcbPrivilege"),
442 8 => Some("SeSecurityPrivilege"),
443 9 => Some("SeTakeOwnershipPrivilege"),
444 10 => Some("SeLoadDriverPrivilege"),
445 11 => Some("SeSystemProfilePrivilege"),
446 12 => Some("SeSystemtimePrivilege"),
447 13 => Some("SeProfileSingleProcessPrivilege"),
448 14 => Some("SeIncreaseBasePriorityPrivilege"),
449 15 => Some("SeCreatePagefilePrivilege"),
450 16 => Some("SeCreatePermanentPrivilege"),
451 17 => Some("SeBackupPrivilege"),
452 18 => Some("SeRestorePrivilege"),
453 19 => Some("SeShutdownPrivilege"),
454 20 => Some("SeDebugPrivilege"),
455 21 => Some("SeAuditPrivilege"),
456 22 => Some("SeSystemEnvironmentPrivilege"),
457 23 => Some("SeChangeNotifyPrivilege"),
458 24 => Some("SeRemoteShutdownPrivilege"),
459 25 => Some("SeUndockPrivilege"),
460 26 => Some("SeSyncAgentPrivilege"),
461 27 => Some("SeEnableDelegationPrivilege"),
462 28 => Some("SeManageVolumePrivilege"),
463 29 => Some("SeImpersonatePrivilege"),
464 30 => Some("SeCreateGlobalPrivilege"),
465 31 => Some("SeTrustedCredManAccessPrivilege"),
466 32 => Some("SeRelabelPrivilege"),
467 33 => Some("SeIncreaseWorkingSetPrivilege"),
468 34 => Some("SeTimeZonePrivilege"),
469 35 => Some("SeCreateSymbolicLinkPrivilege"),
470 36 => Some("SeDelegateSessionUserImpersonatePrivilege"),
471 _ => None,
472 }
473 }
474}
475
476impl std::fmt::Debug for WindowsPrivilege {
477 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
478 match self.name() {
479 Some(name) => write!(f, "{name}"),
480 None => write!(f, "UnknownPrivilege({})", self.low_part()),
481 }
482 }
483}
484
485#[derive(Debug, Copy, Clone)]
487pub struct WindowsTokenPrivilege {
488 pub privilege: WindowsPrivilege,
490
491 pub enabled: bool,
493
494 pub enabled_by_default: bool,
496}
497
498impl<'a, Driver> WindowsToken<'a, Driver>
499where
500 Driver: VmiRead,
501 Driver::Architecture: ArchAdapter<Driver>,
502{
503 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
505 Self { vmi, va }
506 }
507
508 pub fn session_id(&self) -> Result<u32, VmiError> {
514 let TOKEN = offset!(self.vmi, _TOKEN);
515
516 self.vmi.read_u32(self.va + TOKEN.SessionId.offset())
517 }
518
519 pub fn token_source(&self) -> WindowsTokenSource<'a, Driver> {
525 let TOKEN = offset!(self.vmi, _TOKEN);
526
527 WindowsTokenSource::new(self.vmi, self.va + TOKEN.TokenSource.offset())
528 }
529
530 pub fn authentication_id(&self) -> Result<WindowsLuid, VmiError> {
536 let TOKEN = offset!(self.vmi, _TOKEN);
537
538 let raw = self
539 .vmi
540 .read_u64(self.va + TOKEN.AuthenticationId.offset())?;
541
542 Ok(WindowsLuid::from(raw))
543 }
544
545 pub fn token_id(&self) -> Result<WindowsLuid, VmiError> {
551 let TOKEN = offset!(self.vmi, _TOKEN);
552
553 let raw = self.vmi.read_u64(self.va + TOKEN.TokenId.offset())?;
554
555 Ok(WindowsLuid::from(raw))
556 }
557
558 pub fn parent_token_id(&self) -> Result<WindowsLuid, VmiError> {
565 let TOKEN = offset!(self.vmi, _TOKEN);
566
567 let raw = self.vmi.read_u64(self.va + TOKEN.ParentTokenId.offset())?;
568
569 Ok(WindowsLuid::from(raw))
570 }
571
572 pub fn modified_id(&self) -> Result<WindowsLuid, VmiError> {
578 let TOKEN = offset!(self.vmi, _TOKEN);
579
580 let raw = self.vmi.read_u64(self.va + TOKEN.ModifiedId.offset())?;
581
582 Ok(WindowsLuid::from(raw))
583 }
584
585 pub fn originating_logon_session(&self) -> Result<WindowsLuid, VmiError> {
591 let TOKEN = offset!(self.vmi, _TOKEN);
592
593 let raw = self
594 .vmi
595 .read_u64(self.va + TOKEN.OriginatingLogonSession.offset())?;
596
597 Ok(WindowsLuid::from(raw))
598 }
599
600 pub fn token_type(&self) -> Result<WindowsTokenType, VmiError> {
606 let TOKEN = offset!(self.vmi, _TOKEN);
607
608 let raw = self.vmi.read_u32(self.va + TOKEN.TokenType.offset())?;
609
610 Ok(WindowsTokenType::from(raw))
611 }
612
613 pub fn impersonation_level(&self) -> Result<WindowsImpersonationLevel, VmiError> {
619 let TOKEN = offset!(self.vmi, _TOKEN);
620
621 let raw = self
622 .vmi
623 .read_u32(self.va + TOKEN.ImpersonationLevel.offset())?;
624
625 Ok(WindowsImpersonationLevel::from(raw))
626 }
627
628 pub fn token_flags(&self) -> Result<WindowsTokenFlags, VmiError> {
634 let TOKEN = offset!(self.vmi, _TOKEN);
635
636 let raw = self.vmi.read_u32(self.va + TOKEN.TokenFlags.offset())?;
637
638 Ok(WindowsTokenFlags::from_bits_retain(raw))
639 }
640
641 pub fn token_in_use(&self) -> Result<bool, VmiError> {
650 let TOKEN = offset!(self.vmi, _TOKEN);
651
652 Ok(self.vmi.read_u8(self.va + TOKEN.TokenInUse.offset())? != 0)
653 }
654
655 pub fn user_and_group_count(&self) -> Result<u32, VmiError> {
662 let TOKEN = offset!(self.vmi, _TOKEN);
663
664 self.vmi
665 .read_u32(self.va + TOKEN.UserAndGroupCount.offset())
666 }
667
668 pub fn restricted_sid_count(&self) -> Result<u32, VmiError> {
674 let TOKEN = offset!(self.vmi, _TOKEN);
675
676 self.vmi
677 .read_u32(self.va + TOKEN.RestrictedSidCount.offset())
678 }
679
680 pub fn primary_group(&self) -> Result<WindowsSid<'a, Driver>, VmiError> {
686 let TOKEN = offset!(self.vmi, _TOKEN);
687
688 let sid = self
689 .vmi
690 .read_va_native(self.va + TOKEN.PrimaryGroup.offset())?;
691
692 Ok(WindowsSid::new(self.vmi, sid))
693 }
694
695 pub fn user_and_groups(
703 &self,
704 ) -> Result<
705 impl Iterator<Item = Result<WindowsSidAndAttributes<'a, Driver>, VmiError>> + use<'a, Driver>,
706 VmiError,
707 > {
708 let TOKEN = offset!(self.vmi, _TOKEN);
709
710 let count = self.user_and_group_count()?;
711 let base = self
712 .vmi
713 .read_va_native(self.va + TOKEN.UserAndGroups.offset())?;
714
715 Ok(self.sid_and_attributes(base, count))
716 }
717
718 pub fn restricted_sids(
725 &self,
726 ) -> Result<
727 impl Iterator<Item = Result<WindowsSidAndAttributes<'a, Driver>, VmiError>> + use<'a, Driver>,
728 VmiError,
729 > {
730 let TOKEN = offset!(self.vmi, _TOKEN);
731
732 let count = self.restricted_sid_count()?;
733 let base = self
734 .vmi
735 .read_va_native(self.va + TOKEN.RestrictedSids.offset())?;
736
737 Ok(self.sid_and_attributes(base, count))
738 }
739
740 pub fn privileges_present(&self) -> Result<u64, VmiError> {
747 let TOKEN = offset!(self.vmi, _TOKEN);
748 let SEP_TOKEN_PRIVILEGES = offset!(self.vmi, _SEP_TOKEN_PRIVILEGES);
749
750 self.vmi
751 .read_u64(self.va + TOKEN.Privileges.offset() + SEP_TOKEN_PRIVILEGES.Present.offset())
752 }
753
754 pub fn privileges_enabled(&self) -> Result<u64, VmiError> {
760 let TOKEN = offset!(self.vmi, _TOKEN);
761 let SEP_TOKEN_PRIVILEGES = offset!(self.vmi, _SEP_TOKEN_PRIVILEGES);
762
763 self.vmi
764 .read_u64(self.va + TOKEN.Privileges.offset() + SEP_TOKEN_PRIVILEGES.Enabled.offset())
765 }
766
767 pub fn privileges_enabled_by_default(&self) -> Result<u64, VmiError> {
773 let TOKEN = offset!(self.vmi, _TOKEN);
774 let SEP_TOKEN_PRIVILEGES = offset!(self.vmi, _SEP_TOKEN_PRIVILEGES);
775
776 self.vmi.read_u64(
777 self.va + TOKEN.Privileges.offset() + SEP_TOKEN_PRIVILEGES.EnabledByDefault.offset(),
778 )
779 }
780
781 pub fn privileges(&self) -> Result<impl Iterator<Item = WindowsTokenPrivilege>, VmiError> {
783 let present = self.privileges_present()?;
784 let enabled = self.privileges_enabled()?;
785 let enabled_by_default = self.privileges_enabled_by_default()?;
786
787 Ok((0..64).filter_map(move |bit| {
788 let mask = 1u64 << bit;
789 match present & mask {
790 0 => None,
791 _ => Some(WindowsTokenPrivilege {
792 privilege: WindowsPrivilege::new(bit),
793 enabled: enabled & mask != 0,
794 enabled_by_default: enabled_by_default & mask != 0,
795 }),
796 }
797 }))
798 }
799
800 fn sid_and_attributes(
802 &self,
803 base: Va,
804 count: u32,
805 ) -> impl Iterator<Item = Result<WindowsSidAndAttributes<'a, Driver>, VmiError>> + use<'a, Driver>
806 {
807 let vmi = self.vmi;
808 let sizeof_sid_and_attributes = offset!(vmi, _SID_AND_ATTRIBUTES).len() as u64;
809
810 (0..u64::from(count)).map(move |index| {
811 Ok(WindowsSidAndAttributes::new(
812 vmi,
813 base + index * sizeof_sid_and_attributes,
814 ))
815 })
816 }
817}