{
	"id": "fbbdb770-6bbe-4105-81c0-66f9563d9b60",
	"created_at": "2026-04-06T00:13:41.529096Z",
	"updated_at": "2026-04-10T03:29:39.949733Z",
	"deleted_at": null,
	"sha1_hash": "6140c3d4a9486b245b21d1171260e79a69291c79",
	"title": "Bootkitty: Analyzing the first UEFI bootkit for Linux",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 732143,
	"plain_text": "Bootkitty: Analyzing the first UEFI bootkit for Linux\r\nBy Martin SmolárPeter Strýček\r\nArchived: 2026-04-05 17:09:25 UTC\r\nUPDATE (December 2nd, 2024): The bootkit described in this report seems to be part of a project\r\ncreated by cybersecurity students participating in Korea's Best of the Best (BoB) training program. As\r\nthey informed us: \"The primary aim of this project is to raise awareness within the security community\r\nabout potential risks and to encourage proactive measures to prevent similar threats. Unfortunately, few\r\nbootkit samples were disclosed prior to the planned conference presentation.\" This supports our belief\r\nthat it was an initial proof of concept rather than production-ready malware used by real threat actors.\r\nNonetheless, the blog post remains accurate – it is a functional bootkit with limited support and\r\nrepresents the first UEFI bootkit proof of concept for Linux OS.\r\nOver the past few years, the UEFI threat landscape, particularly that of UEFI bootkits, has evolved significantly. It\r\nall started with the first UEFI bootkit proof of concept (PoC) described by Andrea Allievi in 2012, which served\r\nas a demonstration of deploying bootkits on modern UEFI-based Windows systems, and was followed with many\r\nother PoCs (EfiGuard, Boot Backdoor, UEFI-bootkit). It took several years until the first two real UEFI bootkits\r\nwere discovered in the wild (ESPecter, 2021 ESET; FinSpy bootkit, 2021 Kaspersky), and it took two more years\r\nuntil the infamous BlackLotus – the first UEFI bootkit capable of bypassing UEFI Secure Boot on up-to-date\r\nsystems – appeared (2023, ESET).\r\nA common thread among these publicly known bootkits was their exclusive targeting of Windows systems. Today,\r\nwe unveil our latest discovery: the first UEFI bootkit designed for Linux systems, named Bootkitty by its creators.\r\nWe believe this bootkit is merely an initial proof of concept, and based on our telemetry, it has not been deployed\r\nin the wild. That said, its existence underscores an important message: UEFI bootkits are no longer confined to\r\nWindows systems alone.\r\nThe bootkit’s main goal is to disable the kernel’s signature verification feature and to preload two as yet unknown\r\nELF binaries via the Linux init process (which is the first process executed by the Linux kernel during system\r\nstartup). During our analysis, we discovered a possibly related unsigned kernel module – with signs suggesting\r\nthat it could have been developed by the same author(s) as the bootkit – that deploys an ELF binary responsible\r\nfor loading yet another kernel module unknown during our analysis.\r\nKey points of this blogpost:\r\nIn November 2024, a previously unknown UEFI application, named bootkit.efi, was uploaded to\r\nVirusTotal.\r\nOur initial analysis confirmed it is a UEFI bootkit, named Bootkitty by its creators and\r\nsurprisingly the first UEFI bootkit targeting Linux, specifically, a few Ubuntu versions.\r\nBootkitty is signed by a self-signed certificate, thus is not capable of running on systems with\r\nUEFI Secure Boot enabled unless the attackers certificates have been installed.\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 1 of 13\n\nBootkitty is designed to boot the Linux kernel seamlessly, whether UEFI Secure Boot is enabled\r\nor not, as it patches, in memory, the necessary functions responsible for integrity verification\r\nbefore GRUB is executed.\r\nbootkit.efi contains many artifacts suggesting this is more like a proof of concept than the work\r\nof an active threat actor.\r\nWe discovered a possibly related kernel module, which we named BCDropper, that deploys an\r\nELF program responsible for loading another kernel module.\r\nBootkitty overview\r\nAs mentioned in the introduction, Bootkitty contains many artifacts suggesting that we might be dealing with a\r\nproof of concept instead of actively used malware. In this section, we look more closely at these artifacts, plus\r\nother basic information about the bootkit.\r\nBootkitty contains two unused functions, capable of printing special strings to the screen during its execution. The\r\nfirst function, whose output is depicted in Figure 1, can print ASCII art that we believe represents a possible name\r\nof the bootkit: Bootkitty.\r\nFigure 1. ASCII art embedded in the bootkit\r\nThe second function, can print text, shown in Figure 2, containing the list of possible bootkit authors and other\r\npersons that perhaps somehow participated in its development. One of the names mentioned in the image can be\r\nfound on GitHub, but the profile does not have any public repository that would contain or mention a UEFI\r\nbootkit project; therefore, we can neither confirm nor deny authenticity of the names mentioned in the bootkit.\r\nFigure 2. List of names embedded in the bootkit (redacted)\r\nDuring every boot, Bootkitty prints on screen the strings shown in Figure 3.\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 2 of 13\n\nFigure 3. Bootkitty’s welcome message\r\nNote that the BlackCat name is referenced also in the loadable kernel module described later. Despite the name,\r\nwe believe there is no connection to the ALPHV/BlackCat ransomware group. This is because BlackCat is a name\r\nused by researchers and Bootkitty was developed in C, while the group calls itself ALPHV and develops its\r\nmalware exclusively in Rust.\r\nAs mentioned earlier, Bootkitty currently supports only a limited number of systems. The reason is that to find the\r\nfunctions it wants to modify in memory, it uses hardcoded byte patterns. While byte-pattern matching is a\r\ncommon technique when it comes to bootkits, the authors didn’t use the best patterns for covering multiple kernel\r\nor GRUB versions; therefore, the bootkit is fully functional only for a limited number of configurations. What\r\nlimits the use of the bootkit even more is the way it patches the decompressed Linux kernel: as shown in Figure 4,\r\nonce the kernel image is decompressed, Bootkitty simply copies the malicious patches to the hardcoded offsets\r\nwithin the kernel image.\r\nFigure 4. Bootkitty’s code responsible for patching the decompressed kernel before it is executed\r\nWe explain how the bootkit gets to the actual kernel patching later in the Linux kernel image decompression hook\r\nsection; for now, just note that due to the lack of kernel-version checks in the function shown in Figure 4,\r\nBootkitty can get to the point where it patches completely random code or data at these hardcoded offsets, thus\r\ncrashing the system instead of compromising it. This is one of the facts that supports proof of concept. On the\r\nother hand, it might be an initial not-production-ready version of malware created by malicious threat actors.\r\nLast but not least, the bootkit binary is signed by the self-signed certificate shown in Figure 5.\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 3 of 13\n\nFigure 5. Self-signed certificate used to sign the bootkit\r\nTechical analysis\r\nWe start with an overview of Bootkitty’s execution, as depicted in Figure 6. First, we briefly describe the main\r\nfunctionality and then in subsequent sections we go into more details.\r\nThere are three main parts we focus on:\r\nExecution of the bootkit and patching of the legitimate GRUB bootloader (points 4 and 5 in Figure 6).\r\nPatching of the Linux kernel’s EFI stub loader (points 6 and 7 in Figure 6).\r\nPatching of the decompressed Linux kernel image (points 8 and 9 in Figure 6).\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 4 of 13\n\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 5 of 13\n\nFigure 6. Bootkitty execution overview\r\nInitialization and GRUB hooking\r\nAfter Bootkitty is executed by the shim, it checks to see whether UEFI Secure Boot is enabled by examining the\r\nvalue of the SecureBoot UEFI variable, and proceeds to hook two functions from the UEFI authentication\r\nprotocols if so (this process is shown in Figure 7):\r\nEFI_SECURITY2_ARCH_PROTOCOL.FileAuthentication: this function is used by the firmware to\r\nmeasure and verify the integrity of UEFI PE images. Bootkitty’s hook function modifies the output of this\r\nfunction so that it always returns EFI_SUCCESS, meaning that the verification succeeded.\r\nEFI_SECURITY_ARCH_PROTOCOL.FileAuthenticationState: this function is used by the firmware to\r\nexecute a platform-specific policy in response to different authentication status values. Again, the bootkit’s\r\nhook modifies it in a way that it always returns EFI_SUCCESS, meaning that the firmware can use the file\r\nregardless of its actual authentication status.\r\nFigure 7. Hooking of the UEFI security authentication protocols\r\nAfter checking the status of UEFI Secure Boot, Bootkitty proceeds to load the legitimate GRUB from the\r\nhardcoded path on the EFI system partition: /EFI/ubuntu/grubx64-real.efi. This file should be a backup, created by\r\nthe attacker, of a legitimate GRUB. Once GRUB is loaded (not yet executed), the bootkit starts patching and\r\nhooking the following code in GRUB’s memory:\r\nThe start_image function within the peimage GRUB module (a module embedded inside GRUB). This\r\nfunction is responsible for starting an already loaded PE image, and it’s invoked by GRUB to start the\r\nLinux kernel’s EFI stub binary (known in general as vmlinuz.efi or vmlinuz). The hook function takes\r\nadvantage of the fact that at the moment the hook is executed, vmlinuz is already loaded into memory (but\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 6 of 13\n\nhasn’t been executed yet), and patches the function responsible for decompressing the actual Linux kernel\r\nimage inside vmlinuz (note that in some cases, due to the way the Linux kernel is compiled, it can be quite\r\nchallenging to find the exact name of the function being patched; however, we believe that this time it\r\nshould be the zstd_decompress_dctx function). More details about the decompression hook are in the Linux\r\nkernel image decompression hook section.\r\nThe shim_lock_verifier_init function, which is part of the shim_lock verifier mechanism inside GRUB –\r\nthis should be activated automatically if UEFI Secure Boot is enabled. It is responsible for deciding\r\nwhether the files provided (e.g., GRUB modules, Linux kernel, configurations…) should be verified or not\r\nduring the boot. The installed hook, however, is somehow confusing and the author’s intentions are unclear\r\nbecause it modifies shim_lock_verifier_init’s output in a way that it sets the output flag to\r\nGRUB_VERIFY_FLAGS_SINGLE_CHUNK (value 2) for any file type provided, which should,\r\naccording to the GRUB manual, strengthen the security even more. Interestingly, due to the hook described\r\nin the next point, this shim_lock_verifier_init function is not even called during the boot, thus becoming\r\nirrelevant.\r\nThe grub_verifiers_open function. This function is invoked by GRUB anytime it opens a file, and is\r\nresponsible for checking whether the installed GRUB file verifiers (this includes the shim_lock verifier\r\ndescribed above) require integrity verification for the file being loaded. The function is hooked by the\r\nbootkit in a way that it returns immediately without proceeding to any signature checks (note that this\r\nmeans that it does not even execute the previously hooked shim_lock_verifier_init function).\r\nLinux kernel image decompression hook\r\nThis hook is responsible for patching the decompressed Linux kernel image. The hook is called right before the\r\nkernel image is decompressed, so the hook restores the original decompression function’s bytes and executes the\r\noriginal function to decompress the kernel image before proceeding to the kernel patching.\r\nNow, as the kernel is decompressed and lies in the memory untouched (still hasn’t been executed), the hook code\r\npatches it at hardcoded offsets (in memory only). Specifically, as shown in Figure 8, it:\r\nRewrites the kernel version and Linux banner strings with the text BoB13 (this has no significant impact\r\non the system).\r\nHooks the module_sig_check function.\r\nPatches pointer/address to the first environment variable of the init process.\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 7 of 13\n\nFigure 8. Bootkitty’s kernel-decompression hook inside vmlinuz\r\nThe function module_sig_check is patched to always return 0. This function is responsible for checking whether\r\nthe module is validly signed. By patching the function to return 0, the kernel will load any module without\r\nverifying the signature. On Linux systems with UEFI Secure Boot enabled, kernel modules need to be signed if\r\nthey are meant to be loaded. This is also the case when the kernel is built with CONFIG_MODULE_SIG_FORCE\r\nenabled or when module.sig_enforce=1 is passed as a kernel command line argument, as described in the Linux\r\nkernel documentation. The likely scenario is that at least one malicious kernel module is loaded at a later phase,\r\nsuch as the dropper analyzed below.\r\nThe first process that the Linux kernel executes is init from the first hardcoded path that works (starting with /init\r\nfrom initramfs), along with command line arguments and environment variables. The hook code replaces the first\r\nenvironment variable with LD_PRELOAD=/opt/injector.so /init. LD_PRELOAD is an environment variable that\r\nis used to load ELF shared objects before others and can be used to override functions. It is a common technique\r\nused by attackers to load malicious binaries. In this case, the /opt/injector.so and /init ELF shared objects are\r\nloaded when the init process starts. This is where the intention becomes less clear, mainly why the second string\r\n/init is part of LD_PRELOAD.\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 8 of 13\n\nWe have not discovered any of these possibly malicious ELF shared objects, although just as this blogpost was\r\nbeing finalized for publication, a write-up describing the missing components mentioned in our report has been\r\npublished. Now it’s clear they are used just to load another stage.\r\nImpact and remediation\r\nApart from loading unknown ELF shared objects, Bootkitty leaves footprints in the system. The first is the\r\nintended, albeit not necessary, modification of kernel version and Linux banner strings. The former can be seen by\r\nrunning uname -v (Figure 9) and the latter by running dmesg (Figure 10).\r\nFigure 9. BoB13 string in uname output\r\nFigure 10. BoB13 string in dmesg output\r\nDuring our analysis, the output of the command dmesg also included details about how the init process was run.\r\nAs depicted in Figure 11, the process was run with the LD_PRELOAD environment variable (it was originally\r\nHOME=/ and was replaced with LD_PRELOAD=/opt/injector.so /init by the bootkit).\r\nFigure 11. init process arguments and environment variables in dmesg output\r\nNote in Figure 11 that the word /init in the first line corresponds to the legitimate program in initramfs that\r\neventually passes control to systemd on default Ubuntu installations. The presence of the LD_PRELOAD\r\nenvironment variable can also be verified by inspecting the file /proc/1/environ.\r\nAfter booting up a system with Bootkitty in our testing environment, we noticed that the kernel was marked as\r\ntainted (command from Figure 12 can be used to check the tainted value), which was not the case when the\r\nbootkit was absent. Another way to tell whether the bootkit is present on the system with UEFI Secure Boot\r\nenabled is by attempting to load an unsigned dummy kernel module during runtime. If it’s present, the module\r\nwill be loaded; if not – the kernel refuses to load it.\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 9 of 13\n\nFigure 12. Tainted state right after the system has started with Bootkitty\r\nA simple remedy tip to get rid of the bootkit is to move the legitimate /EFI/ubuntu/grubx64-real.efi file back to its\r\noriginal location, which is /EFI/ubuntu/grubx64.efi. This will make shim execute the legitimate GRUB and thus\r\nthe system will boot up without the bootkit (note that this covers only the scenario when the bootkit is deployed as\r\n/EFI/ubuntu/grubx64.efi).\r\nBCDropper and BCObserver\r\nIn addition to the bootkit, we discovered a possibly related unsigned kernel module we named BCDropper,\r\nuploaded to VirusTotal around the same time and by the same submitter’s ID as the bootkit, containing hints that it\r\nmight have been developed by the same author as the bootkit, such as:\r\na BlackCat string in the output of the modinfo command’s output, shown in Figure 13,\r\nanother presence of the blackcat string in the debug paths in the module’s binary, shown in Figure 14, and\r\nit contains an unused file-hiding function that hides specific entries from directory listings. As shown in\r\nFigure 15, one of the hardcoded filename string prefixes used to filter-out these entries is injector (note that\r\nBootkitty tries to preload a shared-library from the path /opt/injector.so)\r\nHowever, even with the evidence presented, we cannot say for sure whether or not the kernel module is related to\r\nBootkitty (or was created by the same developer). Also, the kernel version mentioned in Figure 13 (6.8.0-48-\r\ngeneric) is not supported by the bootkit.\r\nFigure 13. Dropper module information\r\nFigure 14. Dropper debug symbols referencing blackcat\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 10 of 13\n\nFigure 15. List of files, in the dropper, to hide\r\nAs its name suggests, the kernel module drops an embedded ELF file we named BCObserver, specifically to\r\n/opt/observer, and executes it via /bin/bash (Figure 17). On top of that, the module hides itself by removing its\r\nentry from the module list. The kernel module also implements other rootkit-related functionalities like hiding\r\nfiles (those in Figure 15), processes, and open ports, but they are not directly used by the dropper.\r\nFigure 16. Hex-Rays decompiled dropper code\r\nBCObserver is a rather simple application that waits until the display manager gdm3 is running, and then loads an\r\nunknown kernel module from /opt/rootkit_loader.ko via the finit_module system call. By waiting for the display\r\nmanager to start, the code ensures that the kernel module is loaded after the system is fully booted up.\r\nFigure 17. Hex-Rays decompiled observer code\r\nWhile we cannot confirm whether the dropper is somehow related to the bootkit, and if so, how it is meant to be\r\nexecuted, we’re quite sure that the bootkit patches the module_sig_check function for a reason, and loading an\r\nunsigned kernel module (such as the dropper described here) would definitely make sense.\r\nConclusion\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 11 of 13\n\nWhether a proof of concept or not, Bootkitty marks an interesting move forward in the UEFI threat landscape,\r\nbreaking the belief about modern UEFI bootkits being Windows-exclusive threats. Even though the current\r\nversion from VirusTotal does not, at the moment, represent a real threat to the majority of Linux systems, it\r\nemphasizes the necessity of being prepared for potential future threats.\r\nTo keep your Linux systems safe from such threats, make sure that UEFI Secure Boot is enabled, your system\r\nfirmware and OS are up-to-date, and so is your UEFI revocations list.\r\nFor any inquiries about our research published on WeLiveSecurity, please contact us at\r\nthreatintel@eset.com. \r\nESET Research offers private APT intelligence reports and data feeds. For any inquiries about this\r\nservice, visit the ESET Threat Intelligence page.\r\nIoCs\r\nA comprehensive list of indicators of compromise (IoCs) and samples can be found in our GitHub repository.\r\nFiles\r\nSHA-1 Filename Detection Description\r\n35ADF3AED60440DA7B80\r\nF3C452047079E54364C1\r\nbootkit.efi EFI/Agent.A\r\nBootkitty UEFI\r\nbootkit.\r\nBDDF2A7B3152942D3A82\r\n9E63C03C7427F038B86D\r\ndropper.ko Linux/Rootkit.Agent.FM BCDropper.\r\nE8AF4ED17F293665136E\r\n17612D856FA62F96702D\r\nobserver Linux/Rootkit.Agent.FM BCObserver.\r\nMITRE ATT\u0026CK techniques\r\nThis table was built using version 16 of the MITRE ATT\u0026CK framework.\r\nTactic ID Name Description\r\nResource\r\nDevelopment\r\nT1587.001\r\nDevelop Capabilities:\r\nMalware\r\nBootkitty is a brand-new UEFI bootkit\r\ndeveloped by an unknown author.\r\nT1587.002\r\nDevelop Capabilities:\r\nCode Signing\r\nCertificates\r\nBootkitty sample is signed with a self-signed\r\ncertificate.\r\nExecution\r\nT1106 Native API\r\nBCObserver uses the finit_module system call\r\nto load a kernel module.\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 12 of 13\n\nTactic ID Name Description\r\nT1129 Shared Modules\r\nBootkitty uses LD_PRELOAD to preload\r\nshared modules from a hardcoded path into the\r\ninit process during system start.\r\nPersistence\r\nT1574.006\r\nHijack Execution Flow:\r\nDynamic Linker\r\nHijacking\r\nBootkitty patches init’s environment variable\r\nwith LD_PRELOAD so it loads a next stage\r\nwhen executed.\r\nT1542.003 Pre-OS Boot: Bootkit\r\nBootkitty is a UEFI bootkit meant to be\r\ndeployed on the EFI System Partition.\r\nDefense\r\nEvasion\r\nT1014 Rootkit\r\nBCDropper serves as a rootkit implemented as\r\na loadable kernel module for Linux systems.\r\nT1562 Impair Defenses\r\nBootkitty disables signature verification\r\nfeatures in the GRUB bootloader and Linux\r\nkernel.\r\nT1564 Hide Artifacts\r\nBCDropper hides itself by removing its\r\nmodule’s entry from the kernel’s modules list.\r\nSource: https://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nhttps://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/\r\nPage 13 of 13",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.welivesecurity.com/en/eset-research/bootkitty-analyzing-first-uefi-bootkit-linux/"
	],
	"report_names": [
		"bootkitty-analyzing-first-uefi-bootkit-linux"
	],
	"threat_actors": [
		{
			"id": "6e23ce43-e1ab-46e3-9f80-76fccf77682b",
			"created_at": "2022-10-25T16:07:23.303713Z",
			"updated_at": "2026-04-10T02:00:04.530417Z",
			"deleted_at": null,
			"main_name": "ALPHV",
			"aliases": [
				"ALPHV",
				"ALPHVM",
				"Ambitious Scorpius",
				"BlackCat Gang",
				"UNC4466"
			],
			"source_name": "ETDA:ALPHV",
			"tools": [
				"ALPHV",
				"ALPHVM",
				"BlackCat",
				"GO Simple Tunnel",
				"GOST",
				"Impacket",
				"LaZagne",
				"MEGAsync",
				"Mimikatz",
				"Munchkin",
				"Noberus",
				"PsExec",
				"Remcom",
				"RemoteCommandExecution",
				"WebBrowserPassView"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434421,
	"ts_updated_at": 1775791779,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/6140c3d4a9486b245b21d1171260e79a69291c79.pdf",
		"text": "https://archive.orkl.eu/6140c3d4a9486b245b21d1171260e79a69291c79.txt",
		"img": "https://archive.orkl.eu/6140c3d4a9486b245b21d1171260e79a69291c79.jpg"
	}
}