poc repackaging
This commit is contained in:
parent
0f5764c340
commit
d3e005fd68
3 changed files with 121 additions and 74 deletions
2
apk_frauder/.gitignore
vendored
2
apk_frauder/.gitignore
vendored
|
|
@ -1,2 +1,4 @@
|
||||||
*.apk
|
*.apk
|
||||||
*.zip
|
*.zip
|
||||||
|
*.dex
|
||||||
|
*.idsig
|
||||||
|
|
|
||||||
|
|
@ -1,76 +1,78 @@
|
||||||
use apk_frauder::external_file_attributes;
|
|
||||||
use apk_frauder::file_header::FileHeader;
|
|
||||||
use apk_frauder::ZipFileReader;
|
use apk_frauder::ZipFileReader;
|
||||||
use apk_frauder::ZipFileWriter;
|
use apk_frauder::ZipFileWriter;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Cursor;
|
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
//let file = File::open("app-release.apk").expect("failed to open file");
|
// Remove previous generation
|
||||||
//let file = File::open("tst_64.zip").expect("failed to open file");
|
println!("Remove files from previous run");
|
||||||
//let zip_file = ZipFileReader::new(file);
|
Command::new("rm").arg("app-striped.apk").status().unwrap();
|
||||||
/*
|
Command::new("rm")
|
||||||
//println!("{}", zip_file.get_file_names().join("\n"));
|
.arg("app-instrumented.apk")
|
||||||
for file in &zip_file.files {
|
.status()
|
||||||
println!("{}", file.get_name());
|
.unwrap();
|
||||||
println!("local: {:?}", file.local_header.malformed_extra_field);
|
Command::new("rm")
|
||||||
println!("central dir: {:?}", file.header.malformed_extra_field);
|
.arg("app-instrumented-signed.apk")
|
||||||
println!();
|
.status()
|
||||||
|
.unwrap();
|
||||||
|
Command::new("rm")
|
||||||
|
.arg("app-instrumented-aligned.apk")
|
||||||
|
.status()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!("Read the headers of the existing dex file and strip the apk signature and dex files");
|
||||||
|
let file = File::open("app-release.apk").expect("failed to open file");
|
||||||
|
let mut apk = ZipFileReader::new(file);
|
||||||
|
|
||||||
|
let mut file_info_ref = (*apk.get_classes_file_info().first().unwrap()).clone();
|
||||||
|
|
||||||
|
apk.unlink_signature_files();
|
||||||
|
apk.unlink_bytecode_files();
|
||||||
|
|
||||||
|
let out_file = File::create("app-striped.apk").expect("failed to create file");
|
||||||
|
let mut apk_out = ZipFileWriter::new(out_file, apk.zip64_end_of_central_directory.clone());
|
||||||
|
for f in apk.files.clone() {
|
||||||
|
apk_out.insert_file_from_zip(f, &mut apk);
|
||||||
}
|
}
|
||||||
|
apk_out.write_central_directory();
|
||||||
|
|
||||||
println!(
|
println!("Insert the dex file to the stripped apk with the header of the original dex file");
|
||||||
"uncompressed size: {}",
|
let file = File::open("app-striped.apk").expect("failed to open file");
|
||||||
zip_file.files[0].get_uncompressed_size()
|
let mut bytecodes = File::open("classes.dex").expect("failed to open file");
|
||||||
);
|
let mut apk = ZipFileReader::new(file);
|
||||||
println!(
|
let out_file = File::create("app-instrumented.apk").expect("failed to create file");
|
||||||
"{}",
|
let mut apk_out = ZipFileWriter::new(out_file, apk.zip64_end_of_central_directory.clone());
|
||||||
zip_file
|
for f in apk.files.clone() {
|
||||||
.get_jar_sig_files()
|
apk_out.insert_file_from_zip(f, &mut apk);
|
||||||
.iter()
|
|
||||||
.map(|f| f.get_name())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("\n")
|
|
||||||
);
|
|
||||||
if zip_file.is_signed_v2() {
|
|
||||||
println!("Signed >= v2");
|
|
||||||
} else {
|
|
||||||
println!("Not signed whith scheme >= v2");
|
|
||||||
}
|
}
|
||||||
zip_file.check_holes();
|
file_info_ref.set_name("classes.dex");
|
||||||
*/
|
apk_out.insert_file(
|
||||||
//println!("{:#?}", zip_file.get_file_info("classes.dex"));
|
&mut bytecodes,
|
||||||
|
file_info_ref.header,
|
||||||
/*
|
Some(file_info_ref.local_header),
|
||||||
let file = File::open("tst_64.zip").expect("failed to open file");
|
|
||||||
let out_file = File::create("tst_64.out.zip").expect("failed to create file");
|
|
||||||
let mut zip_file = ZipFileReader::new(file);
|
|
||||||
let mut out_file =
|
|
||||||
ZipFileWriter::new(out_file, zip_file.zip64_end_of_central_directory.clone());
|
|
||||||
for f in zip_file.files.clone() {
|
|
||||||
out_file.insert_file_from_zip(f, &mut zip_file);
|
|
||||||
}
|
|
||||||
out_file.write_central_directory();
|
|
||||||
*/
|
|
||||||
//println!("{:#?}", zip_file.zip64_end_of_central_directory);
|
|
||||||
let out_file = File::create("test_write.zip").expect("failed to create file");
|
|
||||||
let mut out_file = ZipFileWriter::new(out_file, None);
|
|
||||||
out_file.insert_file(
|
|
||||||
&mut Cursor::new(b"plop\n"),
|
|
||||||
FileHeader::new_default("plop.txt"),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
out_file.insert_file(
|
|
||||||
&mut Cursor::new(b"Hello World !!!\n"),
|
|
||||||
FileHeader::new_default("plip.txt"),
|
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
|
apk_out.write_central_directory();
|
||||||
|
|
||||||
//let mut header_dir = FileHeader::new_default("dir");
|
println!("Align the apk");
|
||||||
//header_dir.set_file_type(external_file_attributes::DIR_FILE);
|
// This could probably be performed by ourself
|
||||||
//out_file.insert_file(&mut Cursor::new(b""), header_dir, None);
|
Command::new("/home/histausse/Android/Sdk/build-tools/34.0.0/zipalign")
|
||||||
let mut header_link = FileHeader::new_default("dir/link");
|
.arg("-v")
|
||||||
header_link.set_file_type(external_file_attributes::SYMBOLIC_LINK_FILE);
|
.arg("-p")
|
||||||
out_file.insert_file(&mut Cursor::new(b"../plop.txt"), header_link, None);
|
.arg("4")
|
||||||
|
.arg("app-instrumented.apk")
|
||||||
|
.arg("app-instrumented-aligned.apk")
|
||||||
|
.status()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
out_file.write_central_directory();
|
println!("Sign the apk");
|
||||||
|
Command::new("/home/histausse/Android/Sdk/build-tools/34.0.0/apksigner")
|
||||||
|
.arg("sign")
|
||||||
|
.arg("--ks")
|
||||||
|
.arg("/home/histausse/AndroidStudioProjects/TestApplication/my-release-key.jks")
|
||||||
|
.arg("--out")
|
||||||
|
.arg("app-instrumented-signed.apk")
|
||||||
|
.arg("app-instrumented-aligned.apk")
|
||||||
|
.status()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -207,15 +207,7 @@ impl<T: Read + Seek> ZipFileReader<T> {
|
||||||
pub fn get_jar_sig_files(&self) -> Vec<&FileInfo> {
|
pub fn get_jar_sig_files(&self) -> Vec<&FileInfo> {
|
||||||
self.files
|
self.files
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|file| {
|
.filter(|file| match_v1_signature_file(&file.get_name()))
|
||||||
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()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,6 +229,24 @@ impl<T: Read + Seek> ZipFileReader<T> {
|
||||||
self.apk_sign_block.is_some()
|
self.apk_sign_block.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove v1 signature files from the file index.
|
||||||
|
///
|
||||||
|
/// This function does no modify the original file, only the index store
|
||||||
|
/// in the struct.
|
||||||
|
pub fn unlink_signature_files(&mut self) {
|
||||||
|
self.files
|
||||||
|
.retain(|file| !match_v1_signature_file(&file.get_name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unlink bytecode files.
|
||||||
|
///
|
||||||
|
/// This function does no modify the original file, only the index store
|
||||||
|
/// in the struct.
|
||||||
|
pub fn unlink_bytecode_files(&mut self) {
|
||||||
|
self.files
|
||||||
|
.retain(|file| !match_dexfile_name(&file.get_name()));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check_holes(&self) {
|
pub fn check_holes(&self) {
|
||||||
let mut files: Vec<&FileInfo> = self.files.iter().collect();
|
let mut files: Vec<&FileInfo> = self.files.iter().collect();
|
||||||
files.sort_by_key(|f| f.get_offset_local_header());
|
files.sort_by_key(|f| f.get_offset_local_header());
|
||||||
|
|
@ -262,7 +272,7 @@ impl<T: Read + Seek> ZipFileReader<T> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
lst_offset += apk_sign_block.size() as u64;
|
lst_offset = self.get_cd_offset();
|
||||||
}
|
}
|
||||||
if self.get_cd_offset() != lst_offset {
|
if self.get_cd_offset() != lst_offset {
|
||||||
println!(
|
println!(
|
||||||
|
|
@ -285,4 +295,37 @@ impl<T: Read + Seek> ZipFileReader<T> {
|
||||||
pub fn get_file_info(&self, name: &str) -> Option<&FileInfo> {
|
pub fn get_file_info(&self, name: &str) -> Option<&FileInfo> {
|
||||||
self.files.iter().find(|&file| file.get_name() == name)
|
self.files.iter().find(|&file| file.get_name() == name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_classes_file_info(&self) -> Vec<&FileInfo> {
|
||||||
|
self.files
|
||||||
|
.iter()
|
||||||
|
.filter(|&file| match_dexfile_name(&file.get_name()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not worth a regex
|
||||||
|
/// Check if a file is a bytecode file (from its name)
|
||||||
|
fn match_dexfile_name(name: &str) -> bool {
|
||||||
|
if name.len() < 11 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if &name[0..7] != "classes" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if &name[name.len() - 4..name.len()] != ".dex" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
name.len() == 11 || name[7..name.len() - 4].parse::<u32>().is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if a file is used to sign the APK with signature scheme v1.
|
||||||
|
fn match_v1_signature_file(name: &str) -> bool {
|
||||||
|
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-")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue