Detection engineering, threat hunting, malware analysis. One defender bit at a time.

Join for free →
Working on a YouTube video, out this Saturday: my Claude Code hunting workflow on an RMM abuse case. Two validly signed ScreenConnect clients on one lab host. One got the attacker in. The other is the one they kept. Claude Code runs the first pass in KQL and ES|QL. I validate every row. piped.video/@Securityinbits
1
2
3
368
You don't need to ingest a CSV to test a KQL detection on it. Give the CSV the real table's name with one let line: let DeviceProcessEvents = externaldata(...) Your query runs on the file unchanged. Read-only, nothing loaded. I ran my 6 AnyDesk hunt queries on a public lab bundle this way. All 6 returned rows.
10
35
2,028
Microsoft gives anyone with a Microsoft account a free Azure Data Explorer cluster. No subscription, no credit card, full KQL. Mine took under 2 minutes to create. aka.ms/kustofree
1
7
38
2,461
An attacker installed ScreenConnect, then hid it from Programs and Features with one registry value. SystemComponent = 1 on its Uninstall key. - Service: running - Programs and Features: no ScreenConnect Sweep both HKLM Uninstall hives (incl. WOW6432Node) for SystemComponent = 1 and read the DisplayName. Installers hide sub-components this way too. A hidden RMM client is not one of them.
6
19
1,172
My lab runs MDE and Elastic side by side, so I gave Claude Code a skill for each: - mde-hunt: KQL on MDE + my ADX archive - elastic-hunt: ES|QL on Elastic One question, both stacks searched, one table back. Most SOCs run one of these. Whichever is yours, want the skill? I can share it on GitHub.
4
1
19
871
Got tired of pasting KQL into the Defender portal, so I built an mde-hunt skill with Claude Code. - I ask in plain English - Claude writes the KQL - a Python script runs it on live MDE (last 30 days) or my ADX archive (older) First test: remote-access tools over 120 days. 3 hosts, one running AnyDesk renamed Invoice_Viewer.exe. Interested? I can share it on GitHub.
10
9
73
4,170
I ran my detection lab in VMware on my laptop for a long time. But I wanted Proxmox on bare metal, plus room for real monitoring. So I moved the lab to a Beelink SER10 MAX: - 12 cores / 24 threads, 64 GB, 1 TB - 11 VMs: DC, workstations, servers, Kali, router - Elastic, MDE, Suricata and Velociraptor deployed One of those VMs runs Claude, and it controls the rest of the lab.
1
2
595
Two different scanners. Same detection. Advanced IP Scanner hit 254 IPs. Advanced Port Scanner hit 190. Both across 5 ports, both one process, both in one time window. dcount on DeviceNetworkEvents catches the fan-out, not the tool name. Behavior gives it away, not the binary. 🎯
4
23
1,705
Replying to @NathanMcNulty
Agent watching 👀
1
3
75
MDE Advanced Hunting only looks back 30 days. For my lab I wanted to keep my own copy, so: - Streaming API -> Azure Storage - LightIngest -> free ADX cluster - same KQL, now 162 days deep (587k events) How do you keep MDE data past 30 days? Sentinel, data lake, ADX, or something better?
2
2
6
652
Three network scanners show up across 45+ ransomware groups. In my lab the scan had one shape: one process, 254 internal IPs, 5 ports, under 30 seconds. Full walkthrough in Defender KQL + Elastic ES|QL, including how to tell an admin from an operator: piped.video/Iun8zko6EZk
1
3
10
763
Your ScreenConnect child-process rule keys on cmd.exe and powershell.exe. Mine did too. The operator never spawned either. A real operator joined 4 min after install. What spawned: ScreenConnect.ClientService.exe -> ScreenConnect.WindowsBackstageShell.exe Backstage is the product's hidden shell. No desktop window, no cmd, no powershell. Second tell: an MSI staged under C:\Windows\SystemTemp\ScreenConnect\<ver>\Temp\ and run via RunFile. Both anchors and the queries are in the Article.
2
3
20
1,484
2 binaries. 6 failed connections. 1 operator IP exposed. AnyDesk attempts direct P2P (TCP 7070) before relay, ON by default. When it's blocked, the operator's real IP logs as ConnectionFailed in DeviceNetworkEvents. The relay never hid them. Hunt the failures.
1
1
10
685
Ever remediated the ScreenConnect implant your alert fired on and moved on? A real sample dropped two, 9 min apart. The second, self-hosted one (wonderxp[.]top:8041) shipped its own app.config: - AccessShowUnderControlBanner = false - AccessShowBalloonOnConnect = false - AccessShowSystemTrayIcon = false Every "you are being watched" cue the client shows, switched off in XML. The cloud client beside it had no app.config. Two implants means two services. Count them before you close the case.
11
30
3,958
An attacker pointed a signed ScreenConnect client at their own relay. The command line gave it up. ?e=Access&y=Guest&h=<relay>&p=<port> - e= is the role. Access = unattended, Support = attended - h= and p= are the relay. instance-*[.]screenconnect[.]com:443 = cloud, 8041 = theirs 1. Never filter on e=Access. Operators start on Support, then upgrade 2. Baseline h=. Alert on an unseen relay Mine: wonderxp[.]top and relay[.]robertsonins[.]co. Both 8041, both unseen. Deep dive lands Thursday.
2
10
928
There are plenty of ways to build a detection lab, but elastic-container is the fastest Elastic stack setup I know. One script gives you: - Elasticsearch + Kibana + Fleet - Detection Engine on, prebuilt rules bulk-enabled by OS - 100% containerized, one command up or down Have Claude or Codex set it up for you. Credit: Andrew Pease (@andythevariable). github.com/peasead/elastic-c…
5
9
705
Ever closed a ScreenConnect case on EDR timestamps alone? My EDR's last event on the operator: 17:09. The product's own Application log had them working until 17:17. Get-WinEvent -FilterHashtable @{LogName='Application'; ProviderName='ScreenConnect'; Id=100,101,201} | Sort-Object TimeCreated | fl TimeCreated, Id, Message - 100/101 = operator connect/disconnect with session label - 201 = file transfer. Two implants on one box: scream care, then spacex7. A 4 min incident was 12 min.
1
3
17
1,165
Ever closed an RMM alert because the tool was sanctioned? Stop hunting AnyDesk by filename. Rank it by how rare it is across your fleet. A sanctioned tool is everywhere. A renamed copy on 1 host is the lead, even as Invoice_Viewer.exe still carrying AnyDesk's PE metadata. Full case, 32 ransomware groups and why your EDR sees a legit tool, in my Article below. 🔎
1
1
19
2,456
One process. 254 IPs. 5 ports. One time window. That's a network sweep, and the binary name never entered the logic. A dcount threshold on DeviceNetworkEvents catches Advanced IP Scanner, Advanced Port Scanner, and NetScan the same way. Signature-free 🔎
8
520
Your FileZilla alert is buried under installer and auto-update traffic. Cut that chatter and one connection is left standing. 🔎 The vendor noise lives on 80/443. Filter it. What survives on a file server: fzsftp.exe to a public IP on a custom port (3333), non-IT user, outside change windows. That's the connection to triage.
1
2
14
7,966
One SSH tunnel made 302 connections. 296 of them failed. That's not a pivot, that's a subnet sweep. Two signals: destination cardinality and failure rate. A fixed forward holds one IP, one port, zero failures. A subnet sweep churns many IPs, many ports, successes and failures together. Same mechanism. Different shape. I reproduced all three in the lab and put the rows side by side. Full breakdown 👇
1
1
387
You don't need to know which scanner ran. 254 IPs from one process across 5 ports, in a single window, is a network sweep. Advanced IP Scanner, Advanced Port Scanner, NetScan, same shape. dcount on DeviceNetworkEvents flags the behavior. Tune the threshold to your env. 🔎
1
354
When did your last backup target 127.0.0 . 1? That's wbadmin dumping creds, not backing up. Two tells: -include isolates the offline-crack trio: ntds.dit + SYSTEM + SECURITY (AD DB + boot key), not a data volume. -backuptarget is a loopback UNC (\\ 127.0.0[.]1\C$), not backup infra. On disk: a fresh VHDX stamped to the run. Mount it, hives inside. Sigma rule: Sensitive File Dump Via Wbadmin.EXE For more details, check this link 👇
1
4
15
4,657
A 2026 ransomware case where the encryptor was never double-clicked. It shipped as a Group Policy. Two malicious GPOs, 10 minutes apart 1. First killed Defender protections 2. Second created a scheduled task on targeted devices: copy run.bat / run.exe / run.dll from SYSVOL -> rundll32 run.dll Encryptor Alert on new GPOs that create suspicious scheduled tasks. More here: microsoft.com/en-us/security…
1
6
520
Ever measured how late your logs actually arrive? ingestion_time() − TimeGenerated = your real ingestion delay, per table. Use percentiles, not averages - buffered endpoints skew the mean hard. @BertJanCyber tenant: • 50% of DeviceEvents landed within 3 min • 97% within 6 min Your detection’s search window should know this number. More in his blog: kqlquery.com/posts/dxbp-part…
6
33
4,318
Most FileZilla alerts drown in vendor callbacks. Filter those and one connection stands alone. Installer and update traffic sits on 80/443. Strip it out. Left behind on a file server: fzsftp.exe to a public IP on port 3333, non-IT user, outside change windows. That's your candidate for exfil.
7
11
1,238
You watch AnyDesk RMM for remote control. You forget it moves files too. Its File Manager is a clean exfil channel. No web proxy hit, no email DLP trigger. But it logs every transfer to file_transfer_trace.txt: filename, size, direction. My lab caught a 231 MiB documents .zip upload sitting in plaintext. 🔎 Add it to your AnyDesk triage. It tells you what left, no pcap needed.
1
1
17
787
invoice_viewer.exe made 19 connections to AnyDesk infrastructure. It was never an invoice viewer. The binary name is forgeable. The DNS path isn't. Every client still reaches boot[.]net[.]anydesk[.]com and a relay-*[.]net[.]anydesk[.]com server. 🔎
1
5
17
1,239
Most sweep detections chase tool names. Advanced IP Scanner, NetScan, the renamed ones. Wrong layer. One process hitting 254 IPs across 5 ports is a sweep no matter what the binary is called. dcount on DeviceNetworkEvents catches the behavior. 🔎
1
3
22
4,583
Claude Code ultracode is quite good when you want one workflow to spawn multiple agents in parallel. I connected my lab Elastic SIEM and asked: which AnyDesk Sigma rule fired on which field? - 1 agent per rule, 7 in parallel - each reads the rule, names the field it matched - a verify phase re-checks every claim
6
467
A clean SSH pivot and a malicious one run the same command. So how do you tell them apart? Two signals: destination cardinality and failure rate. A fixed forward holds one IP, one port, zero failures. A subnet sweep churns many IPs, many ports, successes and failures together. Same mechanism. Different shape. I reproduced all three in the lab and put the rows side by side. Full breakdown 👇
1
3
14
1,537
wbadmin flagged as a backup job. It was a credential dump. Two tells no real backup has: - -include isolates the offline-crack trio: ntds.dit + SYSTEM + SECURITY (AD DB + boot key), not a data volume. - -backuptarget is a loopback UNC (\\ 127.0[.]0[.]1\C$), not backup infra. On disk: a fresh VHDX stamped to the run. Mount it, the hives are inside. Sigma rule: Sensitive File Dump Via Wbadmin.EXE More native-tool LOLBins next. 🔎
1
5
24
1,681
Digging into an AnyDesk incident? In connection_trace.txt, a single line tells you whether you are looking at persistence or just a phished user. - Passwd / Token = unattended access. They set a password so they can re-enter later. (Fog, Akira) - User = someone clicked Accept and was talked into it. Same actor, same software, but completely different stories and completely different fixes. Start with the approval type.
3
378
fzsftp.exe reaching a public IP on a non-standard port is the signal. Everything on 80/443 is noise. Installer and auto-update chatter lives on 80/443. Filter it. What's left on a file server: fzsftp.exe to a public IP on a custom port (3333), non-IT user, outside change windows. That's your exfil candidate.
3
30
1,677
Ever written off an AnyDesk relay as a dead end for attacker attribution? How it works: 1. Client negotiates via AnyDesk Cloud (443/6568) 2. Direct TCP 7070 attempt + hole punching, in parallel (ON by default) 3. Relay only if direct fails When the direct attempt is blocked, the operator's real IP logs as ConnectionFailed in DeviceNetworkEvents. My lab: 6 failed attempts across 2 binaries. Caveat: a careful operator can force relay-only. Treat the IP as a pivot IOC, not attribution. Hunt the failures 🎯
2
5
19
1,622
254 IPs. 5 ports. One process, no tool name needed. That's a network sweep caught by behavior, not signature. A dcount threshold on DeviceNetworkEvents flags Advanced IP Scanner, Advanced Port Scanner, and NetScan the same way. Rename the binary, the fan-out still shows. 🔎
8
30
2,029
Storm-1175 (Medusa) flips WDigest caching on before dumping creds. reg: UseLogonCredential = 1 Windows ships this OFF. Set to 1, it forces creds into cleartext at next logon, right before the dump. The reg write lands first. Watch DeviceRegistryEvents and you're ahead of the LSASS access. 🔍 microsoft.com/en-us/security…
9
34
2,793
32 ransomware groups abuse AnyDesk for persistence, per the Ransomware Tool Matrix. Longest row in the RMM table. The setup is one piped command: echo Admin#123 | AnyDesk.exe --set-password 2 gifts for defenders: 1. Password lands in plaintext in the echo command line 2. --set-password survives any rename Sigma rule: AnyDesk Piped Password Via CLI Hunt the flag + echo pipe 🔎
8
95
400
48,594
AnyDesk logs the operator's real IP to disk. NetFlow, proxy, EDR network events: all show the relay. Dead end. The host trace file has the actual source. Grep "Logged in from": Service: %PROGRAMDATA%\AnyDesk\ad_svc.trace Portable: %APPDATA%\AnyDesk\ad.trace Egress IP, not attribution. Pivot on it 🔍
3
33
171
19,744
An attacker can rename AnyDesk to anything. Three PE fields still say AnyDesk. CompanyName, ProductName, FileDescription survive the rename. OriginalFileName (the usual rename-proof field) is empty, so it’s no help. Key on those three, exclude legit install paths, and a renamed AnyDesk in Temp lights up. 🔎 Confirm which PE field your binary sets before you bet a detection on it.
1
20
98
8,359
SoftPerfect NetScan isn’t only for admins. It’s been seen in the hands of 32+ ransomware crews, and even popped up with The Gentlemen ransomware in a @TheDFIRReport investigation. Start your hunt with the version metadata. Next, pivot to the command line and look for /hide and /auto. Together, those switches can turn a normal scan into low-noise recon. Detect: Version info: SoftPerfect / Network Scanner / scanning networks Cmdline: /hide + /auto /hide = runs without a GUI /auto: = executes scan + writes XML output
3
6
22
2,001
An attacker renamed AnyDesk to invoice_viewer.exe. The network trace gave it up anyway. Rename the binary all you want. The DNS path doesn't change. Every client still reaches boot[.]net[.]anydesk[.]com and a relay-*.net . anydesk .com server. Baseline *.net[.]anydesk[.] com across your fleet. Unsanctioned host hitting it = lead. 🔎
5
17
148
29,648
If you detect Advanced IP Scanner, stop treating it like “just recon.” It often means the attacker already has an interactive desktop session inside your network. Ransomware operators regularly use Advanced IP Scanner and Advanced Port Scanner during hands-on discovery. These are GUI tools. A hit on them can imply RDP, RMM, or VDI access is already active. I broke down the detection logic and why this matters below 👇
6
24
164
29,858
An attacker can exfil through AnyDesk without triggering web or email DLP. But the endpoint still writes file_transfer_trace.txt. Every transfer gets logged: filename, size, direction, timestamp. My lab ran a 231.44 MiB documents .zip upload. It's sitting in plaintext in that file. If you detect AnyDesk on a host, pull file_transfer_trace.txt. It tells you whether files moved, no packet capture needed. 🔎
2
16
98
6,513
One SSH tunnel made 302 connections. 296 of them failed. That's not a pivot, that's a subnet sweep. You can't see what the attacker runs over an SSH tunnel. The command line only shows ssh.exe -R. But correlate DeviceProcessEvents with DeviceNetworkEvents, and the scan gives itself away. High distinct IPs and ports, failures spiking past successes. KQL query below 👇
1
7
29
2,997
Working an AnyDesk case? One line in connection_trace.txt decides whether it's persistence or a phishing victim. - Passwd / Token = unattended access. Attacker set a password to come back. (Fog, Akira) - User = someone clicked Accept. Social-engineered. Same operator, same tool. Two incidents, two remediations. Check the approval type first. 🔎
2
13
92
12,557
Three ssh.exe -R reverse tunnels in MDE. Same binary, three different shapes. 1️⃣ -R 9090:127.0.0.1:8080: 1 IP, 1 port, 1 success, 0 failures. A fixed forward to one service. 2️⃣ -R 8888: 1 IP, 1 port, 1 success, 1 failure. SOCKS, but pointed at known hosts. 3️⃣ -R *:10400: 250 IPs, 5 ports, 6 successes, 296 failures. SOCKS proxying a subnet sweep. The scanner never touches the command line. The IP and failure counts give it away.
23
75
8,332
One host touching 50+ internal IPs across 5+ ports in under 5 minutes is not “normal admin activity.” That is how ransomware operators map your network before encryption. 👀 The best part? This detection still works when the tool is renamed, packed, or stripped of metadata. Fully tool-agnostic.
1
13
62
7,077
Your SSH tunnel detection probably has a gap. Hunting ssh.exe -R for reverse port forwarding? A contains "-R" filter misses the variants attackers use to background the tunnel: -NR, -fNR, -fNTR. Use regex \s-\w*R instead. It catches the -R inside all of them. Sigma rule: Port Forwarding Activity Via SSH.EXE 👇
2
22
131
7,188
Ever seen ssh.exe on a workstation and ignored it? That -R flag opens a SOCKS pivot. Akira's operators used it to proxy a scanner before dropping ransomware. Your EDR sees ssh.exe. Nothing inside the tunnel. The network telemetry still leaks. Here's how to read it 👇
3
24
113
11,980
One row per rule. Every command line, host, user collapsed into one pivot. That's what VALUES() does in ES|QL. It collects all distinct values of a field inside each group, so they survive the aggregation. Without VALUES(), STATS gives you a count. With it, you get every command, every path, every host that fired under that rule. All on one row. 150+ alerts become 15 rules. Stop reading alerts. Start reading rules.
1
1
3
589
ssh.exe -R proves a tunnel exists. It doesn't prove a pivot. Identical flag in all three rows. What separates a benign port-forward from a SOCKS subnet sweep is the shape of the traffic: fan-out and failure count, not the command line. Full breakdown drops Thursday. KQL + ES|QL so you hunt it the same day. 🔍
1
4
14
642
Replying to @CharlieEriksen
Interesting, attacker also backdated the malicious code to Aug 2025.
1
2
360
ssh.exe -R alert on a workstation deserves attention. Attackers abuse SSH remote tunneling to proxy traffic through compromised hosts and reach internal systems. Correlating process and network telemetry in MDE can expose what's happening inside the tunnel. Lab demo 👇 for detection and triage process piped.video/watch?v=-57OYlKr…
24
104
5,911
Triage before you investigate. In Elastic, this ES|QL query turns an alert flood into a ranked rule list. Two functions do the work: STATS and VALUES. STATS group by rule name and count the alerts. VALUES pulls every distinct host, user, command line, and file path that fired under that rule. No aggregation loss. The full context travels with the count. One row per rule. Count on the left. Evidence on the right.
1
1
15
1,021
If you only hunt for netscan.exe, renamed NetScan binaries will slip past you. Hunt the version info and cmdline instead. SoftPerfect NetScan has been used by 32+ ransomware gangs as mentioned in Ransomware Tool Matrix from @BushidoToken
1
9
45
3,812
SoftPerfect NetScan is not just an admin tool. 32 ransomware gangs have used it, and The Gentlemen ransomware used it in a recent @TheDFIRReport case. Hunt it by version info first. Then check cmdline for /hide and /auto. Those flags can turn scanning into quiet recon.
1
6
33
1,957
This is the github url where we can monitor for dead-drop C2 for v2 Python Linux stealer No change in total count still 32 api.github.com/search/commit…
2
262
- Exits if Russian language settings are detected or CPU count is <= 2. - Function says is_israeli_system(), but the geo-check also looks for Israel & Iran markers, then may play audio from C2 and attempt `rm -rf /*`. - Uses multiple collectors to steal credentials from AWS, Azure, Tailscale, password vaults etc.
1
1
3
413
If this C2 down, it will move to GitHub commit search for FIRESCALE. It follows this pattern FIRESCALE <base64_url>.<signature> If this fails it will GitHub exfiltration fallback with stolen GitHub token
2
1
2
420
Mini Shai-Hulud transformers.pyz is not obfuscated Python Linux stealer has a fallback C2 path that is similar to previous Shai-Hulud dead-drop C2 pattern I checked the latest GitHub commit. No fresh C2 value yet. #TeamPCP will use this when initial C2 fails More details below 👇
5
8
49
4,663
CertUtil dropped the beacon. Your alerts fired. Triaging them one by one in Elastic's default UI, you miss the sequence. No command lines. No chain. This ES|QL query groups by sigma_rule, sorted by first_seen. Entry point is row one.
1
2
4
498