use log::{debug, warn};
use crate::errors::{Error, Result};
use crate::options::status::DisplayInColorTerm;
use crate::options::{BinarySecurityOption, ELFStackProtectionOption};
use crate::parser::BinaryParser;
pub fn analyze_binary(parser: &BinaryParser) -> Result<Vec<Box<dyn DisplayInColorTerm>>> {
let has_stack_protection = ELFStackProtectionOption::default().check(parser)?;
Ok(vec![has_stack_protection])
}
pub fn has_stack_protection(
parser: &BinaryParser,
archive: &goblin::archive::Archive,
) -> Result<bool> {
let bytes = parser.bytes();
for member_name in archive.members() {
let buffer = archive
.extract(member_name, bytes)
.map_err(|source| Error::Goblin1 {
operation: "goblin::archive::Archive",
param1: member_name.into(),
source,
})?;
let r = member_has_stack_protection(member_name, buffer)?;
if r {
return Ok(true);
}
}
Ok(false)
}
fn member_has_stack_protection(member_name: &str, bytes: &[u8]) -> Result<bool> {
let obj = goblin::Object::parse(bytes).map_err(|source| Error::Goblin {
operation: "goblin::Object::parse",
source,
})?;
if let goblin::Object::Elf(elf) = obj {
debug!("Format of archive member '{}' is 'ELF'.", member_name);
let r = elf
.syms
.iter()
.filter_map(|ref symbol| {
crate::elf::symbol_is_named_function_or_unspecified(&elf, symbol)
})
.any(|name| name == "__stack_chk_fail" || name == "__stack_chk_fail_local");
if r {
debug!("Found function symbol '__stack_chk_fail_local' or '__stack_chk_fail' inside symbols section of member '{}'.", member_name);
}
Ok(r)
} else {
warn!("Format of archive member '{}' is not 'ELF'.", member_name);
Err(Error::UnexpectedBinaryFormat {
expected: "ELF",
name: member_name.into(),
})
}
}