Background
Before we get into this analysis, I want to briefly cover the static analysis pipeline behind it. It’s based on semantic analysis — detecting patterns, extracting strings, and inspecting binary headers for signs of obfuscation or packing. I’m not going to go deep into the implementation here, but what matters is that it doesn’t need dynamic execution. No sandbox, no detonation. Just the file.
This sample came up during routine analysis. What happened next was either ironic or predictable, depending on how you look at it.
The Sample
| SHA256 | 3bfc43943390c0faef501ec62465fd85f48cf059d06a1993e5176cedb7c7cd01 |
| Size | 18,579,456 bytes (17.7 MB) |
| Type | ELF 64-bit LSB, x86-64 |
| MalwareBazaar | Threat: Unknown — 7 vendor detections |
| Tags | wraith, elf |
| YARA hits | Warp, WarpStrings (Seth Hardy) |
| Reporter | c2hunter |
A second related sample also exists:
| SHA256 | e097c85216c39c34a37ce0e7cc626c8a43889bda3dec4d28e9001a5081997031 |
| Size | 19,333,120 bytes (18.4 MB) |
| Delta | e097 = 3bfc + 736KB — identical up to 3bfc’s EOF |
Both are Go binaries, dynamically linked, with the same ELF entry point (0x403470) and identical program header layout.
The Script Output
Before anything else — before disassembly, before ML scoring, before YARA — the pipeline produces this:
====================================================
Binary : 3bfc43943390c0faef501ec62465fd85f48cf059d06a1993e5176cedb7c7cd01.elf
SHA256 : 3bfc43943390c0faef501ec62465fd85f48cf059d06a1993e5176cedb7c7cd01
Size : 18,579,456 bytes (17.7 MB)
Verdict : MALWARE_OBFUSCATED
Malicious : 99.0% ###################
Evasive : 99.0% ###################
====================================================
[ELF STRUCTURE ANOMALIES]
✗ section_header_past_eof(shoff=30302232,size=18579456)
✗ load_filesz_past_eof(27158456>18579456)
✗ go_binary_dynamic_linked
→ No legit binary triggers these checks
[Go Symbols]
main.credential
────────────────────────────────────────────────────
Three anomalies, one symbol, verdict in under a second. No sandbox, no dynamic execution.
What the Anomalies Actually Mean
1. Section Header Past EOF
e_shoff = 30,302,232
file size = 18,579,456
The ELF section header table is supposed to live at offset e_shoff. Here, that offset is ~12MB past the end of the file. elftools, objdump -h, Ghidra — they all either crash or return “no sections.”
The thing is, the Linux kernel doesn’t use the section header table to load a binary. It uses program headers (segments). So the binary runs fine. The section table is only there for analysis tools.
Deliberately breaking it is a classic anti-analysis move. It’s also an instant flag.
2. LOAD Segment Larger Than the File
PT_LOAD filesz = 27,158,456
file size = 18,579,456
One of the LOAD segments claims to be 27MB but the file is only 18MB. The kernel handles this by mapping what’s on disk and zero-filling the rest. The binary executes correctly. Any tool that tries to read the full segment from disk either gets garbage or crashes.
3. Go Binary, Dynamically Linked
Go is almost always statically linked — that’s the whole point of its deployment model. A Go binary with /lib64/ld-linux-x86-64.so.2 as interpreter is unusual enough to flag on its own.
Why would they do this? My guess is they were trying to bypass Go binary detection — some signatures specifically look for Go’s static linking patterns, so switching to dynamic linking throws them off. What they didn’t account for is that in doing so, the binary is now loudly announcing itself. No legitimate Go application mangles its section headers and ships an oversized LOAD segment. If you’re going to develop malware, you can’t obfuscate everything — at some point it becomes more obvious, not less.
What the Binary Actually Does
The ELF structure tells us how it hides. The strings tell us what it does.
SSH/SFTP Capability
*sftp.fxp
*ssh.Conn
*ssh.ecdh
SSH_FXP_OPENDIR
SSH_FXP_READDIR
SSH_FXP_SETSTAT
sk-ssh-ed25519-cert-v01@openssh.com
This binary contains a full SSH and SFTP client implementation. Not just connection handling — directory listing, file operations, key exchange. The Go crypto/ssh and pkg/sftp packages are both present.
Credential Harvesting
main.credential ← only symbol left after stripping
pw_passwd ← /etc/passwd field
parsing password
admin
guest
super
sysadmin
sudg
main.credential is the one function the stripper missed — or left intentionally. Combined with pw_passwd, a default credential wordlist, and a full SSH client stack, this is almost certainly an SSH credential harvester or brute-forcer.
Process Masquerading
/bin/systemd-worker
nohup ./
/bin/systemd-worker doesn’t exist on any standard Linux system. This is the persistence name — the binary copies itself there and runs as a fake systemd process. nohup ./ suggests it daemonizes on execution.
Multi-Protocol Support
imap2 imap3 imaps
pop3 smtp ftp sftp
Beyond SSH, the binary handles IMAP, POP3, SMTP, and FTP. This points to multi-service credential testing — not just SSH, but email accounts and FTP servers as well.
The Two Versions
e097 is 736KB larger than 3bfc, byte-for-byte identical up to 3bfc’s EOF. The extra data starts exactly where 3bfc ends.
ClamAV detects e097 as Unix.Trojan.Coinminer and Unix.Dropper.Mirai — neither of which it applies to 3bfc. That 736KB is almost certainly an embedded coinminer or Mirai dropper payload appended to the base binary. Same tool, different deployment stage. 3bfc is the credential harvester. e097 adds the next-stage payload after it’s done harvesting.
The Opsec Paradox
Good malware hides inside legitimate processes and behaviors. The goal is to blend in, not to fight every analysis tool individually. When you go too far with obfuscation, you end up doing the opposite — every anti-analysis trick becomes its own detection signature.
The point is to hide inside the system, not to be evasive on every action.
This binary tried to break static analysis tools by corrupting its own structure. Instead, it handed the pipeline a 99% verdict before a single disassembly pass ran. Three techniques, three flags, one verdict.
IOCs
| Type | Value |
|---|---|
| SHA256 | 3bfc43943390c0faef501ec62465fd85f48cf059d06a1993e5176cedb7c7cd01 |
| SHA256 | e097c85216c39c34a37ce0e7cc626c8a43889bda3dec4d28e9001a5081997031 |
| MD5 | 971d731d72311740260682c1ae3f5148 |
| MD5 | ee88097b09fdf07bb5d89e63d914663d |
| Persistence path | /bin/systemd-worker |
| Family | Warp / Wraith (likely) |
| Protocols | SSH, SFTP, IMAP, POP3, SMTP, FTP |
Detection
The three ELF checks that caught this binary:
|
|
Any one of these alone is worth investigating. All three on the same binary means someone deliberately modified the ELF structure. No build system does this by accident.
Analysis performed with a custom static ELF analysis pipeline. No dynamic execution, no sandbox, no network access to the sample.
MITRE ATT&CK
| Technique | ID | Notes |
|---|---|---|
| Brute Force: Password Guessing | T1110.001 | SSH wordlist: admin, guest, super, sysadmin |
| Brute Force: Password Spraying | T1110.003 | Multi-target credential spray |
| Remote Services: SSH | T1021.004 | Lateral movement via harvested credentials |
| Credentials in Files | T1552.001 | /etc/passwd parsing via pw_passwd |
| Masquerading: Match Legitimate Name | T1036.005 | /bin/systemd-worker |
| File and Directory Discovery | T1083 | SSH_FXP_OPENDIR, SSH_FXP_READDIR |
| Application Layer Protocol: File Transfer | T1071.002 | SSH, SFTP, FTP, IMAP, POP3, SMTP |
| Obfuscated Files or Information | T1027 | ELF section header mangling, oversized LOAD segment |
| Create or Modify System Process | T1543.002 | Persistence as fake systemd service |
| Boot or Logon Autostart Execution | T1547 | nohup ./ daemonization |