Skip to content

Commit

Permalink
Implement failed build notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
moloch-- committed Oct 16, 2022
1 parent 85d2388 commit 3cb0353
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 14 deletions.
35 changes: 22 additions & 13 deletions client/command/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func GenerateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("Invalid target %s\n", fmt.Sprintf("%s:%s/%s", config.Format, config.GOOS, config.GOARCH))
con.PrintErrorf("See 'builders' command for more information\n")
} else {
con.PrintErrorf("%s", err)
con.PrintErrorf("%s\n", err)
}
return
}
Expand Down Expand Up @@ -662,6 +662,14 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
}
start := time.Now()

listenerID, listener := con.CreateEventListener()

waiting := true
spinner := spin.New()

sigint := make(chan os.Signal, 1) // Catch keyboard interrupts
signal.Notify(sigint, os.Interrupt)

con.PrintInfof("Creating external build ... ")
externalImplantConfig, err := con.Rpc.GenerateExternal(context.Background(), &clientpb.ExternalGenerateReq{
Config: config,
Expand All @@ -673,31 +681,32 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
}
con.Printf("done\n")

listenerID, listener := con.CreateEventListener()

waiting := true
spinner := spin.New()

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

msgF := "Waiting for external builder to acknowledge build %s (template: %s) ... %s"

var name string
msgF := "Waiting for external builder to acknowledge build (template: %s) ... %s"
for waiting {
select {

case <-time.After(100 * time.Millisecond):
elapsed := time.Since(start)
msg := fmt.Sprintf(msgF, externalImplantConfig.Config.Name, externalImplantConfig.Config.TemplateName, elapsed.Round(time.Second))
msg := fmt.Sprintf(msgF, externalImplantConfig.Config.TemplateName, elapsed.Round(time.Second))
fmt.Fprintf(con.App.Stdout(), console.Clearln+" %s %s", spinner.Next(), msg)

case event := <-listener:
switch event.EventType {

case consts.ExternalBuildFailedEvent:
parts := strings.SplitN(string(event.Data), ":", 2)
if len(parts) != 2 {
continue
}
if parts[0] == externalImplantConfig.Config.ID {
con.RemoveEventListener(listenerID)
return nil, fmt.Errorf("external build failed: %s", parts[1])
}

case consts.AcknowledgeBuildEvent:
if string(event.Data) == externalImplantConfig.Config.ID {
msgF = "External build %s (template: %s) acknowledged by builder ... %s"
msgF = "External build acknowledged by builder (template: %s) ... %s"
}

case consts.ExternalBuildCompletedEvent:
Expand Down
1 change: 1 addition & 0 deletions client/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const (
// ExternalBuildEvent
ExternalBuildEvent = "external-build"
AcknowledgeBuildEvent = "external-acknowledge"
ExternalBuildFailedEvent = "external-build-failed"
ExternalBuildCompletedEvent = "external-build-completed"

// WireGuardNewPeer - New Wireguard peer added
Expand Down
40 changes: 39 additions & 1 deletion server/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,36 @@ func handleBuildEvent(externalBuilder *clientpb.Builder, event *clientpb.Event,
})
if err != nil {
builderLog.Errorf("Failed to get implant config: %s", err)
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
EventType: consts.ExternalBuildFailedEvent,
Data: []byte(fmt.Sprintf("%s:%s", implantConfigID, err.Error())),
})
return
}
if extConfig == nil {
builderLog.Errorf("nil extConfig")
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
EventType: consts.ExternalBuildFailedEvent,
Data: []byte(fmt.Sprintf("%s:%s", implantConfigID, "nil external config")),
})
return
}
if !isSupportedTarget(externalBuilder.Targets, extConfig.Config) {
builderLog.Warnf("Skipping event, unsupported target %s:%s/%s", extConfig.Config.Format, extConfig.Config.GOOS, extConfig.Config.GOARCH)
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
EventType: consts.ExternalBuildFailedEvent,
Data: []byte(
fmt.Sprintf("%s:%s", implantConfigID, fmt.Sprintf("unsupported target %s:%s/%s", extConfig.Config.Format, extConfig.Config.GOOS, extConfig.Config.GOARCH)),
),
})
return
}
if extConfig.Config.TemplateName != "sliver" {
builderLog.Warnf("Skipping event, unsupported template '%s'", extConfig.Config.TemplateName)
builderLog.Warnf("Reject event, unsupported template '%s'", extConfig.Config.TemplateName)
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
EventType: consts.ExternalBuildFailedEvent,
Data: []byte(fmt.Sprintf("%s:%s", implantConfigID, "Unsupported template")),
})
return
}

Expand All @@ -138,6 +156,10 @@ func handleBuildEvent(externalBuilder *clientpb.Builder, event *clientpb.Event,
err = util.AllowedName(extConfig.Config.Name)
if err != nil {
builderLog.Errorf("Invalid implant name: %s", err)
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
EventType: consts.ExternalBuildFailedEvent,
Data: []byte(fmt.Sprintf("%s:%s", implantConfigID, err.Error())),
})
return
}
_, extModel := generate.ImplantConfigFromProtobuf(extConfig.Config)
Expand All @@ -163,17 +185,29 @@ func handleBuildEvent(externalBuilder *clientpb.Builder, event *clientpb.Event,
fPath, err = generate.SliverShellcode(extConfig.Config.Name, extConfig.OTPSecret, extModel, false)
default:
builderLog.Errorf("invalid output format: %s", extConfig.Config.Format)
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
EventType: consts.ExternalBuildFailedEvent,
Data: []byte(fmt.Sprintf("%s:%s", implantConfigID, err.Error())),
})
return
}
if err != nil {
builderLog.Errorf("Failed to generate sliver: %s", err)
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
EventType: consts.ExternalBuildFailedEvent,
Data: []byte(fmt.Sprintf("%s:%s", implantConfigID, err.Error())),
})
return
}
builderLog.Infof("Build completed successfully: %s", fPath)

data, err := os.ReadFile(fPath)
if err != nil {
builderLog.Errorf("Failed to read generated sliver: %s", err)
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
EventType: consts.ExternalBuildFailedEvent,
Data: []byte(fmt.Sprintf("%s:%s", implantConfigID, err.Error())),
})
return
}

Expand All @@ -193,6 +227,10 @@ func handleBuildEvent(externalBuilder *clientpb.Builder, event *clientpb.Event,
})
if err != nil {
builderLog.Errorf("Failed to save build: %s", err)
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
EventType: consts.ExternalBuildFailedEvent,
Data: []byte(fmt.Sprintf("%s:%s", implantConfigID, err.Error())),
})
return
}
rpc.BuilderTrigger(context.Background(), &clientpb.Event{
Expand Down
2 changes: 2 additions & 0 deletions server/rpc/rpc-generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ func (rpc *Server) BuilderTrigger(ctx context.Context, req *clientpb.Event) (*co
switch req.EventType {

// Only allow certain event types to be triggered
case consts.ExternalBuildFailedEvent:
fallthrough
case consts.AcknowledgeBuildEvent:
fallthrough
case consts.ExternalBuildCompletedEvent:
Expand Down

0 comments on commit 3cb0353

Please sign in to comment.