OSEP study materials
OSEP study resources

OSEP common mistakes

OSEP · Understand the traps and how to avoid them.

Mistake 1

Spending the first hours building the exploit or payload, then treating the delivery mechanism (macro-enabled document, ISO/IMG container, HTML smuggling, LNK) as an afterthought and discovering at the end that the file opens in Protected View or is stripped by the mail gateway.

The exploit is the technically interesting part, so candidates build and debug it in isolation and only assemble the full chain under time pressure, when there is no budget left to redesign delivery.

What to do instead

Walk the full chain once with a benign payload (a dropper that only writes a marker file or beacons to a listener) before investing in the real payload. Confirm the document opens outside Protected View, the container survives the transfer method, and the child process actually launches from the parent application.

Mistake 2

Debugging the payload when no callback arrives, without first confirming that the target network can reach the listener at all (egress filtering, NAT, no route back to the attack host, wrong interface bound).

The payload is the visible artefact of the work, so a missing beacon is assumed to be a payload or AV problem, and hours are spent re-obfuscating something that was never blocked.

What to do instead

Before delivery, prove the return path: bind the listener to the reachable interface and confirm the target's egress rules permit the port/protocol. If a callback fails, check listener logs and target-side outbound connectivity before touching the payload.

Mistake 3

Treating encoding, packing, or string encryption as 'EDR evasion' and shipping a payload whose only defence is that a static signature no longer matches.

Candidates conflate antivirus with a file scanner and assume that if the file is not flagged on disk, execution will succeed; behaviour-based detections (script block logging, AMSI, ETW, userland API hooks, in-memory scanning) are never considered.

What to do instead

Enumerate the detection surface first: what is logged (command line, script content, module loads, process ancestry), what is scanned in memory, and what is hooked. Address each layer explicitly with a matching technique, and verify by observing the telemetry generated during execution rather than only the on-disk verdict.

Mistake 4

Developing and validating payloads in a VM where the real protection is disabled, excluded, or was never re-enabled after a snapshot revert, so the first honest test happens on the exam target.

Iteration is faster with protection off, so it is switched off early and never restored; snapshots silently carry the exclusion list forward.

What to do instead

Keep a clean snapshot with the same protection profile as the target and revert to it before every validation run. Confirm protection state (real-time status, exclusion list, tamper protection) before each test rather than assuming the snapshot is clean.

Mistake 5

Choosing an application-whitelisting or signed-binary bypass without first enumerating what is actually installed and permitted on the target host, then discovering the binary is absent, requires an interactive desktop, needs a specific runtime version, or writes to a blocked path.

Bypass techniques are learned as a catalogue of named binaries; candidates pick one that worked in a lab image and assume universality instead of matching it to the target's real constraints.

What to do instead

Enumerate installed binaries, versions, runtimes, and writable directories on the target first, shortlist candidates that exist there, and validate the chosen bypass on that host with a harmless command before using it as the payload's launch path.

Mistake 6

Running a directory-collection tool once at the start of the engagement and never re-collecting or marking owned principals after each new credential or host compromise.

Collection feels like a one-time reconnaissance step, and the ownership-marking feature is treated as bookkeeping rather than as an analysis input; the result is that the shortest path to the objective is computed from a stale map.

What to do instead

After every credential, hash, or host compromise, mark those principals as owned, re-collect, and re-query the path. Treat each acquisition as an event that can open new edges (sessions, local admin rights, delegation, ACLs) and re-run the analysis before deciding the next move.

Mistake 7

Assuming a credential grants administrative access on a target because it was privileged on a different host, or because it is a domain account, and then scripting it across a range of hosts instead of verifying on one.

Local administrator password reuse and 'domain account therefore powerful' are both partially true often enough that candidates skip the single-host check; the batch then produces mostly failures and ambiguous output that is hard to interpret.

What to do instead

Prove access on exactly one target with a minimal remote command or share check. Only after that succeeds, widen scope host by host, recording which credential worked on which host so the mapping can be reused later.

Mistake 8

Running the implant in a process or session that does not survive normal activity (a parent that exits, a console session that logs off, an exploited process that crashes), and then pivoting through a beacon that dies mid-operation.

The initial execution succeeds and the beacon appears, so stability is assumed; the failure mode only surfaces later when a logoff or process exit silently removes the foothold and the pivot chain collapses.

What to do instead

Launch the implant into a long-lived host process and explicitly test that the beacon reconnects after logging off and back on, after the original parent exits, and after the exploited service restarts. Re-establish a stable beacon before using a host as a pivot point.

Mistake 9

Issuing commands that expect an interactive terminal (sudo with a password prompt, su, ssh with a passphrase, editors, or anything reading from stdin) through a shell that has no TTY, causing the command to hang, fail, or kill the session.

The operator is working from a graphical terminal on their own machine and forgets that the reverse shell or command execution channel is a non-interactive pipe; the failure looks like a broken command rather than a missing terminal.

What to do instead

Spawn a PTY for anything interactive (for example a small Python pty spawn) or use the non-interactive form of every command: sudo with piped or validated credentials, ssh with key files and no passphrase, and flags that suppress prompts.

Mistake 10

Going straight for kernel exploits or noisy local escalation on a Linux host before checking the credential locations that are usually the intended path (shell history, SSH private keys, config files with embedded passwords, cron scripts, service unit files, backup and database files).

Kernel exploitation is the most familiar escalation narrative, so it is attempted first even when the scenario is designed around credential discovery; a failed kernel exploit against a mismatched build also risks crashing the host and losing the foothold.

What to do instead

Follow an ordered checklist before touching exploits: current user's privilege and group membership, readable home directories, history files, SSH keys and authorised_keys, configuration and environment files, schedulable jobs and writable scripts they call, and running services that reload configuration. Only move to exploit-based escalation when the checklist is exhausted.