put all the dex swapping & resigning shenanigans in a function
This commit is contained in:
parent
86a028f0bd
commit
cb34f76063
5 changed files with 160 additions and 73 deletions
|
|
@ -1,4 +1,10 @@
|
|||
use androscalpel_serializer::Serializable;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Seek};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
pub mod apk_signing_block;
|
||||
pub mod compression;
|
||||
|
|
@ -132,3 +138,87 @@ impl FileInfo {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace the dex files a an apk an resigned the apk.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// For now, only jks keystore are allowed.
|
||||
///
|
||||
/// 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)
|
||||
pub fn replace_dex(
|
||||
apk: impl AsRef<Path>,
|
||||
dst: impl AsRef<Path>,
|
||||
dexfiles: &mut [impl Read + Seek],
|
||||
keystore: impl AsRef<Path>, // TODO enum for handling p11 and generating a random cert
|
||||
// `keytool -genkey -v -keystore KEYSTORE.jks -keyalg RSA -keysize
|
||||
// 2048 -validity 10000 -alias ALIAS`
|
||||
zipalign: Option<impl AsRef<Path>>,
|
||||
apksigner: Option<impl AsRef<Path>>,
|
||||
) {
|
||||
let zipalign = if let Some(path) = &zipalign {
|
||||
path.as_ref().as_os_str()
|
||||
} else {
|
||||
"zipalign".as_ref()
|
||||
};
|
||||
let apksigner = if let Some(path) = &apksigner {
|
||||
path.as_ref().as_os_str()
|
||||
} else {
|
||||
"apksigner".as_ref()
|
||||
};
|
||||
let tmp_dir = env::temp_dir().join(format!("apk_frauder_{:x}", rand::random::<u128>()));
|
||||
let unaligned_path = tmp_dir.join("stripped.apk");
|
||||
let aligned_path = tmp_dir.join("aligned.apk");
|
||||
fs::create_dir_all(&tmp_dir).expect("Failed to create temporary directory");
|
||||
|
||||
let file = File::open(apk).expect("failed to open file");
|
||||
let mut apk = ZipFileReader::new(file);
|
||||
let file = File::create(&unaligned_path).expect("failed to create file");
|
||||
let mut apk_out = ZipFileWriter::new(file, apk.zip64_end_of_central_directory.clone());
|
||||
|
||||
let mut file_info_ref = (*apk
|
||||
.get_classes_file_info()
|
||||
.first()
|
||||
.expect("No dex file found in apk"))
|
||||
.clone();
|
||||
|
||||
apk.unlink_signature_files();
|
||||
apk.unlink_bytecode_files();
|
||||
for f in apk.files.clone() {
|
||||
apk_out.insert_file_from_zip(f, &mut apk);
|
||||
}
|
||||
for (i, mut dex) in dexfiles.iter_mut().enumerate() {
|
||||
if i == 0 {
|
||||
file_info_ref.set_name("classes.dex");
|
||||
} else {
|
||||
file_info_ref.set_name(&format!("classes{}.dex", i + 1));
|
||||
}
|
||||
apk_out.insert_file(
|
||||
&mut dex,
|
||||
file_info_ref.header.clone(),
|
||||
Some(file_info_ref.local_header.clone()),
|
||||
);
|
||||
}
|
||||
apk_out.write_central_directory();
|
||||
// TODO: we can probably do that ourself an spare ourself the trouble of finding zipalign
|
||||
Command::new(zipalign)
|
||||
.arg("-v")
|
||||
.arg("-p")
|
||||
.arg("4")
|
||||
.arg(unaligned_path.as_os_str())
|
||||
.arg(aligned_path.as_os_str())
|
||||
.status()
|
||||
.unwrap();
|
||||
|
||||
Command::new(apksigner)
|
||||
.arg("sign")
|
||||
.arg("--ks")
|
||||
.arg(keystore.as_ref().as_os_str())
|
||||
.arg("--out")
|
||||
.arg(dst.as_ref().as_os_str())
|
||||
.arg(aligned_path.as_os_str())
|
||||
.status()
|
||||
.unwrap();
|
||||
fs::remove_dir_all(tmp_dir).expect("Failled to remove tmp dir");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue