An attacker may attempt to reduce its binary size in order to conceal traces of attack. Therefore, we studied to what extent we can reduce binary sizes and what information we can still retrieve from information remaining not erased after reducing binary sizes, using approaches for reducing binary sizes that published information shows.
The build command we use to minimize binary sizes is shown below:
$env:RUSTFLAGS="-Zfmt-debug=none -Zlocation-detail=none";cargo +nightly build -Z build-std=std,panic_abort -Z build-std-features="optimize_for_size" -Z build-std-features=panic_immediate_abort --target x86_64-pc-windows-msvc --release
The location-detail option is a build option that enables us to control backtrace information.
Specifying none for this build option causes the values indicating source code paths, which are used on a panic, in the core::panic::Location struct are replaced with <redacted> and also the values indicating the line and column in the source code to be replaced with zero.
Specifying none for the location-detail option enables us to reduce binary sizes because the source code paths are deleted.
We can also presume that deleting the information causes incorrect backtraces to be output and can affect our study relating to identification of libraries.
The YARA rule is described below that uses the core::panic::Location struct containing <redacted> and the value <redacted> as a signature to determine whether -Zlocation-detail=none is used.
rule Detect_LocationDetail_Is_None
{
metadata:
description = "Detect Rust binary with option remove location details"
author = "JPCERT/CC Incident Response Group"
strings:
$s1 = "<redacted>"
/*
pub struct Location<'a> {
file: &'a str,
line: u32,
col: u32,
}
*/
$c1 = {
0A 00 00 00 00 00 00 00
00 00 00 00
00 00 00 00
}
$c2 = {
0A 00 00 00
00 00 00 00
00 00 00 00
}
condition:
Rust_Binary and $s1 and ($c1 or $c2)
}Using the fmt-debug option allows us to control output from #[derive(Debug)] and {:?}.
Specifying -Zfmt-debug=none for this build option causes output of macros to be partly deleted that internally use #[derive(Debug)] and {:?}, including the dbg!(), assert!() and unwrap() macros.
Therefore, we can use -Zfmt-debug=none to reduce binary sizes.
Standard libraries linked to binaries are optimized for the speed even under their default condition but not for the size.
We can specify the standard library using this build option as -Z build-std=std,panic_abort -Z build-std-features="optimize_for_size" and then rebuild a binary optimized for the size.
Linking a binary optimized for the size can reduce the executable file size.
The panic="abort" option that we can specify for Profile settings in Cargo is not applied to standard libraries.
Using the -Z build-std-features=panic_immediate_abort build option allows us to apply panic="abort" also to standard libraries.
We can use this build option to reduce binary sizes.
Such binaries may not be identified as Rust binaries from a binary with panic_immediate_abort specified, because strings specific to Rust binaries, as described in "Identifying Rust binaries," have been deleted.
Additionally, identifying which libraries are used can be affected because panic messages are deleted.