add file modification

This commit is contained in:
Jean-Marie Mineau 2024-05-06 18:01:27 +02:00
parent fb2ba61d21
commit df9d258780
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
4 changed files with 44 additions and 2 deletions

View file

@ -3,7 +3,7 @@
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::PyBytes; use pyo3::types::PyBytes;
use std::collections::HashSet; use std::collections::{HashMap, HashSet};
use std::fs::File; use std::fs::File;
use std::io::{Cursor, Seek, SeekFrom}; use std::io::{Cursor, Seek, SeekFrom};
use std::path::PathBuf; use std::path::PathBuf;
@ -104,6 +104,10 @@ pub fn is_zip(file: PathBuf) -> bool {
/// ///
/// The `zipalign` and `apksigner` args allow to use a specific version of the /// The `zipalign` and `apksigner` args allow to use a specific version of the
/// tools instead of the one in the PATH (if it even exist) /// tools instead of the one in the PATH (if it even exist)
///
/// `additionnal_files` is a dict of file to add, modify or remove in the apk.
/// The keys are the file names and the values are `None` to remove the file, or
/// `bytes` for the content of the file.
#[pyfunction] #[pyfunction]
pub fn replace_dex( pub fn replace_dex(
apk: PathBuf, apk: PathBuf,
@ -112,9 +116,24 @@ pub fn replace_dex(
keystore: PathBuf, keystore: PathBuf,
zipalign: Option<PathBuf>, zipalign: Option<PathBuf>,
apksigner: Option<PathBuf>, apksigner: Option<PathBuf>,
additionnal_files: Option<HashMap<String, Option<&[u8]>>>,
) { ) {
let mut dexfiles: Vec<_> = dexfiles.iter().map(Cursor::new).collect(); let mut dexfiles: Vec<_> = dexfiles.iter().map(Cursor::new).collect();
apk_frauder::replace_dex(apk, dst, &mut dexfiles, keystore, zipalign, apksigner) let additionnal_files: Option<HashMap<_, _>> = additionnal_files.map(|additionnal_files| {
additionnal_files
.into_iter()
.map(|(k, v)| (k, v.map(Cursor::new)))
.collect()
});
apk_frauder::replace_dex(
apk,
dst,
&mut dexfiles,
keystore,
zipalign,
apksigner,
additionnal_files,
)
} }
/// export the function in a python module /// export the function in a python module

View file

@ -1,4 +1,5 @@
use androscalpel_serializer::Serializable; use androscalpel_serializer::Serializable;
use std::collections::HashMap;
use std::env; use std::env;
use std::fs; use std::fs;
use std::fs::File; use std::fs::File;
@ -156,6 +157,7 @@ pub fn replace_dex(
// 2048 -validity 10000 -alias ALIAS` // 2048 -validity 10000 -alias ALIAS`
zipalign: Option<impl AsRef<Path>>, zipalign: Option<impl AsRef<Path>>,
apksigner: Option<impl AsRef<Path>>, apksigner: Option<impl AsRef<Path>>,
additionnal_files: Option<HashMap<String, Option<impl Read + Seek>>>,
) { ) {
let zipalign = if let Some(path) = &zipalign { let zipalign = if let Some(path) = &zipalign {
path.as_ref().as_os_str() path.as_ref().as_os_str()
@ -185,6 +187,10 @@ pub fn replace_dex(
apk.unlink_signature_files(); apk.unlink_signature_files();
apk.unlink_bytecode_files(); apk.unlink_bytecode_files();
if let Some(additionnal_files) = &additionnal_files {
apk.files
.retain(|file| additionnal_files.get(&file.get_name()).is_none());
}
for f in apk.files.clone() { for f in apk.files.clone() {
apk_out.insert_file_from_zip(f, &mut apk); apk_out.insert_file_from_zip(f, &mut apk);
} }
@ -200,6 +206,18 @@ pub fn replace_dex(
Some(file_info_ref.local_header.clone()), Some(file_info_ref.local_header.clone()),
); );
} }
if let Some(mut additionnal_files) = additionnal_files {
for (name, data) in &mut additionnal_files {
file_info_ref.set_name(name);
if let Some(data) = data.as_mut() {
apk_out.insert_file(
data,
file_info_ref.header.clone(),
Some(file_info_ref.local_header.clone()),
);
}
}
}
apk_out.write_central_directory(); apk_out.write_central_directory();
// TODO: we can probably do that ourself an spare ourself the trouble of finding zipalign // TODO: we can probably do that ourself an spare ourself the trouble of finding zipalign
Command::new(zipalign) Command::new(zipalign)

View file

@ -1,5 +1,7 @@
use std::collections::HashMap;
use std::env; use std::env;
use std::fs::File; use std::fs::File;
use std::io::Cursor;
fn main() { fn main() {
apk_frauder::replace_dex( apk_frauder::replace_dex(
@ -15,5 +17,6 @@ fn main() {
"{}/Android/Sdk/build-tools/34.0.0/apksigner", "{}/Android/Sdk/build-tools/34.0.0/apksigner",
env::var("HOME").expect("$HOME not set") env::var("HOME").expect("$HOME not set")
)), )),
None::<HashMap<String, Option<Cursor<&[u8]>>>>,
); );
} }

View file

@ -297,6 +297,8 @@ impl<T: Read + Seek> ZipFileReader<T> {
} }
pub fn get_classes_file_info(&self) -> Vec<&FileInfo> { pub fn get_classes_file_info(&self) -> Vec<&FileInfo> {
// TODO: check for holes: if classesN.dex does not exist,
// classesM.dex for M>N are ignored.
self.files self.files
.iter() .iter()
.filter(|&file| match_dexfile_name(&file.get_name())) .filter(|&file| match_dexfile_name(&file.get_name()))