Skip to content

Commit 22a3875

Browse files
committed
Add helper methods for ace type checks
1 parent b6ed7f0 commit 22a3875

File tree

1 file changed

+78
-42
lines changed

1 file changed

+78
-42
lines changed

lib/rex/proto/ms_dtyp.rb

Lines changed: 78 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,62 +30,61 @@ class MsDtypAccessMask < BinData::Record
3030
bit2 :reserved1
3131
bit1 :ma
3232
bit1 :as
33-
def bit_names
34-
names = []
35-
names << :GENERIC_READ if self.gr != 0
36-
names << :GENERIC_WRITE if self.gw != 0
37-
names << :GENERIC_EXECUTE if self.gx != 0
38-
names << :GENERIC_ALL if self.ga != 0
39-
names << :MAXIMUM_ALLOWED if self.ma != 0
40-
names << :ACCESS_SYSTEM_SECURITY if self.as != 0
41-
names << :SYNCHRONIZE if self.sy != 0
42-
names << :WRITE_OWNER if self.wo != 0
43-
names << :WRITE_DACL if self.wd != 0
44-
names << :READ_CONTROL if self.rc != 0
45-
names << :DELETE if self.de != 0
46-
names
47-
end
4833

4934
ALL = MsDtypAccessMask.new({ gr: 1, gw: 1, gx: 1, ga: 1, ma: 1, as: 1, sy: 1, wo: 1, wd: 1, rc: 1, de: 1, protocol: 0xffff })
5035
NONE = MsDtypAccessMask.new({ gr: 0, gw: 0, gx: 0, ga: 0, ma: 0, as: 0, sy: 0, wo: 0, wd: 0, rc: 0, de: 0, protocol: 0 })
5136

52-
def to_sddl_text
53-
sddl_text_tokens = []
54-
37+
# Obtain an array of the abbreviated names of permissions that the access mask specifies.
38+
#
39+
# @return Returns nil if the permissions can't be represented as an array of abbreviations.
40+
# @rtype [Array<Symbol>, nil]
41+
def permissions
5542
if (protocol & 0b1111111000000000) != 0 || ma == 1 || as == 1
56-
# if one of these conditions are true, we can't reduce this to a set of flags so dump it as hex
57-
return "0x#{to_binary_s.unpack1('L<').to_s(16).rjust(8, '0')}"
43+
return nil
5844
end
5945

60-
sddl_text_tokens << 'GA' if ga == 1
61-
sddl_text_tokens << 'GR' if gr == 1
62-
sddl_text_tokens << 'GW' if gw == 1
63-
sddl_text_tokens << 'GX' if gx == 1
46+
permissions = []
47+
permissions << :GA if ga == 1
48+
permissions << :GR if gr == 1
49+
permissions << :GW if gw == 1
50+
permissions << :GX if gx == 1
6451

6552
file_access_mask = protocol & 0b000111111111
66-
sddl_text_tokens << 'FA' if file_access_mask == 0b000111111111 && de == 1 && rc == 1 && wd == 1 && wo == 1 && sy == 1
67-
sddl_text_tokens << 'FR' if file_access_mask == 0b000010001001
68-
sddl_text_tokens << 'FW' if file_access_mask == 0b000100010110
69-
sddl_text_tokens << 'FX' if file_access_mask == 0b000010100000
53+
permissions << :FA if file_access_mask == 0b000111111111 && de == 1 && rc == 1 && wd == 1 && wo == 1 && sy == 1
54+
permissions << :FR if file_access_mask == 0b000010001001
55+
permissions << :FW if file_access_mask == 0b000100010110
56+
permissions << :FX if file_access_mask == 0b000010100000
7057

7158
# windows does not reduce registry access flags (i.e. KA, KR, KW) so ignore them here to match it
7259

73-
sddl_text_tokens << 'CC' if (protocol & 0b000000000001) != 0 && !sddl_text_tokens.include?('FA') && !sddl_text_tokens.include?('FR')
74-
sddl_text_tokens << 'DC' if (protocol & 0b000000000010) != 0 && !sddl_text_tokens.include?('FA') && !sddl_text_tokens.include?('FW')
75-
sddl_text_tokens << 'LC' if (protocol & 0b000000000100) != 0 && !sddl_text_tokens.include?('FA') && !sddl_text_tokens.include?('FW')
76-
sddl_text_tokens << 'SW' if (protocol & 0b000000001000) != 0 && !sddl_text_tokens.include?('FA') && !sddl_text_tokens.include?('FR')
77-
sddl_text_tokens << 'RP' if (protocol & 0b000000010000) != 0 && !sddl_text_tokens.include?('FA') && !sddl_text_tokens.include?('FW')
78-
sddl_text_tokens << 'WP' if (protocol & 0b000000100000) != 0 && !sddl_text_tokens.include?('FA') && !sddl_text_tokens.include?('FX')
79-
sddl_text_tokens << 'DT' if (protocol & 0b000001000000) != 0 && !sddl_text_tokens.include?('FA')
80-
sddl_text_tokens << 'LO' if (protocol & 0b000010000000) != 0 && !sddl_text_tokens.include?('FA')
81-
sddl_text_tokens << 'CR' if (protocol & 0b000100000000) != 0 && !sddl_text_tokens.include?('FA')
60+
permissions << :CC if (protocol & 0b000000000001) != 0 && !permissions.include?(:FA) && !permissions.include?(:FR)
61+
permissions << :DC if (protocol & 0b000000000010) != 0 && !permissions.include?(:FA) && !permissions.include?(:FW)
62+
permissions << :LC if (protocol & 0b000000000100) != 0 && !permissions.include?(:FA) && !permissions.include?(:FW)
63+
permissions << :SW if (protocol & 0b000000001000) != 0 && !permissions.include?(:FA) && !permissions.include?(:FR)
64+
permissions << :RP if (protocol & 0b000000010000) != 0 && !permissions.include?(:FA) && !permissions.include?(:FW)
65+
permissions << :WP if (protocol & 0b000000100000) != 0 && !permissions.include?(:FA) && !permissions.include?(:FX)
66+
permissions << :DT if (protocol & 0b000001000000) != 0 && !permissions.include?(:FA)
67+
permissions << :LO if (protocol & 0b000010000000) != 0 && !permissions.include?(:FA)
68+
permissions << :CR if (protocol & 0b000100000000) != 0 && !permissions.include?(:FA)
69+
70+
permissions << :SD if de == 1 && !permissions.include?(:FA)
71+
permissions << :RC if rc == 1 && !permissions.include?(:FA)
72+
permissions << :WD if wd == 1 && !permissions.include?(:FA)
73+
permissions << :WO if wo == 1 && !permissions.include?(:FA)
74+
75+
permissions
76+
end
77+
78+
def to_sddl_text
79+
perms = permissions
80+
81+
if perms.nil?
82+
# if one of these conditions are true, we can't reduce this to a set of flags so dump it as hex
83+
return "0x#{to_binary_s.unpack1('L<').to_s(16).rjust(8, '0')}"
84+
end
8285

83-
sddl_text_tokens << 'SD' if de == 1 && !sddl_text_tokens.include?('FA')
84-
sddl_text_tokens << 'RC' if rc == 1 && !sddl_text_tokens.include?('FA')
85-
sddl_text_tokens << 'WD' if wd == 1 && !sddl_text_tokens.include?('FA')
86-
sddl_text_tokens << 'WO' if wo == 1 && !sddl_text_tokens.include?('FA')
8786

88-
sddl_text_tokens.join('')
87+
permissions.map(&:to_s).join
8988
end
9089

9190
def self.from_sddl_text(sddl_text)
@@ -331,6 +330,43 @@ class MsDtypAceType
331330
def self.name(value)
332331
constants.select { |c| c.upcase == c }.find { |c| const_get(c) == value }
333332
end
333+
334+
def self.alarm?(type)
335+
[
336+
SYSTEM_ALARM_ACE_TYPE,
337+
SYSTEM_ALARM_OBJECT_ACE_TYPE,
338+
SYSTEM_ALARM_CALLBACK_ACE_TYPE,
339+
SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE,
340+
].include? type
341+
end
342+
343+
def self.allowed?(type)
344+
[
345+
ACCESS_ALLOWED_ACE_TYPE,
346+
ACCESS_ALLOWED_COMPOUND_ACE_TYPE,
347+
ACCESS_ALLOWED_OBJECT_ACE_TYPE,
348+
ACCESS_ALLOWED_CALLBACK_ACE_TYPE,
349+
ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE,
350+
].include? type
351+
end
352+
353+
def self.audit?(type)
354+
[
355+
SYSTEM_AUDIT_ACE_TYPE,
356+
SYSTEM_AUDIT_OBJECT_ACE_TYPE,
357+
SYSTEM_AUDIT_CALLBACK_ACE_TYPE,
358+
SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE,
359+
].include? type
360+
end
361+
362+
def self.denied?(type)
363+
[
364+
ACCESS_DENIED_ACE_TYPE,
365+
ACCESS_DENIED_OBJECT_ACE_TYPE,
366+
ACCESS_DENIED_CALLBACK_ACE_TYPE,
367+
ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE,
368+
].include? type
369+
end
334370
end
335371

336372
# [2.4.4.1 ACE_HEADER](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/628ebb1d-c509-4ea0-a10f-77ef97ca4586)

0 commit comments

Comments
 (0)