{
	"id": "bc2f7a96-dc1d-40cf-ad97-fb772c08769a",
	"created_at": "2026-04-06T00:17:35.681753Z",
	"updated_at": "2026-04-10T13:11:47.236572Z",
	"deleted_at": null,
	"sha1_hash": "de108dc6390e998413c2bdcda3578d9aef9533e2",
	"title": "MiKey - A Linux keylogger",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 273348,
	"plain_text": "MiKey - A Linux keylogger\r\nPublished: 2016-12-14 · Archived: 2026-04-05 22:28:41 UTC\r\nSummary:\r\nLinux malware is slowly becoming more popular. Within the past couple years there were several major incidents\r\nthat cited the use of Windows backdoors being ported to Linux. Through our research on the Windows KLRD\r\nkeylogger from the Odinaff report, we were able to discover several new keyloggers. The focus of this blog post is\r\nMiKey, a little-known and poorly detected keylogger.\r\nAt the time of this writing, the malware wasn’t detected by a single engine on Virustotal.\r\nAnalysis\r\nThe malware is a 64 bit Linux executable:\r\n9c07ed03f5bf56495e1d365552f5c9e74bb586ec45dffced2a8368490da4c829: ELF 64-bit LSB executable, x86-64, version 1\r\nAnd depends on the following libraries:\r\n linux-vdso.so.1 (0x00007ffd25123000)\r\n libX11.so.6 =\u003e /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f7f56420000)\r\n libdl.so.2 =\u003e /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f7f5621c000)\r\n libc.so.6 =\u003e /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7f55e7e000)\r\n libxcb.so.1 =\u003e /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f7f55c56000)\r\n /lib64/ld-linux-x86-64.so.2 (0x00005597839c6000)\r\n libXau.so.6 =\u003e /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f7f55a52000)\r\n libXdmcp.so.6 =\u003e /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f7f5584a000)\r\nAnalyzing the symbol table for this binary yielded some interesting function names. (Full output omitted for\r\nreadability):\r\n 63: 00000000004014b2 79 FUNC GLOBAL DEFAULT 14 createProccess\r\n 64: 0000000000400ed6 128 FUNC GLOBAL DEFAULT 14 initPlugins\r\n 67: 0000000000400f56 105 FUNC GLOBAL DEFAULT 14 moduleFeed\r\nhttps://securitykitten.github.io/2016/12/14/mikey.html\r\nPage 1 of 7\n\n68: 000000000040102d 1157 FUNC GLOBAL DEFAULT 14 keylogger\r\n 75: 0000000000400dc6 159 FUNC GLOBAL DEFAULT 14 handleArgs\r\n 83: 0000000000400e65 113 FUNC GLOBAL DEFAULT 14 moduleHandleArgs\r\n 85: 00000000004015fc 209 FUNC GLOBAL DEFAULT 14 addData\r\n 87: 0000000000400cd0 42 FUNC GLOBAL DEFAULT 14 _start\r\n 88: 0000000000400fbf 110 FUNC GLOBAL DEFAULT 14 addParentheses\r\n 92: 0000000000401501 126 FUNC GLOBAL DEFAULT 14 main\r\n 103: 0000000000400b00 0 FUNC GLOBAL DEFAULT 11 _init\r\nComments left by the compiler provide evidence it was compiled on Ubuntu 16.04.2:\r\n9c07ed03f5bf56495e1d365552f5c9e74bb586ec45dffced2a8368490da4c829: file format elf64-x86-64\r\nContents of section .comment:\r\n 0000 4743433a 20285562 756e7475 20352e34 GCC: (Ubuntu 5.4\r\n 0010 2e302d36 7562756e 7475317e 31362e30 .0-6ubuntu1~16.0\r\n 0020 342e3229 20352e34 2e302032 30313630 4.2) 5.4.0 20160\r\n 0030 36303900 609.\r\nThis is further evidenced by the build path in the binary:\r\n/home/ubuntu/MiKey-64-ubuntu\r\nThe strace tool was used to quickly identify high-level function workflows and identify potential focus areas. One\r\nanomaly identified was a failed file opening, “mikey-text.so.” So we began there.\r\nopen(\"./tls/x86_64/mikey-text.so\", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)\r\nopen(\"./tls/mikey-text.so\", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)\r\nopen(\"./x86_64/mikey-text.so\", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)\r\nopen(\"./mikey-text.so\", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)\r\nThe malware isn’t explicitly searching these directories for mikey-text.so. This is a side effect of dlopen. From the\r\nman page:\r\n“If, at the time that the program was started, the environment variable LD_LIBRARY_PATH was defined to contain\r\nAfter a little searching we located a second binary (SHA-256\r\nbc6d25dff00dfb68b19b362c409d2cf497e5dd97d9d6e5ce2bde2ba706f2bdb3) which contained the string “mikey-text.c.” From this, we assessed that mickey-text.so is the compiled version of this binary.\r\nUsing this assertion, we renamed the second binary to mikey-text.so and placed it in the load path identified using\r\nstrace. This caused the successful execution of the malware. The output file (out.log) contained the logged\r\nhttps://securitykitten.github.io/2016/12/14/mikey.html\r\nPage 2 of 7\n\nkeystrokes with associated timestamps.\r\nThrough static analysis, we were able to identify that when the keylogger starts up, it loaded plugins, handle\r\narguments, and then forked its process.\r\nWhen loading the plugins, the keylogger looked for a single hardcoded plugin name “mikey-text.so” and called\r\ndlopen to obtain a handle to it.\r\nOnce everything was loaded, the main functionality of the program was handled through the “keylogger” function.\r\nTo better understand Linux keyloggers and associated function calls, basic X function knowledge is critical. As a\r\nquick primer, here are some routines used by the “keylogger” function to query information about keystrokes or\r\nsimply harvest raw keystroke data.\r\nFunction Purpose\r\nXOpenDisplay\r\nReturns a display structure that serves as the connection to the X server.\r\nCommunication is then carried out through TCP or IPC.\r\nXQueryKeymap\r\nUses the structure from the display to gather information about the state of the\r\nkeyboard. Information about which keys are currently pressed can be gathered\r\nusing this call.\r\nXkbKeycodeToKeysym Uses the structure from the display to return the keysym for a particular key.\r\nXKeysymToString Converts the previously obtained keysym.\r\nXGetInputFocus Controls focus on the desktop.\r\nhttps://securitykitten.github.io/2016/12/14/mikey.html\r\nPage 3 of 7\n\nOnce the keycode is retrieved, it’s compared against a large switch table to convert each keycode into a string.\r\nThis is no different than most keyloggers.\r\nNon-printable keystrokes are then identified and substituted with human-readable outputs.\r\nIf there is a non-printable character returned, a small method to format the string in parentheses is called to make\r\nfor nice output into the log.\r\nOnce completed, the data is stored into a buffer and passed to a loadable module. The Linux dlsym method\r\nprovides similar functionality as “LoadLibrary” on Windows. The previous handle from dlopen is being passed to\r\ndlsym, which we can now use to call the method “getFeed” from mikey-text.so.\r\nhttps://securitykitten.github.io/2016/12/14/mikey.html\r\nPage 4 of 7\n\nPeering into the “getFeed” function on mikey-text.so it simply calls the _log function.\r\nThe _log function will call _time and _localtime (to harvest the timestamps) and build these into a format string.\r\nhttps://securitykitten.github.io/2016/12/14/mikey.html\r\nPage 5 of 7\n\nAt this point, the output file is opened for writing with the appended (“a+”) flag and the file is written to using the\r\n_fputs method. If no option for –output was provided to mikey-text.so then the default name of “out.log” is\r\nprovided. The screenshot below identifies the contents of cs:outputfile_ptr as a pointer to the name of the output\r\nfile.\r\nOutside of a small method to parse arguments, there isn’t much more functionality to mikey-text.so. It’s a simple\r\nlogging plugin for the main MiKey keylogger. Booz Allen assesses that additional plugins may exist (for C2\r\ncommunication, or to hook to other files), but is unable to confirm at this time.\r\nTo run the keylogger and give a custom argument for an output file named keylogged.txt, the following command\r\ncan be used. In addition, providing the “-b” option will “background” the process.\r\nChecking processes on the host, the command “ps aux” was issued.\r\nhttps://securitykitten.github.io/2016/12/14/mikey.html\r\nPage 6 of 7\n\nAnd checking the output of the keylogged file:\r\nConclusion\r\nSmall utilities that are built for a specific purpose often bypass AV with ease. Attackers are able to write a\r\nfunctional keylogger that will dump the contents to a local file. By having modular code, the authors could build\r\nplugins that achieve whatever task they need. The plugin nature of this code also puts the reverse engineer at a\r\ndisadvantage. Without access to each module, only specific known functions of the tool can be documented.\r\nOne unnerving aspect of this keylogger is that, without an active command and control capability, the attacker\r\nwould need to be confident in their ability to repeatedly gain remote access to the victim computer to retrieve the\r\nkeylogged information.\r\nAll it takes to catch this is basic process and file monitoring, but if our Linux field experience is any indicator,\r\nthere aren’t many shops with this level of visibility on non-Windows workstations.\r\nSource: https://securitykitten.github.io/2016/12/14/mikey.html\r\nhttps://securitykitten.github.io/2016/12/14/mikey.html\r\nPage 7 of 7",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://securitykitten.github.io/2016/12/14/mikey.html"
	],
	"report_names": [
		"mikey.html"
	],
	"threat_actors": [],
	"ts_created_at": 1775434655,
	"ts_updated_at": 1775826707,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/de108dc6390e998413c2bdcda3578d9aef9533e2.pdf",
		"text": "https://archive.orkl.eu/de108dc6390e998413c2bdcda3578d9aef9533e2.txt",
		"img": "https://archive.orkl.eu/de108dc6390e998413c2bdcda3578d9aef9533e2.jpg"
	}
}