Skip to content

Commit

Permalink
Many, many internal changes
Browse files Browse the repository at this point in the history
Got rid of Slice() on AttributeValues, fixed race in edge statistics, fixed attribute value bug in Absorb(), Moved some Object methods to Edges(direction), changed Attribute type from int16 to uint16, AttributeValueMap supports pre-allocation if we switch to a map type that supports it, EdgeConnections points to IDs not Objects, created a weak ID -> Object slice tracker, made everything thread safe all the time (LOL, at least that's the ambition), added cache for AttributeValueToIndex to minimize ToLower calls, added Iterate and IterateParallel to Objects,
  • Loading branch information
lkarlslund committed Oct 25, 2022
1 parent 0fe3ebb commit ffc9f9d
Show file tree
Hide file tree
Showing 27 changed files with 505 additions and 495 deletions.
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ require (
github.com/OneOfOne/xxhash v1.2.8
github.com/SaveTheRbtz/generic-sync-map-go v0.0.0-20220414055132-a37292614db8
github.com/Showmax/go-fqdn v1.0.0
github.com/absfs/gofs v0.0.0-20210326223041-415ec8094056
github.com/absfs/osfs v0.0.0-20210816191758-403afc5396f8
github.com/amidaware/taskmaster v0.0.0-20220111015025-c9cd178bbbf2
github.com/antchfx/xmlquery v1.3.12
github.com/gin-gonic/gin v1.7.7
Expand Down Expand Up @@ -45,7 +43,6 @@ require (
atomicgo.dev/cursor v0.1.1 // indirect
atomicgo.dev/keyboard v0.2.8 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
github.com/absfs/absfs v0.0.0-20200602175035-e49edc9fef15 // indirect
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 // indirect
github.com/antchfx/xpath v1.2.1 // indirect
github.com/asergeyev/nradix v0.0.0-20170505151046-3872ab85bb56 // indirect
Expand Down Expand Up @@ -108,11 +105,14 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
)

require github.com/felixge/fgtrace v0.2.0
require (
github.com/akyoto/cache v1.0.6
github.com/elastic/go-windows v1.0.1
github.com/felixge/fgtrace v0.2.0
)

require (
github.com/DataDog/gostackparse v0.6.0 // indirect
github.com/elastic/go-windows v1.0.1 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/tools v0.1.12 // indirect
)
58 changes: 5 additions & 53 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion modules/analyze/webservicefuncs.go
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ func analysisfuncs(ws *webservice) {

var pwnlinks int
for _, object := range ws.Objs.Slice() {
pwnlinks += object.EdgeCount(engine.Out)
pwnlinks += object.Edges(engine.Out).Len()
}
result.Statistics["Total"] = len(ws.Objs.Slice())
result.Statistics["PwnConnections"] = pwnlinks
Expand Down
2 changes: 1 addition & 1 deletion modules/engine/analyzeobjects.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func AnalyzeObjects(opts AnalyzeObjectsOptions) (pg Graph) {

// Iterate over ever outgoing pwn
// This is not efficient, but we sort the pwnlist first
object.EdgeIterator(ec, func(target *Object, eb EdgeBitmap) bool {
object.Edges(ec).Range(func(target *Object, eb EdgeBitmap) bool {
// If this is not a chosen method, skip it
detectededges := eb.Intersect(detectedges)

Expand Down
19 changes: 15 additions & 4 deletions modules/engine/analyzepaths.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ func AnalyzePaths(start, end *Object, obs *Objects, lookforedges EdgeBitmap, min
dist := make(map[*Object]uint32)
prev := make(map[*Object]*Object)

opeb := make(map[ObjectPair]EdgeBitmap)

q := heapqueue{}
// q := queue{}

Expand All @@ -166,7 +168,7 @@ func AnalyzePaths(start, end *Object, obs *Objects, lookforedges EdgeBitmap, min

visited[source] = struct{}{}

source.EdgeIterator(Out, func(target *Object, edges EdgeBitmap) bool {
source.Edges(Out).Range(func(target *Object, edges EdgeBitmap) bool {
if _, found := visited[target]; !found {
// If this is not a chosen method, skip it
detectededges := edges.Intersect(lookforedges)
Expand All @@ -182,6 +184,12 @@ func AnalyzePaths(start, end *Object, obs *Objects, lookforedges EdgeBitmap, min
return true //continue
}

// Save for later
opeb[ObjectPair{
Source: source,
Target: target,
}] = edges

weight := uint32(101 - prob)

sdist, sfound := dist[source]
Expand Down Expand Up @@ -225,9 +233,12 @@ func AnalyzePaths(start, end *Object, obs *Objects, lookforedges EdgeBitmap, min
})
result.Connections = append(result.Connections,
GraphEdge{
Source: prenode,
Target: curnode,
EdgeBitmap: prenode.Edge(Out, curnode),
Source: prenode,
Target: curnode,
EdgeBitmap: opeb[ObjectPair{
Source: prenode,
Target: curnode,
}],
})
if prenode == start {
break
Expand Down
25 changes: 0 additions & 25 deletions modules/engine/attributenode.go

This file was deleted.

12 changes: 6 additions & 6 deletions modules/engine/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ type AttributeGetFunc func(o *Object, a Attribute) (v AttributeValues, found boo
type AttributeSetFunc func(o *Object, a Attribute, v AttributeValues) error

type attributeinfo struct {
onset AttributeSetFunc
onget AttributeGetFunc
name string
tags []string
atype AttributeType
single bool // If true, this attribute can not have multiple values
unique bool // Doing a Find on this attribute will return multiple results
merge bool // If true, objects can be merged on this attribute
hidden bool // If true this does not show up in the list of attributes
onset AttributeSetFunc
onget AttributeGetFunc
}

type AttributeType uint8
Expand All @@ -49,7 +49,7 @@ var mergeapprovers []mergeapproverinfo
var attributenums []attributeinfo

var (
NonExistingAttribute = Attribute(-1)
NonExistingAttribute = ^Attribute(0)

DistinguishedName = NewAttribute("distinguishedName").Single().Unique()
ObjectClass = NewAttribute("objectClass")
Expand Down Expand Up @@ -101,12 +101,12 @@ var (
MetaLAPSInstalled = NewAttribute("_haslaps")
)

type Attribute int16
type Attribute uint16

var attributemutex sync.RWMutex

func NewAttribute(name string) Attribute {
if name[len(name)-1] >= '0' && name[len(name)-1] <= '9' && strings.Index(name, ";") != -1 {
if name[len(name)-1] >= '0' && name[len(name)-1] <= '9' && strings.Contains(name, ";") {
if !strings.HasPrefix(name, "member;") {
ui.Debug().Msgf("Incomplete data detected in attribute %v", name)
}
Expand Down Expand Up @@ -150,7 +150,7 @@ func NewAttribute(name string) Attribute {
}

func (a Attribute) String() string {
if a == -1 {
if a == NonExistingAttribute {
return "N/A"
}
return attributenums[a].name
Expand Down
32 changes: 1 addition & 31 deletions modules/engine/attributevalue.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"time"

"github.com/gofrs/uuid"
"github.com/lkarlslund/adalanche/modules/ui"
"github.com/lkarlslund/adalanche/modules/windowssecurity"
)

Expand Down Expand Up @@ -71,7 +70,6 @@ type AttributeAndValues struct {
type AttributeValues interface {
First() AttributeValue
Iterate(func(val AttributeValue) bool)
Slice() []AttributeValue
StringSlice() []string
Len() int
}
Expand Down Expand Up @@ -112,18 +110,10 @@ func (avs AttributeValueSlice) Iterate(it func(val AttributeValue) bool) {
}
}

func (avs AttributeValueSlice) Slice() []AttributeValue {
return avs
}

func (avs AttributeValueSlice) StringSlice() []string {
result := make([]string, len(avs))
for i := 0; i < len(avs); i++ {
if avs[i] == nil {
ui.Warn().Msg("Encountered NIL value")
} else {
result[i] = avs[i].String()
}
result[i] = avs[i].String()
}
return result
}
Expand All @@ -148,11 +138,6 @@ func (avo AttributeValueOne) Len() int {
return 1
}

// This is really killing us
func (avo AttributeValueOne) Slice() []AttributeValue {
return AttributeValueSlice{avo.Value}
}

func (avo AttributeValueOne) StringSlice() []string {
return []string{avo.Value.String()}
}
Expand All @@ -161,7 +146,6 @@ type AttributeValue interface {
String() string
Raw() interface{}
IsZero() bool
// Compare(other AttributeValue) bool
}

type AttributeValueObject struct {
Expand Down Expand Up @@ -283,17 +267,3 @@ func (as AttributeValueGUID) Raw() interface{} {
func (as AttributeValueGUID) IsZero() bool {
return uuid.UUID(as).IsNil()
}

// type AttributeValueFiletime []byte

// func (as AttributeValueFiletime) String() string {
// return string(as)
// }

// func (as AttributeValueFiletime) Raw() interface{} {
// return string(as)
// }

// func (as AttributeValueFiletime) AsTime() time.Time {
// return nil
// }
71 changes: 50 additions & 21 deletions modules/engine/attributevaluemap.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,67 @@
package engine

import (
gsync "github.com/SaveTheRbtz/generic-sync-map-go"
)

type AttributeValueMap struct {
m map[Attribute]AttributeValues
// m *xsync.MapOf[Attribute, AttributeValues]
// m map[Attribute]AttributeValues
// m *haxmap.Map[Attribute, AttributeValues]
m gsync.MapOf[Attribute, AttributeValues]
}

func (avm *AttributeValueMap) init(preloadAttributes int) {
// avm.m = haxmap.New[Attribute, AttributeValues](1)
// avm.m = make(map[Attribute]AttributeValues)
// avm.m = xsync.NewTypedMapOf[Attribute, AttributeValues](func(a Attribute) uint64 {
// return uint64(a)
// })
}

func (avm AttributeValueMap) Get(a Attribute) (av AttributeValues, found bool) {
if avm.m == nil {
return nil, false
}
av, found = avm.m[a]
func (avm *AttributeValueMap) Get(a Attribute) (av AttributeValues, found bool) {
// av, found = avm.m.Get(a)
// if found && av.Len() == 0 {
// found = false // workaround until haxmap performance for deletes is fixed
// }
// av, found = avm.m[a]
av, found = avm.m.Load(a)
return
}

func (avm *AttributeValueMap) Set(a Attribute, av AttributeValues) {
if avm.m == nil {
avm.m = make(map[Attribute]AttributeValues)
}
avm.m[a] = av
// avm.m.Set(a, av)
// avm.m[a] = av
avm.m.Store(a, av)
}

func (avm AttributeValueMap) Len() int {
return len(avm.m)
func (avm *AttributeValueMap) Len() int {
var count int
avm.m.Range(func(u Attribute, av AttributeValues) bool {
// if av.Len() > 0 {
count++
// }
return true
})
return count
// return len(avm.m)
// return avm.m.Size()
}

func (avm *AttributeValueMap) Clear(a Attribute) {
if avm.m != nil {
delete(avm.m, a)
}
// avm.m.Set(a, NoValues{}) // Workaround until haxmap performance
// delete(avm.m, a)
avm.m.Delete(a)
}

func (avm AttributeValueMap) Iterate(f func(attr Attribute, values AttributeValues) bool) {
for attr, values := range avm.m {
if !f(attr, values) {
break
}
}
func (avm *AttributeValueMap) Iterate(f func(attr Attribute, values AttributeValues) bool) {
avm.m.Range(f)
// for a, av := range avm.m {
// if !f(a, av) {
// break
// }
// }
// avm.m.Range(func(a Attribute, av AttributeValues) bool {
// return f(a, av)
// })
}
Loading

0 comments on commit ffc9f9d

Please sign in to comment.