androscalpel/apk_frauder/src/lib.rs
2024-01-17 16:41:24 +01:00

97 lines
3 KiB
Rust

use androscalpel_serializer::Serializable;
pub mod apk_signing_block;
pub mod compression;
mod cp437;
pub mod end_of_central_directory;
pub mod extra_fields;
pub mod file_header;
pub mod local_file_header;
pub mod zip_reader;
pub mod zip_writer;
use extra_fields::{ExtraField, Zip64ExtraField};
use file_header::FileHeader;
use local_file_header::LocalFileHeader;
pub use zip_reader::ZipFileReader;
pub use zip_writer::ZipFileWriter;
#[derive(Debug, Clone, PartialEq, Eq, Serializable, Default)]
pub struct Signature(pub u32);
pub enum Encoding {
CP437,
UTF8,
}
pub mod general_purpose_flags {
pub const MASK_ENCRYPTED: u16 = 1 << 0;
pub const MASK_COMPRESS_OPTION_1: u16 = 1 << 1;
pub const MASK_COMPRESS_OPTION_2: u16 = 1 << 2;
pub const MASK_USE_DATA_DESCRIPTOR: u16 = 1 << 3;
pub const MASK_STRONG_ENCRYPTION: u16 = 1 << 6;
pub const MASK_UTF8_FILENAME: u16 = 1 << 11;
pub const MASK_ENCRYPTED_CENTRAL_DIR: u16 = 1 << 13;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileInfo {
pub local_header: LocalFileHeader,
pub header: FileHeader,
}
// TODO: support data descriptor (MASK_USE_DATA_DESCRIPTOR)
impl FileInfo {
pub fn get_name(&self) -> String {
self.header.get_name()
}
pub fn get_offset_local_header(&self) -> u64 {
self.header.get_offset_local_header()
}
pub fn get_compressed_size(&self) -> u64 {
self.header.get_compressed_size()
}
pub fn get_file_offset(&self) -> u64 {
self.get_offset_local_header() + self.local_header.size() as u64
}
pub fn set_offset_local_header(&mut self, new_offset: u64) {
let use_z64 = new_offset > u32::MAX as u64;
for extra in &mut self.local_header.extra_field {
if let ExtraField::Zip64(extra) = extra {
if use_z64 {
extra.offset_header = Some(new_offset);
} else {
extra.offset_header = None;
}
}
}
let mut z64found = false;
for extra in &mut self.header.extra_field {
if let ExtraField::Zip64(extra) = extra {
if use_z64 {
extra.offset_header = Some(new_offset);
} else {
extra.offset_header = None;
}
z64found = true;
}
}
if use_z64 && !z64found {
self.header
.extra_field
.push(ExtraField::Zip64(Zip64ExtraField {
original_size: Some(self.header.uncompressed_size as u64),
compressed_size: Some(self.header.compressed_size as u64),
offset_header: Some(new_offset),
disk_number: None,
}));
self.header.uncompressed_size = u32::MAX;
self.header.compressed_size = u32::MAX;
}
if use_z64 {
self.header.offset_local_header = u32::MAX;
} else {
self.header.offset_local_header = new_offset as u32;
}
}
}