1use std::sync::Arc;
4
5use ahash::AHashMap;
6use flate2::{Decompress, FlushDecompress, Status};
7use log::warn;
8use openssl::hash::MessageDigest;
9use openssl::pkcs7::{Pkcs7, Pkcs7Flags};
10use openssl::stack::Stack;
11use openssl::x509::{X509, X509Ref};
12use winnow::binary::{le_u32, le_u64, length_take};
13use winnow::combinator::repeat;
14use winnow::error::ContextError;
15use winnow::prelude::*;
16use winnow::token::take;
17
18use crate::signature::{CertificateInfo, Signature};
19use crate::structs::{CentralDirectory, EndOfCentralDirectory, LocalFileHeader};
20use crate::{CertificateError, FileCompressionType, ZipError};
21
22#[derive(Debug)]
24pub struct ZipEntry {
25 input: Vec<u8>,
27
28 eocd: EndOfCentralDirectory,
30
31 central_directory: CentralDirectory,
33
34 local_headers: AHashMap<Arc<str>, LocalFileHeader>,
36}
37
38impl ZipEntry {
40 pub fn new(input: Vec<u8>) -> Result<ZipEntry, ZipError> {
57 if !input.starts_with(b"PK\x03\x04") {
59 return Err(ZipError::InvalidHeader);
60 }
61
62 let eocd_offset =
63 EndOfCentralDirectory::find_eocd(&input, 4096).ok_or(ZipError::NotFoundEOCD)?;
64
65 let eocd = EndOfCentralDirectory::parse(&mut &input[eocd_offset..])
66 .map_err(|_| ZipError::ParseError)?;
67
68 let central_directory =
69 CentralDirectory::parse(&input, &eocd).map_err(|_| ZipError::ParseError)?;
70
71 let local_headers = central_directory
72 .entries
73 .iter()
74 .filter_map(|(filename, entry)| {
75 LocalFileHeader::parse(&input, entry.local_header_offset as usize)
76 .ok()
77 .map(|header| (Arc::clone(filename), header))
78 })
79 .collect();
80
81 Ok(ZipEntry {
82 input,
83 eocd,
84 central_directory,
85 local_headers,
86 })
87 }
88
89 pub fn namelist(&self) -> impl Iterator<Item = &str> + '_ {
102 self.central_directory.entries.keys().map(|x| x.as_ref())
103 }
104
105 pub fn read(&self, filename: &str) -> Result<(Vec<u8>, FileCompressionType), ZipError> {
133 let local_header = self
134 .local_headers
135 .get(filename)
136 .ok_or(ZipError::FileNotFound)?;
137
138 let central_directory_entry = self
139 .central_directory
140 .entries
141 .get(filename)
142 .ok_or(ZipError::FileNotFound)?;
143
144 let (compressed_size, uncompressed_size) =
145 if local_header.compressed_size == 0 || local_header.uncompressed_size == 0 {
146 (
147 central_directory_entry.compressed_size as usize,
148 central_directory_entry.uncompressed_size as usize,
149 )
150 } else {
151 (
152 local_header.compressed_size as usize,
153 local_header.uncompressed_size as usize,
154 )
155 };
156
157 let offset = central_directory_entry.local_header_offset as usize + local_header.size();
158 let get_slice = |start: usize, end: usize| self.input.get(start..end).ok_or(ZipError::EOF);
160
161 match (
162 local_header.compression_method,
163 compressed_size == uncompressed_size,
164 ) {
165 (0, _) => {
166 let slice = get_slice(offset, offset + uncompressed_size)?;
168 Ok((slice.to_vec(), FileCompressionType::Stored))
169 }
170 (8, _) => {
171 let compressed_data = get_slice(offset, offset + compressed_size)?;
173 let mut uncompressed_data = Vec::with_capacity(uncompressed_size);
174
175 Decompress::new(false)
176 .decompress_vec(
177 compressed_data,
178 &mut uncompressed_data,
179 FlushDecompress::Finish,
180 )
181 .map_err(|_| ZipError::DecompressionError)?;
182
183 Ok((uncompressed_data, FileCompressionType::Deflated))
184 }
185 (_, true) => {
186 let slice = get_slice(offset, offset + uncompressed_size)?;
188 Ok((slice.to_vec(), FileCompressionType::StoredTampered))
189 }
190 (_, false) => {
191 let compressed_data = get_slice(offset, offset + compressed_size)?;
193 let mut uncompressed_data = Vec::with_capacity(uncompressed_size);
194 let mut decompressor = Decompress::new(false);
195
196 let status = decompressor.decompress_vec(
197 compressed_data,
198 &mut uncompressed_data,
199 FlushDecompress::Finish,
200 );
201
202 let is_valid = decompressor.total_in() == compressed_data.len() as u64;
204 match status {
205 Ok(Status::Ok) | Ok(Status::StreamEnd) if is_valid => {
206 Ok((uncompressed_data, FileCompressionType::DeflatedTampered))
207 }
208 _ => {
209 let slice = get_slice(offset, offset + uncompressed_size)?;
211 Ok((slice.to_vec(), FileCompressionType::StoredTampered))
212 }
213 }
214 }
215 }
216 }
217}
218
219impl ZipEntry {
223 pub const APK_SIGNATURE_MAGIC: &[u8] = b"APK Sig Block 42";
227
228 pub const SIGNATURE_SCHEME_V2_BLOCK_ID: u32 = 0x7109871a;
232
233 pub const SIGNATURE_SCHEME_V3_BLOCK_ID: u32 = 0xf05368c0;
237
238 pub const SIGNATURE_SCHEME_V31_BLOCK_ID: u32 = 0x1b93ad61;
242
243 pub const V1_SOURCE_STAMP_BLOCK_ID: u32 = 0x2b09189e;
249
250 pub const V2_SOURCE_STAMP_BLOCK_ID: u32 = 0x6dff800d;
256
257 pub const VERITY_PADDING_BLOCK_ID: u32 = 0x42726577;
261
262 pub const DEPENDENCY_INFO_BLOCK_ID: u32 = 0x504b4453;
270
271 pub const APK_CHANNEL_BLOCK_ID: u32 = 0x71777777;
275
276 pub const GOOGLE_PLAY_FROSTING_ID: u32 = 0x2146444e;
278
279 pub const ZERO_BLOCK_ID: u32 = 0xff3b5998;
281
282 pub const PACKER_NG_SIG_V2: u32 = 0x7a786b21;
286
287 pub const VASDOLLY_V2: u32 = 0x881155ff;
293
294 fn get_certificate_info(
299 &self,
300 certificate: &X509Ref,
301 ) -> Result<CertificateInfo, CertificateError> {
302 #[inline]
303 fn digest_hex(cert: &X509Ref, md: MessageDigest) -> Result<String, CertificateError> {
304 Ok(const_hex::encode(
305 cert.digest(md).map_err(CertificateError::StackError)?,
306 ))
307 }
308
309 let serial_number = {
310 let bn = certificate
311 .serial_number()
312 .to_bn()
313 .map_err(CertificateError::StackError)?;
314
315 const_hex::encode(bn.to_vec())
316 };
317
318 let mut subject = String::with_capacity(128); for entry in certificate.subject_name().entries() {
320 if let Ok(value) = entry.data().as_utf8() {
321 if !subject.is_empty() {
322 subject.push(' ');
323 }
324 subject.push_str(entry.object().nid().short_name().unwrap_or_default());
325 subject.push('=');
326 subject.push_str(value.as_ref());
327 }
328 }
329
330 let mut issuer = String::with_capacity(128);
331
332 for entry in certificate.issuer_name().entries() {
333 if let Ok(value) = entry.data().as_utf8() {
334 if !issuer.is_empty() {
335 issuer.push(' ');
336 }
337 let name = entry.object().nid().short_name().unwrap_or_default();
338 issuer.push_str(name);
339 issuer.push('=');
340 issuer.push_str(value.as_ref());
341 }
342 }
343
344 let valid_from = certificate.not_before().to_string();
345 let valid_until = certificate.not_after().to_string();
346
347 let signature_type = certificate
348 .signature_algorithm()
349 .object()
350 .nid()
351 .long_name()
352 .map_err(CertificateError::StackError)?
353 .to_string();
354
355 let md5_fingerprint = digest_hex(certificate, MessageDigest::md5())?;
356 let sha1_fingerprint = digest_hex(certificate, MessageDigest::sha1())?;
357 let sha256_fingerprint = digest_hex(certificate, MessageDigest::sha256())?;
358
359 Ok(CertificateInfo {
360 serial_number,
361 subject,
362 issuer,
363 valid_from,
364 valid_until,
365 signature_type,
366 md5_fingerprint,
367 sha1_fingerprint,
368 sha256_fingerprint,
369 })
370 }
371
372 pub fn get_signature_v1(&self) -> Result<Signature, CertificateError> {
390 let signature_file = match self.namelist().find(|name| {
391 name.starts_with("META-INF/")
392 && (name.ends_with(".DSA") || name.ends_with(".EC") || name.ends_with(".RSA"))
393 }) {
394 Some(v) => v,
395 None => return Ok(Signature::Unknown),
397 };
398
399 let (data, _) = self
400 .read(signature_file)
401 .map_err(CertificateError::ZipError)?;
402
403 let info = Pkcs7::from_der(&data).map_err(CertificateError::StackError)?;
404 let certs = Stack::new().map_err(CertificateError::StackError)?;
405
406 let certificates = info
407 .signers(&certs, Pkcs7Flags::STREAM)
408 .map_err(|_| CertificateError::SignerError)?
409 .iter()
410 .map(|signer| self.get_certificate_info(signer))
411 .collect::<Result<Vec<CertificateInfo>, CertificateError>>()?;
412
413 Ok(Signature::V1(certificates))
414 }
415
416 pub fn get_signatures_other(&self) -> Result<Vec<Signature>, CertificateError> {
430 let offset = self.eocd.central_dir_offset as usize;
431 let mut slice = match self.input.get(offset.saturating_sub(24)..offset) {
432 Some(v) => v,
433 None => return Ok(Vec::new()),
434 };
435
436 let size_of_block = le_u64::<&[u8], ContextError>
437 .parse_next(&mut slice)
438 .map_err(|_| CertificateError::ParseError)?;
439
440 let magic = take::<usize, &[u8], ContextError>(16usize)
441 .parse_next(&mut slice)
442 .map_err(|_| CertificateError::ParseError)?;
443
444 if magic != Self::APK_SIGNATURE_MAGIC {
446 return Ok(Vec::new());
447 }
448
449 slice = match self
451 .input
452 .get(offset.saturating_sub((size_of_block + 8) as usize)..offset.saturating_sub(24))
453 {
454 Some(v) => v,
455 None => return Ok(Vec::new()),
456 };
457
458 let size_of_block_start = le_u64::<&[u8], ContextError>
459 .parse_next(&mut slice)
460 .map_err(|_| CertificateError::ParseError)?;
461
462 if size_of_block != size_of_block_start {
463 return Err(CertificateError::InvalidFormat(
464 size_of_block_start,
465 size_of_block,
466 ));
467 }
468
469 let signatures: Vec<Signature> =
470 repeat::<&[u8], Signature, Vec<Signature>, ContextError, _>(
471 0..,
472 self.parse_apk_signatures(),
473 )
474 .parse_next(&mut slice)
475 .map_err(|_| CertificateError::ParseError)?
476 .into_iter()
477 .filter(|signature| signature != &Signature::Unknown)
478 .collect();
479
480 Ok(signatures)
481 }
482
483 #[allow(unused)]
484 fn parse_digest<'a>() -> impl Parser<&'a [u8], (u32, &'a [u8]), ContextError> {
485 move |input: &mut &'a [u8]| {
486 let (_, signature_algorithm_id, digest) =
488 (le_u32, le_u32, length_take(le_u32)).parse_next(input)?;
489
490 Ok((signature_algorithm_id, digest))
491 }
492 }
493
494 fn parse_certificate<'a>() -> impl Parser<&'a [u8], X509, ContextError> {
495 move |input: &mut &'a [u8]| {
496 let certificate = length_take(le_u32).parse_next(input)?;
497
498 Ok(X509::from_der(certificate).expect("why openssl can't decode this certificate?"))
499 }
500 }
501
502 #[allow(unused)]
503 fn parse_attribute_v2<'a>() -> impl Parser<&'a [u8], (u32, &'a [u8]), ContextError> {
504 move |input: &mut &'a [u8]| {
505 let (attribute_length, id) = (le_u32, le_u32).parse_next(input)?;
506 let value = take(attribute_length.saturating_sub(4)).parse_next(input)?;
507
508 Ok((id, value))
509 }
510 }
511
512 #[allow(unused)]
513 fn parse_attribute_v3<'a>() -> impl Parser<&'a [u8], (u32, &'a [u8]), ContextError> {
514 move |input: &mut &'a [u8]| {
515 let (attribute_length, id) = (le_u32, le_u32).parse_next(input)?;
516 let value = take(attribute_length.saturating_sub(4)).parse_next(input)?;
517 let _const_id = le_u32.parse_next(input)?;
518 Ok((id, value))
521 }
522 }
523
524 #[allow(unused)]
525 fn parse_signature<'a>() -> impl Parser<&'a [u8], (u32, &'a [u8]), ContextError> {
526 move |input: &mut &'a [u8]| {
527 let (_, signature_algorithm_id, signature) =
529 (le_u32, le_u32, length_take(le_u32)).parse_next(input)?;
530
531 Ok((signature_algorithm_id, signature))
532 }
533 }
534
535 fn parse_signer_v2<'a>() -> impl Parser<&'a [u8], Vec<X509>, ContextError> {
536 move |input: &mut &'a [u8]| {
537 let mut signer_data = length_take(le_u32).parse_next(input)?;
539
540 let mut signed_data = length_take(le_u32).parse_next(&mut signer_data)?;
542
543 let mut _digests_data = length_take(le_u32).parse_next(&mut signed_data)?;
545 let mut certificates_data = length_take(le_u32).parse_next(&mut signed_data)?;
551 let certificates: Vec<X509> =
552 repeat(0.., Self::parse_certificate()).parse_next(&mut certificates_data)?;
553
554 let mut _attributes_data = length_take(le_u32).parse_next(&mut signed_data)?;
556 let mut _signatures_data = length_take(le_u32).parse_next(&mut signer_data)?;
562 let _public_key = length_take(le_u32).parse_next(&mut signer_data)?;
568
569 Ok(certificates)
570 }
571 }
572
573 fn parse_signer_v3<'a>() -> impl Parser<&'a [u8], Vec<X509>, ContextError> {
574 move |input: &mut &'a [u8]| {
575 let mut signer_data = length_take(le_u32).parse_next(input)?;
577
578 let mut signed_data = length_take(le_u32).parse_next(&mut signer_data)?;
580
581 let mut _digests_data = length_take(le_u32).parse_next(&mut signed_data)?;
583 let mut certificates_data = length_take(le_u32).parse_next(&mut signed_data)?;
589 let certificates: Vec<X509> =
590 repeat(0.., Self::parse_certificate()).parse_next(&mut certificates_data)?;
591
592 let (_min_sdk, _max_sdk) = (le_u32, le_u32).parse_next(&mut signed_data)?;
594
595 let mut _attributes_data = length_take(le_u32).parse_next(&mut signed_data)?;
597 let (_duplicate_min_sdk, _duplicate_max_sdk) =
603 (le_u32, le_u32).parse_next(&mut signer_data)?;
604
605 let mut _signatures_data = length_take(le_u32).parse_next(&mut signer_data)?;
607 let _public_key = length_take(le_u32).parse_next(&mut signer_data)?;
613
614 Ok(certificates)
615 }
616 }
617
618 fn parse_apk_signatures<'a>(&self) -> impl Parser<&'a [u8], Signature, ContextError> {
619 move |input: &mut &'a [u8]| {
620 let (size, id) = (le_u64, le_u32).parse_next(input)?;
621
622 match id {
623 Self::SIGNATURE_SCHEME_V2_BLOCK_ID => {
624 let mut signers_data = length_take(le_u32).parse_next(input)?;
625
626 let certificates =
627 repeat::<_, Vec<X509>, Vec<Vec<X509>>, _, _>(1.., Self::parse_signer_v2())
628 .parse_next(&mut signers_data)?
629 .into_iter()
630 .flatten()
631 .filter_map(|cert| self.get_certificate_info(&cert).ok())
632 .collect();
633
634 Ok(Signature::V2(certificates))
635 }
636 Self::SIGNATURE_SCHEME_V3_BLOCK_ID => {
637 let mut signers_data = length_take(le_u32).parse_next(input)?;
638
639 let certificates =
640 repeat::<_, Vec<X509>, Vec<Vec<X509>>, _, _>(1.., Self::parse_signer_v3())
641 .parse_next(&mut signers_data)?
642 .into_iter()
643 .flatten()
644 .filter_map(|cert| self.get_certificate_info(&cert).ok())
645 .collect();
646
647 Ok(Signature::V3(certificates))
648 }
649 Self::SIGNATURE_SCHEME_V31_BLOCK_ID => {
650 let mut signers_data = length_take(le_u32).parse_next(input)?;
651
652 let certificates =
653 repeat::<_, Vec<X509>, Vec<Vec<X509>>, _, _>(1.., Self::parse_signer_v3())
654 .parse_next(&mut signers_data)?
655 .into_iter()
656 .flatten()
657 .filter_map(|cert| self.get_certificate_info(&cert).ok())
658 .collect();
659
660 Ok(Signature::V31(certificates))
661 }
662 Self::APK_CHANNEL_BLOCK_ID => {
663 let data = take(size.saturating_sub(4) as usize).parse_next(input)?;
664
665 Ok(Signature::ApkChannelBlock(
666 String::from_utf8_lossy(data).trim().to_string(),
667 ))
668 }
669 Self::V1_SOURCE_STAMP_BLOCK_ID => {
670 let _stamp_block_prefix = le_u32.parse_next(input)?;
672
673 let certificate = Self::parse_certificate().parse_next(input)?;
674
675 let _signed_data = length_take(le_u32).parse_next(input)?;
677
678 let certificate = self
680 .get_certificate_info(&certificate)
681 .map_err(|_| ContextError::new())?;
682
683 Ok(Signature::StampBlockV1(certificate))
684 }
685 Self::V2_SOURCE_STAMP_BLOCK_ID => {
686 let _stamp_block_prefix = le_u32.parse_next(input)?;
689 let certificate = Self::parse_certificate().parse_next(input)?;
690
691 let _signed_digests_data = length_take(le_u32).parse_next(input)?;
693
694 let _encoded_stamp_attributes = length_take(le_u32).parse_next(input)?;
696
697 let _signed_attributes = length_take(le_u32).parse_next(input)?;
699
700 let certificate = self
702 .get_certificate_info(&certificate)
703 .map_err(|_| ContextError::new())?;
704
705 Ok(Signature::StampBlockV2(certificate))
706 }
707 Self::PACKER_NG_SIG_V2 => {
708 let data = take(size.saturating_sub(4) as usize).parse_next(input)?;
709
710 Ok(Signature::PackerNextGenV2(data.to_vec()))
711 }
712 Self::GOOGLE_PLAY_FROSTING_ID => {
713 let _ = take(size.saturating_sub(4) as usize).parse_next(input)?;
714 Ok(Signature::GooglePlayFrosting)
715 }
716 Self::VASDOLLY_V2 => {
717 let data = take(size.saturating_sub(4) as usize).parse_next(input)?;
718 Ok(Signature::VasDollyV2(
719 String::from_utf8_lossy(data).trim().to_owned(),
720 ))
721 }
722 Self::VERITY_PADDING_BLOCK_ID
723 | Self::DEPENDENCY_INFO_BLOCK_ID
724 | Self::ZERO_BLOCK_ID => {
725 let _ = take(size.saturating_sub(4) as usize).parse_next(input)?;
727 Ok(Signature::Unknown)
728 }
729 _ => {
730 warn!(
732 "got unknown id block - 0x{:08x} (size=0x{:08x}), please open issue on github, let's try to figure out",
733 id, size
734 );
735
736 let _ = take(size.saturating_sub(4) as usize).parse_next(input)?;
737
738 Ok(Signature::Unknown)
739 }
740 }
741 }
742 }
743}