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

Added checksum validation check to zlib #761

Merged
merged 1 commit into from
Nov 22, 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
7 changes: 7 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ threadpool = "1.8.1"
serde_json = "1.0"
env_logger = "0.11.5"
flate2 = "1.0.34"
adler32 = "1.2.0"
md5 = "0.7.0"
miniz_oxide = "0.8.0"
aho-corasick = "1.1.3"
Expand Down
16 changes: 11 additions & 5 deletions src/extractors/gzip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,24 @@ pub fn gzip_decompress(
offset: usize,
output_directory: Option<&String>,
) -> ExtractionResult {
let mut exresult = ExtractionResult {
..Default::default()
};

// Parse the gzip header
if let Ok(gzip_header) = parse_gzip_header(&file_data[offset..]) {
// Deflate compressed data starts at the end of the gzip header
let deflate_data_start: usize = offset + gzip_header.size;

if file_data.len() > deflate_data_start {
return inflate::inflate_decompressor(file_data, deflate_data_start, output_directory);
let inflate_result =
inflate::inflate_decompressor(file_data, deflate_data_start, output_directory);
if inflate_result.success {
exresult.success = true;
exresult.size = Some(inflate_result.size);
}
}
}

// Return failure
ExtractionResult {
..Default::default()
}
exresult
}
44 changes: 24 additions & 20 deletions src/extractors/inflate.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
use crate::extractors::common::{Chroot, ExtractionResult};
use crate::extractors::common::Chroot;
use adler32::RollingAdler32;
use flate2::bufread::DeflateDecoder;
use std::io::Read;

/*
* The inflate_decompressor extractor is currently not directly used by any signature definitions.
*
use crate::extractors::common::{ Extractor, ExtractorType };

// Defines the internal extractor function for decompressing raw deflate data
pub fn inflate_extractor() -> Extractor {
return Extractor { utility: ExtractorType::Internal(inflate_decompressor), ..Default::default() };
#[derive(Debug, Default, Clone)]
pub struct DeflateResult {
pub size: usize,
pub adler32: u32,
pub success: bool,
}
*/

/// Internal extractor for inflating deflated data.
/// Decompressor for inflating deflated data.
/// For internal use, does not conform to the standard extractor format.
pub fn inflate_decompressor(
file_data: &[u8],
offset: usize,
output_directory: Option<&String>,
) -> ExtractionResult {
) -> DeflateResult {
// Size of decompression buffer
const BLOCK_SIZE: usize = 8192;
// Output file for decompressed data
const OUTPUT_FILE_NAME: &str = "decompressed.bin";

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

let mut adler32_checksum = RollingAdler32::new();
let mut decompressed_buffer = [0; BLOCK_SIZE];
let mut decompressor = DeflateDecoder::new(&file_data[offset..]);

Expand All @@ -49,12 +48,16 @@ pub fn inflate_decompressor(
break;
}
Ok(n) => {
// Decompressed a block of data, if extraction was requested write the decompressed block to the output file
if n > 0 && output_directory.is_some() {
let chroot = Chroot::new(output_directory);
if !chroot.append_to_file(OUTPUT_FILE_NAME, &decompressed_buffer[0..n]) {
// If writing data to file fails, break
break;
// Decompressed a block of data, update checksum and if extraction was requested write the decompressed block to the output file
if n > 0 {
adler32_checksum.update_buffer(&decompressed_buffer[0..n]);

if output_directory.is_some() {
let chroot = Chroot::new(output_directory);
if !chroot.append_to_file(OUTPUT_FILE_NAME, &decompressed_buffer[0..n]) {
// If writing data to file fails, break
break;
}
}
}

Expand All @@ -63,7 +66,8 @@ pub fn inflate_decompressor(
// If some data was actually decompressed, report success and the number of input bytes consumed
if decompressor.total_out() > 0 {
result.success = true;
result.size = Some(decompressor.total_in() as usize);
result.adler32 = adler32_checksum.hash();
result.size = decompressor.total_in() as usize;
}

// Nothing else to do, break
Expand Down
28 changes: 22 additions & 6 deletions src/extractors/zlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,31 @@ pub fn zlib_decompress(
// Size of the zlib header
const HEADER_SIZE: usize = 2;

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

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

// If the decompression reported the size of the deflate data, update the reported size
// to include the ZLIB header and checksum fields
if let Some(deflate_size) = result.size {
result.size = Some(HEADER_SIZE + deflate_size + CHECKSUM_SIZE);
// Check that the data decompressed OK
if inflate_result.success {
// Calculate the ZLIB checksum offsets
let checksum_start = offset + HEADER_SIZE + inflate_result.size;
let checksum_end = checksum_start + CHECKSUM_SIZE;

// Get the ZLIB checksum
if let Some(adler32_checksum_bytes) = file_data.get(checksum_start..checksum_end) {
let reported_checksum = u32::from_be_bytes(adler32_checksum_bytes.try_into().unwrap());

// Make sure the checksum matches
if reported_checksum == inflate_result.adler32 {
exresult.success = true;
exresult.size = Some(HEADER_SIZE + inflate_result.size + CHECKSUM_SIZE);
}
}
}

result
exresult
}