I have a SID string (e.g., “S-1-5-21-500000003-1000000000-1000000003-1001”) of a user on a shared Windows server, and I need to get the related username.
I suppose that this may be achieved by:
- Turning the SID string into byte array.
- Using a suitable
ldpa
query to get the related username.
But I failed to find exact and reliable instructions of how to do it (this way or another).
I’ll appreciate any useful guide, especially if it comes with demo Python (ldap3
) code.
Advertisement
Answer
JavaScript
x
41
41
1
def unsigned_number_to_slashed_byte_array_string(number, little_endian, digits_count):
2
"""
3
Convert given unsigned number into a string that represents it as a sequence of bytes in given order (either little or big Endian).
4
In case the total number of digits in the string is greater than given digits count, the string is left-padded with zeroes.
5
Each such byte is represented by a substring that's composed of a preceding slash character followed by two (uppercase) hexadecimal digits (e.g., "\0A").
6
:param number: An unsigned non-negative integer.
7
:param little_endian: A flag that says whether little Endian order is requested; otherwise, big Endian order is selected.
8
:param digits_count: The total count of hexadecimal digits in the resulting possibly left-padded string, which is twice the number of bytes.
9
:except ValueError: In case given number isn't a non-negative number, or given digits count isn't a positive even number.
10
:return: A string that represents given number as a sequence of bytes in given order.
11
"""
12
if number < 0: raise ValueError("{0}: Argument number must be a non-negative! ({1})".format(func_name(), number))
13
if (digits_count <= 0) or ((digits_count % 2) != 0): raise ValueError("{0}: Argument digits_count must be an even positive! ({1})".format(func_name(), digits_count))
14
15
zero_padded_hex_number_str = "{0:0{1}X}".format(number, digits_count) # Format: no leading "0x", zero-padded digits_count digits (or half digits_count bytes), uppercase hexadecimal letters.
16
number_byte_array_str = ""
17
byte_starter_digits_indices_list = range(len(zero_padded_hex_number_str))[::2]
18
if little_endian: byte_starter_digits_indices_list = reversed(byte_starter_digits_indices_list)
19
for byte_starter_digit_index in byte_starter_digits_indices_list:
20
number_byte_array_str = "{0}\{1}".format(number_byte_array_str, zero_padded_hex_number_str[byte_starter_digit_index:(byte_starter_digit_index + 2)])
21
return number_byte_array_str
22
23
24
def sid_str_to_byte_array_str(sid_str):
25
"""
26
:param sid_str: An active-directory SID string (e.g., "S-1-5-21-1241979920-1440912824-1533017923-1106").
27
:return: A string that represents given SID string as a byte array string (e.g., "\01\05\00\00\00\00\00\05\15\00\00\00\10\1C\07\4A\B8\95\E2\55\43\FF\5F\5B").
28
"""
29
dashes_count = sid_str.count("-")
30
sid_numbers_str = sid_str[2:] # Removes the preceding "S-"
31
sid_number_strings = sid_numbers_str.split("-")
32
sid_numbers = [int(sid_number_string) for sid_number_string in sid_number_strings]
33
sid_byte_array_str = unsigned_number_to_slashed_byte_array_string(sid_numbers[0], True, 2)
34
sid_byte_array_str += unsigned_number_to_slashed_byte_array_string((dashes_count - 2), True, 2)
35
sid_byte_array_str += unsigned_number_to_slashed_byte_array_string(sid_numbers[1], False, 12)
36
sid_byte_array_str += unsigned_number_to_slashed_byte_array_string(sid_numbers[2], True, 8)
37
sid_byte_array_str += unsigned_number_to_slashed_byte_array_string(sid_numbers[3], True, 8)
38
sid_byte_array_str += unsigned_number_to_slashed_byte_array_string(sid_numbers[4], True, 8)
39
sid_byte_array_str += unsigned_number_to_slashed_byte_array_string(sid_numbers[5], True, 8)
40
return sid_byte_array_str
41