Skip to content

Commit

Permalink
Merge pull request #475 from BishopFox/extensions
Browse files Browse the repository at this point in the history
Update sideload to use Donut
  • Loading branch information
rkervella authored Jul 20, 2021
2 parents 5bcf9ba + 1079a55 commit f6351f7
Show file tree
Hide file tree
Showing 11 changed files with 493 additions and 463 deletions.
2 changes: 1 addition & 1 deletion client/command/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,6 @@ func BindCommands(con *console.SliverConsoleClient) {
Help: "Load and execute a shared object (shared library/DLL) in a remote process",
LongHelp: help.GetHelpFor([]string{consts.SideloadStr}),
Flags: func(f *grumble.Flags) {
f.String("a", "args", "", "Arguments for the shared library function")
f.String("e", "entry-point", "", "Entrypoint for the DLL (Windows only)")
f.String("p", "process", `c:\windows\system32\notepad.exe`, "Path to process to host the shellcode")
f.Bool("s", "save", false, "save output to file")
Expand All @@ -620,6 +619,7 @@ func BindCommands(con *console.SliverConsoleClient) {
},
Args: func(a *grumble.Args) {
a.String("filepath", "path the shared library file")
a.StringList("args", "arguments for the binary", grumble.Default([]string{}))
},
HelpGroup: consts.SliverHelpGroup,
Run: func(ctx *grumble.Context) error {
Expand Down
6 changes: 5 additions & 1 deletion client/command/exec/sideload.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"

"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
Expand All @@ -38,13 +40,14 @@ func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {

entryPoint := ctx.Flags.String("entry-point")
processName := ctx.Flags.String("process")
args := ctx.Flags.String("args")
args := strings.Join(ctx.Args.StringList("args"), " ")

binData, err := ioutil.ReadFile(binPath)
if err != nil {
con.PrintErrorf("%s", err.Error())
return
}
isDLL := (filepath.Ext(binPath) == ".dll")
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Sideloading %s ...", binPath), ctrl)
sideload, err := con.Rpc.Sideload(context.Background(), &sliverpb.SideloadReq{
Expand All @@ -54,6 +57,7 @@ func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
EntryPoint: entryPoint,
ProcessName: processName,
Kill: !ctx.Flags.Bool("keep-alive"),
IsDLL: isDLL,
})
ctrl <- true
<-ctrl
Expand Down
1 change: 1 addition & 0 deletions client/command/extensions/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ func runExtensionCommand(ctx *grumble.Context, con *console.SliverConsoleClient)
EntryPoint: entryPoint,
ProcessName: processName,
Kill: true,
IsDLL: isDLL,
})
ctrl <- true
<-ctrl
Expand Down
6 changes: 6 additions & 0 deletions implant/sliver/taskrunner/task_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ func SpawnDll(procName string, data []byte, offset uint32, args string, kill boo
if err != nil {
return "", err
}
// {{if .Config.Debug}}
log.Printf("[*] Thread completed execution, attempting to kill remote process\n")
// {{end}}
cmd.Process.Kill()
return stdoutBuff.String() + stderrBuff.String(), nil
}
Expand Down Expand Up @@ -391,6 +394,9 @@ func waitForCompletion(threadHandle windows.Handle) error {
// {{end}}
return err
}
// {{if .Config.Debug}}
log.Printf("[!] Error: %v, code: %d\n", err, code)
// {{end}}
if code == syscalls.STILL_ACTIVE {
time.Sleep(time.Second)
} else {
Expand Down
2 changes: 1 addition & 1 deletion protobuf/clientpb/client.pb.go

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

2 changes: 1 addition & 1 deletion protobuf/commonpb/common.pb.go

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

2 changes: 1 addition & 1 deletion protobuf/rpcpb/services.pb.go

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

909 changes: 459 additions & 450 deletions protobuf/sliverpb/sliver.pb.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions protobuf/sliverpb/sliver.proto
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ message SideloadReq {
string Args = 3;
string EntryPoint = 4;
bool Kill = 5;
bool isDLL = 6;

commonpb.Request Request = 9;
}
Expand Down
19 changes: 14 additions & 5 deletions server/generate/donut.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,25 @@ func DonutShellcodeFromFile(filePath string, arch string, dotnet bool, params st
if err != nil {
return
}
donutType := getDonutType(filepath.Ext(filePath), dotnet)
return DonutShellcodeFromPE(pe, arch, dotnet, params, className, method, donutType)
isDLL := (filepath.Ext(filePath) == ".dll")
return DonutShellcodeFromPE(pe, arch, dotnet, params, className, method, isDLL)
}

// DonutShellcodeFromPE returns a Donut shellcode for the given PE file
func DonutShellcodeFromPE(pe []byte, arch string, dotnet bool, params string, className string, method string, donutType donut.ModuleType) (data []byte, err error) {
func DonutShellcodeFromPE(pe []byte, arch string, dotnet bool, params string, className string, method string, isDLL bool) (data []byte, err error) {
ext := ".exe"
if isDLL {
ext = ".dll"
}
donutArch := getDonutArch(arch)
// We don't use DonutConfig.Thread = 1 because we create our own remote thread
// in the task runner, and we're doing some housekeeping on it.
// Having DonutConfig.Thread = 1 means another thread will be created
// inside the one we created, and that will fuck up our monitoring
// since we can't grab a handle to the thread created by the Donut loader,
// and thus the waitForCompletion call will most of the time never complete.
config := donut.DonutConfig{
Type: donutType,
Type: getDonutType(ext, false),
InstType: donut.DONUT_INSTANCE_PIC,
Parameters: params,
Class: className,
Expand All @@ -33,7 +43,6 @@ func DonutShellcodeFromPE(pe []byte, arch string, dotnet bool, params string, cl
Arch: donutArch,
Entropy: 0, // 1=disable, 2=use random names, 3=random names + symmetric encryption (default)
Compress: uint32(1), // 1=disable, 2=LZNT1, 3=Xpress, 4=Xpress Huffman
Thread: 1, // start a new thread
ExitOpt: 1, // exit thread
Unicode: 0,
}
Expand Down
6 changes: 3 additions & 3 deletions server/rpc/rpc-tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"strings"

"github.com/Binject/debug/pe"
"github.com/binject/go-donut/donut"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/server/core"
Expand Down Expand Up @@ -149,7 +148,8 @@ func (rpc *Server) Sideload(ctx context.Context, req *sliverpb.SideloadReq) (*sl
timeout := rpc.getTimeout(req)
switch session.ToProtobuf().GetOS() {
case "windows":
shellcode, err := generate.ShellcodeRDIFromBytes(req.Data, req.EntryPoint, req.Args)
shellcode, err := generate.DonutShellcodeFromPE(req.Data, session.Arch, false, req.Args, "", "", req.IsDLL)
// shellcode, err := generate.ShellcodeRDIFromBytes(req.Data, req.EntryPoint, req.Args)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -237,7 +237,7 @@ func getSliverShellcode(name string) ([]byte, error) {
if err != nil {
return data, err
}
data, err = generate.DonutShellcodeFromPE(fileData, build.ImplantConfig.GOARCH, false, "", "", "", donut.DONUT_MODULE_EXE)
data, err = generate.DonutShellcodeFromPE(fileData, build.ImplantConfig.GOARCH, false, "", "", "", false)
if err != nil {
rpcLog.Errorf("DonutShellcodeFromPE error: %v\n", err)
return data, err
Expand Down

0 comments on commit f6351f7

Please sign in to comment.