27 Giugno 2025

Unveiling RIFT: Enhancing Rust malware analysis through pattern matching

Today, Microsoft Threat Intelligence Center is excited to announce the release of RIFT, a tool designed to assist malware analysts automate the identification of attacker-written code within Rust binaries. Known for its efficiency, type safety, and robust memory safety, Rust has increasingly become a tool for creating malware, especially among financially motivated groups and nation-state entities. This shift has introduced new challenges for malware analysts as the unique characteristics of Rust binaries make static analysis more complex.

One of the primary challenges in reverse engineering malware developed with Rust lies in its layers of abstraction added through features such as memory safety and concurrency handling, making it more challenging to identify the behavior and intent of the malware. Compared to traditional languages, Rust binaries are often larger and more complex due to the incorporation of extensive library code. Consequently, reverse engineers must undertake the demanding task of distinguishing attacker-written code from standard library code, necessitating advanced expertise and specialized tools.

To address these pressing challenges, Microsoft Threat Intelligence Center has developed RIFT. RIFT underscores the growing need for specialized tools as cyber threat actors continue to leverage Rust’s features to evade detection and complicate analysis. The adoption of Rust by threat actors is a stark reminder of the ever-changing tactics employed in the cyber domain, and the increasing sophistication required to combat these threats effectively. In this blog post, we explore how threat actors are increasingly adopting Rust for malware development due to its versatility and how RIFT can be used to combat this threat by enhancing the efficiency and accuracy of Rust-based malware analysis.

Threat actors continue adopting Rust

As Rust gains popularity as a rapidly growing programming language, its use by malware authors is becoming more noticeable. Over the past five years, Microsoft Threat Intelligence Center and the broader security industry have observed financially motivated and state-supported groups increasingly using Rust for malware development.

Timeline from left to right: In December 2021 a Rust ransomware BlackCat report was released followed by Hive ransomware being rewritten in Rust in June 2022. In May 2023, Rust-based information stealers abused GitHub Codespace, then in March 2025 a report on Rust ransomware RALord was released, and finally in May 2025 the popular malware family AsyncRAT was rewritten in Rust.
Figure 1. Timeline of Rust-based threats

In 2021, the group behind the notorious BlackCat ransomware was among the first significant entities in the ransomware field to write their malicious programs in Rust. Following the appearance of the first malware families written in Rust, reverse engineers indicated that such malware presents a unique challenge for analysis.

Subsequently, several other groups began developing or rewriting their tools in the programming language. Nation-state threat actors have also selectively developed their malware in Rust.

Rust is a versatile language known for its performance, type safety, concurrency, and memory safety. While these features benefit legitimate development, they also complicate static analysis of malicious files. The community has extensively addressed many of these challenges. One of the core issues in analyzing Rust binaries is differentiating between library code and code written by malware authors.

To illustrate the significance of this problem, Microsoft Threat Intelligence Center conducted a simple experiment. A small PE EXE file that downloads data from a website and saves it on disk as sample_data.txt is generated with Microsoft 365 Copilot. The program is first compiled in C++ and then in Rust. The C++ program is compiled using Microsoft Visual C++ (MSVC) with Visual Studio 2022, in release mode for the 64-bit architecture and dynamically linked, using default settings. The Rust binary is compiled using compiler version rustc 1.89.0-nightly (16d2276fa 2025-05-16), also in release mode and with default settings.

Screenshot of code depicting a simple downloader program in C++ (or CPP) to the left and Rust to the right.
Figure 2. Simple downloader program in C++ to the left and Rust to the right

Next, both programs are loaded into IDA Pro, and a simple complexity analysis is performed by counting and comparing the number of disassembled and identified functions. Additionally, functions are categorized as annotated or not annotated. An annotated function is one that is automatically detected by IDA’s built-in signatures or algorithms. It should be noted that IDA has capabilities to enhance library recognition, but these were not used for this experiment.

While both programs implement similar functionalities, the total number of disassembled functions in the C++ program is lower than 100, while the Rust programs pack almost 10,000 functions. Furthermore, the size of the C++ program is lower than 20 KB, while the Rust program is larger than 3 MB.

Programs written in Rust are typically statically linked, embedding all dependencies directly into the executable. As a result, binaries are larger with a high volume of functions, requiring analysts to distinguish first between third-party library code and attacker-authored logic.

To address this key problem, Microsoft Threat Intelligence Center is releasing an internally developed tool: RIFT.

This open-source project is designed to help reverse engineers and analysts more efficiently identify attacker-authored logic within Rust-based malware.

From source code to binary

Diagram of the Rust developer toolset depicting the update manager rustup in the middle as it updates and manages cargo and rustc versions. One the left, the Rust compiler rustc engages with the hot pre-compiled compilation tools at static.rust-lang,org. On the right, the package manager cargo engages with the Rust community's crate registry at crates.io.
Figure 3. Overview of Rust developer toolset

Before delving into the inner workings of RIFT, it is essential to have a fundamental understanding of how Rust binaries are compiled. As illustrated in the diagram above, Rust developers typically engage with three primary components and two endpoints:

  • cargo – The package manager
  • rustc – The Rust compiler
  • rustup – The Rust update manager
  • static.rust-lang.org – S3 bucket that hosts pre-compiled compilers and toolchains
  • crates.io – Rust community’s crate registry

Once a developer has conceptualized what they intend to develop, a typical workflow may proceed as follows:

  1. Using the cargo tool, the developer initializes a new projected named “test”.
  2. They opt not to use the latest Rust compiler but a specific version. They execute rustup install 1.84.0-x86_64-pc-windows-msvc to install the desired compiler version and configure the project to use the installed compiler.
  3. They determine that their project should communicate via HTTP and incorporate a third-party dependency. They run cargo add request to install the latest version of the third-party library, request.

Following these steps will result in a fully configured project. Upon completion, the developer may run cargo build to finalize the binary, compiling the project.

Static artifacts and where to find them

Reverse engineers are usually handed the final development product of the malware author, oftentimes without information such as the compiler used or third-party dependencies. While it is highly likely that malware authors use the same tools as reverse engineers for development, no insights into the exact environment are available.

However, understanding the development toolchain can assist in quickly distinguishing library code from author written logic. Fortunately, various indicators can be extracted that provide insights.

Rust compiler version

Rust binaries typically include metadata from the compiler that identifies the Rust version used to compile the binary. A config.toml file is provided alongside pre-compiled Rust compilers and toolchains. This configuration file contains the commit hash and the corresponding Rust compiler version of the pre-compiled product. By extracting the commit hash from the final binary output, it is possible to map the Git commit hash back to the appropriate Rust compiler version by parsing all available config.toml files from the official release channels.

Rust crates

As mentioned above, cargo is used to add dependencies to a project. Next to the Git commit hash, metadata extracted from Rust binaries also include the statically linked dependencies and their versions.

Screenshot of the extractable dependencies, like rayon-core-1.12.1 and orion-0.19.9, from strings.
Figure 4. Extractable dependencies from strings

The above image shows how filtering for certain strings can display which dependencies were likely statically linked into RALord ransomware.

Introducing RIFT

RIFT is an open-source tool consisting of a set of IDA Pro (supporting versions >=9.0) plugins and Python scripts that aim to assist reverse engineers and other software analysts in annotating library code in Rust malware. It essentially consists of three components:

RIFT Static Analyzer: IDA Pro plugin to extract the Rust compiler commit hash and embedded dependencies from a binary.

RIFT Generator: A Python program to automate the process of Rust compiler identification, FLIRT signature generation of used Rust compiler and dependencies, as well as automation of binary diffing.

RIFT Diff Applier: IDA Pro plugin to consume binary diffing information generated by RIFT Generator.

Extracting static information with RIFT Static Analyzer

In the previous section, we listed which indicators can be extracted from Rust binaries that give insights into which Rust compiler and dependencies were used. RIFT Static Analyzer automates the extraction process and stores the information in a JSON file for further processing. Furthermore, the plugin also extracts the architecture the binary was compiled for and the target operating system. In the below image, the target operating system is labeled as target_triple.

A screenshot of a computer
Figure 5. Overview of RIFT Static Analyzer

RIFT Generator: Automating FLIRT signature generation and auto diffing

Information gathered and stored by RIFT Static Analyzer can then be further processed by RIFT Generator.

Screenshot of code depicting the RIFT Generator command line options, such as -h or --help to show this help message and exit, or --flirt to enable flirt signature generation.
Figure 6. RIFT Generator command line options

The Python program automates the process of compilation, data collection, FLIRT signature generation, and binary comparison.

It is essentially a wrapper around the following tools:

  • Cargo (Rust package manager) to manage the downloading and compiling of dependencies
  • Hexray’s FLAIR tools, specifically sigmake.exe and pcf.exe, to generate FLIRT signatures
  • Hexray’s text interface version of IDA, idat.exe, to automate binary analysis and disassembly
  • The open-source tool Diaphora to facilitate binary diffing
Diagram of RIFT Generator phases. First is the compilation phase to put a wrapper around cargo and rustup, next is the collect phase to collect artifacts from the compilation phase. Third is the FLIRT signature generation which puts a wrapper around pcf and sigmake, then in the fourth phase is disassembly analysis and SQLite generation to put a wrapper around idat.exe and Diaphora. Finally, the fifth phase is SQLite diffing and merging to put a wrapper around Diaphora and automate diffing.
Figure 7. Phases of RIFT Generator

The above image provides an overview of the phases RIFT Generator processes through. RIFT Generator reads the JSON file produced by RIFT Static Analyzer and downloads the corresponding Rust compiler, as well as the dependencies.

It is worth noting that upon completion of phase 1, both the code of the downloaded compiler and compiled crates are compressed as COFF files into RLIB files. RLIB is essentially a Rust-specific archive format similar to TAR. Once decompressed in phase 2, the COFF files are extracted and further processed.

FLIRT signatures and binary diffing

To provide information necessary for annotating library code in Rust binaries accurately, RIFT uses two known techniques for pattern matching: FLIRT signatures and binary diffing.

FLIRT stands for Fast Library Identification and Recognition Technology and enables IDA to identify standard library functions produced by its supported compilers. A characteristic of this technology is that library recognition is very precise. Therefore, functions that have a high similarity may not be flagged by FLIRT signatures due to their strict criteria.

Additionally, RIFT automates the process of binary diffing the collected COFF files against the target binary by leveraging IDA’s command line utility (idat.exe) and the Diaphora plugin.

Diagram of batch binary diffing process. First is the disassembly analysis and SQLite generation, next is the batch binary diffing, and finally is the merging of diffing results to ultimately be consumed by the RIFT Diff Applier plugin.
Figure 8. Overview of experimental batch binary diffing process

In general, both approaches have their own advantages and disadvantages, which are listed below.

FLIRT signatures approach Binary diffing approach
Highly reliable annotation, low false positive rate Higher false positive rate, but less strict and can fill gaps where FLIRT signatures fail due to strictness
With RIFT, in majority of cases, FLIRT signatures can be generated quickly In current state, batch binary diffing approach might take multiple hours
Not well applicable if dependencies and Rust compiler version are not available Approach might yield useful results even if Rust compiler version and dependencies were not available

Consuming binary diffing information

If the binary diffing approach is applied, a second IDA plugin called RIFT Diff Applier can be used to apply the diffing results. In contrast to FLIRT signatures, the RIFT Diff Applier offers analysts an interactive, semi-manual method for identifying library code. It operates in two modes:

  1. Interactive mode
  2. Auto rename mode
Screenshot of the GUI of the RIFT Diff Applier, requesting the JSON file to import, whether to enable auto renaming or name demangling, and selections for the ratio and the auto rename ratio.
Figure 9. GUI of RIFT Diff Applier

By default, symbol names in COFF files are mangled. Consequently, if RIFT Generator generates the binary diffing information and stores it in the JSON format, the symbol names are also mangled. To address this issue, enabling Name Demangling can assist in attempting to demangle these names. We are continuously improving the tool, and currently, rust-demangler is being used for this purpose.

For both modes, a minimum similarity ratio can be specified. Functions will only be displayed or renamed if they meet or exceed the specified similarity threshold. Once the user clicks “OK”, a new window will appear in IDA with the title RIFT. Users can now right click on a function name and display the top three matching functions with the highest similarity determined through binary diffing or use the CTRL+X shortcut.

Screenshot of the RIFT window in IDA displaying the top matching functions.
Figure 10. RIFT window in IDA displaying top matching functions

Applying RIFT on RALord ransomware

Having introduced the functionalities of RIFT, we will now examine its practical application in analyzing RALord ransomware and how RIFT’s FLIRT signature generation can be used to immensely reduce time identifying library functions in RALord.

First, RIFT Static Analyzer is used to dump the extractable dependencies, Git commit hash of the Rust compiler, target architecture, and target operating system. Next, the information is fed into RIFT Generator.

Once RIFT Generator has finished generating FLIRT signatures, they can either be loaded one by one manually or by using our script shared in the RIFT GitHub repository named “ida_apply_flirt_from_folder.py”.

The image below compares parts of the main function before and after application of RIFT. After applying the FLIRT signatures generated from the extracted dependencies and Rust compiler, the majority of library and compiler code is identified in the main function. As a result, reverse engineers can focus solely on the threat actor code instead of spending time weeding out the library code.

Screenshot depicting decompiled code before and after FLIRT signature application.
Figure 11. Comparing decompiled code before and after applying generated FLIRT signatures

Applying RIFT on SPICA

In some use cases, FLIRT signature application might not be enough, for example when conducting a deep dive. RIFT’s binary diffing approach can provide additional information to improve library code recognition in addition to FLIRT signatures.

Having demonstrated the effectiveness of RIFT in applying FLIRT signatures to streamline the analysis of RALord ransomware, we now turn our focus to applying the binary diffing approach on SPICA, a backdoor written in Rust. This transition highlights scenarios where FLIRT signatures alone might be insufficient, necessitating a deeper, complementary analysis.

Similar to before, RIFT Static Analyzer is used first and the extracted information is fed into RIFT Generator. However, this time, we apply FLIRT signature generation and binary diffing.

Screenshot of code depicting enabling FLIRT signature generation and binary diffing
Figure 12. Enabling FLIRT signature generation and binary diffing

To use the binary diffing approach, Diaphora must be used first to generate the corresponding SQLite file. It is worth noting that depending on the size of the binary and extracted dependencies, the binary diffing procedure can take multiple hours.

Once done, RIFT Diff Applier can be used to load the binary diffing output file.

Screenshot of the Riff Diff Applier in use displaying several windows of code and functions
Figure 13. Rift Diff Applier in use

A benefit of this approach is that for certain functions where FLIRT signatures failed to properly label the library function due to its strictness, RIFT Diff Applier can provide useful and reliable information where the similarity is high. Furthermore, thinking about detection engineering, the approach can also help identify or filter out potential library functions, especially when writing signatures on code segments.

Afterwords: Open sourcing RIFT

Rust’s strong performance, safety-focused design, cross-compilation support, and concurrency features have led to its increased adoption by threat actors for developing complex malware. This growing shift towards Rust represents a yet another evolution in the threat landscape, enabling attackers to create malware that is not more resistant to detection and analysis.

For malware analysts, this trend introduces a daunting set of challenges. Rust’s innovative features often result in binaries that are harder to decompile and analyze, making reverse engineering a time-intensive process. Analysts are frequently left grappling with unfamiliar patterns and library-heavy outputs, which further complicate their efforts to dissect malware and develop detection methods.

To address these challenges, we are proud to announce the open sourcing of RIFT. Designed to help accelerate Rust malware analysis by assisting reverse engineers to recognize library code in Rust malware through FLIRT signatures and binary diffing, RIFT further reinforces global efforts to equip security professionals with proper tools to defend against threats. By making RIFT freely available to the cybersecurity community, we aim to foster collaboration and innovation in combating the rise of Rust-based malware. We would like to extend a special thanks to the author of the Diaphora project for their invaluable contribution to the reverse engineering community.

Microsoft’s ongoing research and development efforts, including the creation of tools like RIFT, underscore our commitment to protecting customers and securing the cyber landscape. By enhancing the efficiency and accuracy of malware analysis, we aim to keep pace with evolving threats and ensure the safety of users worldwide. This research highlights the critical need for advanced security measures to safeguard against such increasingly sophisticated cyber threats.

References

Acknowledgments

Learn more

Meet the experts behind Microsoft Threat Intelligence, Incident Response, and the Microsoft Security Response Center at our VIP Mixer at Black Hat 2025. Discover how our end-to-end platform can help you strengthen resilience and elevate your security posture.

For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog

To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky

To hear stories and insights from the Microsoft Threat Intelligence community about the latest changes in the broader threat landscape, listen to the Microsoft Threat Intelligence podcast

The post Unveiling RIFT: Enhancing Rust malware analysis through pattern matching appeared first on Microsoft Security Blog.


Source: Microsoft Security

Share: