rusthound_ce/enums/
sid.rs

1use std::error::Error;
2use regex::Regex;
3use log::{trace,error};
4use crate::enums::secdesc::LdapSid;
5
6/// Function to check if string is SID
7pub fn is_sid(input: &String) -> Result<bool, Box<dyn Error>> {
8    let regex = Regex::new(".*S-1-5.*")?;
9    Ok(regex.is_match(input))
10}
11
12/// Function to make SID String from ldap_sid struct
13pub fn sid_maker(sid: LdapSid, domain: &String) -> String {
14    trace!("sid_maker before: {:?}",&sid);
15
16    let sub = sid.sub_authority.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("-");
17
18    let result = format!("S-{}-{}-{}", sid.revision, sid.identifier_authority.value[5], sub);
19
20    let final_sid = {
21        if result.len() <= 16 {
22            format!("{}-{}", domain.to_uppercase(), result.to_owned())
23        } else {
24            result
25        }
26    };
27
28    trace!("sid_maker value: {}",final_sid);
29    if final_sid.contains("S-0-0"){
30        error!("SID contains null bytes!\n[INPUT: {:?}]\n[OUTPUT: {}]", &sid, final_sid);
31    }
32
33    return final_sid;
34}
35
36/// Change SID value to correct format.
37pub fn objectsid_to_vec8(sid: &String) -> Vec<u8>
38{
39    sid.as_bytes().iter().map(|x| *x).collect::<Vec<u8>>()
40}
41
42/// Function to decode objectGUID binary to string value. 
43/// src: <https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/001eec5a-7f8b-4293-9e21-ca349392db40>
44/// Thanks to: <https://github.com/picketlink/picketlink/blob/master/modules/common/src/main/java/org/picketlink/common/util/LDAPUtil.java>
45pub fn _decode_guid(raw_guid: &Vec<u8>) -> String
46{
47    // A byte-based String representation in the form of \[0]\[1]\[2]\[3]\[4]\[5]\[6]\[7]\[8]\[9]\[10]\[11]\[12]\[13]\[14]\[15]
48    // A string representing the decoded value in the form of [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15].
49    let raw_guid = raw_guid.iter().map(|x| x & 0xFF).collect::<Vec<u8>>();
50    let rev = | x: &[u8] | -> Vec<u8> { x.iter().map(|i| *i).rev().collect::<Vec<u8>>()};
51
52    // Note slice syntax means up to the second number, but not including, so [0..4] is [0, 1, 2, 3] for example.
53    let str_guid = format!(
54        "{}-{}-{}-{}-{}",
55        &hex_push(&raw_guid[0..4]),
56        &hex_push(&rev(&raw_guid[4..6])),
57        &hex_push(&rev(&raw_guid[6..8])),
58        &hex_push(&raw_guid[8..10]),
59        &hex_push(&raw_guid[10..16]),
60    );
61
62    str_guid
63}
64
65/// Function to get a hexadecimal representation from bytes
66/// Thanks to: <https://newbedev.com/how-do-i-convert-a-string-to-hex-in-rust>
67pub fn hex_push(blob: &[u8]) -> String {
68    // For each char in blob, get the capitalised hexadecimal representation (:X) and collect that into a String
69    blob.iter().map(|x| format!("{:X}", x)).collect::<String>()
70}
71
72/// Function to get uuid from bin to string format
73pub fn bin_to_string(raw_guid: &Vec<u8>) -> String
74{
75    // before: e2 49 30 00 aa 00 85 a2 11 d0 0d e6 bf 96 7a ba
76    //         0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
77    // after: bf 96 7a ba - 0d e6 - 11 d0 - a2 85 - 00 aa 00 30 49 e2
78    //        12 13 14 15   10 11   8  9    7  6    5  4  3  2  1  0 
79
80    let raw_guid = raw_guid.iter().map(|x| x & 0xFF).collect::<Vec<u8>>();
81    let rev = | x: &[u8] | -> Vec<u8> { x.iter().map(|i| *i).collect::<Vec<u8>>()};
82
83    let str_guid = format!(
84        "{}-{}-{}-{}-{}",
85        &hex_push(&raw_guid[12..16]),
86        &hex_push(&raw_guid[10..12]),
87        &hex_push(&raw_guid[8..10]),
88        &hex_push(&rev(&raw_guid[6..8])),
89        &hex_push(&rev(&raw_guid[0..6]))
90    );
91
92    return str_guid  
93}
94/// Function to decode GUID from binary to string format with correct little-endian handling
95pub fn decode_guid_le(raw_guid: &Vec<u8>) -> String {
96    // Correct GUID format with proper endianness
97    let str_guid = format!(
98        "{:02X}{:02X}{:02X}{:02X}-{:02X}{:02X}-{:02X}{:02X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
99        raw_guid[3], raw_guid[2], raw_guid[1], raw_guid[0], // Data1 (little-endian)
100        raw_guid[5], raw_guid[4],                           // Data2 (little-endian)
101        raw_guid[7], raw_guid[6],                           // Data3 (little-endian)
102        raw_guid[8], raw_guid[9],                           // Data4 (big-endian)
103        raw_guid[10], raw_guid[11], raw_guid[12], raw_guid[13], raw_guid[14], raw_guid[15] // Data5 (big-endian)
104    );
105
106    str_guid
107}