use std::collections::HashMap; use std::io::Cursor; use std::path::PathBuf; use androscalpel::{IdMethod, IdType}; use patcher::get_apk::{get_apk, ApkLocation}; use patcher::{ transform_method, ReflectionClassNewInstData, ReflectionCnstrNewInstData, ReflectionInvokeData, }; use clap::Parser; #[derive(Parser, Debug)] #[command(version, about, long_about = None, arg_required_else_help = true)] struct Cli { #[clap(flatten)] apk: ApkLocation, #[arg(short, long)] out: PathBuf, #[arg(short, long)] keystore: PathBuf, #[arg(short, long)] zipalign: Option, #[arg(short, long)] apksigner: Option, } fn main() { env_logger::init(); let cli = Cli::parse(); let mut apk = get_apk(&cli.apk); //println!("{:#?}", apk.list_classes()); let class = apk .get_class_mut( &IdType::new("Lcom/example/theseus/reflection/MainActivity;".into()).unwrap(), ) .unwrap(); //println!("{:#?}", class.direct_methods.keys()); //println!("{:#?}", class.virtual_methods.keys()); for m in [ "Lcom/example/theseus/reflection/MainActivity;->callVirtualMethodReflectCall()V", "Lcom/example/theseus/reflection/MainActivity;->callConstructorVirtualMethodReflectConstr()V", "Lcom/example/theseus/reflection/MainActivity;->callVirtualMethodReflectOldConst()V", ] { let method = class .virtual_methods .get_mut(&IdMethod::from_smali(m).unwrap()) .unwrap(); transform_method( method, &ReflectionInvokeData { method: IdMethod::from_smali( "Lcom/example/theseus/reflection/Reflectee;->transfer(Ljava/lang/String;)Ljava/lang/String;", ) .unwrap(), }, &ReflectionClassNewInstData { constructor: IdMethod::from_smali( "Lcom/example/theseus/reflection/Reflectee;->()V", ) .unwrap(), }, &ReflectionCnstrNewInstData{ constructor: IdMethod::from_smali( "Lcom/example/theseus/reflection/Reflectee;->(Ljava/lang/String;)V", ) .unwrap(), }, ) .unwrap(); } let mut dex_files = vec![]; let mut files = apk.gen_raw_dex().unwrap(); let mut i = 0; loop { let name = if i == 0 { "classes.dex".into() } else { format!("classes{}.dex", i + 1) }; if let Some(file) = files.remove(&name) { dex_files.push(Cursor::new(file)) } else { break; } i += 1; } // TODO: aapt would be a lot more stable apk_frauder::replace_dex( cli.apk.path.unwrap(), cli.out, &mut dex_files, cli.keystore, cli.zipalign, cli.apksigner, None::>>>, ); }