Guide · gsocket backdoor

A file called defunct in ~/.config/htop is a remote-access backdoor.

You ran a scan, opened a file manager with hidden files shown, or followed a timestamp — and found something called defunct, or defunct.dat, inside a hidden .config/htop folder in a hosting account. It is not a dead process and it is not part of htop. It is a packed Linux executable that gives whoever placed it an encrypted shell on your server, through a relay, without opening a single inbound port. This guide covers how to check every account, how to confirm what you have without executing it, and how to remove it without destroying the evidence you will need afterwards.

Symptom
A binary at ~/.config/htop/defunct, or a defunct.dat beside it
What it is
Global Socket (gsocket) — an encrypted outbound remote-access channel
Boundary
The hosting account and the server — not the WordPress installation
Risk
Interactive shell access as the account user, surviving every site cleanup

What you found

What ~/.config/htop/defunct actually is

Every part of the path is designed to survive a glance. htop is a real and widely installed interactive process viewer, and ~/.config/htop is exactly where its configuration belongs on a normal Linux system. The leading dot on .config keeps the directory out of ordinary FTP and File Manager listings unless hidden files are explicitly shown. And “defunct” is the word a process listing prints for a zombie process, so it reads as routine system noise to anyone skimming.

Nothing about the location looks like malware until you ask a different question: why does a hosting account that serves web pages, mail, and configuration contain a multi-megabyte compiled binary at all? There is no ordinary answer to that. A cPanel or shared hosting account has no legitimate reason to hold a user-owned executable of that size.

The file is a component of the Global Socket Toolkit — gsocket — which is public open-source software from The Hacker’s Choice. It is not malware in itself, and that is exactly why it gets used this way. gsocket establishes an end-to-end encrypted TCP session between two endpoints through a public relay network, addressed by a shared secret rather than by an IP address and port.

For someone holding a hosting account, that combination is close to ideal. No inbound port has to be opened, so a firewall built around inbound rules never comes into play. NAT and perimeter filtering are traversed by design. The traffic is encrypted and outbound, which is the direction almost nobody inspects. And the binary can be named and placed to look like anything — in this case, a dead process.

Check your server

Read-only checks to run across every account

Run these from a trusted device with root access on the server, not from inside a single account that may already be compromised. Every command below only reads — none of them executes the artifact or changes anything.

  1. 01

    Look for the documented paths in every account home

    find /home -path '*/.config/htop/defunct*' -ls 2>/dev/null lists both the binary and its key file across every account in one pass. On a control-panel server, run it over the whole /home tree rather than one account — the point of the check is to establish whether this is one account’s problem or the server’s.

  2. 02

    Widen to executables where none belong

    find /home -type f -perm -u+x -size +100k -not -path '*/public_html/*' -not -path '*/node_modules/*' -ls 2>/dev/null surfaces user-owned binaries outside the document root. Attackers rename and relocate; the path is a strong indicator, not a definition. Expect some legitimate results on servers where users install their own tooling, and explain each one rather than assuming.

  3. 03

    Check the other common hiding places

    The same technique is used under ~/.cache, ~/.local, ~/.ssh, and directories named after other legitimate tools. Review the dot-directories in each account home, plus /tmp, /dev/shm, and any world-writable path, for files with execute bits and recent timestamps.

  4. 04

    Look for the persistence that usually accompanies it

    crontab -l -u <user> for every hosting user, plus ~/.bashrc, ~/.bash_profile, ~/.profile, and any user service units. A cron entry invoking a binary from a dot-directory is the documented persistence mechanism for this backdoor family. Its absence does not clear you — in the engagement behind this guide there was no cron entry at all.

  5. 05

    Check the process table for implausible owners

    ps -eo user,pid,ppid,etime,comm,args and look for a process owned by a hosting user that presents as a kernel thread in square brackets, or whose executable path has been deleted. Record the process, its owner, its open files, and its network connections before terminating anything.

  6. 06

    Check for long-lived outbound sessions

    ss -tnp shows established outbound connections with their owning process. A persistent outbound session from a web hosting account to a host unrelated to updates, mail, payments, or your CDN is the shape this channel takes. Do not assume your inbound firewall rules would have prevented it — they do not apply to an outbound relay connection.

Confirm it

How to identify the file without executing it

You can establish what this is from its properties alone. Nothing here requires running the binary, and you should not run it, chmod it, or open it in anything that might.

Check the file type

file <path> on a gsocket component typically reports a packed or malformed x86-64 ELF executable. “ELF” means a compiled Linux binary; “packed” means it has been compressed or obfuscated to frustrate static inspection. Neither belongs in a web hosting account.

Check ownership and permissions

stat <path>. In the case behind this guide the binary was mode 0700 — readable, writable, and executable only by the owning user — and owned by the site’s own cPanel user, not root. That matters: no root compromise was needed to place or run it, and it inherited exactly the write access that had been rewriting application files.

Check the size and creation date

A file of roughly 1.3–1.4 MB is consistent with the packed toolkit. The creation timestamp is more useful than the size: it bounds the window in which everything else on the account should be treated as suspect, and it usually correlates with the modification timestamps of any infected application files.

Hash it and compare

sha256sum <path>. The sample recovered from the 261-account server was 745fc2346e9ad0fdd00104c6d8732ecf7759cb053bd61c296c7b26e9ddb98d50. A match confirms the same build; a non-match means nothing either way, because the binary is trivially rebuilt and repacked.

Submit it for a second opinion

Server-side scanners classify this artifact class heuristically — Imunify reports it as SMW-HEUR-ELF, meaning roughly “an ELF binary where one is not expected in a user home directory” rather than a gsocket-specific signature. Useful as corroboration, not as the sole basis for a decision in either direction. Our guide to reading ImunifyAV detections covers how to tell one of these from the false positives that make the whole category easy to dismiss.

Do not reverse-engineer it to decide

You do not need to. Path, file type, size, permission mode, ownership, and account context are together sufficient to justify treating the account as compromised. Waiting for certainty about what the binary does is time the credential rotation should be using.

Why nothing caught it

Why Wordfence and ImunifyAV did not flag it

The engagement this guide is drawn from is the clearest illustration of the problem. Wordfence reported 283 infected files on the affected WooCommerce shop. ImunifyAV produced a comparable file-level picture. A complete database export came back clean — no injected rows, no hidden administrator, no obfuscated code. All three results were accurate. None of them found the backdoor.

That combination is itself the finding, and it is worth learning to read. A file-only infection with a clean database and no obfuscated PHP loader means the attacker never needed WordPress-level persistence — because something outside WordPress already had permission to rewrite those files whenever it wanted. The correct reading of “many infected files, clean database” is not “almost clean”. It is “we have found the damage and none of the mechanism.”

  • A WordPress security plugin runs inside the WordPress installation. The account home directory sits above the document root and is out of scope by design, not by evasion.
  • A compiled ELF binary contains no PHP, so PHP-oriented pattern matching has nothing to match against.
  • The file is not reachable over the web at all, so nothing that crawls or requests URLs will ever see it.
  • Hidden dot-directories do not appear in ordinary FTP or File Manager listings unless hidden files are explicitly shown.
  • Heuristic ELF detections are noisy by nature, and are routinely triaged as false positives, allowlisted wholesale, or switched off.
  • The database is the wrong place to look for a backdoor that never needed WordPress in the first place.
  • A per-site scan result is evidence about one document root — never about the server that document root sits on.

Remove it

Preserve, contain, rotate, then delete — in that order

Deleting the binary first feels like progress. It destroys the evidence needed to establish whether it ran, what it reached, and whether a second copy exists in another account — and it does nothing about the access that placed it there.

  1. 01

    Preserve the artifact and its context

    Keep the file itself, its SHA-256, its timestamps, its ownership and mode, and a listing of the surrounding directory. Export the account’s crontab and copy the relevant system, mail, and web access logs while they still exist. This is the only material that can later answer how far the compromise reached.

  2. 02

    Contain the account

    Suspend the account or restrict it where the business allows, block outbound connections for that user at the firewall, disable its cron, and remove the account user’s ability to execute binaries from its home directory. Record any running processes owned by the user before terminating them.

  3. 03

    Treat the account user as fully compromised

    Everything that user could reach is in scope: its document roots, its cron, its SSH keys, its mail, its databases. Everything it wrote since the artifact’s creation date is untrusted until verified. Assume every credential stored in its wp-config.php and .env files has been read.

  4. 04

    Rotate credentials across the estate, from a clean device

    Control-panel logins, SSH keys and ~/.ssh/authorized_keys, FTP and SFTP accounts, database users, WordPress administrators and application passwords, API tokens, payment and shipping integrations, and deployment secrets. An SSH key or an API token survives every password change and every file cleanup unless it is explicitly removed.

  5. 05

    Now remove the binary and its key file

    With the evidence preserved and access rotated, delete defunct and defunct.dat, along with any cron entry, shell-profile line, or service unit that referenced them. Removing the file at this point closes a door that no longer has a key behind it.

  6. 06

    Rebuild the application layer from verified sources

    Replace WordPress core, plugins, and themes from clean downloads rather than stripping injected lines. Hundreds of flagged files is a rebuild, not an edit — hand-editing leaves behind the ones nobody flagged.

  7. 07

    Verify after normal operation resumes

    Re-check the account and the server over the following days, once cron, caches, updates, and real traffic have run again. A cleanup verified only in the minutes after it finishes has not been verified against the thing that matters: whether anything comes back.

Do not stop at one account

How to sweep every other account on the server

A backdoor in one hosting account on a shared control-panel server is a server-level finding until the same method has been applied to every other account. The engagement behind this guide involved 261 cPanel accounts on a single WHM instance, several of them revenue-critical stores, all sharing one hosting boundary. Certifying the flagged account clean while the rest of the estate is unexamined answers the wrong question.

Work the sweep in priority order: accounts that share an owner, accounts that share a deployment routine, accounts restored from the same backup source, then everything else. The same artifact, the same path, or the same timestamp cluster appearing in more than one account escalates this immediately from an account incident to a server rebuild conversation.

Escalate immediately when

A defunct.dat or equivalent key file is present anywhere, a hosting user owns a running process nobody can explain, the same artifact appears in more than one account, or infected files return after a cleanup you verified.

Check root as well as the accounts

Root and reseller control-panel logins and their access logs, root’s authorized_keys, control-panel API tokens, systemd timers, and whether account isolation and heuristic malware detection are actually enabled and enforcing.

Correlate on timestamps, not on filenames

The creation date of the artifact and the modification window of the infected application files together define what to search. Everything written inside that window across the server is a candidate; everything outside it probably is not.

Accept what the evidence cannot tell you

Absence of a cron entry does not prove the binary never ran. Absence of a key file does not prove no session ever opened. Log retention on shared hosting is rarely sufficient to establish an entry vector after the fact. Record those as undetermined rather than filling them in.

Afterwards

The controls that would have made this visible

  • File-integrity monitoring above the web root, covering account home directories and crontabs — not just public_html.
  • Execution restrictions on home directories and temporary paths, with account isolation enforced for every account rather than configured and forgotten.
  • Outbound (egress) monitoring or restriction, so a relay-based channel cannot phone home unnoticed. Inbound rules do not apply to it.
  • Heuristic ELF and binary detection left enabled in the server-side scanner, with its alerts routed to somebody whose job is to triage them.
  • Two-factor authentication and IP restriction on root and reseller control-panel logins, with periodic review of API tokens and SSH keys.
  • A periodic root-level review of the server, independent of any per-site scan — the layer this entire guide is about.

Common questions

Common questions about the gsocket backdoor

Can I just delete the file and move on?

Deleting it removes one artifact. It does not remove whatever access placed it there, and it destroys the evidence needed to establish whether the binary ran, what it reached, and whether a copy exists in another account. Preserve it, contain the account, rotate every credential that account holds, and only then delete — at which point the deletion closes a door with no key left behind it.

There is no defunct.dat, only defunct. Does that mean I am safe?

No. It means the evidence does not settle the question. The .dat file commonly holds the shared secret, so its absence moves the assessment from “active channel” toward “staged capability” — without proving either. It may also have been removed by a partial cleanup, or activation may have used a route that left nothing behind. In the 261-account engagement the key file was absent and the account was still treated as fully compromised, which was the correct call.

Is gsocket itself malware?

No. The Global Socket Toolkit is legitimate, publicly available open-source software with real administrative uses, and it is used by many unrelated people. That is precisely why it is attractive to attackers: identifying the toolkit tells you about the capability staged on your server and nothing at all about who put it there. Naming the tool is not attribution.

Wordfence and ImunifyAV report clean now. Is the server clean?

They are clean about their own layers. Neither examines the process table, user crontabs, SSH keys, control-panel API tokens, or a packed binary in a hidden dot-directory above the document root. A clean result from a WordPress plugin is evidence about one WordPress installation — it is not evidence about the server that installation runs on.

How did the attacker get in to begin with?

Usually through an earlier compromise that is no longer visible: a vulnerable plugin or theme, stolen SFTP or control-panel credentials, or a neighbouring account on a server with weak isolation. Honest answer: on shared hosting, log retention is rarely sufficient to prove an entry vector after the fact. Treat an unproven entry path as an open question and close the plausible ones rather than assuming the most convenient.

Do I need to rebuild the whole server?

Not always. A contained single-account compromise with intact root controls, a complete sweep of the other accounts, and full credential rotation usually does not require it. Rebuild onto a fresh host when root compromise is suspected, when account isolation was never configured, or when the number of accounts makes a reliable sweep impractical.

Can you review this for a server I manage for clients?

Yes — agencies and resellers are the most common case. The work is scoped as a server audit with incident handling, ownership of client communication and per-site cleanup is agreed up front, and the report separates server-level findings from per-account actions.