{
	"id": "097b35c9-4976-4aff-9b54-30b1f9818f01",
	"created_at": "2026-04-06T00:16:10.453393Z",
	"updated_at": "2026-04-10T03:22:01.26001Z",
	"deleted_at": null,
	"sha1_hash": "ed7a5e18579f6b3a7655e0437c440f468015e4b1",
	"title": "An In-depth Analysis of Linux/Ebury",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 441681,
	"plain_text": "An In-depth Analysis of Linux/Ebury\r\nBy Marc-Etienne M.Léveillé\r\nArchived: 2026-04-05 18:25:24 UTC\r\nESET has been analyzing and tracking an OpenSSH backdoor and credential stealer named Linux/Ebury. The\r\nresult of this work on the Linux/Ebury malware family is part of a joint research effort with CERT‑Bund, the\r\nSwedish National Infrastructure for Computing, the European Organization for Nuclear Research (CERN) and\r\nother organizations forming an international Working Group.\r\nIn this blog post, we provide an in-depth analysis of Linux/Ebury. It is a sophisticated backdoor used to steal\r\nOpenSSH credentials and maintain access to a compromised server. According to previous reports, this backdoor\r\nhas been in the wild for at least two years. Linux/Ebury comes in two different shapes: a malicious library and a\r\npatch to the main OpenSSH binaries.  The malicious library is a modified version of libkeyutils.so. This\r\nshared library is loaded by all OpenSSH executables files such as ssh, sshd and ssh-agent.  We will describe\r\nhow the backdoor works and how the OpenSSH functionalities are hooked.  We will also show how passwords are\r\ncaptured and exfiltrated.  Finally, we will provide detailed information on how system administrators can identify\r\ninfected systems.\r\nIf a system is found to be infected with Linux/Ebury, we strongly recommend re-installing the operating system.\r\n It is also very important to consider all credentials used to log into this machine as compromised.  All passwords\r\nand private OpenSSH keys should be changed\r\nKnown variants\r\nLinux/Ebury is noteworthy for multiple reasons.  Although this is something common under the Windows\r\noperating system, it is the first time we've seen a malicious library being used on POSIX systems.  Linux/Ebury\r\nalso uses innovative tricks to hook functions, discover the address space of the ELF executable that loaded the\r\nlibrary and apply patches to its code at runtime. We believe that before using the external library to hook into\r\nOpenSSH processes, the author of Linux/Ebury used a patch to modify the source code of OpenSSH, thereby\r\nadding “new functionalities” to the software. The first variants found were modified binaries left on the disk. The\r\nthree affected files are ssh, sshd and ssh-add. We have also seen usage of the rpm commands to remove\r\nsignature from the original OpenSSH packages (openssh-server,openssh-clients) and modify the RPM\r\ndatabase to update the file hashes with those of the malicious files. This will make the output of rpm --verify\r\nopenssh-servers report the files as unmodified.  However, the output from rpm -qi openssh-servers will\r\nclearly show the package is missing its signatures.\r\nLater variants of Linux/Ebury do not modify the OpenSSH files directly. Instead, a shared library that is loaded by\r\nall OpenSSH executable files is modified to change the behaviour of the programs. The changes are the same as\r\nthe patched OpenSSH variants, except that the some functions are hooked and patches to the original code are\r\napplied at run time. The shared library that is modified on the system is libkeyutils.so. Usually, this file is\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 1 of 10\n\nabout 10KB in size. The malware adds approximately 20KB of additional malicious code, making the file weigh\r\nin at about 30KB in total.\r\nHere are two examples of how the backdoor is deployed. The first one shows a Linux/Ebury-infected file next to\r\nthe clean libkeyutils.so. The symbolic link is modified to point the rogue version.\r\nThe second screenshot shows the libkeyutils.so is replaced with Linux/Ebury’s version.\r\nAlthough placing malicious code inside libraries has already been seen before, this is the first time we have\r\nobserved this technique being used on the Linux operating system to modify the behaviour of OpenSSH.\r\nTo enable the different features of the malware, a constructor function was added in thelibkeyutils.so. This\r\nfunction is called when the library is loaded. This function detects which binary it was loaded from, applies\r\npatches to the original code, and hooks functions from the original import table.\r\nIn the most recent variants of Linux/Ebury, strings are obfuscated with a simple XOR encryption with a static key.\r\nAfter unpacking, the malware loads various functions it requires using multiple calls to the dlsym function.\r\nLinux/Ebury then discovers the original executable address space by calling dlopen(NULL, RTLD_NOW) and\r\npassing the returned handle to dlinfo(handle, RTLD_DI_LINKMAP, ...). This will work even if ASLR is enabled\r\non a system. This behaviour gives Linux/Ebury the ability to walk the import table of an ELF executable and\r\nreplace the original imported function address in memory. The result is that when the programsssh, sshd or ssh-add call one of the hooked function, it will be redirected to the malicious libkeyutils.so implementation that can\r\nreplace the original behaviour. The following code snippet shows the calls to dlopen and dlinfo to find the main\r\nprogram address space and walk the ELF header information:\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 2 of 10\n\nThe logging functions are hooked so that whenever the backdoor is used, nothing gets sent to the logging facility,\r\nleaving no trace of the backdoor in the log files on disk. If the backdoor is not in use, logging will behave\r\nnormally and function calls will get redirected to the original function implementation.\r\nThe following functions are hooked when the malicious libkeyutils.so is loaded inside the sshd process.\r\naudit_log_user_message\r\naudit_log_acct_message\r\nhosts_access\r\nconnect\r\n__syslog_chk\r\nwrite\r\nsyslog\r\npopen\r\nhosts_access\r\ncrypt\r\npam_start\r\nThe other functions such as pam_startand cryptare used to get the password used by a user to authenticate.\r\nInterestingly, the pam_start hook will place an additional hook for pam_authenticate to grab the password. The\r\nfunction connect is hooked so that when the Xbnd (documented below) command is used, a call to bind is made\r\nwith the socket before the real call to connect is made.\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 3 of 10\n\nRuntime code modification\r\nWhen hooking from the import table is not an option, Linux/Ebury will modify the code segment by patching\r\nspecific sections of the program to redirect call instruction to its own implementation. The following figure shows\r\nan example where the ssh program calls its own function key_parse_private_pem and the execution flow is\r\nredirected to malicious code. The address is shown in red because it is in the libkeyutils.so address space,\r\noutside ssh’s. The hook will call the original implementation and log the private key in memory that will later be\r\nfetched by the operators.\r\nBefore attempting to modify the code segment, the program carefully sets a handler to intercept any segmentation\r\nfault it may cause. More specifically, the handler will be called if the process receives\r\na SIGSEGV or SIGBUS signal. In the case such signal is caught, Linux/Ebury will simply abort its task and let\r\nthe OpenSSH do its legitimate behavior. The way to recover from a segmentation fault is interesting. Before doing\r\nsomething that could potentially crash the process, sigsetjmp is called to create a snapshot of the current state.\r\nThen, if an access violation ever happens, siglongjmp is used in the signal hander to restore to the previous state.\r\nThis code patching technique is limited because offsets of code to patch is hardcoded inside the libkeyutils.so\r\ntrojan. Thus, its effectiveness is limited to the binary targeted by the variant. Typically eachlibkeyutils.so\r\nvariant will work for 3 to 5 different OpenSSH builds from a specific Linux distribution.\r\nFunctionalities\r\nThe backdoor is activated by sending specially-crafted data inside of the SSH client protocol version identification\r\nstring. Here is what the SSH specification has to say about protocol version identification.\r\nAfter the socket is opened, the server sends an identification string, which is of the form\r\n\"SSH-\u003cprotocolmajor\u003e.\u003cprotocolminor\u003e-\u003cversion\u003e\\n\", where \u003cprotocolmajor\u003e and\r\n\u003cprotocolminor\u003e are integers and specify the protocol version number (not software\r\ndistribution version). \u003cversion\u003e is server side software version string (max 40\r\ncharacters); it is not interpreted by the remote side but may be useful for debugging.\r\nhttp://www.openssh.com/txt/ssh-rfc-v1.5.txt — T. Ylonen\r\nThe \u003cversion\u003e portion could be anything and should not be interpreted by the SSH server. In the case of a\r\nLinux/Ebury backdoor connection, the \u003cversion\u003e contains a hexadecimal string of twenty-two (22) characters or\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 4 of 10\n\nmore. It embeds an eleven (11) character password that is first encrypted with the client IP address and then\r\nencoded as a hexadecimal string; optionally a four (4) byte command may be encrypted and encoded as well after\r\nthe password.\r\nNote that the protocol version identification is also sent before the encryption handshake is done, making it\r\npossible to flag potential intrusion detection from a network trace.\r\nAn example SSH protocol version to start a root shell looks like this:\r\nSSH-2.0-fb54c28ba102cd73c1fe43\r\nOnce the backdoor password is verified, the sshd process will allow any password to work during a password\r\nauthentication. If PermitRootLogin, PasswordAuthentication or PermitEmptyPassword is disabled, it will\r\nenable them to make sure it works. It will also disable all logging of the successful session creation. It will be like\r\nnothing happened.In version 1.3.1 and newer, a SHA-1 sum of the password is kept in the binary instead of an\r\neleven (11) character string (basic security practice by the Linux/Ebury’s authors). This makes guessing of the\r\npassword impractical unless you have a packet capture of the operators logging in successfully. Furthermore, the\r\npassword is different from one variant to another. This leads us to think the operators have a database of infected\r\nservers with corresponding backdoor passwords so they can activate each backdoor successfully.\r\n \r\nThe main purpose of the Linux/Ebury module is to steal credentials.  The stolen credentials are most likely used to\r\ninfect more servers. There is no code in Linux/Ebury to propagate itself; the backdoor is probably spread manually\r\nby an attacker or installed through deployment scripts.\r\nCredential Stealing\r\nCredentials are intercepted at multiple locations, when they are typed or used by the victim:\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 5 of 10\n\nPassword from successful login to the infected server:  Whenever someone logs in a system infected\r\nwith Linux/Ebury, the sshd daemon will save the password and send it to the exfiltration server.\r\nAny password login attempt to the infected server: Even if the attempt is unsuccessful, the username\r\nand password used will be sent to the operators. They will be formatted differently, however, allowing the\r\noperators to differentiate these invalid credentials from the valid ones.\r\nPassword on successful login from the infected server: When someone uses the ssh client on an infected\r\nserver, Linux/Ebury will intercept the password and sent it to its exfiltration server.\r\nPrivate key passphrase: When the ssh client on an infected server prompts the user for an private key\r\npassphrase, the passphrase will be sent to the remote exfiltration server.\r\nUnencrypted private key: When a private key is used to authenticate to a remote server, the unencrypted\r\nversion is intercepted by the malware. Unlike passwords, it will not send the key to the exfiltration server.\r\nInstead, it will store it memory and wait for the operators to fetch the key with the Xcat command.\r\nPrivate keys added to the OpenSSH agent with ssh-add: The keys added to an OpenSSH agent are also\r\nintercepted by the malware. Both the unencrypted key itself and the passphrase typed by the user will be\r\nlogged.\r\nWhatever the credential type, Linux/Ebury will add all relevant information for the operators to be able to use it,\r\nlike the username, the target IP address and its OpenSSH listening port.\r\nPassword exfiltration\r\nWhen a password is intercepted by Linux/Ebury, the information is sent to a remote server via a crafted DNS\r\nrequest sent to a specific IP address. The malware creates a regular A record request that will be sent on UDP port\r\n53. The domain name requested contains encrypted and hexadecimal-encoded data as well as an IP address.  The\r\ndata has the following format:\r\n\u003chexadecimal-encoded data\u003e.\u003cIP address\u003e\r\nThe \u003chexadecimal-encoded data\u003e contains the credentials previously described. It is XOR encrypted with the 4-\r\nbyte static key 0x000d5345 before being hexadecimal-encoded.\r\nThe IP address included in the query depends on the type of stolen credentials. If the credentials are for the\r\ninfected server itself, the client IP address is used. Otherwise, the remote IP address where the infected server is\r\nconnecting to is used.\r\nWe believe the malware authors chose to send packets that look like legitimate DNS requests over UDP port 53 to\r\navoid being blocked by firewalls. It is very common to whitelist DNS requests in firewall configurations because\r\nblocking them could disrupt name resolution.\r\nThere are 2 ways by which Linux/Ebury can choose a server where the DNS packets are sent. First, it can be set\r\nexplicitly by the operator when sending an Xver command. The second method uses an algorithm to generate a\r\ndomain name dynamically. This domain name will be queried for its A and TXT records. The TXT record will be\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 6 of 10\n\nused to verify that it is under the control of the operators using public key cryptography. Details about the domain\r\ngeneration algorithm and the verification processed will be published later.\r\nExtra commands\r\nThree commands are available to the malicious actors to ease the management of the compromised server. A\r\ncommand is appended to the backdoor password before being encrypted. When the backdoor identifies a\r\ncommand, it interprets it instead of starting a shell.  Here is a list of commands that can be processed by the\r\nbackdoor:\r\nXcat: print all the passwords, passphrases, and keys saved in the shared memory and exit.\r\nXver: print the installed Linux/Ebury version and exit. Xver also accept an optional four (4) byte argument.\r\nIf present, it will set the exfiltration server IP address to the given one.\r\nXbnd: Xbnd takes a four (4) byte argument. When creating a tunnel to a remote host, bind the client socket\r\nto the specified interface IP address.\r\nVersion tracking\r\nThe authors of Linux/Ebury have a good practice of leaving version number inside their binaries. This allows\r\noperators to know what version is installed on each system. It also helped researchers understand the chronology\r\nof events and sort samples more easily.\r\nFor example, since version 1.3.2, Linux/Ebury will not send any information to a remote server if an interface is in\r\npromiscuous mode. An interface is set to promiscuous mode when software like tcpdump is capturing the traffic\r\non a network interface. The authors probably added this feature in reaction to an article from cPanel about\r\nLinux/Ebury that suggested running tcpdump to monitor DNS requests and notice exfiltration data as an indicator\r\nof compromise.\r\nIndicators of Compromise (IOCs)\r\nWe will provide two means of identifying the presence of the Linux/Ebury SSH backdoor. The easiest way to\r\nidentify an infected server relies on the presence of a feature added by the malware to the ssh binary. A longer\r\nprocess involves inspection of the shared memory segments used by the malware.\r\nThe command ssh -G has a different behaviour on a system with Linux/Ebury. A clean server will print\r\nssh: illegal option -- G\r\nto stderr but an infected server will only print the typical “usage” message. One can use the following command\r\nto determine if the server he is on is compromised:\r\n$ ssh -G 2\u003e\u00261 | grep -e illegal -e unknown \u003e /dev/null \u0026\u0026 echo \"System clean\" || echo\r\n\"System infected\"\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 7 of 10\n\nLinux/Ebury relies on POSIX shared memory segments (SHMs) for interprocess communications. The current\r\nversion uses large segments of over 3 megabytes of memory with broad permissions allowing everyone to read\r\nand write to this segment.\r\nOther processes could legitimately create shared memory segments with broad permissions. Make sure to validate\r\nthat sshd is the process that created the segment like we show below.\r\nOne can identify large shared memory segment with broad permissions by running the following as root:\r\n# ipcs -m\r\n------ Shared Memory Segments --------\r\nkey shmid owner perms bytes nattch\r\n0x00000000 0 root 644 80 2\r\n0x00000000 32769 root 644 16384 2\r\n0x00000000 65538 root 644 280 2\r\n0x000010e0 465272836 root 666 3282312 0\r\nThen to look for the process that created the shared memory segment, use:\r\n# ipcs -m -p\r\n------ Shared Memory Creator/Last-op PIDs --------\r\nshmid owner cpid lpid\r\n0 root 4162 4183\r\n32769 root 4162 4183\r\n65538 root 4162 4183\r\n465272836 root 15029 17377\r\nIf the process matches sshd:\r\n# ps aux | grep \u003cpid\u003e\r\nroot 11531 0.0 0.0 103284 828 pts/0 S+ 16:40 0:00 grep 15029\r\nroot 15029 0.0 0.0 66300 1204 ? Ss Jan26 0:00 /usr/sbin/sshd\r\nAn sshd process using shared memory segments larger than three (3) megabytes (3,145,728 bytes) and with broad\r\npermissions (666) is a strong indicator of compromise.\r\nNetwork-based indicators\r\nWe are providing simple snort rules in order to easily pinpoint malicious activity in large networks. The Internet\r\nbeing a wild place these have greater chances of triggering false positives. Use wisely.\r\nThis first rule matches against the SSH Client Protocol field that the backdoor uses to connect to a victim. Any\r\nexternal host trying to connect to the backdoor on properly identified SSH ports will trigger the alert.\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 8 of 10\n\nalert tcp $EXTERNAL_NET any -\u003e $HOME_NET $SSH_PORTS (msg:\"Linux/Ebury SSH backdoor activty\"; content:\"SSH-2.0\";\r\nThe following Snort rule for detecting Linux/Ebury infected machines sending harvested credentials to a\r\nexfiltration server has been provided by CERT‑Bund.\r\nalert udp $HOME_NET any -\u003e $EXTERNAL_NET 53 (msg:\"Linux/Ebury SSH backdoor data exfiltration\"; content:\"|12 0b\r\nConclusion\r\nThe Linux/Ebury malware clearly is a complex threat with many interesting features such as code hooking,\r\nadvanced POSIX exception handling and various ways of hiding itself on an infected system. Based on data we\r\ncaptured, we estimate that thousands of systems are currently infected with Linux/Ebury. We feel it is important to\r\nspecify that we have not witnessed a weakness in the OpenSSH software itself. The Linux/Ebury trojan\r\npropagates using the stolen credentials collected by the operators. With the administrator’s credentials, there is no\r\nneed for a “0-day” exploit, although how the operators bootstrapped the whole credential stealing operation is still\r\na mystery.\r\nFile Details\r\nTrojanizedlibkeyutils.so file SHA-1 hashes.\r\n09c8af3be4327c83d4a7124a678bbc81e12a1de4 - Linux/Ebury - Version 1.3.2\r\n2e571993e30742ee04500fbe4a40ee1b14fa64d7 - Linux/Ebury - Version 1.3.4\r\n39ec9e03edb25f1c316822605fe4df7a7b1ad94a - Linux/Ebury - Version 1.3.2\r\n3c5ec2ab2c34ab57cba69bb2dee70c980f26b1bf - Linux/Ebury - Version 1.3.2\r\n471ee431030332dd636b8af24a428556ee72df37 - Linux/Ebury - Version 1.2.1\r\n5d3ec6c11c6b5e241df1cc19aa16d50652d6fac0 - Linux/Ebury - Version 1.3.3\r\n74aa801c89d07fa5a9692f8b41cb8dd07e77e407 - Linux/Ebury - Version 1.3.2\r\n7adb38bf14e6bf0d5b24fa3f3c9abed78c061ad1 - Linux/Ebury - Version 1.3.2\r\n9bb6a2157c6a3df16c8d2ad107f957153cba4236 - Linux/Ebury - Version 1.3.2\r\n9e2af0910676ec2d92a1cad1ab89029bc036f599 - Linux/Ebury - Version 1.3.3\r\nadfcd3e591330b8d84ab2ab1f7814d36e7b7e89f - Linux/Ebury - Version 1.3.2\r\nbf1466936e3bd882b47210c12bf06cb63f7624c0 - Linux/Ebury - Version 1.3.2\r\nd552cbadee27423772a37c59cb830703b757f35e - Linux/Ebury - Version 1.3.3\r\ne14da493d70ea4dd43e772117a61f9dbcff2c41c - Linux/Ebury - Version 1.3.2\r\nf1ada064941f77929c49c8d773cbad9c15eba322 - Linux/Ebury - Version 1.3.2\r\nReferences\r\nCERT‑Bund: Ebury FAQ - https://www.cert-bund.de/ebury-faq\r\ncPanel - http://docs.cpanel.net/twiki/bin/view/AllDocumentation/CompSystem\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 9 of 10\n\nDr. Web - http://news.drweb.com/show/?i=3600\u0026lng=en\u0026c=5\r\nDr.Web - http://news.drweb.com/?i=3332\u0026lng=en\r\nGunderson, Steinar - http://plog.sesse.net/blog/tech/2011-11-15-21-44_ebury_a_new_ssh_trojan.html\r\nSANS https://isc.sans.edu/diary/SSHD+rootkit+in+the+wild/15229\r\nWebHosting Talk - http://www.webhostingtalk.com/showthread.php?t=1235797\r\nSource: https://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nhttps://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/\r\nPage 10 of 10",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia",
		"MITRE",
		"ETDA"
	],
	"references": [
		"https://www.welivesecurity.com/2014/02/21/an-in-depth-analysis-of-linuxebury/"
	],
	"report_names": [
		"an-in-depth-analysis-of-linuxebury"
	],
	"threat_actors": [],
	"ts_created_at": 1775434570,
	"ts_updated_at": 1775791321,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/ed7a5e18579f6b3a7655e0437c440f468015e4b1.pdf",
		"text": "https://archive.orkl.eu/ed7a5e18579f6b3a7655e0437c440f468015e4b1.txt",
		"img": "https://archive.orkl.eu/ed7a5e18579f6b3a7655e0437c440f468015e4b1.jpg"
	}
}