UPDATE (December 2nd, 2024): The bootkit described on this report appears to be a part of a venture created by cybersecurity college students collaborating in Korea’s Better of the Finest (BoB) coaching program. As they knowledgeable us: “The first intention of this venture is to lift consciousness inside the safety neighborhood about potential dangers and to encourage proactive measures to stop comparable threats. Sadly, few bootkit samples had been disclosed previous to the deliberate convention presentation.” This helps our perception that it was an preliminary proof of idea somewhat than production-ready malware utilized by actual risk actors. Nonetheless, the weblog put up stays correct – it’s a practical bootkit with restricted help and represents the primary UEFI bootkit proof of idea for Linux OS.
Over the previous few years, the UEFI risk panorama, significantly that of UEFI bootkits, has advanced considerably. It began with the primary UEFI bootkit proof of idea (PoC) described by Andrea Allievi in 2012, which served as an illustration of deploying bootkits on fashionable UEFI-based Home windows programs, and was adopted with many different PoCs (EfiGuard, Boot Backdoor, UEFI-bootkit). It took a number of years till the primary two actual UEFI bootkits had been found within the wild (ESPecter, 2021 ESET; FinSpy bootkit, 2021 Kaspersky), and it took two extra years till the notorious BlackLotus – the primary UEFI bootkit able to bypassing UEFI Safe Boot on up-to-date programs – appeared (2023, ESET).
A standard thread amongst these publicly recognized bootkits was their unique focusing on of Home windows programs. In the present day, we unveil our newest discovery: the primary UEFI bootkit designed for Linux programs, named Bootkitty by its creators. We imagine this bootkit is merely an preliminary proof of idea, and based mostly on our telemetry, it has not been deployed within the wild. That mentioned, its existence underscores an vital message: UEFI bootkits are now not confined to Home windows programs alone.
The bootkit’s predominant purpose is to disable the kernel’s signature verification characteristic and to preload two as but unknown ELF binaries through the Linux init course of (which is the primary course of executed by the Linux kernel throughout system startup). Throughout our evaluation, we found a probably associated unsigned kernel module – with indicators suggesting that it might have been developed by the identical creator(s) because the bootkit – that deploys an ELF binary chargeable for loading yet one more kernel module unknown throughout our evaluation.
Key factors of this blogpost:
- In November 2024, a beforehand unknown UEFI utility, named bootkit.efi, was uploaded to VirusTotal.
- Our preliminary evaluation confirmed it’s a UEFI bootkit, named Bootkitty by its creators and surprisingly the primary UEFI bootkit focusing on Linux, particularly, a number of Ubuntu variations.
- Bootkitty is signed by a self-signed certificates, thus isn’t able to operating on programs with UEFI Safe Boot enabled until the attackers certificates have been put in.
- Bootkitty is designed besides the Linux kernel seamlessly, whether or not UEFI Safe Boot is enabled or not, because it patches, in reminiscence, the mandatory features chargeable for integrity verification earlier than GRUB is executed.
- bootkit.efi incorporates many artifacts suggesting that is extra like a proof of idea than the work of an energetic risk actor.
- We found a probably associated kernel module, which we named BCDropper, that deploys an ELF program chargeable for loading one other kernel module.
Bootkitty overview
As talked about within the introduction, Bootkitty incorporates many artifacts suggesting that we could be coping with a proof of idea as a substitute of actively used malware. On this part, we glance extra intently at these artifacts, plus different primary details about the bootkit.
Bootkitty incorporates two unused features, able to printing particular strings to the display screen throughout its execution. The primary operate, whose output is depicted in Determine 1, can print ASCII artwork that we imagine represents a potential identify of the bootkit: Bootkitty.
The second operate, can print textual content, proven in Determine 2, containing the record of potential bootkit authors and different individuals that maybe in some way participated in its growth. One of many names talked about within the picture will be discovered on GitHub, however the profile doesn’t have any public repository that might comprise or point out a UEFI bootkit venture; subsequently, we are able to neither verify nor deny authenticity of the names talked about within the bootkit.
Throughout each boot, Bootkitty prints on display screen the strings proven in Determine 3.
Notice that the BlackCat identify is referenced additionally within the loadable kernel module described later. Regardless of the identify, we imagine there isn’t a connection to the ALPHV/BlackCat ransomware group. It is because BlackCat is a reputation utilized by researchers and Bootkitty was developed in C, whereas the group calls itself ALPHV and develops its malware completely in Rust.
As talked about earlier, Bootkitty presently helps solely a restricted variety of programs. The reason being that to seek out the features it desires to change in reminiscence, it makes use of hardcoded byte patterns. Whereas byte-pattern matching is a standard approach in terms of bootkits, the authors didn’t use the most effective patterns for masking a number of kernel or GRUB variations; subsequently, the bootkit is totally practical just for a restricted variety of configurations. What limits using the bootkit much more is the way in which it patches the decompressed Linux kernel: as proven in Determine 4, as soon as the kernel picture is decompressed, Bootkitty merely copies the malicious patches to the hardcoded offsets inside the kernel picture.
We clarify how the bootkit will get to the precise kernel patching later within the Linux kernel picture decompression hook part; for now, simply be aware that as a result of lack of kernel-version checks within the operate proven in Determine 4, Bootkitty can get to the purpose the place it patches utterly random code or knowledge at these hardcoded offsets, thus crashing the system as a substitute of compromising it. This is among the info that helps proof of idea. Alternatively, it could be an preliminary not-production-ready model of malware created by malicious risk actors.
Final however not least, the bootkit binary is signed by the self-signed certificates proven in Determine 5.
Techical evaluation
We begin with an outline of Bootkitty’s execution, as depicted in Determine 6. First, we briefly describe the principle performance after which in subsequent sections we go into extra particulars.
There are three predominant components we concentrate on:
- Execution of the bootkit and patching of the reliable GRUB bootloader (factors 4 and 5 in Determine 6).
- Patching of the Linux kernel’s EFI stub loader (factors 6 and seven in Determine 6).
- Patching of the decompressed Linux kernel picture (factors 8 and 9 in Determine 6).
Initialization and GRUB hooking
After Bootkitty is executed by the shim, it checks to see whether or not UEFI Safe Boot is enabled by analyzing the worth of the SecureBoot UEFI variable, and proceeds to hook two features from the UEFI authentication protocols if that’s the case (this course of is proven in Determine 7):
- EFI_SECURITY2_ARCH_PROTOCOL.FileAuthentication: this operate is utilized by the firmware to measure and confirm the integrity of UEFI PE photos. Bootkitty’s hook operate modifies the output of this operate in order that it at all times returns EFI_SUCCESS, which means that the verification succeeded.
- EFI_SECURITY_ARCH_PROTOCOL.FileAuthenticationState: this operate is utilized by the firmware to execute a platform-specific coverage in response to completely different authentication standing values. Once more, the bootkit’s hook modifies it in a manner that it at all times returns EFI_SUCCESS, which means that the firmware can use the file no matter its precise authentication standing.
After checking the standing of UEFI Safe Boot, Bootkitty proceeds to load the reliable GRUB from the hardcoded path on the EFI system partition: /EFI/ubuntu/grubx64-real.efi. This file ought to be a backup, created by the attacker, of a reliable GRUB. As soon as GRUB is loaded (not but executed), the bootkit begins patching and hooking the next code in GRUB’s reminiscence:
- The start_image operate inside the peimage GRUB module (a module embedded inside GRUB). This operate is chargeable for beginning an already loaded PE picture, and it’s invoked by GRUB to begin the Linux kernel’s EFI stub binary (recognized normally as vmlinuz.efi or vmlinuz). The hook operate takes benefit of the truth that for the time being the hook is executed, vmlinuz is already loaded into reminiscence (however hasn’t been executed but), and patches the operate chargeable for decompressing the precise Linux kernel picture inside vmlinuz (be aware that in some instances, as a result of manner the Linux kernel is compiled, it may be fairly difficult to seek out the precise identify of the operate being patched; nevertheless, we imagine that this time it ought to be the zstd_decompress_dctx operate). Extra particulars concerning the decompression hook are within the Linux kernel picture decompression hook part.
- The shim_lock_verifier_init operate, which is a part of the shim_lock verifier mechanism inside GRUB – this ought to be activated robotically if UEFI Safe Boot is enabled. It’s chargeable for deciding whether or not the information supplied (e.g., GRUB modules, Linux kernel, configurations…) ought to be verified or not in the course of the boot. The put in hook, nevertheless, is in some way complicated and the creator’s intentions are unclear as a result of it modifies shim_lock_verifier_init’s output in a manner that it units the output flag to GRUB_VERIFY_FLAGS_SINGLE_CHUNK (worth 2) for any file sort supplied, which ought to, in line with the GRUB handbook, strengthen the safety much more. Apparently, as a result of hook described within the subsequent level, this shim_lock_verifier_init operate isn’t even known as in the course of the boot, thus changing into irrelevant.
- The grub_verifiers_open operate. This operate is invoked by GRUB anytime it opens a file, and is chargeable for checking whether or not the put in GRUB file verifiers (this consists of the shim_lock verifier described above) require integrity verification for the file being loaded. The operate is hooked by the bootkit in a manner that it returns instantly with out continuing to any signature checks (be aware that which means that it doesn’t even execute the beforehand hooked shim_lock_verifier_init operate).
Linux kernel picture decompression hook
This hook is chargeable for patching the decompressed Linux kernel picture. The hook is known as proper earlier than the kernel picture is decompressed, so the hook restores the unique decompression operate’s bytes and executes the unique operate to decompress the kernel picture earlier than continuing to the kernel patching.
Now, because the kernel is decompressed and lies within the reminiscence untouched (nonetheless hasn’t been executed), the hook code patches it at hardcoded offsets (in reminiscence solely). Particularly, as proven in Determine 8, it:
- Rewrites the kernel model and Linux banner strings with the textual content BoB13 (this has no important affect on the system).
- Hooks the module_sig_check operate.
- Patches pointer/handle to the primary atmosphere variable of the init course of.
The operate module_sig_check is patched to at all times return 0. This operate is chargeable for checking whether or not the module is validly signed. By patching the operate to return 0, the kernel will load any module with out verifying the signature. On Linux programs with UEFI Safe Boot enabled, kernel modules want to be signed if they’re meant to be loaded. That is additionally the case when the kernel is constructed with CONFIG_MODULE_SIG_FORCE enabled or when module.sig_enforce=1 is handed as a kernel command line argument, as described within the Linux kernel documentation. The doubtless state of affairs is that at the least one malicious kernel module is loaded at a later part, such because the dropper analyzed beneath.
The primary course of that the Linux kernel executes is init from the primary hardcoded path that works (beginning with /init from initramfs), together with command line arguments and atmosphere variables. The hook code replaces the primary atmosphere variable with LD_PRELOAD=/choose/injector.so /init. LD_PRELOAD is an atmosphere variable that’s used to load ELF shared objects earlier than others and can be utilized to override features. It’s a frequent approach utilized by attackers to load malicious binaries. On this case, the /choose/injector.so and /init ELF shared objects are loaded when the init course of begins. That is the place the intention turns into much less clear, primarily why the second string /init is a part of LD_PRELOAD.
We now have not found any of those probably malicious ELF shared objects, though simply as this blogpost was being finalized for publication, a write-up describing the lacking parts talked about in our report has been revealed. Now it’s clear they’re used simply to load one other stage.
Impression and remediation
Aside from loading unknown ELF shared objects, Bootkitty leaves footprints within the system. The primary is the supposed, albeit not mandatory, modification of kernel model and Linux banner strings. The previous will be seen by operating uname -v (Determine 9) and the latter by operating dmesg (Determine 10).
Throughout our evaluation, the output of the command dmesg additionally included particulars about how the init course of was run. As depicted in Determine 11, the method was run with the LD_PRELOAD atmosphere variable (it was initially HOME=/ and was changed with LD_PRELOAD=/choose/injector.so /init by the bootkit).
Notice in Determine 11 that the phrase /init within the first line corresponds to the reliable program in initramfs that ultimately passes management to systemd on default Ubuntu installations. The presence of the LD_PRELOAD atmosphere variable can be verified by inspecting the file /proc/1/environ.
After booting up a system with Bootkitty in our testing atmosphere, we observed that the kernel was marked as tainted (command from Determine 12 can be utilized to verify the contaminated worth), which was not the case when the bootkit was absent. One other technique to inform whether or not the bootkit is current on the system with UEFI Safe Boot enabled is by making an attempt to load an unsigned dummy kernel module throughout runtime. If it’s current, the module will probably be loaded; if not – the kernel refuses to load it.
A easy treatment tip to do away with the bootkit is to maneuver the reliable /EFI/ubuntu/grubx64-real.efi file again to its unique location, which is /EFI/ubuntu/grubx64.efi. It will make shim execute the reliable GRUB and thus the system will boot up with out the bootkit (be aware that this covers solely the state of affairs when the bootkit is deployed as /EFI/ubuntu/grubx64.efi).
BCDropper and BCObserver
Along with the bootkit, we found a probably associated unsigned kernel module we named BCDropper, uploaded to VirusTotal across the identical time and by the identical submitter’s ID because the bootkit, containing hints that it might need been developed by the identical creator because the bootkit, akin to:
- a BlackCat string within the output of the modinfo command’s output, proven in Determine 13,
- one other presence of the blackcat string within the debug paths within the module’s binary, proven in Determine 14, and
- it incorporates an unused file-hiding operate that hides particular entries from listing listings. As proven in Determine 15, one of many hardcoded filename string prefixes used to filter-out these entries is injector (be aware that Bootkitty tries to preload a shared-library from the trail /choose/injector.so)
Nonetheless, even with the proof offered, we can not say for positive whether or not or not the kernel module is expounded to Bootkitty (or was created by the identical developer). Additionally, the kernel model talked about in Determine 13 (6.8.0-48-generic) isn’t supported by the bootkit.
As its identify suggests, the kernel module drops an embedded ELF file we named BCObserver, particularly to /choose/observer, and executes it through /bin/bash (Determine 17). On high of that, the module hides itself by eradicating its entry from the module record. The kernel module additionally implements different rootkit-related functionalities like hiding information (these in Determine 15), processes, and open ports, however they aren’t straight utilized by the dropper.
BCObserver is a somewhat easy utility that waits till the show supervisor gdm3 is operating, after which hundreds an unknown kernel module from /choose/rootkit_loader.ko through the finit_module system name. By ready for the show supervisor to begin, the code ensures that the kernel module is loaded after the system is totally booted up.
Whereas we can not verify whether or not the dropper is in some way associated to the bootkit, and if that’s the case, how it’s meant to be executed, we’re fairly positive that the bootkit patches the module_sig_check operate for a cause, and loading an unsigned kernel module (such because the dropper described right here) would undoubtedly make sense.
Conclusion
Whether or not a proof of idea or not, Bootkitty marks an fascinating transfer ahead within the UEFI risk panorama, breaking the assumption about fashionable UEFI bootkits being Home windows-exclusive threats. Although the present model from VirusTotal doesn’t, for the time being, characterize an actual risk to nearly all of Linux programs, it emphasizes the need of being ready for potential future threats.
To maintain your Linux programs protected from such threats, ensure that UEFI Safe Boot is enabled, your system firmware and OS are up-to-date, and so is your UEFI revocations record.
For any inquiries about our analysis revealed on WeLiveSecurity, please contact us at [email protected].ÂESET Analysis presents personal APT intelligence studies and knowledge feeds. For any inquiries about this service, go to the ESET Menace Intelligence web page.
IoCs
A complete record of indicators of compromise (IoCs) and samples will be present in our GitHub repository.
Recordsdata
SHA-1 | Filename | Detection | Description |
35ADF3AED60440DA7B80 |
bootkit.efi | EFI/Agent.A | Bootkitty UEFI bootkit. |
BDDF2A7B3152942D3A82 |
dropper.ko | Linux/Rootkit.Agent.FM | BCDropper. |
E8AF4ED17F293665136E |
observer | Linux/Rootkit.Agent.FM | BCObserver. |
MITRE ATT&CK strategies
This desk was constructed utilizing model 16 of the MITRE ATT&CK framework.
Tactic | ID | Title | Description |
Useful resource Improvement | T1587.001 | Develop Capabilities: Malware | Bootkitty is a brand-new UEFI bootkit developed by an unknown creator. |
T1587.002 | Develop Capabilities: Code Signing Certificates | Bootkitty pattern is signed with a self-signed certificates. | |
Execution | T1106 | Native API | BCObserver makes use of the finit_module system name to load a kernel module. |
T1129 | Shared Modules | Bootkitty makes use of LD_PRELOAD to preload shared modules from a hardcoded path into the init course of throughout system begin. | |
Persistence | T1574.006 | Hijack Execution Move: Dynamic Linker Hijacking | Bootkitty patches init’s atmosphere variable with LD_PRELOAD so it hundreds a subsequent stage when executed. |
T1542.003 | Pre-OS Boot: Bootkit | Bootkitty is a UEFI bootkit meant to be deployed on the EFI System Partition. | |
Protection Evasion | T1014 | Rootkit | BCDropper serves as a rootkit carried out as a loadable kernel module for Linux programs. |
T1562 | Impair Defenses | Bootkitty disables signature verification options within the GRUB bootloader and Linux kernel. | |
T1564 | Cover Artifacts | BCDropper hides itself by eradicating its module’s entry from the kernel’s modules record. |