mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-08 01:38:17 -10:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce27108c1a | ||
|
|
235fb87842 | ||
|
|
a0d71f4fe8 | ||
|
|
0502f82967 | ||
|
|
2553772ec0 | ||
|
|
406a10d639 | ||
|
|
92b2d2464c |
No files matched your search
@@ -32,9 +32,11 @@ import (
|
||||
"github.com/bishopfox/sliver/client/command/help"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/util"
|
||||
"github.com/desertbit/grumble"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -64,12 +66,14 @@ type loadedAlias struct {
|
||||
Command *grumble.Command
|
||||
}
|
||||
|
||||
// AliasFile - An OS/Arch specific file
|
||||
type AliasFile struct {
|
||||
OS string `json:"os"`
|
||||
Arch string `json:"arch"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
// AliasManifest - The manifest for an alias, contains metadata
|
||||
type AliasManifest struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
@@ -230,17 +234,27 @@ func ParseAliasManifest(data []byte) (*AliasManifest, error) {
|
||||
}
|
||||
|
||||
func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
var goos string
|
||||
var goarch string
|
||||
if session != nil {
|
||||
goos = session.OS
|
||||
goarch = session.Arch
|
||||
} else {
|
||||
goos = beacon.OS
|
||||
goarch = beacon.Arch
|
||||
}
|
||||
|
||||
loadedAlias, ok := loadedAliases[ctx.Command.Name]
|
||||
if !ok {
|
||||
con.PrintErrorf("No alias found for `%s` command\n", ctx.Command.Name)
|
||||
return
|
||||
}
|
||||
aliasManifest := loadedAlias.Manifest
|
||||
binPath, err := aliasManifest.getFileForTarget(ctx.Command.Name, session.GetOS(), session.GetArch())
|
||||
binPath, err := aliasManifest.getFileForTarget(ctx.Command.Name, goos, goarch)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Fail to find alias file: %s\n", err)
|
||||
return
|
||||
@@ -255,14 +269,14 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
entryPoint := aliasManifest.Entrypoint
|
||||
processName := ctx.Flags.String("process")
|
||||
if processName == "" {
|
||||
processName, err = aliasManifest.getDefaultProcess(session.GetOS())
|
||||
processName, err = aliasManifest.getDefaultProcess(goos)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
isDLL := false
|
||||
if filepath.Ext(binPath) == ".dll" {
|
||||
if strings.ToLower(filepath.Ext(binPath)) == ".dll" {
|
||||
isDLL = true
|
||||
}
|
||||
binData, err := ioutil.ReadFile(binPath)
|
||||
@@ -272,14 +286,17 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
var outFilePath *os.File
|
||||
if ctx.Flags.Bool("save") {
|
||||
outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
|
||||
outFile := filepath.Base(fmt.Sprintf("%s_%s*.log", filepath.Base(ctx.Command.Name), filepath.Base(session.GetHostname())))
|
||||
outFilePath, err = ioutil.TempFile("", outFile)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if aliasManifest.IsAssembly {
|
||||
|
||||
// Execute Assembly
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, extArgs)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
@@ -300,12 +317,24 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Output:\n%s", string(executeAssemblyResp.GetOutput()))
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write(executeAssemblyResp.GetOutput())
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
|
||||
if executeAssemblyResp.Response != nil && executeAssemblyResp.Response.Async {
|
||||
con.AddBeaconCallback(executeAssemblyResp.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, executeAssemblyResp)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode call ext response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintAssemblyOutput(ctx.Command.Name, executeAssemblyResp, outFilePath, con)
|
||||
})
|
||||
con.PrintAsyncResponse(executeAssemblyResp.Response)
|
||||
} else {
|
||||
PrintAssemblyOutput(ctx.Command.Name, executeAssemblyResp, outFilePath, con)
|
||||
}
|
||||
|
||||
} else if aliasManifest.IsReflective {
|
||||
|
||||
// Spawn DLL
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, extArgs)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
@@ -319,18 +348,28 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
con.PrintInfof("Output:\n%s", spawnDllResp.GetResult())
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write([]byte(spawnDllResp.GetResult()))
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
if spawnDllResp.Response != nil && spawnDllResp.Response.Async {
|
||||
con.AddBeaconCallback(spawnDllResp.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, spawnDllResp)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode call ext response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintSpawnDLLOutput(ctx.Command.Name, spawnDllResp, outFilePath, con)
|
||||
})
|
||||
con.PrintAsyncResponse(spawnDllResp.Response)
|
||||
} else {
|
||||
PrintSpawnDLLOutput(ctx.Command.Name, spawnDllResp, outFilePath, con)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Sideload
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, extArgs)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
@@ -345,20 +384,54 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
con.PrintInfof("Output:\n%s", sideloadResp.GetResult())
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write([]byte(sideloadResp.GetResult()))
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
if sideloadResp.Response != nil && sideloadResp.Response.Async {
|
||||
con.AddBeaconCallback(sideloadResp.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, sideloadResp)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode call ext response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintSideloadOutput(ctx.Command.Name, sideloadResp, outFilePath, con)
|
||||
})
|
||||
con.PrintAsyncResponse(sideloadResp.Response)
|
||||
} else {
|
||||
PrintSideloadOutput(ctx.Command.Name, sideloadResp, outFilePath, con)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PrintSpawnDLLOutput - Prints the output of a spawn dll command
|
||||
func PrintSpawnDLLOutput(cmdName string, spawnDllResp *sliverpb.SpawnDll, outFilePath *os.File, con *console.SliverConsoleClient) {
|
||||
con.PrintInfof("%s output:\n%s", cmdName, spawnDllResp.GetResult())
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write([]byte(spawnDllResp.GetResult()))
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// PrintSideloadOutput - Prints the output of a sideload command
|
||||
func PrintSideloadOutput(cmdName string, sideloadResp *sliverpb.Sideload, outFilePath *os.File, con *console.SliverConsoleClient) {
|
||||
con.PrintInfof("%s output:\n%s", cmdName, sideloadResp.GetResult())
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write([]byte(sideloadResp.GetResult()))
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// PrintAssemblyOutput - Prints the output of an execute-assembly command
|
||||
func PrintAssemblyOutput(cmdName string, execAsmResp *sliverpb.ExecuteAssembly, outFilePath *os.File, con *console.SliverConsoleClient) {
|
||||
con.PrintInfof("%s output:\n%s", cmdName, string(execAsmResp.GetOutput()))
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write(execAsmResp.GetOutput())
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func cmdExists(name string, app *grumble.App) bool {
|
||||
for _, c := range app.Commands().All() {
|
||||
if name == c.Name {
|
||||
|
||||
@@ -38,11 +38,13 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/util"
|
||||
"github.com/desertbit/grumble"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTimeout = 60
|
||||
|
||||
// ManifestFileName - Extension manifest file name
|
||||
ManifestFileName = "extension.json"
|
||||
)
|
||||
|
||||
@@ -113,7 +115,7 @@ func ExtensionLoadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintInfof("Added %s command: %s\n", extCmd.CommandName, extCmd.Help)
|
||||
}
|
||||
|
||||
// ParseExtensions - Parse extension files
|
||||
// LoadExtensionManifest - Parse extension files
|
||||
func LoadExtensionManifest(manifestPath string) (*ExtensionManifest, error) {
|
||||
data, err := ioutil.ReadFile(manifestPath)
|
||||
if err != nil {
|
||||
@@ -178,11 +180,11 @@ func ExtensionRegisterCommand(extCmd *ExtensionManifest, con *console.SliverCons
|
||||
return nil
|
||||
},
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Bool("s", "save", false, "Save output to disk")
|
||||
// f.Bool("s", "save", false, "Save output to disk")
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Args: func(a *grumble.Args) {
|
||||
if len(extCmd.Arguments) > 0 {
|
||||
if 0 < len(extCmd.Arguments) {
|
||||
// BOF specific
|
||||
for _, arg := range extCmd.Arguments {
|
||||
var (
|
||||
@@ -212,27 +214,26 @@ func ExtensionRegisterCommand(extCmd *ExtensionManifest, con *console.SliverCons
|
||||
con.App.AddCommand(extensionCmd)
|
||||
}
|
||||
|
||||
func loadExtension(ctx *grumble.Context, session *clientpb.Session, con *console.SliverConsoleClient, ext *ExtensionManifest) error {
|
||||
func loadExtension(goos string, goarch string, checkCache bool, ext *ExtensionManifest, ctx *grumble.Context, con *console.SliverConsoleClient) error {
|
||||
var extensionList []string
|
||||
binPath, err := ext.getFileForTarget(ctx.Command.Name, session.OS, session.Arch)
|
||||
binPath, err := ext.getFileForTarget(ctx.Command.Name, goos, goarch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Try to find the extension in the loaded extensions
|
||||
if len(session.Extensions) == 0 {
|
||||
if checkCache {
|
||||
extList, err := con.Rpc.ListExtensions(context.Background(), &sliverpb.ListExtensionsReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
con.PrintErrorf("List extensions error: %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
if extList.Response != nil && extList.Response.Err != "" {
|
||||
return errors.New(extList.Response.Err)
|
||||
}
|
||||
extensionList = extList.Names
|
||||
} else {
|
||||
extensionList = session.Extensions
|
||||
}
|
||||
depLoaded := false
|
||||
for _, extName := range extensionList {
|
||||
@@ -248,7 +249,7 @@ func loadExtension(ctx *grumble.Context, session *clientpb.Session, con *console
|
||||
// BOFs are not loaded by the DLL loader, but we make sure the loader itself is loaded
|
||||
// Auto load the coff loader if we have it
|
||||
if !depLoaded {
|
||||
if errLoad := loadDep(session, con, ctx, ext.DependsOn); errLoad != nil {
|
||||
if errLoad := loadDep(goos, goarch, ext.DependsOn, ctx, con); errLoad != nil {
|
||||
return errLoad
|
||||
}
|
||||
}
|
||||
@@ -258,31 +259,17 @@ func loadExtension(ctx *grumble.Context, session *clientpb.Session, con *console
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if errRegister := registerExtension(con, ext, binData, session, ctx); errRegister != nil {
|
||||
if errRegister := registerExtension(goos, ext, binData, ctx, con); errRegister != nil {
|
||||
return errRegister
|
||||
}
|
||||
// Update session info
|
||||
if filepath.Ext(binPath) != ".o" {
|
||||
// Don't update session for BOFs, we don't cache them
|
||||
// on the implant side (yet)
|
||||
// update the Session info
|
||||
_, err = con.Rpc.UpdateSession(context.Background(), &clientpb.UpdateSession{
|
||||
Extensions: extensionList,
|
||||
SessionID: session.ID,
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerExtension(con *console.SliverConsoleClient, ext *ExtensionManifest, binData []byte, session *clientpb.Session, ctx *grumble.Context) error {
|
||||
func registerExtension(goos string, ext *ExtensionManifest, binData []byte, ctx *grumble.Context, con *console.SliverConsoleClient) error {
|
||||
registerResp, err := con.Rpc.RegisterExtension(context.Background(), &sliverpb.RegisterExtensionReq{
|
||||
Name: ext.CommandName,
|
||||
Data: binData,
|
||||
OS: session.OS,
|
||||
OS: goos,
|
||||
Init: ext.Init,
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
@@ -295,10 +282,10 @@ func registerExtension(con *console.SliverConsoleClient, ext *ExtensionManifest,
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadDep(session *clientpb.Session, con *console.SliverConsoleClient, ctx *grumble.Context, depName string) error {
|
||||
depExt, f := loadedExtensions[depName]
|
||||
if f {
|
||||
depBinPath, err := depExt.getFileForTarget(depExt.CommandName, session.OS, session.Arch)
|
||||
func loadDep(goos string, goarch string, depName string, ctx *grumble.Context, con *console.SliverConsoleClient) error {
|
||||
depExt, ok := loadedExtensions[depName]
|
||||
if ok {
|
||||
depBinPath, err := depExt.getFileForTarget(depExt.CommandName, goos, goarch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -306,23 +293,31 @@ func loadDep(session *clientpb.Session, con *console.SliverConsoleClient, ctx *g
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return registerExtension(con, depExt, depBinData, session, ctx)
|
||||
return registerExtension(goos, depExt, depBinData, ctx, con)
|
||||
}
|
||||
return fmt.Errorf("missing dependency %s", depName)
|
||||
}
|
||||
|
||||
func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
var (
|
||||
callExtension *sliverpb.CallExtension
|
||||
err error
|
||||
extensionArgs []byte
|
||||
extName string
|
||||
entryPoint string
|
||||
)
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
var goos string
|
||||
var goarch string
|
||||
if session != nil {
|
||||
goos = session.OS
|
||||
goarch = session.Arch
|
||||
} else {
|
||||
goos = beacon.OS
|
||||
goarch = beacon.Arch
|
||||
}
|
||||
|
||||
ext, ok := loadedExtensions[ctx.Command.Name]
|
||||
if !ok {
|
||||
@@ -330,23 +325,15 @@ func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = loadExtension(ctx, session, con, ext); err != nil {
|
||||
checkCache := session != nil
|
||||
if err = loadExtension(goos, goarch, checkCache, ext, ctx, con); err != nil {
|
||||
con.PrintErrorf("Could not load extension: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
var outFilePath *os.File
|
||||
if ctx.Flags.Bool("save") {
|
||||
outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
|
||||
outFilePath, err = ioutil.TempFile("", outFile)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
binPath, err := ext.getFileForTarget(ctx.Command.Name, session.OS, session.Arch)
|
||||
binPath, err := ext.getFileForTarget(ctx.Command.Name, goos, goarch)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
con.PrintErrorf("Failed to read extension file: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -361,7 +348,7 @@ func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
// Beacon Object File -- requires a COFF loader
|
||||
extensionArgs, err = getBOFArgs(ctx, binPath, ext)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error: %s\n", err)
|
||||
con.PrintErrorf("BOF args error: %s\n", err)
|
||||
return
|
||||
}
|
||||
extName = ext.DependsOn
|
||||
@@ -373,10 +360,11 @@ func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
extName = ext.CommandName
|
||||
entryPoint = ext.Entrypoint
|
||||
}
|
||||
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Executing %s ...", ctx.Command.Name)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
callExtension, err = con.Rpc.CallExtension(context.Background(), &sliverpb.CallExtensionReq{
|
||||
callExtResp, err := con.Rpc.CallExtension(context.Background(), &sliverpb.CallExtensionReq{
|
||||
Name: extName,
|
||||
Export: entryPoint,
|
||||
Args: extensionArgs,
|
||||
@@ -385,22 +373,39 @@ func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
con.PrintErrorf("Call extension error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if callExtResp.Response != nil && callExtResp.Response.Async {
|
||||
con.AddBeaconCallback(callExtResp.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, callExtResp)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode call ext response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintExtOutput(extName, ext.CommandName, callExtResp, con)
|
||||
})
|
||||
con.PrintAsyncResponse(callExtResp.Response)
|
||||
} else {
|
||||
PrintExtOutput(extName, ext.CommandName, callExtResp, con)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintExtOutput - Print the ext execution output
|
||||
func PrintExtOutput(extName string, commandName string, callExtension *sliverpb.CallExtension, con *console.SliverConsoleClient) {
|
||||
if extName == commandName {
|
||||
con.PrintInfof("Successfully executed %s\n", extName)
|
||||
} else {
|
||||
con.PrintInfof("Successfully executed %s (%s)\n", commandName, extName)
|
||||
}
|
||||
if 0 < len(string(callExtension.Output)) {
|
||||
con.PrintInfof("Got output:\n%s\n", callExtension.Output)
|
||||
}
|
||||
if callExtension.Response != nil && callExtension.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", callExtension.Response.Err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Successfully executed %s\n", extName)
|
||||
if len(callExtension.Output) > 0 {
|
||||
con.PrintInfof("Got output:\n%s", string(callExtension.Output))
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write(callExtension.Output)
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
}
|
||||
con.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func getBOFArgs(ctx *grumble.Context, binPath string, ext *ExtensionManifest) ([]byte, error) {
|
||||
|
||||
@@ -37,15 +37,15 @@ const (
|
||||
)
|
||||
|
||||
type WindowsExtension struct {
|
||||
id string
|
||||
data []byte
|
||||
module *memmod.Module
|
||||
arch string
|
||||
init string
|
||||
onFinish func([]byte)
|
||||
serverStore bool
|
||||
id string
|
||||
data []byte
|
||||
module *memmod.Module
|
||||
arch string
|
||||
init string
|
||||
onFinish func([]byte)
|
||||
}
|
||||
|
||||
// NewWindowsExtension - Load a new windows extension
|
||||
func NewWindowsExtension(data []byte, id string, arch string, init string) *WindowsExtension {
|
||||
return &WindowsExtension{
|
||||
id: id,
|
||||
@@ -55,14 +55,17 @@ func NewWindowsExtension(data []byte, id string, arch string, init string) *Wind
|
||||
}
|
||||
}
|
||||
|
||||
// GetID - Get the extension ID
|
||||
func (w *WindowsExtension) GetID() string {
|
||||
return w.id
|
||||
}
|
||||
|
||||
// GetArch - Get the extension architecture
|
||||
func (w *WindowsExtension) GetArch() string {
|
||||
return w.arch
|
||||
}
|
||||
|
||||
// Load - Load the extension into memory
|
||||
func (w *WindowsExtension) Load() error {
|
||||
var err error
|
||||
if len(w.data) == 0 {
|
||||
@@ -86,6 +89,7 @@ func (w *WindowsExtension) Load() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Call - Call an extension export
|
||||
func (w *WindowsExtension) Call(export string, arguments []byte, onFinish func([]byte)) error {
|
||||
var (
|
||||
argumentsPtr uintptr
|
||||
|
||||
@@ -602,20 +602,17 @@ func getPrivsHandler(data []byte, resp RPCResponse) {
|
||||
|
||||
func registerExtensionHandler(data []byte, resp RPCResponse) {
|
||||
registerReq := &sliverpb.RegisterExtensionReq{}
|
||||
|
||||
err := proto.Unmarshal(data, registerReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ext := extension.NewWindowsExtension(registerReq.Data, registerReq.Name, registerReq.OS, registerReq.Init)
|
||||
extension.Add(ext)
|
||||
err = ext.Load()
|
||||
registerResp := &sliverpb.RegisterExtension{
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
registerResp := &sliverpb.RegisterExtension{Response: &commonpb.Response{}}
|
||||
if err != nil {
|
||||
registerResp.Response.Err = err.Error()
|
||||
} else {
|
||||
extension.Add(ext)
|
||||
}
|
||||
data, err = proto.Marshal(registerResp)
|
||||
resp(data, err)
|
||||
@@ -623,15 +620,12 @@ func registerExtensionHandler(data []byte, resp RPCResponse) {
|
||||
|
||||
func callExtensionHandler(data []byte, resp RPCResponse) {
|
||||
callReq := &sliverpb.CallExtensionReq{}
|
||||
|
||||
err := proto.Unmarshal(data, callReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
callResp := &sliverpb.CallExtension{
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
callResp := &sliverpb.CallExtension{Response: &commonpb.Response{}}
|
||||
gotOutput := false
|
||||
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, func(out []byte) {
|
||||
gotOutput = true
|
||||
|
||||
+819
-782
File diff suppressed because it is too large.
Load diff
@@ -215,6 +215,8 @@ message Mkdir {
|
||||
|
||||
message DownloadReq {
|
||||
string Path = 1;
|
||||
int64 Start = 2;
|
||||
int64 Stop = 3;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
@@ -223,7 +225,9 @@ message Download {
|
||||
string Path = 1;
|
||||
string Encoder = 2;
|
||||
bool Exists = 3;
|
||||
bytes Data = 4;
|
||||
int64 Start = 4;
|
||||
int64 Stop = 5;
|
||||
bytes Data = 6;
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ func ListBeacons() ([]*models.Beacon, error) {
|
||||
return beacons, err
|
||||
}
|
||||
|
||||
// PendingBeaconTasksByBeaconID - Select a Beacon by ID
|
||||
// PendingBeaconTasksByBeaconID - Select a Beacon by ID, ordered by creation time
|
||||
func PendingBeaconTasksByBeaconID(beaconID string) ([]*models.BeaconTask, error) {
|
||||
tasks := []*models.BeaconTask{}
|
||||
err := Session().Where(
|
||||
@@ -301,7 +301,7 @@ func PendingBeaconTasksByBeaconID(beaconID string) ([]*models.BeaconTask, error)
|
||||
BeaconID: uuid.FromStringOrNil(beaconID),
|
||||
State: models.PENDING,
|
||||
},
|
||||
).Find(&tasks).Error
|
||||
).Order("created_at").Find(&tasks).Error
|
||||
return tasks, err
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,8 @@ func beaconTasksHandler(implantConn *core.ImplantConnection, data []byte) *slive
|
||||
}
|
||||
|
||||
beaconHandlerLog.Infof("Beacon %s requested pending task(s)", beaconTasks.ID)
|
||||
|
||||
// Pending tasks are ordered by their creation time.
|
||||
pendingTasks, err := db.PendingBeaconTasksByBeaconID(beaconTasks.ID)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
beaconHandlerLog.Errorf("Beacon task database error: %s", err)
|
||||
|
||||
@@ -187,11 +187,11 @@ func (rpc *Server) SaveImplantProfile(ctx context.Context, profile *clientpb.Imp
|
||||
}
|
||||
core.EventBroker.Publish(core.Event{
|
||||
EventType: consts.ProfileEvent,
|
||||
Data: []byte(fmt.Sprintf("%s", profile.Name)),
|
||||
Data: []byte(profile.Name),
|
||||
})
|
||||
return profile, nil
|
||||
}
|
||||
return nil, errors.New("Invalid profile name")
|
||||
return nil, errors.New("invalid profile name")
|
||||
}
|
||||
|
||||
// DeleteImplantProfile - Delete an implant profile
|
||||
@@ -204,7 +204,7 @@ func (rpc *Server) DeleteImplantProfile(ctx context.Context, req *clientpb.Delet
|
||||
if err == nil {
|
||||
core.EventBroker.Publish(core.Event{
|
||||
EventType: consts.ProfileEvent,
|
||||
Data: []byte(fmt.Sprintf("%s", profile.Name)),
|
||||
Data: []byte(profile.Name),
|
||||
})
|
||||
}
|
||||
return &commonpb.Empty{}, err
|
||||
@@ -224,7 +224,7 @@ func (rpc *Server) DeleteImplantBuild(ctx context.Context, req *clientpb.DeleteR
|
||||
if err == nil {
|
||||
core.EventBroker.Publish(core.Event{
|
||||
EventType: consts.BuildEvent,
|
||||
Data: []byte(fmt.Sprintf("%s", build.Name)),
|
||||
Data: []byte(build.Name),
|
||||
})
|
||||
}
|
||||
return &commonpb.Empty{}, err
|
||||
|
||||
@@ -100,9 +100,9 @@ func (rpc *Server) HijackDLL(ctx context.Context, req *clientpb.DllHijackReq) (*
|
||||
}
|
||||
|
||||
if p.Config.Format != clientpb.OutputFormat_SHARED_LIB {
|
||||
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf(
|
||||
return nil, status.Error(codes.InvalidArgument,
|
||||
"please select a profile targeting a shared library format",
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
name, config := generate.ImplantConfigFromProtobuf(p.Config)
|
||||
@@ -145,7 +145,7 @@ func (rpc *Server) HijackDLL(ctx context.Context, req *clientpb.DllHijackReq) (*
|
||||
Path: req.TargetLocation,
|
||||
Request: &commonpb.Request{
|
||||
SessionID: session.ID,
|
||||
Timeout: int64(defaultTimeout),
|
||||
Timeout: int64(minTimeout),
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -24,12 +24,11 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
)
|
||||
|
||||
var (
|
||||
hostsRPCLog = log.NamedLogger("rpc", "hosts")
|
||||
)
|
||||
// var (
|
||||
// hostsRPCLog = log.NamedLogger("rpc", "hosts")
|
||||
// )
|
||||
|
||||
// Hosts - List all hosts
|
||||
func (rpc *Server) Hosts(ctx context.Context, _ *commonpb.Empty) (*clientpb.AllHosts, error) {
|
||||
|
||||
@@ -43,7 +43,7 @@ const (
|
||||
|
||||
var (
|
||||
// ErrInvalidPort - Invalid TCP port number
|
||||
ErrInvalidPort = errors.New("Invalid listener port")
|
||||
ErrInvalidPort = errors.New("invalid listener port")
|
||||
)
|
||||
|
||||
// GetJobs - List jobs
|
||||
@@ -78,7 +78,7 @@ func (rpc *Server) KillJob(ctx context.Context, kill *clientpb.KillJobReq) (*cli
|
||||
}
|
||||
} else {
|
||||
killJob.Success = false
|
||||
err = errors.New("Invalid Job ID")
|
||||
err = errors.New("invalid Job ID")
|
||||
}
|
||||
return killJob, err
|
||||
}
|
||||
|
||||
@@ -25,13 +25,12 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
"github.com/bishopfox/sliver/server/loot"
|
||||
)
|
||||
|
||||
var (
|
||||
lootRPCLog = log.NamedLogger("rpc", "loot")
|
||||
)
|
||||
// var (
|
||||
// lootRPCLog = log.NamedLogger("rpc", "loot")
|
||||
// )
|
||||
|
||||
// LootAdd - Add loot
|
||||
func (rpc *Server) LootAdd(ctx context.Context, lootReq *clientpb.Loot) (*clientpb.Loot, error) {
|
||||
|
||||
@@ -20,6 +20,7 @@ package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"path"
|
||||
@@ -170,7 +171,7 @@ func (rpc *Server) MsfStage(ctx context.Context, req *clientpb.MsfStagerReq) (*c
|
||||
payload = "meterpreter/reverse_https"
|
||||
uri = generateCallbackURI()
|
||||
default:
|
||||
return MSFStage, fmt.Errorf("Protocol not supported")
|
||||
return MSFStage, errors.New("protocol not supported")
|
||||
}
|
||||
|
||||
// We only support windows at the moment
|
||||
|
||||
@@ -86,7 +86,7 @@ func (rpc *Server) GetSystem(ctx context.Context, req *clientpb.GetSystemReq) (*
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
shellcode, err = ioutil.ReadFile(shellcodePath)
|
||||
shellcode, _ = ioutil.ReadFile(shellcodePath)
|
||||
}
|
||||
data, err := proto.Marshal(&sliverpb.InvokeGetSystemReq{
|
||||
Data: shellcode,
|
||||
|
||||
@@ -134,15 +134,8 @@ func (s *Server) CreateSocks(ctx context.Context, req *sliverpb.Socks) (*sliverp
|
||||
// CloseSocks - Client requests we close a Socks
|
||||
func (s *Server) CloseSocks(ctx context.Context, req *sliverpb.Socks) (*commonpb.Empty, error) {
|
||||
err := core.SocksTunnels.Close(req.TunnelID)
|
||||
|
||||
if _, ok := toImplantCacheSocks[req.TunnelID]; ok {
|
||||
delete(toImplantCacheSocks, req.TunnelID)
|
||||
}
|
||||
|
||||
if _, ok := fromImplantCacheSocks[req.TunnelID]; ok {
|
||||
delete(fromImplantCacheSocks, req.TunnelID)
|
||||
}
|
||||
|
||||
delete(toImplantCacheSocks, req.TunnelID)
|
||||
delete(fromImplantCacheSocks, req.TunnelID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+42
-43
@@ -24,7 +24,6 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
@@ -78,7 +77,7 @@ func (rpc *Server) Migrate(ctx context.Context, req *clientpb.MigrateReq) (*sliv
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
shellcode, err = ioutil.ReadFile(shellcodePath)
|
||||
shellcode, _ = ioutil.ReadFile(shellcodePath)
|
||||
}
|
||||
reqData, err := proto.Marshal(&sliverpb.InvokeMigrateReq{
|
||||
Request: req.Request,
|
||||
@@ -332,49 +331,49 @@ func getOrdinal(index uint32, rawData []byte, fpe *pe.File, funcArrayFoa uint32)
|
||||
return funcOffset
|
||||
}
|
||||
|
||||
func getExportOffsetFromFile(filepath string, exportName string) (funcOffset uint32, err error) {
|
||||
rawData, err := ioutil.ReadFile(filepath)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
handle, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer handle.Close()
|
||||
fpe, _ := pe.NewFile(handle)
|
||||
var exportDirectoryRVA uint32
|
||||
switch (fpe.OptionalHeader).(type) {
|
||||
case *pe.OptionalHeader32:
|
||||
exportDirectoryRVA = fpe.OptionalHeader.(*pe.OptionalHeader32).DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
|
||||
case *pe.OptionalHeader64:
|
||||
exportDirectoryRVA = fpe.OptionalHeader.(*pe.OptionalHeader64).DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
|
||||
}
|
||||
var offset = rvaToFoa(exportDirectoryRVA, fpe)
|
||||
exportDir := ExportDirectory{}
|
||||
buff := &bytes.Buffer{}
|
||||
buff.Write(rawData[offset:])
|
||||
err = binary.Read(buff, binary.LittleEndian, &exportDir)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
current := exportDir.AddressOfNames
|
||||
nameArrayFOA := rvaToFoa(exportDir.AddressOfNames, fpe)
|
||||
ordinalArrayFOA := rvaToFoa(exportDir.AddressOfNameOrdinals, fpe)
|
||||
funcArrayFoa := rvaToFoa(exportDir.AddressOfFunctions, fpe)
|
||||
// func getExportOffsetFromFile(filepath string, exportName string) (funcOffset uint32, err error) {
|
||||
// rawData, err := ioutil.ReadFile(filepath)
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// handle, err := os.Open(filepath)
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// defer handle.Close()
|
||||
// fpe, _ := pe.NewFile(handle)
|
||||
// var exportDirectoryRVA uint32
|
||||
// switch (fpe.OptionalHeader).(type) {
|
||||
// case *pe.OptionalHeader32:
|
||||
// exportDirectoryRVA = fpe.OptionalHeader.(*pe.OptionalHeader32).DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
|
||||
// case *pe.OptionalHeader64:
|
||||
// exportDirectoryRVA = fpe.OptionalHeader.(*pe.OptionalHeader64).DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
|
||||
// }
|
||||
// var offset = rvaToFoa(exportDirectoryRVA, fpe)
|
||||
// exportDir := ExportDirectory{}
|
||||
// buff := &bytes.Buffer{}
|
||||
// buff.Write(rawData[offset:])
|
||||
// err = binary.Read(buff, binary.LittleEndian, &exportDir)
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// current := exportDir.AddressOfNames
|
||||
// nameArrayFOA := rvaToFoa(exportDir.AddressOfNames, fpe)
|
||||
// ordinalArrayFOA := rvaToFoa(exportDir.AddressOfNameOrdinals, fpe)
|
||||
// funcArrayFoa := rvaToFoa(exportDir.AddressOfFunctions, fpe)
|
||||
|
||||
for i := uint32(0); i < exportDir.NumberOfNames; i++ {
|
||||
index := nameArrayFOA + i*8
|
||||
name := getFuncName(index, rawData, fpe)
|
||||
if strings.Contains(name, exportName) {
|
||||
ordIndex := ordinalArrayFOA + i*2
|
||||
funcOffset = getOrdinal(ordIndex, rawData, fpe, funcArrayFoa)
|
||||
}
|
||||
current += uint32(binary.Size(i))
|
||||
}
|
||||
// for i := uint32(0); i < exportDir.NumberOfNames; i++ {
|
||||
// index := nameArrayFOA + i*8
|
||||
// name := getFuncName(index, rawData, fpe)
|
||||
// if strings.Contains(name, exportName) {
|
||||
// ordIndex := ordinalArrayFOA + i*2
|
||||
// funcOffset = getOrdinal(ordIndex, rawData, fpe, funcArrayFoa)
|
||||
// }
|
||||
// current += uint32(binary.Size(i))
|
||||
// }
|
||||
|
||||
return
|
||||
}
|
||||
// return
|
||||
// }
|
||||
|
||||
func getExportOffsetFromMemory(rawData []byte, exportName string) (funcOffset uint32, err error) {
|
||||
peReader := bytes.NewReader(rawData)
|
||||
|
||||
@@ -63,15 +63,8 @@ func (s *Server) CreateTunnel(ctx context.Context, req *sliverpb.Tunnel) (*slive
|
||||
// CloseTunnel - Client requests we close a tunnel
|
||||
func (s *Server) CloseTunnel(ctx context.Context, req *sliverpb.Tunnel) (*commonpb.Empty, error) {
|
||||
err := core.Tunnels.Close(req.TunnelID)
|
||||
|
||||
if _, ok := toImplantCache[req.TunnelID]; ok {
|
||||
delete(toImplantCache, req.TunnelID)
|
||||
}
|
||||
|
||||
if _, ok := fromImplantCache[req.TunnelID]; ok {
|
||||
delete(fromImplantCache, req.TunnelID)
|
||||
}
|
||||
|
||||
delete(toImplantCache, req.TunnelID)
|
||||
delete(fromImplantCache, req.TunnelID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -107,7 +100,7 @@ func (s *Server) TunnelData(stream rpcpb.SliverRPC_TunnelDataServer) error {
|
||||
|
||||
go func() {
|
||||
|
||||
sendCache, _ := toImplantCache[tunnel.ID]
|
||||
sendCache := toImplantCache[tunnel.ID]
|
||||
for tunnelData := range tunnel.FromImplant {
|
||||
|
||||
tunnelLog.Debugf("Tunnel %d: From implant %d byte(s), seq: %d ack: %d",
|
||||
@@ -170,7 +163,7 @@ func (s *Server) TunnelData(stream rpcpb.SliverRPC_TunnelDataServer) error {
|
||||
|
||||
go func() {
|
||||
session := core.Sessions.Get(tunnel.SessionID)
|
||||
sendCache, _ := toImplantCache[tunnel.ID]
|
||||
sendCache := toImplantCache[tunnel.ID]
|
||||
for data := range tunnel.ToImplant {
|
||||
tunnelLog.Debugf("Tunnel %d: To implant %d byte(s), seq: %d", tunnel.ID, len(data), tunnel.ToImplantSequence)
|
||||
tunnelData := sliverpb.TunnelData{
|
||||
|
||||
@@ -20,7 +20,6 @@ package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"mime"
|
||||
"path/filepath"
|
||||
|
||||
@@ -83,7 +82,7 @@ func (rpc *Server) WebsiteRemove(ctx context.Context, req *clientpb.Website) (*c
|
||||
|
||||
core.EventBroker.Publish(core.Event{
|
||||
EventType: consts.WebsiteEvent,
|
||||
Data: []byte(fmt.Sprintf("%s", req.Name)),
|
||||
Data: []byte(req.Name),
|
||||
})
|
||||
|
||||
return &commonpb.Empty{}, nil
|
||||
@@ -122,7 +121,7 @@ func (rpc *Server) WebsiteAddContent(ctx context.Context, req *clientpb.WebsiteA
|
||||
|
||||
core.EventBroker.Publish(core.Event{
|
||||
EventType: consts.WebsiteEvent,
|
||||
Data: []byte(fmt.Sprintf("%s", req.Name)),
|
||||
Data: []byte(req.Name),
|
||||
})
|
||||
|
||||
return website.MapContent(req.Name, false)
|
||||
@@ -149,7 +148,7 @@ func (rpc *Server) WebsiteUpdateContent(ctx context.Context, req *clientpb.Websi
|
||||
|
||||
core.EventBroker.Publish(core.Event{
|
||||
EventType: consts.WebsiteEvent,
|
||||
Data: []byte(fmt.Sprintf("%s", req.Name)),
|
||||
Data: []byte(req.Name),
|
||||
})
|
||||
|
||||
return website.MapContent(req.Name, false)
|
||||
@@ -167,7 +166,7 @@ func (rpc *Server) WebsiteRemoveContent(ctx context.Context, req *clientpb.Websi
|
||||
|
||||
core.EventBroker.Publish(core.Event{
|
||||
EventType: consts.WebsiteEvent,
|
||||
Data: []byte(fmt.Sprintf("%s", req.Name)),
|
||||
Data: []byte(req.Name),
|
||||
})
|
||||
|
||||
return website.MapContent(req.Name, false)
|
||||
|
||||
+5
-4
@@ -44,7 +44,7 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTimeout = time.Duration(30 * time.Second)
|
||||
minTimeout = time.Duration(30 * time.Second)
|
||||
)
|
||||
|
||||
// Server - gRPC server
|
||||
@@ -132,12 +132,13 @@ func (rpc *Server) GenericHandler(req GenericRequest, resp GenericResponse) erro
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rpc.getError(resp.(GenericResponse))
|
||||
return rpc.getError(resp)
|
||||
}
|
||||
|
||||
// asyncGenericHandler - Generic handler for async request/response's for beacon tasks
|
||||
func (rpc *Server) asyncGenericHandler(req GenericRequest, resp GenericResponse) error {
|
||||
rpcLog.Debugf("Async Generic Handler: %#v", req)
|
||||
// VERY VERBOSE
|
||||
// rpcLog.Debugf("Async Generic Handler: %#v", req)
|
||||
request := req.GetRequest()
|
||||
if request == nil {
|
||||
return ErrMissingRequestField
|
||||
@@ -202,7 +203,7 @@ func (rpc *Server) getClientCommonName(ctx context.Context) string {
|
||||
func (rpc *Server) getTimeout(req GenericRequest) time.Duration {
|
||||
timeout := req.GetRequest().Timeout
|
||||
if time.Duration(timeout) < time.Second {
|
||||
return defaultTimeout
|
||||
return minTimeout
|
||||
}
|
||||
return time.Duration(timeout)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user