Compare commits

...
Author SHA1 Message Date
Tim Makram Ghatas 1af9071e4d update handlers to use new callbacks struct 2024-05-08 15:22:32 +02:00
Tim Makram Ghatas be62e6f9e6 added callbacks struct and moved onFinish pointer to callbacks.onFinish 2024-05-08 11:44:26 +02:00
Joe 79d22bafbf Merge pull request #1669 from ngn13/wg-config-fix
fix: add missing newline
2024-05-05 10:56:55 -05:00
ngn 6396a64878 add missing newline
Signed-off-by: ngn <[email protected]>
2024-05-04 23:41:34 +00:00
Joe 335797e661 Merge pull request #1667 from BishopFox/docs/community-guides
Docs/community guides
2024-05-03 21:13:39 -05:00
moloch-- d767bd019c Add youtube embed component 2024-05-03 19:13:02 -07:00
moloch-- 590f9c3f96 Add youtube embed component 2024-05-03 18:59:42 -07:00
Joe cff899aa49 Merge pull request #1646 from testwill/close_resource
fix: close resource
2024-05-03 12:17:46 -05:00
Joe ca2dc9d267 Merge pull request #1665 from BishopFox/c2profile_update_bugfix
C2profile update bugfix
2024-05-03 12:17:19 -05:00
Ronan Kervella afdd77c642 Merge branch 'master' into close_resource 2024-05-03 09:21:54 -07:00
Ronan Kervella 8a5970c3da Merge branch 'master' into c2profile_update_bugfix 2024-05-03 09:21:40 -07:00
Ronan Kervella 2eb2ac8121 Merge pull request #1659 from C-Sto/bugfix-extensions
fix extension registration, run, and load flows
2024-05-03 09:21:29 -07:00
Ronan Kervella daf7d404b1 Merge branch 'master' into c2profile_update_bugfix 2024-05-03 09:21:23 -07:00
Ronan Kervella 3b308920f4 Merge branch 'master' into close_resource 2024-05-03 08:34:23 -07:00
Ronan Kervella c73b183f74 Merge branch 'master' into bugfix-extensions 2024-05-03 08:32:44 -07:00
Ronan Kervella 7564312f5e Merge pull request #1666 from BishopFox/v1.6.0/fix-alias-hostproc
Fix Default Linux Host Process for Aliases
2024-05-03 08:32:22 -07:00
Raf 6134b78afb Fix default linux host process for aliases 2024-05-03 08:24:32 -04:00
Ronan Kervella 3db9946608 Merge branch 'master' into bugfix-extensions 2024-05-02 14:11:02 -07:00
Joe ef09058498 Merge pull request #1664 from BishopFox/v1.6.0/ls-rootdir
Adding root directory entry to `ls` command
2024-05-02 16:06:46 -05:00
Tim Makram Ghatas 331faeb8ef fix commandline paramameters for profile staging 2024-05-02 20:30:33 +02:00
Tim Makram Ghatas 4ae195e3eb fix c2 profile update issue with headers, cookies and segments 2024-05-02 19:09:46 +02:00
Ronan Kervella f8f8ba5864 Merge branch 'master' into bugfix-extensions 2024-05-02 09:59:25 -07:00
Raf 216e3b9759 Adds an entry in the directory listing returned by ls for the root directory ('.'). 2024-05-02 12:12:32 -04:00
Joe f1bc5074f9 Merge pull request #1663 from BishopFox/docs/compile-from-source
Add to index
2024-05-01 21:40:10 -05:00
Joe 1b5d3436eb Merge pull request #1662 from BishopFox/docs/compile-from-source
Improve compile from source docs
2024-05-01 21:23:20 -05:00
Joe 9397fcb4ae Merge pull request #1661 from BishopFox/fix_stage_encoder
fix merge error for stage encoders
2024-05-01 20:11:35 -05:00
Joe 04c6c3f800 Merge pull request #1658 from C-Sto/bugfix-extensionnoargs
fix: handle noargs case
2024-05-01 20:08:17 -05:00
C-Sto 7842a6c4c6 add init back in, handle nils/zero values more elegantly 2024-05-02 08:49:21 +08:00
Tim Makram Ghatas 6c815a4432 fix merge error for stage encoders 2024-05-02 02:06:54 +02:00
C-Sto 81358e31bb fix extension registration, run, and load flows 2024-05-01 12:31:19 +08:00
C-Sto 7bea772dbd fix: handle noargs case 2024-05-01 12:15:33 +08:00
guangwu 7fe0b295f5 fix: close resource
Signed-off-by: guangwu <[email protected]>
2024-04-25 20:54:30 +08:00
18 changed files with 338 additions and 65 deletions

No files matched your search

+1 -1
View File
@@ -57,7 +57,7 @@ var (
defaultHostProc = map[string]string{
"windows": windowsDefaultHostProc,
"linux": windowsDefaultHostProc,
"linux": linuxDefaultHostProc,
"darwin": macosDefaultHostProc,
}
)
+101 -33
View File
@@ -99,6 +99,7 @@ type ExtCommand struct {
Arguments []*extensionArgument `json:"arguments"`
Entrypoint string `json:"entrypoint"`
DependsOn string `json:"depends_on"`
Init string `json:"init"`
Manifest *ExtensionManifest
}
@@ -371,38 +372,50 @@ func loadExtension(goos string, goarch string, checkCache bool, ext *ExtCommand,
}
extensionList = extList.Names
}
depLoaded := false
//extensionList contains all *implant* loaded extensions. Is a sha256 sum of the relevant file.
//get the file hash to compare against implant extensions later
toberunfilepath, err := ext.getFileForTarget(goos, goarch)
if err != nil {
return err
}
//we need to check the dependent if it's a bof
if ext.DependsOn != "" {
//verify extension is in loaded list
if extension, found := loadedExtensions[ext.DependsOn]; found {
toberunfilepath, err = extension.getFileForTarget(goos, goarch)
if err != nil {
return err
}
} else {
// handle error
return fmt.Errorf("attempted to load non-existing extension: %s", ext.DependsOn)
}
}
//todo, maybe cache these values somewhere
toberunfiledata, err := os.ReadFile(toberunfilepath)
if err != nil {
return err
}
if len(toberunfiledata) == 0 {
//read an empty file, bail out
return errors.New("read empty extension file content")
}
bd := sha256.Sum256(toberunfiledata)
toberunhash := hex.EncodeToString(bd[:])
for _, extName := range extensionList {
if !depLoaded {
if extN, ok := loadedExtensions[cmd.Name()]; ok && extName == extN.DependsOn {
depLoaded = true
}
}
//check if the file suffixes are the same (should only be relevant to the same extension package), and don't load the file if it's already there
extN := loadedExtensions[cmd.Name()]
if extN != nil {
//confirm we haven't already loaded the file
for _, extf := range extN.Files {
if strings.HasSuffix(binPath, extf.Path) {
//file already exists, no need to load it
return nil
}
}
}
if extN, ok := loadedExtensions[cmd.Name()]; ok && extN.CommandName == extName {
//check if extension we are trying to run (ext.CommandName or ext.DependsOn, for bofs) is already loaded
if extName == toberunhash {
//exists on the other side, exit early
return nil
}
}
// Extension not found, let's load it
if filepath.Ext(binPath) == ".o" {
// 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(goos, goarch, ext.DependsOn, cmd, con); errLoad != nil {
return errLoad
}
}
return nil
// BOFs are not loaded by the DLL loader, but we need to load the loader (more load more good)
if ext.DependsOn != "" {
return loadDep(goos, goarch, ext.DependsOn, cmd, con)
}
binData, err := os.ReadFile(binPath)
if err != nil {
@@ -414,17 +427,45 @@ func loadExtension(goos string, goarch string, checkCache bool, ext *ExtCommand,
return nil
}
func registerExtension(goos string, _ *ExtCommand, binData []byte, cmd *cobra.Command, con *console.SliverClient) error {
func registerExtension(goos string, ext *ExtCommand, binData []byte, cmd *cobra.Command, con *console.SliverClient) error {
//set extension name to a hash of the data to avoid loading more than one instance
bd := sha256.Sum256(binData)
name := hex.EncodeToString(bd[:])
sess, beac := con.ActiveTarget.GetInteractive()
ctrl := make(chan bool)
//first time run of an extension will require some waiting depending on the size
if sess != nil {
msg := fmt.Sprintf("Sending %s to implant ...", ext.CommandName)
con.SpinUntil(msg, ctrl)
}
//don't block if we are in beacon mode
if beac != nil && sess == nil {
go func() {
registerResp, err := con.Rpc.RegisterExtension(context.Background(), &sliverpb.RegisterExtensionReq{
Name: name,
Data: binData,
OS: goos,
Init: ext.Init,
Request: con.ActiveTarget.Request(cmd),
})
if err != nil {
con.PrintErrorf("Error registering extension: %s\n", err)
}
if registerResp.Response != nil && registerResp.Response.Err != "" {
con.PrintErrorf("Error registering extension: %s\n", errors.New(registerResp.Response.Err))
}
}()
return nil
}
//session mode (hopefully)
registerResp, err := con.Rpc.RegisterExtension(context.Background(), &sliverpb.RegisterExtensionReq{
Name: name,
Data: binData,
OS: goos,
//Init: ext.Init, ?
Name: name,
Data: binData,
OS: goos,
Request: con.ActiveTarget.Request(cmd),
})
ctrl <- true
<-ctrl
if err != nil {
return err
}
@@ -525,6 +566,33 @@ func runExtensionCmd(cmd *cobra.Command, con *console.SliverClient, args []strin
}
bd := sha256.Sum256(extdata)
name := hex.EncodeToString(bd[:])
if isBOF {
//if we are using a bof, we are actually calling the coffloader extension - so get the file from dep ref and use that shasum
if extension, found := loadedExtensions[ext.DependsOn]; found {
dep, err := extension.getFileForTarget(goos, goarch)
if err != nil {
con.PrintErrorf("could not get file for extension %s", ext.DependsOn)
return
}
depdata, err := os.ReadFile(dep)
if err != nil {
con.PrintErrorf("dep read file error: %s\n", err)
return
}
if len(depdata) == 0 {
con.PrintErrorf("read empty file: %s\n", dep)
return
}
bd = sha256.Sum256(depdata)
name = hex.EncodeToString(bd[:])
} else {
// handle error
con.PrintErrorf("attempted to load non-existing extension: %s", ext.DependsOn)
return
}
}
callExtResp, err := con.Rpc.CallExtension(context.Background(), &sliverpb.CallExtensionReq{
Name: name,
Export: entryPoint,
@@ -579,7 +647,7 @@ func getExtArgs(_ *cobra.Command, args []string, _ string, ext *ExtCommand) ([]b
missingRequiredArgs := make([]string, 0)
// If we have an extension that expects a single string, but more than one has been parsed, combine them
if len(ext.Arguments) == 1 && strings.Contains(ext.Arguments[0].Type, "string") {
if len(ext.Arguments) == 1 && strings.Contains(ext.Arguments[0].Type, "string") && len(args) > 0 {
// The loop below will only read the first element of args because ext.Arguments is 1
args[0] = strings.Join(args, " ")
}
+22
View File
@@ -184,6 +184,28 @@ func Commands(con *console.SliverClient) []*cobra.Command {
}
profilesCmd.AddCommand(profilesNewCmd)
profilesStageCmd := &cobra.Command{
Use: consts.StageStr,
Short: "Generate implant from a profile and encode or encrypt it",
Args: cobra.ExactArgs(1),
Long: help.GetHelpFor([]string{consts.ProfilesStr, consts.StageStr}),
Run: func(cmd *cobra.Command, args []string) {
ProfilesStageCmd(cmd, con, args)
},
}
flags.Bind("profiles", false, profilesStageCmd, func(f *pflag.FlagSet) {
f.StringP("save", "s", "", "directory/file to the binary to")
f.StringP("name", "n", "", "Implant name")
f.StringP("aes-encrypt-key", "k", "", "AES Encryption Key")
f.StringP("aes-encrypt-iv", "i", "", "AES Encryption IV")
f.StringP("rc4-encrypt-key", "r", "", "RC4 encryption key")
f.BoolP("prepend-size", "p", false, "Prepend stage size")
f.StringP("compress", "c", "", "Compress stage (zlib, gzip, deflate9 or deflate)")
})
carapace.Gen(profilesStageCmd).PositionalCompletion(ProfileNameCompleter(con))
profilesCmd.AddCommand(profilesStageCmd)
// Session flags and completions.
coreImplantFlags("session", profilesNewCmd)
compileImplantFlags("session", profilesNewCmd)
+4
View File
@@ -108,6 +108,7 @@ var (
// Profiles
consts.ProfilesStr + sep + consts.NewStr: newProfileHelp,
consts.ProfilesStr + sep + consts.GenerateStr: generateProfileHelp,
consts.ProfilesStr + sep + consts.StageStr: generateProfileStageHelp,
// Reactions
consts.ReactionStr: reactionHelp,
@@ -249,6 +250,9 @@ settings. Generated implants will still have per-binary certificates/obfuscation
generateProfileHelp = `[[.Bold]]Command:[[.Normal]] generate [name] <options>
[[.Bold]]About:[[.Normal]] Generate an implant from a saved profile (see 'profiles new --help').`
generateProfileStageHelp = `[[.Bold]]Command:[[.Normal]] stage [name] <options>
[[.Bold]]About:[[.Normal]] Generate and encrypt or encode an implant from a saved profile (see 'profiles stage --help').`
msfHelp = `[[.Bold]]Command:[[.Normal]] msf [--lhost] <options>
[[.Bold]]About:[[.Normal]] Execute a metasploit payload in the current process.`
+2
View File
@@ -264,11 +264,13 @@ func downloadAsset(client *http.Client, asset *version.Asset, saveTo string) err
if err != nil {
return err
}
defer writer.Close()
resp, err := client.Get(asset.BrowserDownloadURL)
if err != nil {
return err
}
defer resp.Body.Close()
bar := pb.Full.Start64(limit)
barReader := bar.NewProxyReader(resp.Body)
+1 -1
View File
@@ -88,7 +88,7 @@ func WGConfigCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
save, _ := cmd.Flags().GetString("save")
if save == "" {
con.PrintInfof("New client config:")
con.PrintInfof("New client config:\n")
con.Println(output.String())
} else {
if !strings.HasSuffix(save, ".conf") {
+6
View File
@@ -7,6 +7,7 @@ import { useRouter } from "next/router";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import AsciinemaPlayer from "./asciinema";
import Youtube from "./youtube";
export type MarkdownProps = {
key?: string;
@@ -131,6 +132,11 @@ const MarkdownViewer = (props: MarkdownProps) => {
);
}
if (lang === "youtube") {
const embedId = (children as string) || "";
return <Youtube embedId={embedId.trim()} />;
}
if (lang === "asciinema") {
const asciiCast: MarkdownAsciiCast = JSON.parse(
children as string
+22
View File
@@ -0,0 +1,22 @@
export type YoutubeProps = {
className?: string;
width?: number;
height?: number;
embedId: string;
};
export default function Youtube(props: YoutubeProps) {
return (
<div className={props.className}>
<iframe
width={`${props.width ? props.width : 640}`}
height={`${props.height ? props.height : 360}`}
src={`https://youtu.be/embed/${props.embedId}`}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
/>
</div>
);
}
+1 -2
View File
@@ -2,7 +2,7 @@ import Document, { Head, Html, Main, NextScript } from "next/document";
import React from "react";
// This generates the https: and wss: "connect-src" directives based on the above backends list so its a little easier to edit.
const CSP = `default-src 'none'; script-src 'self' 'unsafe-eval'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'`;
const CSP = `default-src 'none'; script-src 'self' 'unsafe-eval'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; frame-src https://youtu.be; connect-src 'self'`;
class MyDocument extends Document {
static async getInitialProps(ctx: any) {
@@ -17,7 +17,6 @@ class MyDocument extends Document {
return (
<Html lang="en">
<Head>
<title>Sliver Docs</title>
<meta httpEquiv="Content-Security-Policy" content={CSP} />
</Head>
<body>
@@ -7,10 +7,10 @@
### Videos
- https://youtu.be/3R6WKUgN0K4?t=456
- https://www.youtube.com/watch?v=QO_1UMaiWHk
- https://www.youtube.com/watch?v=izMMmOaLn9g
- https://www.youtube.com/watch?v=qIbrozlf2wM
- https://www.youtube.com/watch?v=CKfjLnEMfvI
- https://youtu.be/watch?v=QO_1UMaiWHk
- https://youtu.be/watch?v=izMMmOaLn9g
- https://youtu.be/watch?v=qIbrozlf2wM
- https://youtu.be/watch?v=CKfjLnEMfvI
### Blogs
+9 -3
View File
@@ -28,9 +28,15 @@ import (
var extensions map[string]Extension
type Callbacks struct {
SendData func([]byte)
OnFinish func([]byte)
SendError func([]byte)
}
type Extension interface {
Load() error
Call(exportName string, arguments []byte, callback func([]byte)) error
Call(exportName string, arguments []byte, callbacks Callbacks) error
GetID() string
GetArch() string
}
@@ -47,9 +53,9 @@ func List() []string {
return extList
}
func Run(extID string, funcName string, arguments []byte, callback func([]byte)) error {
func Run(extID string, funcName string, arguments []byte, callbacks Callbacks) error {
if ext, found := extensions[extID]; found {
return ext.Call(funcName, arguments, callback)
return ext.Call(funcName, arguments, callbacks)
}
// {{if .Config.Debug}}
for id, ext := range extensions {
+2 -2
View File
@@ -85,7 +85,7 @@ func (d *DarwinExtension) Load() error {
return nil
}
func (d *DarwinExtension) Call(export string, arguments []byte, onFinish func([]byte)) error {
func (d *DarwinExtension) Call(export string, arguments []byte, callbacks Callbacks) error {
// We currently have 2 issues with Darwin extensions:
// - cppgo (used by universal) fucks up when calling a function with more than 1 argument
// - we don't have Go callback support for the loaded extension,
@@ -124,7 +124,7 @@ func (d *DarwinExtension) Call(export string, arguments []byte, onFinish func([]
// We currently don't have a way to trigger a callback
// in the loaded code for Darwin.
if outData.Len() > 0 {
onFinish(outData.Bytes())
callbacks.OnFinish(outData.Bytes())
}
return nil
}
+17 -5
View File
@@ -36,6 +36,12 @@ const (
Failure = 1
)
type CallbacksPtr struct {
sendData uintptr
onFinish uintptr
sendError uintptr
}
type WindowsExtension struct {
id string
data []byte
@@ -92,15 +98,21 @@ func (w *WindowsExtension) Load() error {
}
// Call - Call an extension export
func (w *WindowsExtension) Call(export string, arguments []byte, onFinish func([]byte)) error {
func (w *WindowsExtension) Call(export string, arguments []byte, callbacks Callbacks) error {
var (
argumentsPtr uintptr
argumentsSize uintptr
argumentsPtr uintptr
argumentsSize uintptr
callbacksPtr CallbacksPtr
callbacksStructPtr uintptr
)
if w.module == nil {
return errors.New("{{if .Config.Debug}} module not loaded {{end}}")
}
callback := syscall.NewCallback(newWindowsExtensionCallback(onFinish))
callbacksPtr.onFinish = syscall.NewCallback(newWindowsExtensionCallback(callbacks.OnFinish))
callbacksPtr.sendData = syscall.NewCallback(newWindowsExtensionCallback(callbacks.SendData))
callbacksPtr.sendError = syscall.NewCallback(newWindowsExtensionCallback(callbacks.SendError))
callbacksStructPtr = uintptr(unsafe.Pointer(&callbacks))
exportPtr, err := w.module.ProcAddressByName(export)
if err != nil {
return err
@@ -117,7 +129,7 @@ func (w *WindowsExtension) Call(export string, arguments []byte, onFinish func([
// where goCallback = int(char *, int)
w.Lock()
defer w.Unlock()
_, _, errNo := syscall.Syscall(exportPtr, 3, argumentsPtr, argumentsSize, callback)
_, _, errNo := syscall.Syscall(exportPtr, 3, argumentsPtr, argumentsSize, callbacksStructPtr)
if errNo != 0 {
return errors.New(errNo.Error())
}
+30 -6
View File
@@ -155,7 +155,7 @@ func dirListHandler(data []byte, resp RPCResponse) {
path, filter := determineDirPathFilter(targetPath)
dir, files, err := getDirList(path)
dir, rootDirEntry, files, err := getDirList(path)
// Convert directory listing to protobuf
timezone, offset := time.Now().Zone()
@@ -166,6 +166,19 @@ func dirListHandler(data []byte, resp RPCResponse) {
dirList.Exists = false
}
dirList.Files = []*sliverpb.FileInfo{}
rootDirInfo, err := rootDirEntry.Info()
if err == nil && filter == "" {
// We should not get an error because we created the DirEntry object from the FileInfo object
dirList.Files = append(dirList.Files, &sliverpb.FileInfo{
Name: ".", // Cannot use the name from the FileInfo / DirEntry because that is the name of the directory
Size: rootDirInfo.Size(),
ModTime: rootDirInfo.ModTime().Unix(),
Mode: rootDirInfo.Mode().String(),
Uid: getUid(rootDirInfo),
Gid: getGid(rootDirInfo),
IsDir: rootDirInfo.IsDir(),
})
}
var match bool = false
var linkPath string = ""
@@ -226,19 +239,30 @@ func dirListHandler(data []byte, resp RPCResponse) {
resp(data, err)
}
func getDirList(target string) (string, []fs.DirEntry, error) {
func getDirList(target string) (string, fs.DirEntry, []fs.DirEntry, error) {
dir, err := filepath.Abs(target)
if err != nil {
// {{if .Config.Debug}}
log.Printf("dir list failed to construct path %s", err)
// {{end}}
return "", nil, err
return "", nil, nil, err
}
if _, err := os.Stat(dir); !os.IsNotExist(err) {
if rootInfo, err := os.Stat(dir); !os.IsNotExist(err) {
/*
We could place the entry for the directory itself
at the beginning of the returned slice of DirEntry
objects, but then it is not clear if that is the
root directory or a directory / file in the root
directory with the same name as the root directory.
Using WalkDir is not great here because you cannot
tell it to not be recursive, so we will be wasting
cycles telling it to skip directories and files
*/
files, err := os.ReadDir(dir)
return dir, files, err
return dir, fs.FileInfoToDirEntry(rootInfo), files, err
}
return dir, []fs.DirEntry{}, errors.New("directory does not exist")
return dir, nil, []fs.DirEntry{}, errors.New("directory does not exist")
}
func rmHandler(data []byte, resp RPCResponse) {
+22 -1
View File
@@ -122,11 +122,32 @@ func callExtensionHandler(data []byte, resp RPCResponse) {
Response: &commonpb.Response{},
}
gotOutput := false
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, func(out []byte) {
onFinish := func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
sendData := func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
sendError := func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, extension.Callbacks{
OnFinish: onFinish,
SendData: sendData,
SendError: sendError,
})
// Only send back synchronously if there was an error
if err != nil || !gotOutput {
+15 -2
View File
@@ -31,8 +31,8 @@ import (
"time"
"unsafe"
"github.com/bishopfox/sliver/implant/sliver/procdump"
"github.com/bishopfox/sliver/implant/sliver/mount"
"github.com/bishopfox/sliver/implant/sliver/procdump"
"github.com/bishopfox/sliver/implant/sliver/taskrunner"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
@@ -190,7 +190,7 @@ func memfilesListHandler(_ []byte, resp RPCResponse) {
pid := os.Getpid()
path := fmt.Sprintf("/proc/%d/fd/", pid)
dir, files, err := getDirList(path)
dir, rootDirEntry, files, err := getDirList(path)
// Convert directory listing to protobuf
timezone, offset := time.Now().Zone()
@@ -201,6 +201,19 @@ func memfilesListHandler(_ []byte, resp RPCResponse) {
dirList.Exists = false
}
dirList.Files = []*sliverpb.FileInfo{}
rootDirInfo, err := rootDirEntry.Info()
if err == nil {
// We should not get an error because we created the DirEntry object from the FileInfo object
dirList.Files = append(dirList.Files, &sliverpb.FileInfo{
Name: ".", // Cannot use the name from the FileInfo / DirEntry because that is the name of the directory
Size: rootDirInfo.Size(),
ModTime: rootDirInfo.ModTime().Unix(),
Mode: rootDirInfo.Mode().String(),
Uid: getUid(rootDirInfo),
Gid: getGid(rootDirInfo),
IsDir: rootDirInfo.IsDir(),
})
}
for _, dirEntry := range files {
//log.Printf("File: %s\n", dirEntry.Name())
+21 -1
View File
@@ -924,11 +924,31 @@ func callExtensionHandler(data []byte, resp RPCResponse) {
callResp := &sliverpb.CallExtension{Response: &commonpb.Response{}}
gotOutput := false
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, func(out []byte) {
var onFinish = func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
var sendData = func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
var sendError = func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, extension.Callbacks{
OnFinish: onFinish,
SendData: sendData,
SendError: sendError,
})
// Only send back synchronously if there was an error
if err != nil || !gotOutput {
+58 -4
View File
@@ -436,20 +436,74 @@ func SaveHTTPC2Config(httpC2Config *clientpb.HTTPC2Config) error {
func HTTPC2ConfigUpdate(newConf *clientpb.HTTPC2Config, oldConf *clientpb.HTTPC2Config) error {
clientID, _ := uuid.FromString(oldConf.ImplantConfig.ID)
c2Config := models.HTTPC2ConfigFromProtobuf(newConf)
err := Session().Where(&models.ImplantConfig{
err := Session().Where(&models.HttpC2PathSegment{
HttpC2ImplantConfigID: clientID,
}).Delete(&models.HttpC2PathSegment{})
if err.Error != nil {
return err.Error
}
err = Session().Where(&models.ImplantConfig{
ID: clientID,
}).Updates(c2Config.ImplantConfig)
if err != nil {
if err.Error != nil {
return err.Error
}
for _, segment := range c2Config.ImplantConfig.PathSegments {
segment.HttpC2ImplantConfigID = clientID
err = Session().Clauses(clause.OnConflict{
UpdateAll: true,
}).Create(&segment)
if err.Error != nil {
return err.Error
}
}
serverID, _ := uuid.FromString(oldConf.ServerConfig.ID)
err = Session().Where(&models.HttpC2Cookie{
HttpC2ServerConfigID: serverID,
}).Delete(&models.HttpC2Cookie{})
if err.Error != nil {
return err.Error
}
err = Session().Where(&models.HttpC2Header{
HttpC2ServerConfigID: serverID,
}).Delete(&models.HttpC2Header{})
if err.Error != nil {
return err.Error
}
serverID, _ := uuid.FromString(oldConf.ImplantConfig.ID)
err = Session().Where(&models.HttpC2ServerConfig{
ID: serverID,
}).Updates(c2Config.ServerConfig)
if err != nil {
if err.Error != nil {
return err.Error
}
for _, cookie := range c2Config.ServerConfig.Cookies {
cookie.HttpC2ServerConfigID = serverID
err = Session().Clauses(clause.OnConflict{
UpdateAll: true,
}).Create(&cookie)
if err.Error != nil {
return err.Error
}
}
for _, header := range c2Config.ServerConfig.Headers {
header.HttpC2ServerConfigID = serverID
err = Session().Clauses(clause.OnConflict{
UpdateAll: true,
}).Create(&header)
if err.Error != nil {
return err.Error
}
}
return nil
}