← Back to list

Implementing Hell’s Gate Indirect Syscalls in Go for EDR Evasion

Implementing Hell’s Gate Indirect Syscalls in Go for EDR Evasion

Wadecalvin · 2026-04-25 14:19 · 0 claps · 1.3 min read
#cybersecurity #command-and-control #red-team #c2 #hacker
Open on Medium ↗
Wiki topics: SAF · Safety & Alignment 🔒 · Cybersecurity 🥊 · Combat Sports

Implementing Hell’s Gate Indirect Syscalls in Go for EDR Evasion

Implementing Hell’s Gate Indirect Syscalls in Go for EDR Evasion

Or: How I built a C2 agent that bypasses Windows Defender

The Problem

You’re on a red team engagement. You generate a Havoc payload. You execute it on Windows 11. Windows Defender catches it immediately.

This happened to me. Repeatedly.

Stock open-source C2 frameworks (Havoc, Sliver, Covenant) are heavily signatured. EDR vendors have had years to reverse them. The signatures aren’t just for the binaries anymore — they’re for the behaviors.

I decided to build a new C2 framework called ByteCode from scratch, with one priority:evasion.

After months of work, here are the results:

  • Undetected on Windows Defender (24H2)
  • Undetected on Triage, Any.Run, and Joe Sandbox

This post explains the core evasion technique: Hell’s Gate indirect syscalls implemented in Go

## Why Syscalls Matter

Most Windows APIs (CreateFile, WriteProcessMemory, etc.) eventually call into `ntdll.dll`, which transitions to the kernel via a `syscall` instruction.

EDRs hook these APIs **in user-mode** by patching `ntdll.dll`. When you call `CreateFile`, you're actually calling into the EDR's monitoring code first.

**The bypass:** Call the syscall directly, skipping `ntdll.dll` entirely.

But there's a catch. Syscall numbers (SSNs) change with every Windows version.

| API | Windows 10 20H2 | Windows 11 22H2 | Windows 11 24H2 |
|-----|-----------------|-----------------|-----------------|
| NtCreateFile | 0x55 | 0x55 | 0x56 |
| NtAllocateVirtualMemory | 0x18 | 0x18 | 0x19 |
| NtProtectVirtualMemory | 0x50 | 0x50 | 0x51 |

Hardcoding SSNs means your agent breaks on the next Windows update.

**The solution:** Hell's Gate — dynamically extract SSNs from `ntdll.dll` at runtime.

---

## Hell's Gate in Theory

Hell's Gate works in three steps:

1. **Parse `ntdll.dll` in memory** from `PEB->Ldr`
2. **Find target function** (e.g., `NtCreateFile`) by walking exports
3. **Extract SSN** from the function's assembly prologue

The prologue pattern for most syscall functions looks like:

```asm
mov r10, rcx
mov eax, SSN    ; <-- This byte is the syscall number
test byte ptr [r7], 0
syscall
ret

Repo Url: https://github.com/wadecalvin9/ByteCode.git


메타데이터
post_id
e528e1610df2
slug
implementing-hells-gate-indirect-syscalls-in-go-for-edr-evasion-e528e1610df2
url
https://medium.com/@wadecalvin9/implementing-hells-gate-indirect-syscalls-in-go-for-edr-evasion-e528e1610df2
canonical_url
https://medium.com/@wadecalvin9/implementing-hells-gate-indirect-syscalls-in-go-for-edr-evasion-e528e1610df2
author_url
https://medium.com/@wadecalvin9
status
ok
fetched_at
2026-06-09 21:21:26