#![allow(clippy::uninlined_format_args)]
#![allow(unused_variables)]
use pretty_assertions::assert_eq;
#[cfg(any(feature = "elf", feature = "pe", feature = "macho", feature = "java"))]
use rstest::*;
use threatflux_binary_analysis::types::*;
use threatflux_binary_analysis::BinaryAnalyzer;
mod common;
use common::fixtures::*;
#[cfg(feature = "elf")]
#[test]
fn test_elf_gcc_detection() {
let data = create_elf_with_gcc_comment();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
println!("Format detected: {:?}", result.format);
println!("Compiler info: {:?}", metadata.compiler_info);
assert!(
metadata.compiler_info.is_some(),
"Should detect compiler info"
);
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info.contains("GCC") || compiler_info.contains("gcc"),
"Should detect GCC compiler"
);
}
}
#[cfg(feature = "elf")]
#[rstest]
#[case(
create_elf_with_clang_comment(),
"Clang",
"Should detect Clang from .comment"
)]
#[case(create_elf_with_gcc_version(), "GCC", "Should detect GCC version")]
#[case(create_elf_with_rust_metadata(), "Rust", "Should detect Rust compiler")]
#[case(create_elf_with_go_buildinfo(), "Go", "Should detect Go toolchain")]
#[case(
create_elf_with_mixed_sections(),
"Unknown",
"Should handle mixed/unclear info"
)]
fn test_elf_compiler_variants(
#[case] data: Vec<u8>,
#[case] expected_compiler: &str,
#[case] description: &str,
) {
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
println!("Test case: {}", description);
println!(
"Format: {:?}, Compiler info: {:?}",
result.format, metadata.compiler_info
);
if expected_compiler == "Unknown" {
assert!(metadata.compiler_info.is_some() || metadata.compiler_info.is_none());
} else {
assert!(
metadata.compiler_info.is_some(),
"Should detect compiler: {}",
description
);
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info
.to_lowercase()
.contains(&expected_compiler.to_lowercase()),
"Should contain '{}' for: {}, got: {}",
expected_compiler,
description,
compiler_info
);
}
}
}
#[cfg(feature = "elf")]
#[test]
fn test_elf_note_section_compiler_detection() {
let data = create_elf_with_build_id_note();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
assert_eq!(result.format, BinaryFormat::Elf);
}
#[cfg(feature = "pe")]
#[test]
fn test_pe_rich_header_msvc_detection() {
let data = create_pe_with_rich_header();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info.contains("MSVC") || compiler_info.contains("Visual"),
"Should detect MSVC from Rich header"
);
}
}
#[cfg(feature = "pe")]
#[rstest]
#[case(create_pe_with_msvc_2022(), "MSVC", "2022", "Visual Studio 2022")]
#[case(create_pe_with_msvc_2019(), "MSVC", "2019", "Visual Studio 2019")]
#[case(create_pe_with_msvc_2017(), "MSVC", "2017", "Visual Studio 2017")]
#[case(create_pe_with_msvc_2015(), "MSVC", "2015", "Visual Studio 2015")]
#[case(create_pe_with_msvc_2013(), "MSVC", "2013", "Visual Studio 2013")]
#[case(create_pe_with_mingw(), "MinGW", "", "MinGW/GCC toolchain")]
#[case(create_pe_with_clang(), "Clang", "", "Clang/LLVM toolchain")]
#[case(create_pe_with_intel_compiler(), "Intel", "", "Intel C++ Compiler")]
fn test_pe_compiler_variants(
#[case] data: Vec<u8>,
#[case] expected_compiler: &str,
#[case] expected_version: &str,
#[case] description: &str,
) {
let result = BinaryAnalyzer::new().analyze(&data);
if let Ok(parsed) = result {
let metadata = &parsed.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info
.to_lowercase()
.contains(&expected_compiler.to_lowercase()),
"Should contain '{}' for: {}, got: {}",
expected_compiler,
description,
compiler_info
);
if !expected_version.is_empty() {
assert!(
compiler_info.contains(expected_version),
"Should contain version '{}' for: {}, got: {}",
expected_version,
description,
compiler_info
);
}
}
}
}
#[cfg(feature = "pe")]
#[test]
fn test_pe_debug_directory_compiler_detection() {
let data = create_pe_with_pdb_debug_info();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info.contains("MSVC") || compiler_info.contains("PDB"),
"Should detect MSVC from PDB debug info"
);
}
}
#[cfg(feature = "pe")]
#[test]
fn test_pe_import_table_compiler_hints() {
let data = create_pe_with_msvc_runtime_imports();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let imports = &result.imports;
let metadata = &result.metadata;
let msvc_runtime_imports: Vec<_> = imports
.iter()
.filter(|i| {
if let Some(ref lib) = i.library {
lib.contains("msvcr")
|| lib.contains("vcruntime")
|| lib.contains("msvcp")
|| lib.contains("ucrtbase")
} else {
false
}
})
.collect();
if !msvc_runtime_imports.is_empty() {
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(compiler_info.contains("MSVC") || compiler_info.contains("Visual"));
}
}
}
#[cfg(feature = "macho")]
#[test]
fn test_macho_build_version_detection() {
let data = create_macho_with_build_version();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info.contains("Platform")
|| compiler_info.contains("SDK")
|| compiler_info.contains("Apple")
|| compiler_info.contains("Xcode"),
"Should detect Apple toolchain info"
);
}
}
#[cfg(feature = "macho")]
#[rstest]
#[case(create_macho_with_xcode_15(), "Xcode", "15", "Xcode 15")]
#[case(create_macho_with_xcode_14(), "Xcode", "14", "Xcode 14")]
#[case(
create_macho_with_command_line_tools(),
"Apple",
"command",
"Command Line Tools"
)]
#[case(create_macho_with_swift_metadata(), "Swift", "", "Swift compiler")]
#[case(
create_macho_with_objective_c(),
"Objective-C",
"",
"Objective-C compiler"
)]
fn test_macho_compiler_variants(
#[case] data: Vec<u8>,
#[case] expected_compiler: &str,
#[case] expected_version: &str,
#[case] description: &str,
) {
let result = BinaryAnalyzer::new().analyze(&data);
if let Ok(parsed) = result {
let metadata = &parsed.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info
.to_lowercase()
.contains(&expected_compiler.to_lowercase()),
"Should contain '{}' for: {}, got: {}",
expected_compiler,
description,
compiler_info
);
if !expected_version.is_empty() {
assert!(
compiler_info.contains(expected_version),
"Should contain version '{}' for: {}, got: {}",
expected_version,
description,
compiler_info
);
}
}
}
}
#[cfg(feature = "macho")]
#[rstest]
#[case(create_macho_for_macos(), "macOS", "Should detect macOS platform")]
#[case(create_macho_for_ios(), "iOS", "Should detect iOS platform")]
#[case(
create_macho_for_watchos(),
"watchOS",
"Should detect watchOS platform"
)]
#[case(create_macho_for_tvos(), "tvOS", "Should detect tvOS platform")]
#[case(create_macho_for_catalyst(), "Catalyst", "Should detect Mac Catalyst")]
fn test_macho_platform_detection(
#[case] data: Vec<u8>,
#[case] expected_platform: &str,
#[case] description: &str,
) {
let result = BinaryAnalyzer::new().analyze(&data);
if let Ok(parsed) = result {
let metadata = &parsed.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info.contains(expected_platform),
"Should contain '{}' for: {}, got: {}",
expected_platform,
description,
compiler_info
);
}
}
}
#[cfg(feature = "java")]
#[rstest]
#[case(52, 0, "Java 8", "Should detect Java 8")]
#[case(55, 0, "Java 11", "Should detect Java 11")]
#[case(61, 0, "Java 17", "Should detect Java 17")]
#[case(65, 0, "Java 21", "Should detect Java 21")]
fn test_java_version_detection(
#[case] major: u16,
#[case] minor: u16,
#[case] expected_version: &str,
#[case] description: &str,
) {
let data = create_java_class_with_version(major, minor);
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
assert!(
metadata.compiler_info.is_some(),
"Should have compiler info for: {}",
description
);
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info.contains(&major.to_string()),
"Should contain major version for: {}, got: {}",
description,
compiler_info
);
}
}
#[cfg(feature = "java")]
#[test]
fn test_java_compiler_attributes() {
let data = create_java_class_with_source_file_attribute();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
assert_eq!(result.format, BinaryFormat::Java);
}
#[test]
fn test_cross_compiler_detection() {
let cross_compile_scenarios = vec![
("ELF for ARM on x86", create_elf_arm_cross_compiled()),
("PE for x64 on Linux", create_pe_cross_compiled_mingw()),
("Mach-O Universal Binary", create_macho_universal_binary()),
];
for (description, data) in cross_compile_scenarios {
let format = threatflux_binary_analysis::formats::detect_format(&data);
assert!(format.is_ok(), "Should detect format for: {}", description);
let format_type = format.unwrap();
let result = match format_type {
BinaryFormat::Elf => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::Pe => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::MachO => BinaryAnalyzer::new().analyze(&data),
_ => continue,
};
if let Ok(parsed) = result {
let metadata = &parsed.metadata;
assert_eq!(
parsed.format, format_type,
"Format should match for: {}",
description
);
}
}
}
#[test]
fn test_compiler_confidence_scoring() {
let test_cases = vec![
(
create_elf_with_strong_gcc_indicators(),
"Strong GCC indicators",
),
(create_pe_with_weak_msvc_hints(), "Weak MSVC hints"),
(
create_macho_with_mixed_toolchain_signs(),
"Mixed toolchain indicators",
),
];
for (data, description) in test_cases {
let format = threatflux_binary_analysis::formats::detect_format(&data).unwrap();
let result = match format {
BinaryFormat::Elf => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::Pe => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::MachO => BinaryAnalyzer::new().analyze(&data),
_ => continue,
};
if let Ok(parsed) = result {
let metadata = &parsed.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
!compiler_info.is_empty(),
"Compiler info should not be empty for: {}",
description
);
}
}
}
}
#[test]
fn test_compiler_detection_edge_cases() {
let edge_cases = vec![
("Stripped binary", create_completely_stripped_elf()),
("Packed binary", create_packed_pe_upx()),
("Obfuscated binary", create_obfuscated_macho()),
("Corrupted debug info", create_elf_with_corrupted_debug()),
("Missing sections", create_pe_with_missing_sections()),
];
for (description, data) in edge_cases {
let format = threatflux_binary_analysis::formats::detect_format(&data);
if let Ok(format_type) = format {
let result = match format_type {
BinaryFormat::Elf => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::Pe => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::MachO => BinaryAnalyzer::new().analyze(&data),
_ => continue,
};
match result {
Ok(parsed) => {
let metadata = &parsed.metadata;
assert_eq!(
parsed.format, format_type,
"Should maintain format correctness for: {}",
description
);
}
Err(_) => {
}
}
}
}
}
#[test]
fn test_compiler_detection_performance() {
let large_elf = create_large_elf_with_debug_info(50 * 1024 * 1024);
let start = std::time::Instant::now();
let result = BinaryAnalyzer::new().analyze(&large_elf);
let duration = start.elapsed();
assert!(result.is_ok(), "Should parse large binary with debug info");
assert!(
duration.as_secs() < 30,
"Compiler detection should be reasonably fast"
);
if let Ok(parsed) = result {
let metadata = &parsed.metadata;
if metadata.compiler_info.is_some() {
}
}
}
#[allow(dead_code)]
fn create_elf_with_comment(comment: &[u8]) -> Vec<u8> {
let mut data = vec![0u8; 8192];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00, 0x05, 0x00, 0x03, 0x00, ];
data[..64].copy_from_slice(&elf_header);
let ph_load = [
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[64..120].copy_from_slice(&ph_load);
let comment_offset = 512;
data[comment_offset..comment_offset + comment.len()].copy_from_slice(comment);
let shstrtab_offset = 600;
let shstrtab = b"\0.text\0.comment\0.shstrtab\0.strtab\0";
data[shstrtab_offset..shstrtab_offset + shstrtab.len()].copy_from_slice(shstrtab);
let sh_offset = 1024;
let null_section = [0u8; 64];
data[sh_offset..sh_offset + 64].copy_from_slice(&null_section);
let text_section = [
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[sh_offset + 64..sh_offset + 128].copy_from_slice(&text_section);
let comment_section = [
0x07,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00, 0x30,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, (comment_offset as u32).to_le_bytes()[0],
(comment_offset as u32).to_le_bytes()[1],
(comment_offset as u32).to_le_bytes()[2],
(comment_offset as u32).to_le_bytes()[3],
0x00,
0x00,
0x00,
0x00, (comment.len() as u32).to_le_bytes()[0],
(comment.len() as u32).to_le_bytes()[1],
(comment.len() as u32).to_le_bytes()[2],
(comment.len() as u32).to_le_bytes()[3],
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, ];
data[sh_offset + 128..sh_offset + 192].copy_from_slice(&comment_section);
let shstrtab_section = [
0x10,
0x00,
0x00,
0x00, 0x03,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, (shstrtab_offset as u32).to_le_bytes()[0],
(shstrtab_offset as u32).to_le_bytes()[1],
(shstrtab_offset as u32).to_le_bytes()[2],
(shstrtab_offset as u32).to_le_bytes()[3],
0x00,
0x00,
0x00,
0x00, (shstrtab.len() as u32).to_le_bytes()[0],
(shstrtab.len() as u32).to_le_bytes()[1],
(shstrtab.len() as u32).to_le_bytes()[2],
(shstrtab.len() as u32).to_le_bytes()[3],
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, ];
data[sh_offset + 192..sh_offset + 256].copy_from_slice(&shstrtab_section);
let strtab_section = [
0x1a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[sh_offset + 256..sh_offset + 320].copy_from_slice(&strtab_section);
data
}
#[allow(dead_code)]
fn create_elf_with_custom_section(section_name: &str, content: &[u8]) -> Vec<u8> {
let mut data = vec![0u8; 8192];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00, 0x05, 0x00, 0x03, 0x00, ];
data[..64].copy_from_slice(&elf_header);
let ph_load = [
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[64..120].copy_from_slice(&ph_load);
let content_offset = 512;
data[content_offset..content_offset + content.len()].copy_from_slice(content);
let shstrtab_offset = 600;
let shstrtab = format!("\0.text\0{}\0.shstrtab\0.strtab\0", section_name);
let shstrtab_bytes = shstrtab.as_bytes();
data[shstrtab_offset..shstrtab_offset + shstrtab_bytes.len()].copy_from_slice(shstrtab_bytes);
let sh_offset = 1024;
let null_section = [0u8; 64];
data[sh_offset..sh_offset + 64].copy_from_slice(&null_section);
let text_section = [
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[sh_offset + 64..sh_offset + 128].copy_from_slice(&text_section);
let custom_name_offset = 7; let custom_section = [
(custom_name_offset as u32).to_le_bytes()[0],
(custom_name_offset as u32).to_le_bytes()[1],
(custom_name_offset as u32).to_le_bytes()[2],
(custom_name_offset as u32).to_le_bytes()[3], 0x01,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, (content_offset as u32).to_le_bytes()[0],
(content_offset as u32).to_le_bytes()[1],
(content_offset as u32).to_le_bytes()[2],
(content_offset as u32).to_le_bytes()[3],
0x00,
0x00,
0x00,
0x00, (content.len() as u32).to_le_bytes()[0],
(content.len() as u32).to_le_bytes()[1],
(content.len() as u32).to_le_bytes()[2],
(content.len() as u32).to_le_bytes()[3],
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, ];
data[sh_offset + 128..sh_offset + 192].copy_from_slice(&custom_section);
let shstrtab_name_offset = 7 + section_name.len() + 1; let shstrtab_section = [
(shstrtab_name_offset as u32).to_le_bytes()[0],
(shstrtab_name_offset as u32).to_le_bytes()[1],
(shstrtab_name_offset as u32).to_le_bytes()[2],
(shstrtab_name_offset as u32).to_le_bytes()[3], 0x03,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, (shstrtab_offset as u32).to_le_bytes()[0],
(shstrtab_offset as u32).to_le_bytes()[1],
(shstrtab_offset as u32).to_le_bytes()[2],
(shstrtab_offset as u32).to_le_bytes()[3],
0x00,
0x00,
0x00,
0x00, (shstrtab_bytes.len() as u32).to_le_bytes()[0],
(shstrtab_bytes.len() as u32).to_le_bytes()[1],
(shstrtab_bytes.len() as u32).to_le_bytes()[2],
(shstrtab_bytes.len() as u32).to_le_bytes()[3],
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, ];
data[sh_offset + 192..sh_offset + 256].copy_from_slice(&shstrtab_section);
let strtab_name_offset = shstrtab_name_offset + 10; let strtab_section = [
(strtab_name_offset as u32).to_le_bytes()[0],
(strtab_name_offset as u32).to_le_bytes()[1],
(strtab_name_offset as u32).to_le_bytes()[2],
(strtab_name_offset as u32).to_le_bytes()[3], 0x03,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x03,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, ];
data[sh_offset + 256..sh_offset + 320].copy_from_slice(&strtab_section);
data
}
#[allow(dead_code)]
fn create_elf_with_gcc_comment() -> Vec<u8> {
create_elf_with_comment(b"GCC: (GNU) 11.2.0\0")
}
#[allow(dead_code)]
fn create_elf_with_clang_comment() -> Vec<u8> {
create_elf_with_comment(b"clang version 14.0.0\0")
}
#[allow(dead_code)]
fn create_elf_with_gcc_version() -> Vec<u8> {
create_elf_with_comment(b"GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0\0")
}
#[allow(dead_code)]
fn create_elf_with_rust_metadata() -> Vec<u8> {
create_elf_with_custom_section(".rustc", b"rustc metadata\0")
}
#[allow(dead_code)]
fn create_elf_with_go_buildinfo() -> Vec<u8> {
create_elf_with_custom_section(".go.buildinfo", b"go1.19.3\0")
}
#[allow(dead_code)]
fn create_elf_with_mixed_sections() -> Vec<u8> {
create_elf_with_comment(b"Mixed compiler info: GCC and Clang\0")
}
#[allow(dead_code)]
fn create_elf_with_build_id_note() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(6144, 0);
data
}