<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://playingwithpackets.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://playingwithpackets.com/" rel="alternate" type="text/html" /><updated>2026-06-11T17:19:30+00:00</updated><id>https://playingwithpackets.com/feed.xml</id><title type="html">Playing with Packets</title><subtitle>Detection writeups, adversary infra research, deception, and threat hunting.</subtitle><author><name>Tyler Bohlmann</name></author><entry><title type="html">Inside a Chokepoint Entry: A ClickFix Walkthrough</title><link href="https://playingwithpackets.com/blog/inside-a-chokepoint-entry/" rel="alternate" type="text/html" title="Inside a Chokepoint Entry: A ClickFix Walkthrough" /><published>2026-06-08T00:00:00+00:00</published><updated>2026-06-08T00:00:00+00:00</updated><id>https://playingwithpackets.com/blog/inside-a-chokepoint-entry</id><content type="html" xml:base="https://playingwithpackets.com/blog/inside-a-chokepoint-entry/"><![CDATA[<p>In the <a href="/blog/detection-chokepoints-where-to-start/">Detection Chokepoints</a> post I made the case
for anchoring detection to the one step an attacker can’t avoid. That’s the idea. This post is the
practical side: what an actual entry gives you and how to work through one. I’ll use the
<a href="https://iimp0ster.github.io/detection-chokepoints/chokepoints/clickfix-techniques/">ClickFix entry</a>
as the tour, since it’s a technique most defenders are already fighting.</p>

<h2 id="the-constant-up-top">The constant, up top</h2>

<p>Every entry leads with the invariant, the thing that doesn’t change. For ClickFix it’s:</p>

<blockquote>
  <p>Clipboard write → user pastes into interpreter → outbound C2 connection.</p>
</blockquote>

<p>Alongside it you get the quick read on the technique: severity (HIGH), prevalence (HIGH),
detection difficulty (LOW), and the ATT&amp;CK mapping (T1204.004, malicious copy-paste). That one
line is the whole reason the entry exists. It holds across every variant the project tracks, so
if you instrument it, you’re not chasing names.</p>

<h2 id="the-chokepoint-broken-into-stages">The chokepoint, broken into stages</h2>

<p>The entry doesn’t hand you a single rule. It breaks the invariant into the stages the attacker
has to move through, and each stage is its own detection opportunity:</p>

<ol>
  <li><strong>Clipboard Seeding</strong>: the lure page writes a command to the clipboard via JavaScript <em>and</em>
shows paste instructions. Both have to be true; that co-occurrence is the tell.</li>
  <li><strong>Interpreter Execution</strong>: a script interpreter spawns as a child of <code class="language-plaintext highlighter-rouge">explorer.exe</code>, a
browser, or <code class="language-plaintext highlighter-rouge">wt.exe</code>.</li>
  <li><strong>Second Stage Retrieval</strong>: the interpreter reaches out to attacker infrastructure to pull
the real payload.</li>
</ol>

<p>The reason this matters: if one stage is blind in your environment, you still have two more shots
at it. You’re not betting the detection on a single event.</p>

<h2 id="detection-at-the-tier-your-soc-can-actually-run">Detection at the tier your SOC can actually run</h2>

<p>Each stage carries rules at the maturity tiers, and, where it’s possible, earlier pre-execution
options like an ETW clipboard-write rule or an IOK rule on the lure page itself. For every rule
the entry spells out:</p>

<ul>
  <li><strong>Goal</strong>: what the rule is trying to catch</li>
  <li><strong>Log / Data Sources</strong>: what you need to be collecting for it to work</li>
  <li><strong>FP Rate</strong>: how noisy it’ll be</li>
  <li><strong>Use Case</strong>: when to deploy it (baseline, hunt, or production alert)</li>
  <li><strong>Detection Logic</strong>: the condition in plain pseudocode</li>
  <li><strong>Bypass Risk</strong>: how it can be evaded, stated honestly</li>
  <li><strong>Sigma rule</strong>: the full YAML, copy it or pull it from GitHub</li>
</ul>

<p>So you’re not just told “detect ClickFix.” You’re told what to deploy, where, and what it’ll cost
you in noise, which is the part that decides whether a detection survives contact with a real SOC.</p>

<h2 id="variations-the-proof-the-chokepoint-holds">Variations: the proof the chokepoint holds</h2>

<p>The entry tracks nine variants: the original ClickFix, FileFix, TerminalFix, DownloadFix, the
JackFix/GlitchFix/ConsentFix family, WebDAV ClickFix, InstallFix, a Windows Terminal version that
parents off <code class="language-plaintext highlighter-rouge">wt.exe</code>, and a DNS-based one that stages its payload through <code class="language-plaintext highlighter-rouge">nslookup</code> to dodge URL
filtering. Each one shows the lure the user sees, a defanged copy of the clipboard payload, and a
one-line note that it routes through the <em>same</em> chokepoint.</p>

<p>That’s the point of the section. It’s not a list to memorize: it’s evidence. Every new lure since
2024 still funnels through clipboard seeding, interpreter execution, and a network callback. The
constant held.</p>

<h2 id="the-evidence-and-a-way-to-generate-it-yourself">The evidence, and a way to generate it yourself</h2>

<p>Two sections I lean on the most. <strong>Raw Log Samples</strong> shows the real Sysmon events the chain
produces: process creation (the interpreter spawning), the DNS query, and the outbound network
connection, so you know exactly what you’re looking for before you go looking. And <strong>Emulation</strong>
gives you a lab-only script that reproduces the behavior, so you can fire the chain in a controlled
box and confirm your rules actually trigger. I don’t deploy a detection I’ve never watched fire,
and this is how you avoid having to.</p>

<p>Rounding it out, <strong>OSINT Pivots</strong> gives URLScan and VirusTotal queries to hunt the infrastructure,
and <strong>Related Chokepoints</strong> links out to the entries this commonly chains with (Renamed RMM Tools,
Ransomware Service Manipulation) so you can follow the kill chain instead of stopping at one step.</p>

<h2 id="thats-the-whole-shape">That’s the whole shape</h2>

<p>Invariant up top, staged detections in the middle, variants and raw telemetry to back it,
emulation to test it. Every chokepoint in the project is built the same way; ClickFix is just a
good one to learn on. Pick the stage your telemetry already covers, deploy the Research-tier rule,
watch it in your environment, and climb from there.</p>

<p>Browse it for yourself:
<a href="https://iimp0ster.github.io/detection-chokepoints/chokepoints/clickfix-techniques/"><strong>the ClickFix entry</strong></a>.</p>]]></content><author><name>Tyler Bohlmann</name></author><category term="detection" /><category term="chokepoints" /><category term="clickfix" /><category term="sigma" /><summary type="html"><![CDATA[The chokepoints post made the case for anchoring detection to what attackers can't avoid. This one is the practical side: what an actual entry gives you, walked through with ClickFix.]]></summary></entry><entry><title type="html">Detection Chokepoints: Where to Start</title><link href="https://playingwithpackets.com/blog/detection-chokepoints-where-to-start/" rel="alternate" type="text/html" title="Detection Chokepoints: Where to Start" /><published>2026-06-01T00:00:00+00:00</published><updated>2026-06-01T00:00:00+00:00</updated><id>https://playingwithpackets.com/blog/detection-chokepoints-where-to-start</id><content type="html" xml:base="https://playingwithpackets.com/blog/detection-chokepoints-where-to-start/"><![CDATA[<p>If you do detection work long enough, you start to notice the same pattern. A new loader
shows up, then a renamed RMM campaign, then a fresh phishing kit, and each one gets its own
detection. You write it, ship it, and move on to the next report. The problem is what most of
those detections are pinned to (a file name, a hash, a specific tool) is the part the attacker
fully controls. They can recompile, rename, or swap the whole framework for free. Pin your rule
to <code class="language-plaintext highlighter-rouge">mimikatz.exe</code> and you’ve signed up to lose the moment someone changes a filename.</p>

<figure class="post-screenshot">
  <div class="post-screenshot-frame">
    <img src="/assets/img/posts/detection-chokepoints-where-to-start/de_life.png" alt="A wall of recent security headlines: new ransomware variants, EDR bypasses, infostealers, and ClickFix surges" loading="lazy" />
  </div>
  
  <figcaption>A normal week of headlines. This is the job: a new variant, a fresh bypass, another stealer, every single day. You can't ship a detection per headline; chokepoints are how you stop trying to.</figcaption>
  
</figure>

<p>A better way to think about it is to flip the question. Instead of asking what the attacker is
using, ask what part of this they <em>can’t</em> change.</p>

<figure class="post-pixel-art">
  <div class="post-pixel-art-frame">
    <img src="/assets/img/pixel/concepts/chokepoint.png" alt="A steel bear trap with a glowing trigger plate" loading="lazy" />
  </div>
  
  <figcaption>A chokepoint is the one step the attacker can't route around, so it's where you wait for them.</figcaption>
  
</figure>

<h2 id="what-a-chokepoint-actually-is">What a chokepoint actually is</h2>

<p>The term comes from military strategy. You force an opponent into a narrow passage they have to
move through to reach their objective, and that bottleneck is where you hold the advantage: they
can’t bring their full strength through it. It isn’t a new idea in detection engineering, either.
The chokepoint language I use comes straight out of Matt Graeber’s threat research at Red Canary.
The way he framed how to research a technique (work through what has to be true for it to succeed,
then find the step the attacker can’t control) stuck with me, and it’s genuinely how I think about
threats now. That step they can’t control is the chokepoint, and it’s where durable detection lives.</p>

<p>Take credential theft from LSASS. There are a lot of tools that do it (Mimikatz, <code class="language-plaintext highlighter-rouge">comsvcs.dll</code>,
ProcDump, Nanodump, the credential-dumping built-ins in just about every C2 framework) and they
all use different code, different syscalls, and different tricks to stay quiet. But every one of
them has to do the same thing:</p>

<blockquote>
  <p>Open a handle to <code class="language-plaintext highlighter-rouge">lsass.exe</code> and read its memory to get at the credential material.</p>
</blockquote>

<p>The kernel mediates that handle. You can’t read the memory without it. The tooling has rotated
for over a decade (the LOLBin era, direct syscalls, handle duplication, BYOVD PPL bypasses) and
that one step never moved. It can’t, because it’s the mechanism of the technique. That’s the
chokepoint.</p>

<h2 id="detection-is-a-game-of-economics">Detection is a game of economics</h2>

<p>Anchoring to an invariant isn’t only about durability: it’s about who pays. A detection pinned to
a tool is a free reset for the attacker: rename it, recompile it, swap the whole framework, and your
rule is dead at no cost to them. A detection pinned to the step they <em>can’t</em> skip makes every evasion
attempt cost real engineering time. Time is money on both sides of this, and the whole game is to
spend theirs instead of yours.</p>

<p>That trade gets more lopsided every year, because the offense keeps getting cheaper and faster. The
2020 ransomware chain was a manual, roughly 10–14-day affair: break in, run discovery, dump
credentials, escalate, move laterally, then deploy. The 2025 version is broker-enabled and squeezed
to <strong>under 48 hours</strong>, with whole phases (discovery, recon, often privilege escalation) skipped
because someone else already did them. Mandiant’s M-Trends 2025 shows the same thing in aggregate:
median dwell time has fallen year over year. You have far less window to catch an intrusion, so the
detection had better sit on something that’s <em>always</em> present, not on a name you’d need luck to
recognize in time.</p>

<p>And the inputs have commoditized. Infostealer logs are now a routine first step into a network
(HudsonRock, Red Canary), and Initial Access Brokers sell that foothold pre-enriched: privilege
level, access type, even which EDR is running in the environment (Cyberint). The tooling layered on
top rotates constantly precisely because it’s cheap and interchangeable, which is the exact reason a
detection pinned to it keeps dying.</p>

<p>A chokepoint is where you flip that math. Because unrelated threats overlap on the same invariant
steps, one detection placed there covers many actors at once, and one log source ends up catching
many techniques: you pay the engineering cost once, on the part that can’t change, instead of
re-paying it for every renamed tool. And because you’re reasoning about what <em>has</em> to be true for the
technique to work, you can usually see the next variation coming before it even has a name.</p>

<p>That’s the bet the whole project makes: when the tooling rotates and the TTPs evolve, the chokepoint
remains.</p>

<h2 id="so-i-built-a-place-to-keep-them">So I built a place to keep them</h2>

<p><a href="https://iimp0ster.github.io/detection-chokepoints/">Detection Chokepoints</a> is a free, open
knowledge base built around that one question, applied across techniques. Right now there are 13
chokepoint entries spanning six ATT&amp;CK tactics (initial access, execution, defense evasion,
credential access, lateral movement, and persistence) with more on the way.</p>

<p>Each entry isn’t a single rule. It breaks the technique down to its invariant, the observable
that exposes it, the log sources that cover it, and the actual detection logic. And the rules come
at three maturity tiers, because where you deploy a detection matters as much as whether it’s
correct:</p>

<table>
  <thead>
    <tr>
      <th>Tier</th>
      <th>What it’s for</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><img class="tier-badge" src="/assets/img/pixel/tiers/research.png" alt="" /> <strong>Research</strong></td>
      <td>Broad baseline, high noise: for establishing visibility, not for alerting</td>
    </tr>
    <tr>
      <td><img class="tier-badge" src="/assets/img/pixel/tiers/hunt.png" alt="" /> <strong>Hunt</strong></td>
      <td>Behavioral context, moderate noise: for periodic sweeps and analyst triage</td>
    </tr>
    <tr>
      <td><img class="tier-badge" src="/assets/img/pixel/tiers/analyst.png" alt="" /> <strong>Analyst</strong></td>
      <td>Production-ready, low noise: for the alert that pages someone</td>
    </tr>
  </tbody>
</table>

<p>The tiers exist because the most common way a good detection idea dies is someone dropping the
high-fidelity rule straight into an environment that was never baselined, drowning in false
positives, and ripping it out. Start at Research, learn what normal looks like in your
environment, then climb.</p>

<figure class="post-pixel-art">
  <div class="post-pixel-art-frame">
    <img src="/assets/img/pixel/concepts/attack-chain.png" alt="A ball-and-chain chomp creature straining to break its chain" loading="lazy" />
  </div>
  
  <figcaption>Attack Chains: where different actors strain toward the same link. That overlap is where you start.</figcaption>
  
</figure>

<p>Beyond the chokepoint entries, <strong>Attack Chains</strong> look at where unrelated actors converge on the
same kill-chain stage: when several groups all route through the same step, that overlap is your
priority, because the adversaries effectively voted on it for you.</p>

<h2 id="trends">Trends</h2>

<figure class="post-pixel-art">
  <div class="post-pixel-art-frame">
    <img src="/assets/img/pixel/concepts/trends.png" alt="A cresting wave with foam" loading="lazy" />
  </div>
  
  <figcaption>Trends: what's accelerating in the landscape. Read the wave and tune the Hunt-tier rule before it breaks, not after the incident.</figcaption>
  
</figure>

<p>Chokepoints tell you what’s invariant; Trends tell you what’s <em>moving</em>. This section is data-driven
analysis of how the landscape is shifting (which delivery families are accelerating, which evasions
are showing up, which variant is about to become the dominant one) so you can tune the Hunt-tier
rule before the wave instead of after the incident.</p>

<p>The methodology that ties all of it together lives in the <strong>Framework</strong> section: every technique
gets worked through the same three questions: what’s its <em>scope</em> (one technique, or a chain of
them?), what <em>variations</em> exist or could plausibly exist, and what <em>prerequisites</em> have to be true
for it to work at all. That last question is where the chokepoint falls out: the prerequisite that
can’t be designed away. I’ll give Attack Chains and Trends a closer look in their own post.</p>

<h2 id="the-example-that-made-it-click">The example that made it click</h2>

<p>The idea crystallized for me with ClickFix. I spent a while pulling that family apart for
<a href="https://www.huntress.com/blog/dont-sweat-clickfix-techniques">Huntress</a>, and the variants just
kept coming: FileFix, TerminalFix, DownloadFix, each with a different lure. Chase the variants
and you’re back on the treadmill. But step back and they all funnel through the same place: a user
is talked into running a command, a scripting interpreter executes it under <code class="language-plaintext highlighter-rouge">explorer.exe</code> or a
browser, and a second stage comes down from the network. Detect that shape and you catch the
variants that haven’t been named yet. If you want to see what that looks like as an actual entry
(the staged detections, the Sigma rules, the emulation script) I walked through the ClickFix one
<a href="/blog/inside-a-chokepoint-entry/">here</a>.</p>

<h2 id="where-to-start">Where to start</h2>

<p>None of this replaces keeping up with tooling. But if you’re underwater and don’t know where to
begin, start with what the attacker can’t avoid. Pick a chokepoint, deploy the Research-tier rule,
watch it for a week to learn your noise, and climb the tiers from there. When the tool rotates
next month, your detection is still sitting on the part that can’t change.</p>

<p>It’s all open on GitHub. If you’ve reverse-engineered a technique down to its invariant, or you
spot one I’ve gotten wrong, I’d genuinely like to hear it:
<a href="https://iimp0ster.github.io/detection-chokepoints/"><strong>Detection Chokepoints</strong></a>.</p>]]></content><author><name>Tyler Bohlmann</name></author><category term="detection" /><category term="chokepoints" /><category term="sigma" /><category term="threat-hunting" /><category term="attack-chains" /><summary type="html"><![CDATA[A free, open knowledge base built around one question: what can't the attacker avoid? Anchor your detections there instead of to the tool of the week.]]></summary></entry></feed>