[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
66 lines · 1.2 KB
| 1 | package ese |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "io" |
| 6 | "os" |
| 7 | |
| 8 | "github.com/Velocidex/ordereddict" |
| 9 | "www.velocidex.com/golang/go-ese/parser" |
| 10 | ) |
| 11 | |
| 12 | type DB struct { |
| 13 | file *os.File |
| 14 | ctx *parser.ESEContext |
| 15 | catalog *parser.Catalog |
| 16 | } |
| 17 | |
| 18 | func OpenDB(path string) (*DB, error) { |
| 19 | f, err := os.Open(path) |
| 20 | if err != nil { |
| 21 | return nil, fmt.Errorf("failed to open ESE file %s: %w", path, err) |
| 22 | } |
| 23 | |
| 24 | ctx, err := parser.NewESEContext(f) |
| 25 | if err != nil { |
| 26 | f.Close() |
| 27 | return nil, fmt.Errorf("failed to initialize ESE context: %w", err) |
| 28 | } |
| 29 | |
| 30 | catalog, err := parser.ReadCatalog(ctx) |
| 31 | if err != nil { |
| 32 | f.Close() |
| 33 | return nil, fmt.Errorf("failed to read ESE catalog: %w", err) |
| 34 | } |
| 35 | |
| 36 | return &DB{ |
| 37 | file: f, |
| 38 | ctx: ctx, |
| 39 | catalog: catalog, |
| 40 | }, nil |
| 41 | } |
| 42 | |
| 43 | func (db *DB) Close() error { |
| 44 | if db.file != nil { |
| 45 | return db.file.Close() |
| 46 | } |
| 47 | return nil |
| 48 | } |
| 49 | |
| 50 | func (db *DB) TableNames() []string { |
| 51 | if db.catalog == nil || db.catalog.Tables == nil { |
| 52 | return nil |
| 53 | } |
| 54 | return db.catalog.Tables.Keys() |
| 55 | } |
| 56 | |
| 57 | func (db *DB) StreamTable(name string, cb func(row *ordereddict.Dict) error) error { |
| 58 | if db.catalog == nil { |
| 59 | return fmt.Errorf("database catalog is nil") |
| 60 | } |
| 61 | return db.catalog.DumpTable(name, cb) |
| 62 | } |
| 63 | |
| 64 | func (db *DB) Reader() io.ReaderAt { |
| 65 | return db.file |
| 66 | } |