Skip to content

Commit

Permalink
Add feature to support compressed archives
Browse files Browse the repository at this point in the history
Add a new feature "archives" to support scanning (compresses) archives.
Extracting archives is done via the create compress-tools, which uses
the C library libarchive.  Thus in order to build and run checksec
installing libarchive is required.

    $ checksec -f /var/cache/apt/archives/xterm_376-1_amd64.deb
    ELF64: | Canary: true  CFI: false SafeStack: false Fortify: Partial     Fortified:  3 Fortifiable:  1 NX: true  PIE: Full Relro: Full    RPATH: None RUNPATH: None | File: /var/cache/apt/archives/xterm_376-1_amd64.deb➔data.tar.xz➔./usr/bin/resize
    ELF64: | Canary: true  CFI: false SafeStack: false Fortify: Partial     Fortified:  8 Fortifiable: 11 NX: true  PIE: Full Relro: Full    RPATH: None RUNPATH: None | File: /var/cache/apt/archives/xterm_376-1_amd64.deb➔data.tar.xz➔./usr/bin/xterm
  • Loading branch information
cgzones committed Mar 18, 2023
1 parent cc0131f commit 854f60b
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
36 changes: 36 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ panic = 'abort' # Abort on panic
clap = {version = "4.0.14", features = ["cargo"]}
colored = {version = "2.0.0", optional = true}
colored_json = {version = "3.0.1", optional = true}
compress-tools = {version = "0.14.0", optional = true}
either = "1.8.1"
glob = "0.3.0"
goblin = "0.6.0"
Expand Down Expand Up @@ -65,6 +66,7 @@ name = "checksec"
path = "src/main.rs"

[features]
archives = ["compress-tools"]
color = ["colored", "colored_json", "xattr"]
default = ["elf", "macho", "pe", "color", "maps"]
elf = ["shared"]
Expand Down
57 changes: 57 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ use std::collections::HashMap;
#[cfg(all(target_os = "linux", feature = "elf"))]
use std::collections::HashSet;
use std::ffi::OsStr;
#[cfg(feature = "archives")]
use std::io::Cursor;
use std::io::ErrorKind;
#[cfg(all(feature = "color", not(target_os = "windows")))]
use std::os::unix::fs::PermissionsExt;
Expand All @@ -46,6 +48,8 @@ use colored::{ColoredString, Colorize};

#[cfg(feature = "color")]
use colored_json::to_colored_json_auto;
#[cfg(feature = "archives")]
use compress_tools::{ArchiveContents, ArchiveIterator};

mod binary;
mod proc;
Expand Down Expand Up @@ -269,6 +273,8 @@ enum ParseError {
IO(std::io::Error),
#[cfg(all(target_os = "linux", feature = "elf"))]
LdSo(LdSoError),
#[cfg(feature = "archives")]
Decompress(compress_tools::Error),
#[allow(dead_code)]
Unimplemented(&'static str),
}
Expand All @@ -282,6 +288,8 @@ impl fmt::Display for ParseError {
Self::LdSo(e) => {
write!(f, "Failed to initialize library lookup: {e}")
}
#[cfg(feature = "archives")]
Self::Decompress(e) => e.fmt(f),
Self::Unimplemented(str) => {
write!(f, "Support for files of type {str} not implemented")
}
Expand All @@ -308,6 +316,13 @@ impl From<LdSoError> for ParseError {
}
}

#[cfg(feature = "archives")]
impl From<compress_tools::Error> for ParseError {
fn from(err: compress_tools::Error) -> ParseError {
ParseError::Decompress(err)
}
}

type Cache = Arc<Mutex<HashMap<PathBuf, Vec<Binary>>>>;

fn parse(
Expand Down Expand Up @@ -427,6 +442,48 @@ fn parse_bytes(bytes: &[u8], file: &Path) -> Result<Vec<Binary>, ParseError> {
#[cfg(not(feature = "macho"))]
Object::Mach(_) => Err(ParseError::Unimplemented("MachO")),
Object::Archive(archive) => Ok(parse_archive(&archive, file, bytes)),
#[cfg(feature = "archives")]
Object::Unknown(magic) => {
let mut results = Vec::new();
let mut handled = false;

let mut name = String::default();
let mut buffer = Vec::new();

for content in ArchiveIterator::from_read(Cursor::new(bytes))? {
match content {
ArchiveContents::StartOfEntry(s, _) => {
name = s;
buffer.clear();
}
ArchiveContents::DataChunk(v) => buffer.extend(v),
ArchiveContents::EndOfEntry => {
if buffer != bytes {
handled = true;

if let Ok(mut res) = parse_bytes(
&buffer,
Path::new(&format!(
"{}\u{2794}{}",
file.display(),
name
)),
) {
results.append(&mut res);
}
}
}
ArchiveContents::Err(e) => Err(e)?,
}
}

if handled {
Ok(results)
} else {
Err(ParseError::Goblin(Error::BadMagic(magic)))
}
}
#[cfg(not(feature = "archives"))]
Object::Unknown(magic) => {
Err(ParseError::Goblin(Error::BadMagic(magic)))
}
Expand Down

0 comments on commit 854f60b

Please sign in to comment.