惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Cloudflare Blog
L
LangChain Blog
WordPress大学
WordPress大学
V
V2EX
M
MIT News - Artificial intelligence
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Stack Overflow Blog
Stack Overflow Blog
J
Java Code Geeks
F
Fortinet All Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
腾讯CDC
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
D
Docker
Recent Announcements
Recent Announcements
GbyAI
GbyAI
博客园 - 叶小钗
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
T
The Blog of Author Tim Ferriss
人人都是产品经理
人人都是产品经理
Engineering at Meta
Engineering at Meta
Y
Y Combinator Blog
雷峰网
雷峰网
The GitHub Blog
The GitHub Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Detecting Ingress Tool Transfer (T1105) with Python
Charles Givre · 2026-05-31 · via DEV Community

Charles Givre

After initial access, attackers almost always need to pull more tooling onto the host: a beacon, a credential dumper, a tunneler. That step is Ingress Tool Transfer (T1105) in MITRE ATT&CK, and it is hard to catch with signatures because the transfer mechanisms are legitimate. certutil, bitsadmin, curl, and PowerShell all download files for normal reasons. The signal is in the combination and the rarity, not the binary itself.

This is where a little data science beats another detection rule. Here is how to hunt T1105 in Python across three layers: the process command line, the process-to-network relationship, and the payload on the wire.

Where T1105 Shows Up in Your Logs

Three sources cover most of it:

  • Sysmon Event ID 1 (process creation) for the download command line and parent process
  • Sysmon Event ID 3 (network connection) to confirm the process actually reached out
  • Zeek http.log (or proxy logs) for the file coming across the wire

You can run all three as pandas DataFrames. No SIEM required, which matters when you are working an exported archive from a host you do not control.

Catching LOLBin Downloaders in the Command Line

Start with the living-off-the-land binaries attackers reach for. Load Sysmon Event ID 1 and flag the download patterns:

import pandas as pd

proc = pd.read_csv("sysmon_eid1.csv")  # UtcTime, Image, CommandLine, ParentImage, ProcessGuid

# Download patterns by LOLBin (see the LOLBAS project)
patterns = {
    "certutil":   r"certutil.*(-urlcache|-f|-split).*http",
    "bitsadmin":  r"bitsadmin.*(/transfer|/addfile)",
    "powershell": r"(downloadstring|downloadfile|invoke-webrequest|\biwr\b|start-bitstransfer)",
    "mshta":      r"mshta.*http",
    "curl_wget":  r"\b(curl|wget)\b.*http",
}

cmd = proc["CommandLine"].fillna("").str.lower()
for name, rx in patterns.items():
    proc[name] = cmd.str.contains(rx, regex=True, na=False)

suspect = proc[proc[list(patterns)].any(axis=1)]

This catches the noisy cases. It will also fire on legitimate admin activity, so the command line alone is a lead, not a verdict. The next two layers are what cut the false positives.

Beyond Signatures: Rare Process-to-Network Pairs

The stronger signal for T1105 is a process that does not normally talk to the internet suddenly making an external connection. Build a baseline from Sysmon Event ID 3 and flag the rare pairs:

import ipaddress

net = pd.read_csv("sysmon_eid3.csv")  # Image, DestinationIp, DestinationPort, DestinationHostname

def is_external(ip):
    try:
        return not ipaddress.ip_address(ip).is_private
    except ValueError:
        return False

ext = net[net["DestinationIp"].map(is_external)].copy()
ext["proc"] = ext["Image"].str.lower()

# How often does each process talk externally across the whole environment?
freq = ext.groupby("proc")["DestinationIp"].count()
rare = freq[freq <= 3].index            # processes that almost never egress

flagged = ext[ext["proc"].isin(rare)]

certutil.exe or notepad.exe opening an external connection lands in rare because, fleet-wide, those processes almost never egress. Tune the <= 3 threshold to your environment size. For a more principled version, score each (process, destination) pair by frequency and treat the long tail as the hunt queue, which is the same idea behind scikit-learn's rarity-based anomaly methods without the model overhead.

Catching the Payload on the Wire

Attackers rename payloads, so do not trust the file extension. Zeek records the actual response MIME type, which is what you want. Parse http.log and filter for executable content regardless of how the URL ends:

def load_zeek(path):
    cols = None
    with open(path) as f:
        for line in f:
            if line.startswith("#fields"):
                cols = line.strip().split("\t")[1:]
                break
    return pd.read_csv(path, sep="\t", comment="#", names=cols,
                       na_values=["-", "(empty)"])

http = load_zeek("http.log")  # ts, host, uri, method, resp_mime_types, user_agent

exe_mimes = ["application/x-dosexec", "application/x-msdownload", "application/octet-stream"]
downloads = http[http["resp_mime_types"].fillna("").str.contains("|".join(exe_mimes), regex=True)]

# A .jpg URL that returns a PE file is a strong T1105 lead
downloads["ext"] = downloads["uri"].str.extract(r"\.([a-z0-9]{1,5})(?:\?|$)", expand=False)
mismatched = downloads[~downloads["ext"].isin(["exe", "dll", "msi", None])]

A URI ending in .jpg that returns application/x-dosexec is the kind of mismatch that almost never has a benign explanation. Pair it with the rare-egress process list above and you have high-confidence T1105 without a single static signature.

Putting It Together

The three layers reinforce each other. The command-line patterns give you candidate processes, the rare process-to-network baseline tells you which ones are abnormal, and the wire data confirms an executable actually moved. A finding that lights up all three is worth waking someone for. One layer alone is a lead to triage.

This is the workflow we teach in GTK Cyber's Threat Hunting with Data Science course: building detections from log data and statistics rather than waiting for a vendor signature. If you want the full reference on the technique itself, the T1105 page has the ATT&CK detail and related techniques, and the threat hunting pipeline post shows how to wire these queries into something repeatable.