#![allow(clippy::uninlined_format_args)]
#![cfg(feature = "elf")]
use threatflux_binary_analysis::types::*;
use threatflux_binary_analysis::BinaryAnalyzer;
mod elf_test_data {
pub fn create_elf_64_x86_64_le() -> Vec<u8> {
let mut data = vec![0u8; 2048];
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, 0x02, 0x00, 0x40, 0x00, 0x04, 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, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let ph_gnu_stack = [
0x51, 0xe5, 0x74, 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[64..120].copy_from_slice(&ph_load);
data[120..176].copy_from_slice(&ph_gnu_stack);
let sh_null = [0u8; 64]; let sh_text = [
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, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let sh_data = [
0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let sh_shstrtab = [
0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 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[1024..1088].copy_from_slice(&sh_null);
data[1088..1152].copy_from_slice(&sh_text);
data[1152..1216].copy_from_slice(&sh_data);
data[1216..1280].copy_from_slice(&sh_shstrtab);
let shstrtab = b"\0.text\0.data\0.shstrtab\0";
data[1920..1920 + shstrtab.len()].copy_from_slice(shstrtab);
let instructions = [
0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x10, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xc4, 0x10, 0x5d, 0xc3, ];
data[512..512 + instructions.len()].copy_from_slice(&instructions);
data
}
pub fn create_elf_32_x86_le() -> Vec<u8> {
let mut data = vec![0u8; 1024];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x28, 0x00, 0x03, 0x00, 0x02, 0x00, ];
data[..52].copy_from_slice(&elf_header);
let ph_load = [
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, ];
data[52..84].copy_from_slice(&ph_load);
data
}
pub fn create_elf_64_arm64_le() -> Vec<u8> {
let mut data = vec![0u8; 1024];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb7, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x00, 0x01, 0x00, ];
data[..64].copy_from_slice(&elf_header);
data
}
pub fn create_elf_shared_object() -> Vec<u8> {
let mut data = vec![0u8; 2048];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 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, 0x02, 0x00, 0x40, 0x00, 0x04, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let ph_dynamic = [
0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[64..120].copy_from_slice(&ph_load);
data[120..176].copy_from_slice(&ph_dynamic);
data
}
pub fn create_elf_with_security_features() -> Vec<u8> {
let mut data = vec![0u8; 2048];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 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, 0x03, 0x00, 0x40, 0x00, 0x03, 0x00, 0x02, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let ph_gnu_stack = [
0x51, 0xe5, 0x74, 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let ph_gnu_relro = [
0x52, 0xe5, 0x74, 0x64, 0x04, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[64..120].copy_from_slice(&ph_load);
data[120..176].copy_from_slice(&ph_gnu_stack);
data[176..232].copy_from_slice(&ph_gnu_relro);
data
}
pub fn create_elf_with_symbols() -> Vec<u8> {
let mut data = vec![0u8; 4096];
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, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00, 0x06, 0x00, 0x05, 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, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[64..120].copy_from_slice(&ph_load);
let sections_offset = 2048;
let sh_null = [0u8; 64];
data[sections_offset..sections_offset + 64].copy_from_slice(&sh_null);
let sh_text = [
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, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[sections_offset + 64..sections_offset + 128].copy_from_slice(&sh_text);
let sh_symtab = [
0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[sections_offset + 128..sections_offset + 192].copy_from_slice(&sh_symtab);
let sh_strtab = [
0x0f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 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[sections_offset + 192..sections_offset + 256].copy_from_slice(&sh_strtab);
let sh_dynsym = [
0x17, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[sections_offset + 256..sections_offset + 320].copy_from_slice(&sh_dynsym);
let sh_shstrtab = [
0x1f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 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[sections_offset + 320..sections_offset + 384].copy_from_slice(&sh_shstrtab);
let sym_null = [0u8; 24]; data[1024..1048].copy_from_slice(&sym_null);
let sym_file = [
0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[1048..1072].copy_from_slice(&sym_file);
let sym_main = [
0x0a, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[1072..1096].copy_from_slice(&sym_main);
let sym_printf = [
0x0f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[1096..1120].copy_from_slice(&sym_printf);
let strtab = b"\0test.c\0main\0printf\0";
data[1120..1120 + strtab.len()].copy_from_slice(strtab);
data[1152..1176].copy_from_slice(&sym_null);
let dynsym_printf = [
0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[1176..1200].copy_from_slice(&dynsym_printf);
let dynsym_exported = [
0x08, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0x10, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[1200..1224].copy_from_slice(&dynsym_exported);
let dynstr = b"\0printf\0exported\0";
if data.len() > 1300 + dynstr.len() {
data[1300..1300 + dynstr.len()].copy_from_slice(dynstr);
}
let shstrtab = b"\0.text\0.symtab\0.strtab\0.dynsym\0.shstrtab\0";
data[1224..1224 + shstrtab.len()].copy_from_slice(shstrtab);
data
}
pub fn create_truncated_elf() -> Vec<u8> {
vec![0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01] }
pub fn create_invalid_magic() -> Vec<u8> {
let mut data = vec![0u8; 1024];
data[0..4].copy_from_slice(&[0x12, 0x34, 0x56, 0x78]); data
}
pub fn create_elf_big_endian() -> Vec<u8> {
let mut data = vec![0u8; 1024];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x00, 0x01, ];
data[..64].copy_from_slice(&elf_header);
data
}
pub fn create_elf_mips() -> Vec<u8> {
let mut data = vec![0u8; 1024];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x00, 0x01, 0x00, ];
data[..64].copy_from_slice(&elf_header);
data
}
pub fn create_elf_powerpc() -> Vec<u8> {
let mut data = vec![0u8; 1024];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x15, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x00, 0x01, 0x00, ];
data[..64].copy_from_slice(&elf_header);
data
}
pub fn create_elf_riscv() -> Vec<u8> {
let mut data = vec![0u8; 1024];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf3, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x00, 0x01, 0x00, ];
data[..64].copy_from_slice(&elf_header);
data
}
pub fn create_elf_relocatable() -> Vec<u8> {
let mut data = vec![0u8; 1024];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x03, 0x00, 0x02, 0x00, ];
data[..64].copy_from_slice(&elf_header);
data
}
}
#[test]
fn test_elf_parser_can_parse_valid_magic() {
let valid_elf = vec![0x7f, 0x45, 0x4c, 0x46];
assert!(matches!(
threatflux_binary_analysis::formats::detect_format(&valid_elf),
Ok(BinaryFormat::Elf)
));
let elf_with_data = vec![0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00];
assert!(matches!(
threatflux_binary_analysis::formats::detect_format(&elf_with_data),
Ok(BinaryFormat::Elf)
));
}
#[test]
fn test_elf_parser_can_parse_invalid_data() {
assert!(threatflux_binary_analysis::formats::detect_format(&[]).is_err());
assert!(!matches!(
threatflux_binary_analysis::formats::detect_format(&[0x7f, 0x45, 0x4c]),
Ok(BinaryFormat::Elf)
));
assert!(!matches!(
threatflux_binary_analysis::formats::detect_format(&[0x12, 0x34, 0x56, 0x78]),
Ok(BinaryFormat::Elf)
));
assert!(!matches!(
threatflux_binary_analysis::formats::detect_format(&[0x4d, 0x5a, 0x90, 0x00]),
Ok(BinaryFormat::Elf)
));
assert!(!matches!(
threatflux_binary_analysis::formats::detect_format(&[0xce, 0xfa, 0xed, 0xfe]),
Ok(BinaryFormat::Elf)
));
assert!(!matches!(
threatflux_binary_analysis::formats::detect_format(&[0x7f, 0x45, 0x4c, 0x47]),
Ok(BinaryFormat::Elf)
));
}
#[test]
fn test_elf_parser_parse_64_bit_x86_64() {
let data = elf_test_data::create_elf_64_x86_64_le();
let result = BinaryAnalyzer::new().analyze(&data);
assert!(result.is_ok());
let binary = result.unwrap();
assert_eq!(binary.format, BinaryFormat::Elf);
assert_eq!(binary.architecture, Architecture::X86_64);
assert_eq!(binary.entry_point, Some(0x401000));
let metadata = &binary.metadata;
assert_eq!(metadata.format, BinaryFormat::Elf);
assert_eq!(metadata.architecture, Architecture::X86_64);
assert_eq!(metadata.endian, Endianness::Little);
assert_eq!(metadata.size, data.len());
assert!(metadata.security_features.nx_bit); }
#[test]
fn test_elf_parser_parse_32_bit_x86() {
let data = elf_test_data::create_elf_32_x86_le();
let result = BinaryAnalyzer::new().analyze(&data);
assert!(result.is_ok());
let binary = result.unwrap();
assert_eq!(binary.format, BinaryFormat::Elf);
assert_eq!(binary.architecture, Architecture::X86);
let metadata = &binary.metadata;
assert_eq!(metadata.endian, Endianness::Little);
}
#[test]
fn test_elf_parser_parse_arm64() {
let data = elf_test_data::create_elf_64_arm64_le();
let result = BinaryAnalyzer::new().analyze(&data);
assert!(result.is_ok());
let binary = result.unwrap();
assert_eq!(binary.format, BinaryFormat::Elf);
assert_eq!(binary.architecture, Architecture::Arm64);
}
#[test]
fn test_elf_parser_parse_various_architectures() {
let test_cases = vec![
(elf_test_data::create_elf_mips(), Architecture::Mips),
(elf_test_data::create_elf_powerpc(), Architecture::PowerPC64),
(elf_test_data::create_elf_riscv(), Architecture::RiscV),
];
for (data, expected_arch) in test_cases {
let result = BinaryAnalyzer::new().analyze(&data);
if let Ok(binary) = result {
assert_eq!(binary.architecture, expected_arch);
assert_eq!(binary.architecture, expected_arch);
}
}
}
#[test]
fn test_elf_parser_parse_file_types() {
let exec_data = elf_test_data::create_elf_64_x86_64_le();
let exec_result = BinaryAnalyzer::new().analyze(&exec_data);
assert!(exec_result.is_ok());
let so_data = elf_test_data::create_elf_shared_object();
let so_result = BinaryAnalyzer::new().analyze(&so_data);
assert!(so_result.is_ok());
let so_binary = so_result.unwrap();
assert!(so_binary.metadata.security_features.pie);
let rel_data = elf_test_data::create_elf_relocatable();
let rel_result = BinaryAnalyzer::new().analyze(&rel_data);
assert!(rel_result.is_ok());
let rel_binary = rel_result.unwrap();
assert_eq!(rel_binary.entry_point, None); }
#[test]
fn test_elf_parser_endianness_detection() {
let le_data = elf_test_data::create_elf_64_x86_64_le();
let le_binary = BinaryAnalyzer::new().analyze(&le_data).unwrap();
assert_eq!(le_binary.metadata.endian, Endianness::Little);
let be_data = elf_test_data::create_elf_big_endian();
let be_result = BinaryAnalyzer::new().analyze(&be_data);
if let Ok(be_binary) = be_result {
assert_eq!(be_binary.metadata.endian, Endianness::Big);
}
}
#[test]
fn test_elf_parser_section_parsing() {
let data = elf_test_data::create_elf_64_x86_64_le();
let binary = BinaryAnalyzer::new().analyze(&data).unwrap();
let sections = &binary.sections;
assert!(!sections.is_empty());
let text_section = sections.iter().find(|s| s.name == ".text");
assert!(text_section.is_some());
let text_section = text_section.unwrap();
assert_eq!(text_section.section_type, SectionType::Code);
assert!(text_section.permissions.read);
assert!(!text_section.permissions.write);
assert!(text_section.permissions.execute);
let data_section = sections.iter().find(|s| s.name == ".data");
assert!(data_section.is_some());
let data_section = data_section.unwrap();
assert_eq!(data_section.section_type, SectionType::Data);
assert!(data_section.permissions.read);
assert!(data_section.permissions.write);
assert!(!data_section.permissions.execute);
}
#[test]
fn test_elf_parser_symbol_parsing() {
let data = elf_test_data::create_elf_with_symbols();
let result = BinaryAnalyzer::new().analyze(&data);
if let Ok(binary) = result {
let symbols = &binary.symbols;
for symbol in symbols {
assert!(!symbol.name.is_empty());
assert!(symbol.address < u64::MAX);
assert!(symbol.size < u64::MAX);
}
} else {
println!("Symbol parsing test skipped due to incomplete test data");
}
}
#[test]
fn test_elf_parser_imports_exports() {
let data = elf_test_data::create_elf_with_symbols();
let result = BinaryAnalyzer::new().analyze(&data);
if let Ok(binary) = result {
let imports = &binary.imports;
let exports = &binary.exports;
for import in imports {
assert!(!import.name.is_empty());
}
for export in exports {
assert!(!export.name.is_empty());
assert!(export.address > 0);
}
} else {
println!("Import/export parsing test skipped due to incomplete test data");
}
}
#[test]
fn test_elf_parser_security_features() {
let data = elf_test_data::create_elf_with_security_features();
let binary = BinaryAnalyzer::new().analyze(&data).unwrap();
let security = &binary.metadata.security_features;
assert!(security.nx_bit); assert!(security.pie); assert!(security.aslr); assert!(security.relro); }
#[test]
fn test_elf_parser_error_handling() {
let truncated = elf_test_data::create_truncated_elf();
let result = BinaryAnalyzer::new().analyze(&truncated);
assert!(result.is_err());
let invalid_magic = elf_test_data::create_invalid_magic();
let result = BinaryAnalyzer::new().analyze(&invalid_magic);
if let Ok(analysis) = result {
assert_ne!(analysis.format, BinaryFormat::Elf);
}
let result = BinaryAnalyzer::new().analyze(&[]);
assert!(result.is_err());
let minimal = vec![0x7f, 0x45, 0x4c, 0x46];
let result = BinaryAnalyzer::new().analyze(&minimal);
assert!(result.is_err());
}
#[test]
fn test_elf_binary_format_trait_methods() {
let data = elf_test_data::create_elf_64_x86_64_le();
let binary = BinaryAnalyzer::new().analyze(&data).unwrap();
assert_eq!(binary.format, BinaryFormat::Elf);
assert_eq!(binary.architecture, Architecture::X86_64);
assert_eq!(binary.entry_point, Some(0x401000));
let sections = &binary.sections;
assert!(!sections.is_empty());
let symbols = &binary.symbols;
let _ = symbols.len();
let imports = &binary.imports;
let _ = imports.len();
let exports = &binary.exports;
let _ = exports.len();
let metadata = &binary.metadata;
assert_eq!(metadata.format, BinaryFormat::Elf);
assert_eq!(metadata.architecture, Architecture::X86_64);
assert_eq!(metadata.size, data.len());
}
#[test]
fn test_elf_section_type_classification() {
let data = elf_test_data::create_elf_64_x86_64_le();
let binary = BinaryAnalyzer::new().analyze(&data).unwrap();
let sections = &binary.sections;
for section in sections {
match section.section_type {
SectionType::Code => {
assert!(section.permissions.execute);
assert!(!section.permissions.write);
}
SectionType::Data => {
assert!(section.permissions.write);
assert!(!section.permissions.execute);
}
SectionType::ReadOnlyData => {
assert!(!section.permissions.write);
assert!(!section.permissions.execute);
}
SectionType::Bss => {
assert!(section.permissions.write);
assert!(!section.permissions.execute);
assert_eq!(section.data, None); }
SectionType::String => {
assert!(!section.permissions.execute);
}
_ => {
}
}
}
}
#[test]
fn test_elf_section_data_extraction() {
let data = elf_test_data::create_elf_64_x86_64_le();
let binary = BinaryAnalyzer::new().analyze(&data).unwrap();
let sections = &binary.sections;
for section in sections {
if section.size <= 1024 && section.offset > 0 {
if section.section_type != SectionType::Bss {
if section.offset + section.size <= data.len() as u64 {
assert!(section.data.is_some() || section.data.is_none());
}
}
}
}
}
#[test]
fn test_elf_symbol_demangling() {
let data = elf_test_data::create_elf_with_symbols();
let binary = BinaryAnalyzer::new().analyze(&data).unwrap();
let symbols = &binary.symbols;
for symbol in symbols {
if symbol.name.starts_with("_Z") {
assert!(symbol.demangled_name.is_some());
let demangled = symbol.demangled_name.as_ref().unwrap();
assert!(demangled.starts_with("demangled_"));
}
}
}
#[test]
fn test_elf_compiler_info_extraction() {
let data = elf_test_data::create_elf_64_x86_64_le();
let binary = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &binary.metadata;
if let Some(compiler_info) = &metadata.compiler_info {
assert!(!compiler_info.is_empty());
}
}
#[test]
fn test_elf_edge_cases() {
let min_header = vec![0x7f, 0x45, 0x4c, 0x46];
let result = BinaryAnalyzer::new().analyze(&min_header);
assert!(result.is_err());
assert!(matches!(
threatflux_binary_analysis::formats::detect_format(&[0x7f, 0x45, 0x4c, 0x46]),
Ok(BinaryFormat::Elf)
));
assert!(!matches!(
threatflux_binary_analysis::formats::detect_format(&[0x12, 0x34, 0x56, 0x78]),
Ok(BinaryFormat::Elf)
));
assert!(!matches!(
threatflux_binary_analysis::formats::detect_format(&[0x7f, 0x45, 0x4c]),
Ok(BinaryFormat::Elf)
));
}
#[test]
fn test_elf_unknown_architecture_handling() {
let mut data = elf_test_data::create_elf_64_x86_64_le();
data[18] = 0xff;
data[19] = 0xff;
let result = BinaryAnalyzer::new().analyze(&data);
if let Ok(binary) = result {
assert_eq!(binary.architecture, Architecture::Unknown);
assert_eq!(binary.architecture, Architecture::Unknown);
}
}
#[test]
fn test_elf_program_header_parsing() {
let data = elf_test_data::create_elf_with_security_features();
let binary = BinaryAnalyzer::new().analyze(&data).unwrap();
let security = &binary.metadata.security_features;
assert!(security.nx_bit); assert!(security.relro); assert!(security.pie); }
#[test]
fn test_elf_memory_usage() {
let data = elf_test_data::create_elf_with_symbols();
for _ in 0..10 {
let binary = BinaryAnalyzer::new().analyze(&data).unwrap();
let _sections = &binary.sections;
let _symbols = &binary.symbols;
let _imports = &binary.imports;
let _exports = &binary.exports;
}
}
#[test]
fn test_elf_consistency() {
let data = elf_test_data::create_elf_64_x86_64_le();
let results: Vec<_> = (0..5)
.map(|_| BinaryAnalyzer::new().analyze(&data).unwrap())
.collect();
let first = &results[0];
for result in &results[1..] {
assert_eq!(result.format, first.format);
assert_eq!(result.architecture, first.architecture);
assert_eq!(result.entry_point, first.entry_point);
assert_eq!(&result.sections.len(), &first.sections.len());
assert_eq!(&result.symbols.len(), &first.symbols.len());
}
}