Skip to content

Commit

Permalink
Merge pull request #464 from BishopFox/ux/generate
Browse files Browse the repository at this point in the history
Add warning when cross-compiling to targets without a cross-compiler …
  • Loading branch information
moloch-- authored Jul 6, 2021
2 parents 3e8ce33 + 249f935 commit b20ee29
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 11 deletions.
78 changes: 73 additions & 5 deletions client/command/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"path"
"path/filepath"
"regexp"
"runtime"
"strings"

"time"
Expand Down Expand Up @@ -67,6 +68,10 @@ const (
DefaultMaxErrors = 1000
)

const (
crossCompilerInfoURL = "https://github.com/BishopFox/sliver/wiki/Cross-Compiling-Implants"
)

var (
// SupportedCompilerTargets - Supported compiler targets
SupportedCompilerTargets = map[string]bool{
Expand Down Expand Up @@ -263,17 +268,21 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
}

targetOS := strings.ToLower(ctx.Flags.String("os"))
arch := strings.ToLower(ctx.Flags.String("arch"))
targetOS, arch = getTargets(targetOS, arch, con)
if targetOS == "" || arch == "" {
targetArch := strings.ToLower(ctx.Flags.String("arch"))
targetOS, targetArch = getTargets(targetOS, targetArch, con)
if targetOS == "" || targetArch == "" {
return nil
}

if len(namedPipeC2) > 0 && targetOS != "windows" {
con.PrintErrorf("Named pipe pivoting can only be used in Windows.")
return nil
}

// Check to see if we can *probably* build the target binary
if !checkBuildTargetCompatibility(configFormat, targetOS, targetArch, con) {
return nil
}

var tunIP net.IP
if wg := ctx.Flags.String("wg"); wg != "" {
uniqueWGIP, err := con.Rpc.GenerateUniqueIP(context.Background(), &commonpb.Empty{})
Expand All @@ -287,7 +296,7 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *

config := &clientpb.ImplantConfig{
GOOS: targetOS,
GOARCH: arch,
GOARCH: targetArch,
Name: name,
Debug: ctx.Flags.Bool("debug"),
Evasion: ctx.Flags.Bool("evasion"),
Expand Down Expand Up @@ -555,3 +564,62 @@ func getLimitsString(config *clientpb.ImplantConfig) string {
}
return strings.Join(limits, "; ")
}

func checkBuildTargetCompatibility(format clientpb.OutputFormat, targetOS string, targetArch string, con *console.SliverConsoleClient) bool {
if format == clientpb.OutputFormat_EXECUTABLE {
return true // We don't need cross-compilers when targeting EXECUTABLE formats
}

compilers, err := con.Rpc.GetCompiler(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintWarnf("Failed to check target compatibility: %s\n", err)
return true
}

if runtime.GOOS != "windows" && targetOS == "windows" {
if !hasCC(targetOS, targetArch, compilers.CrossCompilers) {
return warnMissingCrossCompiler(format, targetOS, targetArch, con)
}
}

if runtime.GOOS != "darwin" && targetOS == "darwin" {
if !hasCC(targetOS, targetArch, compilers.CrossCompilers) {
return warnMissingCrossCompiler(format, targetOS, targetArch, con)
}
}

if runtime.GOOS != "linux" && targetOS == "linux" {
if !hasCC(targetOS, targetArch, compilers.CrossCompilers) {
return warnMissingCrossCompiler(format, targetOS, targetArch, con)
}
}

return true
}

func hasCC(targetOS string, targetArch string, crossCompilers []*clientpb.CrossCompiler) bool {
for _, cc := range crossCompilers {
if cc.GetTargetGOOS() == targetOS && cc.GetTargetGOARCH() == targetArch {
return true
}
}
return false
}

func warnMissingCrossCompiler(format clientpb.OutputFormat, targetOS string, targetArch string, con *console.SliverConsoleClient) bool {
con.PrintWarnf("WARNING: Missing cross-compiler for %s on %s/%s\n", nameOfOutputFormat(format), targetOS, targetArch)
switch targetOS {
case "windows":
con.PrintWarnf("The server cannot find an installation of mingw")
case "darwin":
con.PrintWarnf("The server cannot find an installation of osxcross")
case "linux":
con.PrintWarnf("The server cannot find an installation of musl-cross")
}
con.PrintWarnf("For more information please read %s\n", crossCompilerInfoURL)

confirm := false
prompt := &survey.Confirm{Message: "Try to compile anyways (will likely fail)?"}
survey.AskOne(prompt, &confirm, nil)
return confirm
}
14 changes: 8 additions & 6 deletions server/generate/binaries.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func SliverShellcode(name string, config *models.ImplantConfig) (string, error)
// as the sliver-server.
if runtime.GOOS != config.GOOS {
buildLog.Infof("Cross-compiling from %s/%s to %s/%s", runtime.GOOS, runtime.GOARCH, config.GOOS, config.GOARCH)
cc, cxx = getCrossCompilers(config.GOOS, config.GOARCH)
cc, cxx = findCrossCompilers(config.GOOS, config.GOARCH)
if cc == "" {
return "", fmt.Errorf("CC '%s/%s' not found", config.GOOS, config.GOARCH)
}
Expand Down Expand Up @@ -333,7 +333,7 @@ func SliverSharedLibrary(name string, config *models.ImplantConfig) (string, err
// as the sliver-server.
if runtime.GOOS != config.GOOS {
buildLog.Infof("Cross-compiling from %s/%s to %s/%s", runtime.GOOS, runtime.GOARCH, config.GOOS, config.GOARCH)
cc, cxx = getCrossCompilers(config.GOOS, config.GOARCH)
cc, cxx = findCrossCompilers(config.GOOS, config.GOARCH)
if cc == "" {
return "", fmt.Errorf("CC '%s/%s' not found", config.GOOS, config.GOARCH)
}
Expand Down Expand Up @@ -691,8 +691,8 @@ func getCrossCompilersFromEnv(targetGoos string, targetGoarch string) (string, s
return cc, cxx
}

func getCrossCompilers(targetGoos string, targetGoarch string) (string, string) {
var found bool // meh, ugly
func findCrossCompilers(targetGoos string, targetGoarch string) (string, string) {
var found bool

// Get CC and CXX from ENV
cc, cxx := getCrossCompilersFromEnv(targetGoos, targetGoarch)
Expand All @@ -713,9 +713,11 @@ func getCrossCompilers(targetGoos string, targetGoarch string) (string, string)
// Check to see if CC and CXX exist
if _, err := os.Stat(cc); os.IsNotExist(err) {
buildLog.Warnf("CC path '%s' does not exist", cc)
cc = "" // Path does not exist
}
if _, err := os.Stat(cxx); os.IsNotExist(err) {
buildLog.Warnf("CXX path '%s' does not exist", cxx)
cxx = "" // Path does not exist
}
buildLog.Infof(" CC = '%s'", cc)
buildLog.Infof("CXX = '%s'", cxx)
Expand Down Expand Up @@ -752,7 +754,7 @@ func GetCompilerTargets() []*clientpb.CompilerTarget {

// Cross-compile with the right configuration
if runtime.GOOS == LINUX || runtime.GOOS == DARWIN {
cc, _ := getCrossCompilers(platform[0], platform[1])
cc, _ := findCrossCompilers(platform[0], platform[1])
if cc != "" {
if runtime.GOOS == DARWIN && platform[0] == LINUX && platform[1] == "386" {
continue // Darwin can't target 32-bit Linux, even with a cc/cxx
Expand Down Expand Up @@ -806,7 +808,7 @@ func GetCrossCompilers() []*clientpb.CrossCompiler {
if runtime.GOOS == platform[0] {
continue
}
cc, cxx := getCrossCompilers(platform[0], platform[1])
cc, cxx := findCrossCompilers(platform[0], platform[1])
if cc != "" {
compilers = append(compilers, &clientpb.CrossCompiler{
TargetGOOS: platform[0],
Expand Down

0 comments on commit b20ee29

Please sign in to comment.