detect apk signatur

This commit is contained in:
Jean-Marie Mineau 2024-01-15 14:42:26 +01:00
parent 98f00c4066
commit fafbdb6537
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
3 changed files with 138 additions and 6 deletions

View file

@ -2,10 +2,12 @@ use std::io::{Read, Seek, SeekFrom};
use androscalpel_serializer::Serializable;
pub mod apk_signing_block;
mod cp437;
pub mod end_of_central_directory;
pub mod file_header;
use apk_signing_block::*;
use end_of_central_directory::*;
use file_header::FileHeader;
@ -16,6 +18,7 @@ pub struct ZipFile<T: Read + Seek> {
pub end_of_central_directory: EndCentralDirectory,
pub zip64_end_of_central_directory: Option<Zip64EndCentralDirectory>,
pub files: Vec<FileHeader>,
pub apk_sign_block: Option<ApkSigningBlock>,
pub data: T,
}
@ -59,6 +62,7 @@ impl<T: Read + Seek> ZipFile<T> {
zip64_end_of_central_directory,
data: reader,
files: vec![],
apk_sign_block: None,
};
zip_file
.data
@ -74,9 +78,28 @@ impl<T: Read + Seek> ZipFile<T> {
zip_file.files.push(file_header);
}
assert_eq!(size_read, cd_size);
for f in &zip_file.files {
println!("{f:#?}");
if zip_file.get_ed_offset() > 16 {
zip_file
.data
.seek(SeekFrom::Start(zip_file.get_ed_offset() - 16))
.unwrap();
let magic = Magic::deserialize(&mut zip_file.data).unwrap();
if magic == ApkSigningBlock::MAGIC {
zip_file
.data
.seek(SeekFrom::Start(zip_file.get_ed_offset() - 16 - 8))
.unwrap();
let block_size = u64::deserialize(&mut zip_file.data).unwrap();
zip_file
.data
.seek(SeekFrom::Start(zip_file.get_ed_offset() - block_size - 8))
.unwrap();
zip_file.apk_sign_block = ApkSigningBlock::deserialize(&mut zip_file.data).ok();
}
}
//println!("{:?}", zip_file.apk_sign_block);
zip_file
}
@ -160,4 +183,43 @@ impl<T: Read + Seek> ZipFile<T> {
pub fn get_file_names(&self) -> Vec<String> {
self.files.iter().map(|f| f.get_name()).collect()
}
/// Test if the zipfile contains files used to signe jar file (apk signature v1):
/// META-INF/MANIFEST.MF
/// META-INF/*.SF
/// META-INF/*.DSA
/// META-INF/*.RSA
/// META-INF/SIG-*
pub fn get_jar_sig_files(&self) -> Vec<&FileHeader> {
self.files
.iter()
.filter(|file| {
let name = file.get_name();
let l = name.len();
(name == "META-INF/MANIFEST.MF")
|| (l >= 13 && &name[..9] == "META-INF/" && &name[l - 3..] == ".SF")
|| (l >= 14 && &name[..9] == "META-INF/" && &name[l - 4..] == ".DSA")
|| (l >= 14 && &name[..9] == "META-INF/" && &name[l - 4..] == ".RSA")
|| (l >= 14 && &name[..13] == "META-INF/SIG-")
})
.collect()
}
/// Test if the zipfile contains files used to signe jar file (apk signature v1):
/// META-INF/MANIFEST.MF
/// META-INF/*.SF
/// META-INF/*.DSA
/// META-INF/*.RSA
/// META-INF/SIG-*
///
/// TODO: there is a field `X-Android-APK-Signed` in .SF that indicate the use of v2 and v3
/// (and v4?) signature.
pub fn is_signed_v1(&self) -> bool {
!self.get_jar_sig_files().is_empty()
}
/// Test if the zipfile as apk signature block.
pub fn is_signed_v2(&self) -> bool {
self.apk_sign_block.is_some()
}
}