Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2024-42642 — Proof-of-concept exploits for three vulnerabilities in Crucial MX500 SSD firmware update mechanism, enabling buffer overflows and potential code execution via ATA commands. | Kitploit
Tools/GitHubGitHub/vl4dr/cve-2024-42642
Embedded Systems SecurityVulnerability AnalysisExploitationReverse EngineeringHardware HackingHardware SecurityBinary AnalysisFirmware Analysis
GitHubvl4dr/cve-2024-42642

CVE-2024-42642

Proof-of-concept exploits for three vulnerabilities in Crucial MX500 SSD firmware update mechanism, enabling buffer overflows and potential code execution via ATA commands.

141212 years agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository

CVE-2024-42642

Introduction

The device in question is any MX500-series SSD. These SSDs are controlled by a Sillicon-Motion SM2259 controller (older batches had an older controller, Sillicon-Motion SM2258, but the main focus of this document is the newer one). SM2259 is a 4-channel SATA 6Gb/s micro-controller which sports a 32-bit little-endian CPU based on the ARC architecture. By observing the latest firmware applicable for the date of this document, which is M3CR046, a few issues were identified and confirmed both statically and dynamically. All of the issues were identified in the firmware update mechanism of the controller, which corresponds to the micro-controller handler of ATA PIO DOWNLOAD-MICROCODE (0x92) command, specifically in the logic that downloads the firmware using the offsets method, which corresponds to subcommands 0x03 and 0x0E. All the bugs that are covered in this document were verified on Crucial MX500 500GB SSD (CT500MX500SSD1), SM2259H-AC controller running M3CR046 FW with NY112 flash chips, using a PC with an x86_64 CPU.

The FW code is mapped to base address 0x80020000, and the vulnerable ATA handler is located at address 0x80024A9C. A decompiled version of the function can be found under resources/download_microcode_handler.c for your convenience.

For those who would rather not deal with the technical details and would rather understand the bottom line, please refer to the FAQ section down below.

As M3CR046 contains multiple firmware images from which the appropriate one is chosen by the firmware update mechanism (maybe depending on the actual flash chips used, or some other hardware characteristics), this document will cover the specifics of the first firmware variant (as this is the firmware that is supported on our specific drive, and thus we could only test that firmware variant). However, the bugs presented in this document seem to apply to all firmware variants, but there may be some differences in the actual specifics when reproducing them.

Bug #1

This issue refers to cases in which the first chunk sent is of size larger than 0x200 sectors. If we take a look inside the ATA command handler, specifically at the logic that is executed when the chunk size is larger than sector size and when the chunk is the first one sent:

image info

This sets some variables based on the next offset (which in our case, since we only sent a single chunk so far, is the chunk’s length in sectors) and on a variable named lower_bound_fw_offset which is the block offset (i.e., offset in granularity of sectors) within the input download image our firmware image is expected to be found. This is a hardcoded value per firmware variant, which in our case (the first variant), is equal to 0. In this case, an underflow occurs when calculating the subtraction result for some_index, causing some_index to be as high as 0xFFFF. This is unexpected behavior, as based on the logic that moves the data to the download buffer:

image info

We observe that the source address from which the data is copied might not be valid given the unexpected value calculated for some_index. When testing this dynamically by sending a firmware update request with the first chunk being of size larger than 0x200 sectors, the controller hangs and does not even send a response to the original request. This is consistent and easily reproducible. It is likely that this happens due to an invalid reference to the computed source address, which then triggers an exception that causes the controller hang. This has not been proven, but rather a conjecture that might explain the hang.

Bug #2

The input download image (for M3CR046) is of size 0x242400 bytes, and inside this image there are 3 internal firmware images that only one of them is eventually written to flash after a firmware update process, each such image is of size 0xC0C00 bytes (or 0x606 sectors). That means, that when the firmware update mechanism extracts the correct firmware copy from the input download image, it must verify that its size does not exceed 0xC0C00 bytes. The controller indeed attempts to do so, but there are some corner cases that can lead to unexpected behavior. Let us take a look at the following snippet (which shares some code with the previous bug):

image info

If the current chunk is of size greater than 0x200 sectors and it is not the first chunk in the sequence, then 0x200 sectors (0x40000 bytes) will be copied at a time. Then, there is a check whose purpose is to truncate the excess bytes from the number of bytes to copy if the total size of the firmware image exceeds higher_bound_fw_offset (which in our case, is 0x606 sectors, since the firmware size should be exactly this). This logic makes sense overall, but there is a flaw – if the last chunk that is sent causes the next offset to become too high, such that the excess number of bytes exceeds 0x200 sectors (or 0x40000 bytes), then curr_bytes_to_copy gets a “negative” value, which underflows to about ~4GB (~0xFFFFFFFF). Like we saw before, this variable is used to determine the number of bytes to be transferred to the download buffer. If we take a look inside r_maybe_some_efficient_data_transfer, we see the following piece of code:

image info

Which means that the copy size is truncated to 32MB (from the original ~4GB copy size), but that is still a large number which might also cause an undefined behavior if the memory range starting at 0x40000000 is of size less than 32MB. When testing this dynamically by sending ATA chunks to arrive at an offset of 0x600, and then sending a large chunk of size 0x207 sectors to trigger the underflow, the controller hangs yet again, probably due to an invalid memory access during copy. This bug is more interesting than the previous one, because even though we do not have a controlled overwrite (but rather, a big overwrite that possibly triggers an exception which hangs the controller), if the function that moves the data to the download buffer actually manages to transfer that much data before crashing (overwriting the memory range which is located right after the download buffer in main memory), then perhaps the exception handler’s behavior may be altered based on the overwritten data. That can possibly happen, if, for instance, the exception handler reads a pointer from the overwritten area and then jumping to it (this specific case is not particularly likely, but with some more research, something of the sort might be discovered).

Bug #3

As stated, the size of the download image is of size 0x242400 (or 0x1212 sectors). The firmware verifies that the total size of the transferred image does not exceed this size by verifying that the next offset does not exceed 0x1212 sectors. This check makes sense, but the computation of the next offset is flawed:

image info

If the current offset is 0x600 sectors, and the next ATA command to be processed is of size large enough (say 0xFC00 sectors, which is permitted by the ATA standard), then the next offset wraps around, such that the aforementioned check does not work properly:

Download Tool