forensic_rs/utils/win/
sid.rs

1use std::fmt::Write;
2
3use crate::prelude::{ForensicError, ForensicResult};
4
5pub const LOCAL_SYSTEM_SID_STR: &str = "S-1-5-18";
6pub const LOCAL_SYSTEM_SID_BIN: [u8; 12] = [
7    0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00,
8];
9pub const BUILTIN_ADMINS_SID_STR: &str = "S-1-5-32-544";
10pub const BUILTIN_ADMINS_SID_BIN: [u8; 16] = [
11    0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00,
12];
13pub const BUILTIN_USERS_SID_STR: &str = "S-1-5-32-545";
14pub const BUILTIN_USERS_SID_BIN: [u8; 16] = [
15    0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00,
16];
17pub const BUILTIN_GUESTS_SID_STR: &str = "S-1-5-32-546";
18pub const BUILTIN_GUESTS_SID_BIN: [u8; 16] = [
19    0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x22, 0x02, 0x00, 0x00,
20];
21
22/// Converts a binary SID to a string
23///
24/// https://learn.microsoft.com/es-es/windows/win32/secauthz/sid-components?redirectedfrom=MSDN
25///
26/// ```rust
27/// use forensic_rs::utils::win::to_string_sid;
28/// // Builtin/Administrators
29/// assert_eq!("S-1-5-32-544", to_string_sid(&[0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x05,0x20,0x00,0x00,0x00,0x20,0x02,0x00,0x00]).unwrap());
30/// ```
31pub fn to_string_sid(sid: &[u8]) -> ForensicResult<String> {
32    if sid.len() < 8 {
33        return Err(ForensicError::bad_format_str(
34            "SID must have at least 8 bytes",
35        ));
36    }
37
38    let mut id = String::with_capacity(32);
39
40    let subauthority_count = sid[1];
41    let mut identifier_authority =
42        (u16::from_be_bytes(sid[2..4].try_into().unwrap_or_default()) as u64) << 32;
43    identifier_authority |= u32::from_be_bytes(sid[4..8].try_into().unwrap_or_default()) as u64;
44    let _ = write!(&mut id, "S-{}-{}", sid[0], identifier_authority);
45    let mut start = 8;
46
47    for _ in 0..subauthority_count {
48        if start + 4 > sid.len() {
49            break;
50        }
51        let authority = &sid[start..start + 4];
52        let tmp = u32::from_le_bytes(authority.try_into().unwrap_or_default());
53        let _ = write!(&mut id, "-{}", tmp);
54        start += 4;
55    }
56
57    Ok(id)
58}
59
60#[test]
61fn should_generate_valid_sids() {
62    // https://devblogs.microsoft.com/oldnewthing/20040315-00/?p=40253
63    assert_eq!(
64        "S-1-5-21-2127521184-1604012920-1887927527-72713",
65        to_string_sid(&[
66            0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xA0, 0x65,
67            0xCF, 0x7E, 0x78, 0x4B, 0x9B, 0x5F, 0xE7, 0x7C, 0x87, 0x70, 0x09, 0x1C, 0x01, 0x00
68        ])
69        .unwrap()
70    );
71    assert_eq!(
72        BUILTIN_ADMINS_SID_STR,
73        to_string_sid(&BUILTIN_ADMINS_SID_BIN).unwrap()
74    );
75    assert_eq!(
76        BUILTIN_USERS_SID_STR,
77        to_string_sid(&BUILTIN_USERS_SID_BIN).unwrap()
78    );
79    assert_eq!(
80        BUILTIN_GUESTS_SID_STR,
81        to_string_sid(&BUILTIN_GUESTS_SID_BIN).unwrap()
82    );
83    assert_eq!(
84        LOCAL_SYSTEM_SID_STR,
85        to_string_sid(&LOCAL_SYSTEM_SID_BIN).unwrap()
86    );
87    assert_eq!(
88        "S-1-5-21-1366093794-4292800403-1155380978-513",
89        to_string_sid(&[
90            0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xe2, 0xef,
91            0x6c, 0x51, 0x93, 0xef, 0xde, 0xff, 0xf2, 0xb6, 0xdd, 0x44, 0x01, 0x02, 0x00, 0x00
92        ])
93        .unwrap()
94    );
95}