Analyzing A Recent Agent Tesla Sample

Breaking down a January 2026 Agent Tesla sample that hides its payload until runtime. Covers credential harvesting across 15+ applications, Startup folder persistence, and FTP exfil to attacker infrastructure. Includes ready to use KQL queries for hunting.

1/31/20268 min read

Analyzing A Recent Agent Tesla Sample

I've been poking at infostealers now as a I start my way through malware analysis so it's only fitting that I pick up this classic, Agent Tesla. This week I grabbed the Agent Tesla sample from MalwareBazaar and spent some time picking it apart. This was the most recently found sample of Agent Tesla as it was last seen 01/30/2026. Here's what I found.

Spoiler: Static analysis told me almost nothing. The interesting stuff only showed up once I executed it.


What's Agent Tesla?

Before diving in, some quick background. Agent Tesla is an infostealer that's been around since 2014. It's sold as malware-as-a-service, which means pretty much anyone can buy access and use it without writing their own code.

It steals credentials from browsers, email clients, VPNs, FTP clients, basically anything that stores passwords. It can also do keylogging and take screenshots. The reason it's still popular is that it keeps getting updates and it's cheap to use.


The Attack Chain (High Overview)

Initial access
├─ User executes WinForms EXE
└─ Masquerades as Oracle tool
       ↓
In-memory staging
├─ Runtime unpacks payload
└─ No payload on disk
       ↓
Credential enumeration
├─ Probes browser/mail stores
└─ PATH NOT FOUND = logic works
       ↓
Persistence
├─ Startup folder shortcut
└─ ZoRodAS0tns.lnk → payload
       ↓
Environment awareness
├─ ip-api.com hosting check
└─ Potential sandbox evasion
       ↓
Data exfiltration
├─ Credential harvest
└─ FTP to operator infra

The Sample

File
sample.exe
SHA256
ad131f58df2bb784cc7182a2afb12c7dbc9c139bcd881d913eb7776e9b399c02
FTP
ftp[:]//ftp[.]duct-master[.]com
Email
[redacted]@duct-master[.]com
Payload
ZoRodAS0tns[.]lnk
MalwareBazaar
VirusTotal

Stage 0: Static Analysis (The Boring Part)

I started off by examining the initial file, which I renamed to sample.exe. I loaded it in DIE (Detect It Easy) to see what type of file it was. Then threw the sample into ILSpy since it's a .NET executable. The metadata immediately looked suspicious:

AssemblyProduct:    Advanced Query Builder
AssemblyCompany:    Oracle
AssemblyCopyright:  Copyright © Oracle 2026

This didn't stand out to me right away as being deceiving because I don't know much about what's recent and what's not but given the nature of Agent Tesla, I know they loves to masquerade as database tools and admin utilities. This fit the pattern.

I kept poking around in sample.exe but couldn't find anything unique or fun. I couldn't find any payload. No embedded config, no obvious malicious code, just what looked like a basic WinForms app. The resources were all UI stuff.

I spent way too long looking for something hidden before realizing this is the point. The sample is a dropper. The actual payload doesn't exist until runtime.

Lesson learned: Don't assume static analysis will give you everything. Sometimes you just have to run it.


Stage 1: Behavioral Analysis

I spun up the sample in my lab VM with ProcMon running. Unfiltered, I got over a thousand events. Way too noisy. I narrowed it down with these filters:

  • Operations: Process Create, WriteFile, CreateFile, SetDispositionInformationFile, Load Image
  • Paths: AppData, Temp, ProgramData, Users\Public

That brought it down to about 100 relevant events.

Credential Enumeration

The first interesting behavior: the process started hitting credential storage locations for a bunch of applications.

Browsers:

  • SeaMonkey, Waterfox, IceDragon, Flock, QQBrowser

Email clients:

  • Thunderbird, Postbox, Foxmail, Opera Mail, Mailbird, Trillian

Legacy/obscure stuff:

  • The Bat!, Claws Mail, K-Meleon

It was looking for files like profiles.ini, accounts.ini, accounts.dat, and various mail databases.

Most of these came back PATH NOT FOUND because my lab VM doesn't have these apps installed. At first I thought this might be sandbox detection, but it's not, it's just the malware checking everywhere it knows to check. The failures actually confirm the harvesting logic is real.


Stage 2: Persistence

After the credential sweep, things got more interesting. ProcMon caught this:

WriteFile: C:\Users\<VM>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\ZoRodAS0tns.lnk

A Startup folder persistence. It dropped a shortcut pointing to a copy of itself:

C:\Users\<VM>\AppData\Roaming\ZoRodAS0tns.exe

A randomized filename (ZoRodAS0tns) is typical for Agent Tesla but at this point it didn't really matter. Nothing fancy, but it works.


Stage 2.5: The Payload

Once persistence was set, I took a look at the dropped executable. String analysis showed:

mscoree.dll
System.Net.Http
System.ServiceModel.Http
LoadLibraryExW

This tells me it's running managed .NET code in-process. No child processes spawned, everything happens inside the same process and it's pretty short-lived.

Environment Check

The payload makes a request to:

http[:]//ip-api[.]com/line/?fields=hosting

This checks if it's running in a hosting/VPS environment. What I've found in my research, to be a simple sandbox evasion technique, if the response indicates a hosting provider, the malware might bail. When I ran it offline, I just got noisy .NET networking exceptions.

Exfiltration Config

This is where memory analysis paid off. I found these strings near the networking code:

FTP Endpoint:   ftp[:]//ftp[.]duct-master[.]com
Operator Email: [redacted][@]duct-master[.]com

The operator email has been partially redacted. I have it, just felt off putting someone's creds on blast even in this context.

So this sample uses FTP for exfiltration. Agent Tesla has also been seen to use SMTP, HTTP, or Telegram depending on how the operator configured it.


The Full Attack Chain

Putting it all together:

Decoy EXE executed
      ↓
Unpacks in memory
      ↓
Credential enumeration
      ↓
Drops to AppData\Roaming
      ↓
Startup persistence (.lnk)
      ↓
ip-api.com env check
      ↓
Harvest + FTP exfil

IOCs

SHA256Sample hash
ad131f58df2bb784cc7182a2afb12c7dbc9c139bcd881d913eb7776e9b399c02
URLEnvironment check
http[:]//ip-api[.]com/line/?fields=hosting
FTPExfil endpoint
ftp[:]//ftp[.]duct-master[.]com
EmailOperator email
[redacted][@]duct-master[.]com
File pathDropped payload
C:\Users\<user>\AppData\Roaming\ZoRodAS0tns.exe
File pathPersistence
...\Start Menu\Programs\Startup\ZoRodAS0tns.lnk
.NETFramework version
v4.5

Detection Ideas

Here are some KQL queries I'd use to hunt for this kind of activity in Sentinel.

Startup Folder Persistence

This catches .lnk files being created in the Startup folder. I'm excluding common legitimate installers to cut down on noise.

DeviceFileEvents
| where ActionType == "FileCreated"
| where FolderPath has @"\Start Menu\Programs\Startup\"
| where FileName endswith ".lnk"
| where InitiatingProcessFileName !in ("explorer.exe", "msiexec.exe", "setup.exe")
| project
    Timestamp,
    DeviceName,
    FileName,
    FolderPath,
    InitiatingProcessFileName,
    InitiatingProcessFolderPath,
    InitiatingProcessCommandLine

Executables Dropped to AppData\Roaming

Agent Tesla copied itself to AppData\Roaming with a random name. This looks for executables written there by processes that aren't installers.

DeviceFileEvents
| where ActionType == "FileCreated"
| where FolderPath has @"\AppData\Roaming\"
| where FileName endswith ".exe"
| where InitiatingProcessFolderPath !has "Program Files"
| where InitiatingProcessFileName !in ("msiexec.exe", "setup.exe", "Update.exe")
| project
    Timestamp,
    DeviceName,
    FileName,
    FolderPath,
    InitiatingProcessFileName,
    InitiatingProcessCommandLine,
    SHA256

Credential Store Access

This one looks for processes touching multiple credential storage locations in a short window.

DeviceFileEvents
| where ActionType in ("FileAccessed", "FileRead")
| where FolderPath has_any (
    "Thunderbird",
    "Firefox",
    "Chrome",
    "Opera",
    "Foxmail",
    "Postbox",
    "Mailbird",
    "SeaMonkey",
    "Waterfox"
)
| where FileName has_any ("profiles.ini", "accounts.ini", "logins.json", "Login Data", "cookies.sqlite")
| summarize
    TargetCount = dcount(FolderPath),
    Targets = make_set(FolderPath),
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp)
    by DeviceName, InitiatingProcessFileName, InitiatingProcessId
| where TargetCount > 3
| where datetime_diff('second', LastSeen, FirstSeen) < 60

Environment Awareness Check

Agent Tesla hit ip-api.com to check if it's in a sandbox. This is a pretty weak signal on its own, but useful for correlation.

DeviceNetworkEvents
| where RemoteUrl has "ip-api.com"
| where InitiatingProcessFolderPath has_any (@"\AppData\", @"\Temp\", @"\Users\Public\")
| project
    Timestamp,
    DeviceName,
    RemoteUrl,
    InitiatingProcessFileName,
    InitiatingProcessFolderPath,
    InitiatingProcessCommandLine

Outbound FTP

FTP from a user workstation is unusual enough that it's worth flagging. This catches connections on port 21.

DeviceNetworkEvents
| where RemotePort == 21
| where ActionType == "ConnectionSuccess"
| where InitiatingProcessFolderPath has @"\Users\"
| project
    Timestamp,
    DeviceName,
    RemoteIP,
    RemotePort,
    InitiatingProcessFileName,
    InitiatingProcessFolderPath,
    InitiatingProcessCommandLine

Putting It Together

Any single query might catch legitimate activity. The real signal is when you see multiple hits from the same device in a short timeframe. Startup persistence + credential access + outbound FTP is a pretty solid Agent Tesla signature.


MITRE ATT&CK

T1566Phishing

Likely initial delivery method

T1036Masquerading

Fake Oracle branding

T1547.001Startup Folder Persistence

The .lnk drop

T1555Credentials from Password Stores

All the credential harvesting

T1082System Information Discovery

The ip-api environment check

T1048Exfil Over Alternative Protocol

FTP to attacker infrastructure


What I Learned

  1. Static analysis has limits. I wasted time looking for an embedded payload that didn't exist. The real action happens at runtime.

  2. ProcMon filtering is essential. Unfiltered logs are useless. Knowing which paths and operations to watch for makes a huge difference.

  3. "PATH NOT FOUND" is still signal. Failed file access attempts tell you what the malware is looking for, even if it doesn't find anything.

  4. Memory analysis matters. The exfil config wasn't on disk anywhere. I only found it by looking at strings in memory.


References