[SHEHZADE//ABDULLAH ANSARI]
Red Team Consultant @ Google | MS in Cybersecurity @ NYU
● 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
68 lines · 1.0 KB
| 1 | package ad |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "strings" |
| 6 | ) |
| 7 | |
| 8 | type TreeNode struct { |
| 9 | DNT uint64 |
| 10 | PDNT uint64 |
| 11 | RDN string |
| 12 | Prefix string |
| 13 | } |
| 14 | |
| 15 | type Tree struct { |
| 16 | nodes map[uint64]*TreeNode |
| 17 | } |
| 18 | |
| 19 | func NewTree() *Tree { |
| 20 | return &Tree{ |
| 21 | nodes: make(map[uint64]*TreeNode), |
| 22 | } |
| 23 | } |
| 24 | |
| 25 | func (t *Tree) AddNode(dnt, pdnt uint64, rdn, prefix string) { |
| 26 | if prefix == "" { |
| 27 | prefix = "CN=" |
| 28 | } |
| 29 | t.nodes[dnt] = &TreeNode{ |
| 30 | DNT: dnt, |
| 31 | PDNT: pdnt, |
| 32 | RDN: rdn, |
| 33 | Prefix: prefix, |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | func (t *Tree) GetRDN(dnt uint64) string { |
| 38 | if n, ok := t.nodes[dnt]; ok { |
| 39 | return n.RDN |
| 40 | } |
| 41 | return "" |
| 42 | } |
| 43 | |
| 44 | func (t *Tree) ResolveDN(startDNT uint64) string { |
| 45 | curr := startDNT |
| 46 | var parts []string |
| 47 | visited := make(map[uint64]bool) |
| 48 | |
| 49 | for curr != 0 && curr != 2 { |
| 50 | if visited[curr] { |
| 51 | break |
| 52 | } |
| 53 | visited[curr] = true |
| 54 | |
| 55 | node, exists := t.nodes[curr] |
| 56 | if !exists || node.RDN == "" { |
| 57 | break |
| 58 | } |
| 59 | |
| 60 | parts = append(parts, fmt.Sprintf("%s%s", node.Prefix, node.RDN)) |
| 61 | if node.PDNT == 0 || node.PDNT == curr { |
| 62 | break |
| 63 | } |
| 64 | curr = node.PDNT |
| 65 | } |
| 66 | |
| 67 | return strings.Join(parts, ",") |
| 68 | } |