Skip to content

Commit

Permalink
BHCEupload commit
Browse files Browse the repository at this point in the history
  • Loading branch information
olafhartong committed Feb 20, 2024
0 parents commit f2ecd8d
Show file tree
Hide file tree
Showing 7 changed files with 448 additions and 0 deletions.
5 changes: 5 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Bloodhound CE JSON Uploader

Simple binary to upload files over the API to BloodHound CE.

## Usage

```bash
./BHCEupload -tokenid <tokenid> -tokenkey <tokenkey> -dir <dir> -url <url>
```

By default the url is set to localhost:8080, and the dir is set to the current directory.
For large environments, with collections above 15-20Gigs, it is recommended to split the files for upload into smaller chunks before uploading upload Otherwise the server will time out.

Additionally, make sure to have enough RAM or SWAP space to handle the large files. Since the uploads need to be signed they'll need to be loaded into memory before being sent to the server.

```markdown
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⣶⣾⠿⠶⢶⣶⣤⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⡿⠟⠋⠉⠀⠀⠀⠀⠀⠀⠈⠉⠉⠻⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⠟⠉⠀⠀⣠⣤⣶⣷⢀⡀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢀⣼⡟⠁⠀⠀⠀⠘⠛⠁⠀⣀⣼⣿⣦⠀⠀⠀⠀⠀⠙⣦⣮⣹⡆⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣠⣾⡿⠀⠀⠀⠀⠀⠀⠀⠰⢿⡿⠿⠟⠛⠉⠀⠀⠀⠀⠀⠈⠙⠛⠳⠶⣤⣄⡀⠀⠀
⠀⠀⠀⠀⢀⣾⡿⠛⢀⡀⠀⠀⢀⣠⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⠚⣉⣉⣉⣙⣧⠀
⠀⠀⠀⠀⣼⠏⠀⠀⠀⣷⠀⣴⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⣠⠀⠀⠀⣿⠀⢿⣿⣿⣿⣿⣿⠀
⠀⠀⠀⢀⡿⠀⠀⠀⠀⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣯⣤⡾⠃⠀⠀⠀⠈⠻⠶⣾⣿⣿⣿⣿⠄
⠀⠀⠀⣸⡇⠀⠀⠀⢰⣿⣿⠀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⡿⠀
⠀⠀⣰⡿⠀⠀⠀⠀⠈⢹⣿⡼⠁⠀⠀⠀⠀⠀⢠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣾⣿⣿⠟⠁⠀
⠀⣰⡿⢡⠂⠀⠀⠀⠀⠀⣿⣇⣰⣂⣠⠀⠀⠀⣟⣀⣀⠀⠀⠀⠀⠀⣠⣤⠶⠿⠿⠿⠛⠿⣧⠀⠀⠀
⣰⡿⢠⣏⡔⠀⠀⠀⠀⠀⢿⣿⣿⣿⡇⢠⡀⠀⢿⣿⣿⣿⣍⣙⠛⢻⣏⣤⠾⣦⡀⠀⠀⠀⢹⡇⠀⠀
⣿⣷⣿⣿⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣧⠀⠈⠻⢿⣿⣿⣿⣿⣿⣿⡿⣶⣾⣿⣶⣦⣴⡟⠁⠀⠀
⠹⢿⣿⣿⡇⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⡏⠀⠀⠀⠀⠈⠉⠉⠉⠙⠿⠟⠁⠈⠙⠛⢻⡿⠀⠀⠀⠀
⠀⠀⠙⠻⣧⡀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⠋⠀⠀⡴⣾⣿⣷⣶⣤⣤⣤⣤⣤⣶⠤⠶⠛⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠙⢿⣶⣤⣤⣤⣴⣿⣿⣿⣿⠃⠀⠀⠀⢰⡟⢿⣿⣿⡿⠻⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠉⠙⠛⠛⠋⠁⠙⢿⣿⠀⢠⠄⠀⡼⠀⢸⣿⢹⡇⠀⢹⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣶⡟⣸⠁⠃⠀⣿⣿⡀⠧⠀⣸⣿⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣟⣴⣿⠀⠀⠀⣿⠹⡇⠀⢠⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠛⣻⡿⢿⣆⢠⣿⠀⠁⢀⣾⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠾⠋⠁⢈⣿⣿⣿⡇⠀⣾⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⡿⠋⠉⢿⣾⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⠀⠈⠿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
BloodhoundCE json uploader⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Please provide all required flags: -tokenid, -tokenkey
OPTIONAL: -url, -dir, -h for help
```
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module BHCEupload

go 1.22
30 changes: 30 additions & 0 deletions internal/banner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package internal

import "fmt"

func Banner() {
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⣶⣾⠿⠶⢶⣶⣤⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⡿⠟⠋⠉⠀⠀⠀⠀⠀⠀⠈⠉⠉⠻⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⠟⠉⠀⠀⣠⣤⣶⣷⢀⡀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⢀⣼⡟⠁⠀⠀⠀⠘⠛⠁⠀⣀⣼⣿⣦⠀⠀⠀⠀⠀⠙⣦⣮⣹⡆⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⣠⣾⡿⠀⠀⠀⠀⠀⠀⠀⠰⢿⡿⠿⠟⠛⠉⠀⠀⠀⠀⠀⠈⠙⠛⠳⠶⣤⣄⡀⠀⠀")
fmt.Println("⠀⠀⠀⠀⢀⣾⡿⠛⢀⡀⠀⠀⢀⣠⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⠚⣉⣉⣉⣙⣧⠀")
fmt.Println("⠀⠀⠀⠀⣼⠏⠀⠀⠀⣷⠀⣴⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⣠⠀⠀⠀⣿⠀⢿⣿⣿⣿⣿⣿⠀")
fmt.Println("⠀⠀⠀⢀⡿⠀⠀⠀⠀⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣯⣤⡾⠃⠀⠀⠀⠈⠻⠶⣾⣿⣿⣿⣿⠄")
fmt.Println("⠀⠀⠀⣸⡇⠀⠀⠀⢰⣿⣿⠀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⡿⠀")
fmt.Println("⠀⠀⣰⡿⠀⠀⠀⠀⠈⢹⣿⡼⠁⠀⠀⠀⠀⠀⢠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣾⣿⣿⠟⠁⠀")
fmt.Println("⠀⣰⡿⢡⠂⠀⠀⠀⠀⠀⣿⣇⣰⣂⣠⠀⠀⠀⣟⣀⣀⠀⠀⠀⠀⠀⣠⣤⠶⠿⠿⠿⠛⠿⣧⠀⠀⠀")
fmt.Println("⣰⡿⢠⣏⡔⠀⠀⠀⠀⠀⢿⣿⣿⣿⡇⢠⡀⠀⢿⣿⣿⣿⣍⣙⠛⢻⣏⣤⠾⣦⡀⠀⠀⠀⢹⡇⠀⠀")
fmt.Println("⣿⣷⣿⣿⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣧⠀⠈⠻⢿⣿⣿⣿⣿⣿⣿⡿⣶⣾⣿⣶⣦⣴⡟⠁⠀⠀")
fmt.Println("⠹⢿⣿⣿⡇⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⡏⠀⠀⠀⠀⠈⠉⠉⠉⠙⠿⠟⠁⠈⠙⠛⢻⡿⠀⠀⠀⠀")
fmt.Println("⠀⠀⠙⠻⣧⡀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⠋⠀⠀⡴⣾⣿⣷⣶⣤⣤⣤⣤⣤⣶⠤⠶⠛⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠙⢿⣶⣤⣤⣤⣴⣿⣿⣿⣿⠃⠀⠀⠀⢰⡟⢿⣿⣿⡿⠻⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠉⠙⠛⠛⠋⠁⠙⢿⣿⠀⢠⠄⠀⡼⠀⢸⣿⢹⡇⠀⢹⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣶⡟⣸⠁⠃⠀⣿⣿⡀⠧⠀⣸⣿⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣟⣴⣿⠀⠀⠀⣿⠹⡇⠀⢠⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠛⣻⡿⢿⣆⢠⣿⠀⠁⢀⣾⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠾⠋⠁⢈⣿⣿⣿⡇⠀⣾⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⡿⠋⠉⢿⣾⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⠀⠈⠿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀")
fmt.Println("BloodhoundCE json uploader⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀")
}
184 changes: 184 additions & 0 deletions internal/bh_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package internal

import "encoding/json"

// This file was created based on the following two sources:
// https://github.com/SpecterOps/BloodHound/blob/b3fb3b79334fbb3d4ad8c5f025c89b7f8a92c4da/packages/go/ein/incoming_models.go#L88
// https://github.com/SpecterOps/BloodHound/blob/b3fb3b79334fbb3d4ad8c5f025c89b7f8a92c4da/cmd/api/src/daemons/datapipe/models.go#L28

type DataWrapper struct {
Metadata Metadata `json:"meta"`
Payload json.RawMessage `json:"data"`
}

type Metadata struct {
Type DataType `json:"type"`
Methods CollectionMethod `json:"methods"`
Version int `json:"version"`
}

type DataType string

const (
DataTypeSession DataType = "sessions"
DataTypeUser DataType = "users"
DataTypeGroup DataType = "groups"
DataTypeComputer DataType = "computers"
DataTypeGPO DataType = "gpos"
DataTypeOU DataType = "ous"
DataTypeDomain DataType = "domains"
DataTypeRemoved DataType = "deleted"
DataTypeContainer DataType = "containers"
DataTypeLocalGroups DataType = "localgroups"
DataTypeAzure DataType = "azure"
)

type CollectionMethod uint64

const (
CollectionMethodGroup CollectionMethod = 1
CollectionMethodLocalAdmin CollectionMethod = 1 << 1
CollectionMethodGPOLocalGroup CollectionMethod = 1 << 2
CollectionMethodSession CollectionMethod = 1 << 3
CollectionMethodLoggedOn CollectionMethod = 1 << 4
CollectionMethodTrusts CollectionMethod = 1 << 5
CollectionMethodACL CollectionMethod = 1 << 6
CollectionMethodContainer CollectionMethod = 1 << 7
CollectionMethodRDP CollectionMethod = 1 << 8
CollectionMethodObjectProps CollectionMethod = 1 << 9
CollectionMethodSessionLoop CollectionMethod = 1 << 10
CollectionMethodLoggedOnLoop CollectionMethod = 1 << 11
CollectionMethodDCOM CollectionMethod = 1 << 12
CollectionMethodSPNTargets CollectionMethod = 1 << 13
CollectionMethodPSRemote CollectionMethod = 1 << 14
)

type TypedPrincipal struct {
ObjectIdentifier string
ObjectType string
}

type ACE struct {
PrincipalSID string
PrincipalType string
RightName string
IsInherited bool
}

type SPNTarget struct {
ComputerSID string
Port int
Service string
}

type IngestBase struct {
ObjectIdentifier string
Properties map[string]any
Aces []ACE
IsDeleted bool
IsACLProtected bool
ContainedBy TypedPrincipal
}

type GPO IngestBase

type Session struct {
ComputerSID string
UserSID string
LogonType int
}

type Group struct {
IngestBase
Members []TypedPrincipal
}

type User struct {
IngestBase
AllowedToDelegate []TypedPrincipal
SPNTargets []SPNTarget
PrimaryGroupSID string
HasSIDHistory []TypedPrincipal
}

type Container struct {
IngestBase
ChildObjects []TypedPrincipal
}

type Trust struct {
TargetDomainSid string
IsTransitive bool
TrustDirection string
TrustType string
SidFilteringEnabled bool
TargetDomainName string
}

type GPLink struct {
Guid string
IsEnforced bool
}

type Domain struct {
IngestBase
ChildObjects []TypedPrincipal
Trusts []Trust
Links []GPLink
}

type SessionAPIResult struct {
APIResult
Results []Session
}

type ComputerStatus struct {
Connectable bool
Error string
}

type APIResult struct {
Collected bool
FailureReason string
}

type NamedPrincipal struct {
ObjectIdentifier string
PrincipalName string
}

type LocalGroupAPIResult struct {
APIResult
Results []TypedPrincipal
LocalNames []NamedPrincipal
Name string
ObjectIdentifier string
}

type UserRightsAssignmentAPIResult struct {
APIResult
Results []TypedPrincipal
LocalNames []NamedPrincipal
Privilege string
}

type Computer struct {
IngestBase
PrimaryGroupSID string
AllowedToDelegate []TypedPrincipal
AllowedToAct []TypedPrincipal
DumpSMSAPassword []TypedPrincipal
Sessions SessionAPIResult
PrivilegedSessions SessionAPIResult
RegistrySessions SessionAPIResult
LocalGroups []LocalGroupAPIResult
UserRights []UserRightsAssignmentAPIResult
Status ComputerStatus
HasSIDHistory []TypedPrincipal
}

type OU struct {
IngestBase
ChildObjects []TypedPrincipal
Links []GPLink
}
7 changes: 7 additions & 0 deletions internal/credentials.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package internal

type Credentials struct {
BHUrl string `config:"bloodhound.url"`
BHTokenID string `config:"bloodhound.tokenID"`
BHTokenKey string `config:"bloodhound.tokenKey"`
}
Loading

0 comments on commit f2ecd8d

Please sign in to comment.