● Notice //GitHub (@shehzade) is temporarily suspended pending an automated false-positive review. All tools are hosted on this Code Mirror and available on request (contact); GitHub links will return once reinstated.
PUBLIC MIRRORGo v1.0.0

Offline Active Directory database (ntds.dit) parser and BloodHound graph reconstructor in pure Go. Extracts directory objects, group memberships, domain trusts, and binary DACLs from dead-disk ESE database pages and registry hives.

$ git clone https://shehzade.io/repos/ntds-to-bloodhound.git Copy
Source ZIP (246.9 KB) Prebuilt Binaries
Code 21 Commits 1 Releases 5
ntds-to-bloodhound / pkg / ad / model.go
← Back to directory
276 lines · 9.5 KB
Raw
1package ad
2
3import "github.com/shehzade/ntds-to-bloodhound/pkg/acl"
4
5type MemberReference struct {
6 ObjectIdentifier string `json:"ObjectIdentifier"`
7 ObjectType string `json:"ObjectType"`
8}
9
10type TypedPrincipal struct {
11 ObjectIdentifier string `json:"ObjectIdentifier"`
12 ObjectType string `json:"ObjectType"`
13}
14
15type SessionCollection struct {
16 Collected bool `json:"Collected"`
17 FailureReason *string `json:"FailureReason"`
18 Results []interface{} `json:"Results"`
19}
20
21func EmptySessionCollection() SessionCollection {
22 return SessionCollection{
23 Collected: false,
24 FailureReason: nil,
25 Results: make([]interface{}, 0),
26 }
27}
28
29type DomainTrust struct {
30 TargetDomainName string
31 TargetDomainSid string
32 IsTransitive bool
33 TrustDirection int
34 TrustType int
35 SidFilteringEnabled bool
36}
37
38type DomainTrustV4 struct {
39 TargetDomainName string `json:"TargetDomainName"`
40 TargetDomainSid string `json:"TargetDomainSid"`
41 IsTransitive bool `json:"IsTransitive"`
42 TrustDirection int `json:"TrustDirection"`
43 TrustType int `json:"TrustType"`
44 SidFilteringEnabled bool `json:"SidFilteringEnabled"`
45}
46
47type DomainTrustV5 struct {
48 TargetDomainName string `json:"TargetDomainName"`
49 TargetDomainSid string `json:"TargetDomainSid"`
50 IsTransitive bool `json:"IsTransitive"`
51 TrustDirection string `json:"TrustDirection"`
52 TrustType string `json:"TrustType"`
53 SidFilteringEnabled bool `json:"SidFilteringEnabled"`
54}
55
56func (t DomainTrust) DirectionString() string {
57 switch t.TrustDirection {
58 case 0:
59 return "Disabled"
60 case 1:
61 return "Inbound"
62 case 2:
63 return "Outbound"
64 case 3:
65 return "Bidirectional"
66 default:
67 return "Disabled"
68 }
69}
70
71func (t DomainTrust) TypeString() string {
72 switch t.TrustType {
73 case 0:
74 return "ParentChild"
75 case 1:
76 return "CrossLink"
77 case 2:
78 return "Forest"
79 case 3:
80 return "External"
81 default:
82 return "Unknown"
83 }
84}
85
86func (t DomainTrust) ToV4() DomainTrustV4 {
87 return DomainTrustV4{
88 TargetDomainName: t.TargetDomainName,
89 TargetDomainSid: t.TargetDomainSid,
90 IsTransitive: t.IsTransitive,
91 TrustDirection: t.TrustDirection,
92 TrustType: t.TrustType,
93 SidFilteringEnabled: t.SidFilteringEnabled,
94 }
95}
96
97func (t DomainTrust) ToV5() DomainTrustV5 {
98 return DomainTrustV5{
99 TargetDomainName: t.TargetDomainName,
100 TargetDomainSid: t.TargetDomainSid,
101 IsTransitive: t.IsTransitive,
102 TrustDirection: t.DirectionString(),
103 TrustType: t.TypeString(),
104 SidFilteringEnabled: t.SidFilteringEnabled,
105 }
106}
107
108type UserObject struct {
109 ObjectIdentifier string `json:"ObjectIdentifier"`
110 PrimaryGroupSID string `json:"PrimaryGroupSID,omitempty"`
111 AllowedToDelegate []TypedPrincipal `json:"AllowedToDelegate"`
112 SPNTargets []interface{} `json:"SPNTargets"`
113 HasSIDHistory []TypedPrincipal `json:"HasSIDHistory"`
114 Aces []acl.Ace `json:"Aces"`
115 IsACLProtected bool `json:"IsACLProtected"`
116 IsDeleted bool `json:"IsDeleted"`
117 Properties map[string]interface{} `json:"Properties"`
118 DNT uint64 `json:"-"`
119 PDNT uint64 `json:"-"`
120 NTHash string `json:"-"`
121 LMHash string `json:"-"`
122 RawDelegateTargets []string `json:"-"`
123 RawSIDHistory []string `json:"-"`
124}
125
126type GroupObject struct {
127 ObjectIdentifier string `json:"ObjectIdentifier"`
128 Members []MemberReference `json:"Members"`
129 Aces []acl.Ace `json:"Aces"`
130 IsACLProtected bool `json:"IsACLProtected"`
131 IsDeleted bool `json:"IsDeleted"`
132 Properties map[string]interface{} `json:"Properties"`
133 DNT uint64 `json:"-"`
134 PDNT uint64 `json:"-"`
135 Synthetic bool `json:"-"`
136}
137
138type ComputerObject struct {
139 ObjectIdentifier string `json:"ObjectIdentifier"`
140 PrimaryGroupSID string `json:"PrimaryGroupSID,omitempty"`
141 AllowedToDelegate []TypedPrincipal `json:"AllowedToDelegate"`
142 AllowedToAct []TypedPrincipal `json:"AllowedToAct"`
143 HasSIDHistory []TypedPrincipal `json:"HasSIDHistory"`
144 DumpSMSAPassword []TypedPrincipal `json:"DumpSMSAPassword"`
145 Sessions SessionCollection `json:"Sessions"`
146 PrivilegedSessions SessionCollection `json:"PrivilegedSessions"`
147 RegistrySessions SessionCollection `json:"RegistrySessions"`
148 LocalGroups []interface{} `json:"LocalGroups"`
149 UserRights []interface{} `json:"UserRights"`
150 Aces []acl.Ace `json:"Aces"`
151 IsACLProtected bool `json:"IsACLProtected"`
152 IsDeleted bool `json:"IsDeleted"`
153 IsDC bool `json:"IsDC"`
154 Status *string `json:"Status"`
155 Properties map[string]interface{} `json:"Properties"`
156 NTHash string `json:"-"`
157 LMHash string `json:"-"`
158 DNT uint64 `json:"-"`
159 PDNT uint64 `json:"-"`
160 RawDelegateTargets []string `json:"-"`
161 RawAllowedToAct []string `json:"-"`
162 RawSIDHistory []string `json:"-"`
163}
164
165type DomainObject struct {
166 ObjectIdentifier string `json:"ObjectIdentifier"`
167 ChildObjects []TypedPrincipal `json:"ChildObjects"`
168 Trusts []DomainTrust `json:"Trusts"`
169 Links []interface{} `json:"Links"`
170 Aces []acl.Ace `json:"Aces"`
171 IsACLProtected bool `json:"IsACLProtected"`
172 IsDeleted bool `json:"IsDeleted"`
173 Properties map[string]interface{} `json:"Properties"`
174 DNT uint64 `json:"-"`
175}
176
177type DomainObjectV4 struct {
178 ObjectIdentifier string `json:"ObjectIdentifier"`
179 ChildObjects []TypedPrincipal `json:"ChildObjects"`
180 Trusts []DomainTrustV4 `json:"Trusts"`
181 Links []interface{} `json:"Links"`
182 Aces []acl.Ace `json:"Aces"`
183 IsACLProtected bool `json:"IsACLProtected"`
184 IsDeleted bool `json:"IsDeleted"`
185 Properties map[string]interface{} `json:"Properties"`
186}
187
188type DomainObjectV5 struct {
189 ObjectIdentifier string `json:"ObjectIdentifier"`
190 ChildObjects []TypedPrincipal `json:"ChildObjects"`
191 Trusts []DomainTrustV5 `json:"Trusts"`
192 Links []interface{} `json:"Links"`
193 Aces []acl.Ace `json:"Aces"`
194 IsACLProtected bool `json:"IsACLProtected"`
195 IsDeleted bool `json:"IsDeleted"`
196 Properties map[string]interface{} `json:"Properties"`
197}
198
199func (d *DomainObject) ToV4() DomainObjectV4 {
200 trusts := make([]DomainTrustV4, len(d.Trusts))
201 for i, t := range d.Trusts {
202 trusts[i] = t.ToV4()
203 }
204 return DomainObjectV4{
205 ObjectIdentifier: d.ObjectIdentifier,
206 ChildObjects: d.ChildObjects,
207 Trusts: trusts,
208 Links: d.Links,
209 Aces: d.Aces,
210 IsACLProtected: d.IsACLProtected,
211 IsDeleted: d.IsDeleted,
212 Properties: d.Properties,
213 }
214}
215
216func (d *DomainObject) ToV5() DomainObjectV5 {
217 trusts := make([]DomainTrustV5, len(d.Trusts))
218 for i, t := range d.Trusts {
219 trusts[i] = t.ToV5()
220 }
221 return DomainObjectV5{
222 ObjectIdentifier: d.ObjectIdentifier,
223 ChildObjects: d.ChildObjects,
224 Trusts: trusts,
225 Links: d.Links,
226 Aces: d.Aces,
227 IsACLProtected: d.IsACLProtected,
228 IsDeleted: d.IsDeleted,
229 Properties: d.Properties,
230 }
231}
232
233type OUObject struct {
234 ObjectIdentifier string `json:"ObjectIdentifier"`
235 ChildObjects []TypedPrincipal `json:"ChildObjects"`
236 Links []interface{} `json:"Links"`
237 Aces []acl.Ace `json:"Aces"`
238 IsACLProtected bool `json:"IsACLProtected"`
239 IsDeleted bool `json:"IsDeleted"`
240 Properties map[string]interface{} `json:"Properties"`
241 DNT uint64 `json:"-"`
242 PDNT uint64 `json:"-"`
243}
244
245type ADSnapshot struct {
246 DomainName string
247 DomainSID string
248 Users []*UserObject
249 Groups []*GroupObject
250 Computers []*ComputerObject
251 Domains []*DomainObject
252 OUs []*OUObject
253
254 UsersBySID map[string]*UserObject
255 GroupsBySID map[string]*GroupObject
256 ComputersBySID map[string]*ComputerObject
257 OUsByGUID map[string]*OUObject
258 ObjectsByDNT map[uint64]TypedPrincipal
259 PDNTByDNT map[uint64]uint64
260}
261
262func NewADSnapshot() *ADSnapshot {
263 return &ADSnapshot{
264 Users: make([]*UserObject, 0),
265 Groups: make([]*GroupObject, 0),
266 Computers: make([]*ComputerObject, 0),
267 Domains: make([]*DomainObject, 0),
268 OUs: make([]*OUObject, 0),
269 UsersBySID: make(map[string]*UserObject),
270 GroupsBySID: make(map[string]*GroupObject),
271 ComputersBySID: make(map[string]*ComputerObject),
272 OUsByGUID: make(map[string]*OUObject),
273 ObjectsByDNT: make(map[uint64]TypedPrincipal),
274 PDNTByDNT: make(map[uint64]uint64),
275 }
276}