Skip to content

Commit

Permalink
Refactor to support tracking builder state
Browse files Browse the repository at this point in the history
  • Loading branch information
moloch-- committed Oct 15, 2022
1 parent 3160c8f commit dbee282
Show file tree
Hide file tree
Showing 12 changed files with 1,274 additions and 854 deletions.
321 changes: 250 additions & 71 deletions protobuf/clientpb/client.pb.go

Large diffs are not rendered by default.

16 changes: 15 additions & 1 deletion protobuf/clientpb/client.proto
Expand Up @@ -668,4 +668,18 @@ message ShellcodeEncode {

message ShellcodeEncoderMap {
map<string, ShellcodeEncoder> Encoders = 1;
}
}

// [ Builder ] ----------------------------------------
message Builders {
repeated Builder Builders = 1;
}

message Builder {
string Name = 1;
string OperatorName = 2;
repeated string GOOSs = 3;
repeated string GOARCHs = 4;
repeated OutputFormat Formats = 5;
repeated string Templates = 6;
}
1,489 changes: 751 additions & 738 deletions protobuf/rpcpb/services.pb.go

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions protobuf/rpcpb/services.proto
Expand Up @@ -69,6 +69,11 @@ service SliverRPC {
rpc GenerateExternal(clientpb.GenerateReq) returns (clientpb.ExternalImplantConfig);
rpc GenerateExternalSaveBuild(clientpb.ExternalImplantBinary) returns (commonpb.Empty);
rpc GenerateExternalGetImplantConfig(clientpb.ImplantConfig) returns (clientpb.ExternalImplantConfig);
// rpc BuilderRegister(clientpb.Builder) returns (commonpb.Empty);

rpc BuilderRegister(clientpb.Builder) returns (stream clientpb.Event);
rpc Builders(commonpb.Empty) returns (clientpb.Builders);

rpc Regenerate(clientpb.RegenerateReq) returns (clientpb.Generate);
rpc ImplantBuilds(commonpb.Empty) returns (clientpb.ImplantBuilds);
rpc DeleteImplantBuild(clientpb.DeleteReq) returns (commonpb.Empty);
Expand Down
105 changes: 102 additions & 3 deletions protobuf/rpcpb/services_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 12 additions & 25 deletions server/builder/builder.go
Expand Up @@ -46,25 +46,21 @@ type Config struct {
}

// StartBuilder - main entry point for the builder
func StartBuilder(rpc rpcpb.SliverRPCClient, conf Config) {
func StartBuilder(externalBuilder *clientpb.Builder, rpc rpcpb.SliverRPCClient) {

sigint := make(chan os.Signal, 1)
signal.Notify(sigint, os.Interrupt)

events := buildEvents(rpc)
events := buildEvents(externalBuilder, rpc)

builderLog.Infof("Successfully started process as external builder")
builder := sliverBuilder{
rpc: rpc,
config: conf,
}
// Wait for signal or builds
for {
select {
case <-sigint:
return
case event := <-events:
go builder.HandleBuildEvent(event)
go handleBuildEvent(externalBuilder, event, rpc)
}
}
}
Expand All @@ -74,8 +70,8 @@ type sliverBuilder struct {
config Config
}

func buildEvents(rpc rpcpb.SliverRPCClient) <-chan *clientpb.Event {
eventStream, err := rpc.Events(context.Background(), &commonpb.Empty{})
func buildEvents(externalBuilder *clientpb.Builder, rpc rpcpb.SliverRPCClient) <-chan *clientpb.Event {
eventStream, err := rpc.BuilderRegister(context.Background(), externalBuilder)
if err != nil {
builderLog.Fatal(err)
}
Expand All @@ -99,11 +95,11 @@ func buildEvents(rpc rpcpb.SliverRPCClient) <-chan *clientpb.Event {
return events
}

// HandleBuildEvent - Handle an individual build event
func (b *sliverBuilder) HandleBuildEvent(event *clientpb.Event) {
// handleBuildEvent - Handle an individual build event
func handleBuildEvent(externalBuilder *clientpb.Builder, event *clientpb.Event, rpc rpcpb.SliverRPCClient) {
implantConfigID := string(event.Data)
builderLog.Infof("Build event for implant config id: %s", implantConfigID)
extConfig, err := b.rpc.GenerateExternalGetImplantConfig(context.Background(), &clientpb.ImplantConfig{
extConfig, err := rpc.GenerateExternalGetImplantConfig(context.Background(), &clientpb.ImplantConfig{
ID: implantConfigID,
})
if err != nil {
Expand All @@ -116,15 +112,15 @@ func (b *sliverBuilder) HandleBuildEvent(event *clientpb.Event) {
}

// check to see if the event matches a target we're configured to build for
if !contains(b.config.GOOSs, extConfig.Config.GOOS) {
if !util.Contains(externalBuilder.GOOSs, extConfig.Config.GOOS) {
builderLog.Warnf("This builder is not configured to build for goos %s, ignore event", extConfig.Config.GOOS)
return
}
if !contains(b.config.GOARCHs, extConfig.Config.GOARCH) {
if !util.Contains(externalBuilder.GOARCHs, extConfig.Config.GOARCH) {
builderLog.Warnf("This builder is not configured to build for goarch %s, ignore event", extConfig.Config.GOARCH)
return
}
if !contains(b.config.Formats, extConfig.Config.Format) {
if !util.Contains(externalBuilder.Formats, extConfig.Config.Format) {
builderLog.Warnf("This builder is not configured to build for format %s, ignore event", extConfig.Config.Format)
return
}
Expand Down Expand Up @@ -174,7 +170,7 @@ func (b *sliverBuilder) HandleBuildEvent(event *clientpb.Event) {
}

builderLog.Infof("Uploading '%s' to server ...", extConfig.Config.Name)
_, err = b.rpc.GenerateExternalSaveBuild(context.Background(), &clientpb.ExternalImplantBinary{
_, err = rpc.GenerateExternalSaveBuild(context.Background(), &clientpb.ExternalImplantBinary{
Name: extConfig.Config.Name,
ImplantConfigID: extConfig.Config.ID,
File: &commonpb.File{
Expand All @@ -188,12 +184,3 @@ func (b *sliverBuilder) HandleBuildEvent(event *clientpb.Event) {
}
builderLog.Infof("All done, built and saved %s", fileName)
}

func contains[T comparable](elems []T, v T) bool {
for _, s := range elems {
if v == s {
return true
}
}
return false
}
27 changes: 14 additions & 13 deletions server/cli/builder.go
Expand Up @@ -65,14 +65,15 @@ var builderCmd = &cobra.Command{
return
}

builderConfig := parseBuilderConfigFlags(cmd)
externalBuilder := parseBuilderConfigFlags(cmd)

// load the client configuration from the filesystem
config, err := clientAssets.ReadConfig(configPath)
if err != nil {
builderLog.Fatalf("Invalid config file: %s", err)
os.Exit(-1)
}

// connect to the server
builderLog.Infof("Connecting to %s@%s:%d ...", config.Operator, config.LHost, config.LPort)
rpc, ln, err := transport.MTLSConnect(config)
Expand All @@ -81,24 +82,24 @@ var builderCmd = &cobra.Command{
os.Exit(-2)
}
defer ln.Close()
builder.StartBuilder(rpc, builderConfig)
builder.StartBuilder(externalBuilder, rpc)
},
}

func parseBuilderConfigFlags(cmd *cobra.Command) builder.Config {
conf := builder.Config{}
func parseBuilderConfigFlags(cmd *cobra.Command) *clientpb.Builder {
externalBuilder := &clientpb.Builder{}
var err error

conf.GOOSs, err = cmd.Flags().GetStringSlice(goosFlagStr)
externalBuilder.GOOSs, err = cmd.Flags().GetStringSlice(goosFlagStr)
if err != nil {
builderLog.Fatalf("Failed to parse --%s flag %s\n", goosFlagStr, err)
}
builderLog.Debugf("GOOS enabled: %v", conf.GOOSs)
conf.GOARCHs, err = cmd.Flags().GetStringSlice(goarchFlagStr)
builderLog.Debugf("GOOS enabled: %v", externalBuilder.GOOSs)
externalBuilder.GOARCHs, err = cmd.Flags().GetStringSlice(goarchFlagStr)
if err != nil {
builderLog.Fatalf("Failed to parse --%s flag %s\n", goarchFlagStr, err)
}
builderLog.Debugf("GOARCH enabled: %v", conf.GOARCHs)
builderLog.Debugf("GOARCH enabled: %v", externalBuilder.GOARCHs)
rawFormats, err := cmd.Flags().GetStringSlice(formatFlagStr)
if err != nil {
builderLog.Fatalf("Failed to parse --%s flag %s\n", formatFlagStr, err)
Expand All @@ -108,18 +109,18 @@ func parseBuilderConfigFlags(cmd *cobra.Command) builder.Config {
switch strings.ToLower(rawFormat) {
case "exe", "executable", "pe":
builderLog.Debugf("Executable format enabled (%d)", clientpb.OutputFormat_EXECUTABLE)
conf.Formats = append(conf.Formats, clientpb.OutputFormat_EXECUTABLE)
externalBuilder.Formats = append(externalBuilder.Formats, clientpb.OutputFormat_EXECUTABLE)
case "dll", "so", "shared", "dylib", "lib", "library":
builderLog.Debugf("Library format enabled (%d)", clientpb.OutputFormat_SHARED_LIB)
conf.Formats = append(conf.Formats, clientpb.OutputFormat_SHARED_LIB)
externalBuilder.Formats = append(externalBuilder.Formats, clientpb.OutputFormat_SHARED_LIB)
case "service":
builderLog.Debugf("Service format enabled (%d)", clientpb.OutputFormat_SERVICE)
conf.Formats = append(conf.Formats, clientpb.OutputFormat_SERVICE)
externalBuilder.Formats = append(externalBuilder.Formats, clientpb.OutputFormat_SERVICE)
case "bin", "shellcode":
builderLog.Debugf("Shellcode format enabled (%d)", clientpb.OutputFormat_SHELLCODE)
conf.Formats = append(conf.Formats, clientpb.OutputFormat_SHELLCODE)
externalBuilder.Formats = append(externalBuilder.Formats, clientpb.OutputFormat_SHELLCODE)
}
}

return conf
return externalBuilder
}

0 comments on commit dbee282

Please sign in to comment.