Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed signed GPG decompression bug #796

Merged
merged 2 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/extractors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ pub mod dtb;
pub mod dumpifs;
pub mod dxbc;
pub mod gif;
pub mod gpg;
pub mod gzip;
pub mod inflate;
pub mod jboot;
Expand Down
57 changes: 57 additions & 0 deletions src/extractors/gpg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use crate::extractors::common::{ExtractionResult, Extractor, ExtractorType};
use crate::extractors::inflate;

/// Defines the internal extractor function for decompressing signed GPG data
///
/// ```
/// use std::io::ErrorKind;
/// use std::process::Command;
/// use binwalk::extractors::common::ExtractorType;
/// use binwalk::extractors::gpg::gpg_extractor;
///
/// match gpg_extractor().utility {
/// ExtractorType::None => panic!("Invalid extractor type of None"),
/// ExtractorType::Internal(func) => println!("Internal extractor OK: {:?}", func),
/// ExtractorType::External(cmd) => {
/// if let Err(e) = Command::new(&cmd).output() {
/// if e.kind() == ErrorKind::NotFound {
/// panic!("External extractor '{}' not found", cmd);
/// } else {
/// panic!("Failed to execute external extractor '{}': {}", cmd, e);
/// }
/// }
/// }
/// }
/// ```
pub fn gpg_extractor() -> Extractor {
Extractor {
utility: ExtractorType::Internal(gpg_decompress),
..Default::default()
}
}

/// Internal extractor for decompressing signed GPG data
pub fn gpg_decompress(
file_data: &[u8],
offset: usize,
output_directory: Option<&String>,
) -> ExtractionResult {
// Size of the GPG header
const HEADER_SIZE: usize = 2;

let mut exresult = ExtractionResult {
..Default::default()
};

// Do the decompression, ignoring the GPG header
let inflate_result =
inflate::inflate_decompressor(file_data, offset + HEADER_SIZE, output_directory);

// Check that the data decompressed OK
if inflate_result.success {
exresult.success = true;
exresult.size = Some(HEADER_SIZE + inflate_result.size);
}

exresult
}
2 changes: 1 addition & 1 deletion src/magic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ pub fn patterns() -> Vec<signatures::common::Signature> {
magic: signatures::gpg::gpg_signed_magic(),
parser: signatures::gpg::gpg_signed_parser,
description: signatures::gpg::GPG_SIGNED_DESCRIPTION.to_string(),
extractor: Some(extractors::zlib::zlib_extractor()),
extractor: Some(extractors::gpg::gpg_extractor()),
},
// pem certificates
signatures::common::Signature {
Expand Down
7 changes: 3 additions & 4 deletions src/signatures/gpg.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::extractors::zlib::{zlib_decompress, CHECKSUM_SIZE};
use crate::extractors::gpg::gpg_decompress;
use crate::signatures::common::{SignatureError, SignatureResult, CONFIDENCE_HIGH};

/// Human readable description
Expand Down Expand Up @@ -26,13 +26,12 @@ pub fn gpg_signed_parser(
* GPG signed files are just zlib compressed files with the zlib magic bytes replaced with the GPG magic bytes.
* Decompress the signed file; no output directory specified, dry run only.
*/
let decompression_dry_run = zlib_decompress(file_data, offset, None);
let decompression_dry_run = gpg_decompress(file_data, offset, None);

// If the decompression dry run was a success, this signature is almost certianly valid
if decompression_dry_run.success {
if let Some(total_size) = decompression_dry_run.size {
// GPG doesn't include the trailing checksum
result.size = total_size - CHECKSUM_SIZE;
result.size = total_size;
result.description =
format!("{}, total size: {} bytes", result.description, result.size);
return Ok(result);
Expand Down
Loading