diff --git a/patcher/.gitignore b/patcher/.gitignore index eb5a316..906cab7 100644 --- a/patcher/.gitignore +++ b/patcher/.gitignore @@ -1 +1,2 @@ target +tests diff --git a/patcher/Cargo.toml b/patcher/Cargo.toml index 9176ec7..2df6abe 100644 --- a/patcher/Cargo.toml +++ b/patcher/Cargo.toml @@ -6,8 +6,8 @@ edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -#androscalpel = { git = "ssh://git@gitlab.inria.fr/androidoftheseus/androscalpel.git", rev = "110f0c0", features = ["code-analysis", "platform-list"] } -#apk_frauder = { git = "ssh://git@gitlab.inria.fr/androidoftheseus/androscalpel.git", rev = "110f0c0"} +#androscalpel = { git = "ssh://git@gitlab.inria.fr/androidoftheseus/androscalpel.git", rev = "3a0b9bb", features = ["code-analysis", "platform-list"] } +#apk_frauder = { git = "ssh://git@gitlab.inria.fr/androidoftheseus/androscalpel.git", rev = "3a0b9bb"} androscalpel = { path = "../../androscalpel/androscalpel", features = ["code-analysis", "platform-list"] } apk_frauder = { path = "../../androscalpel/apk_frauder"} anyhow = { version = "1.0.95", features = ["backtrace"] } diff --git a/patcher/src/bin/patcher.rs b/patcher/src/bin/patcher.rs index ba01b83..7ad7100 100644 --- a/patcher/src/bin/patcher.rs +++ b/patcher/src/bin/patcher.rs @@ -43,6 +43,7 @@ fn main() { env_logger::init(); let cli = Cli::parse(); let mut apk = Apk::load_apk(File::open(&cli.path).unwrap(), labeling, false).unwrap(); + //println!("{:#?}", apk.list_classes()); let mut json = String::new(); File::open(&cli.runtime_data) @@ -107,19 +108,9 @@ fn main() { .into_values() .map(|v| (v.descriptor.clone(), v)) .collect(); - // Add the new testing class in a separateed dex file to avoid breaking - // the dex method limit. - // TODO: check the number of methods in the existing dex files to avoid generated - // a new one each time. - let mut i = 2; - let new_dex_name = loop { - let name = format!("classes{}.dex", i); - if !apk.dex_files.contains_key(&name) { - break name; - }; - i += 1; - }; - apk.add_class(&new_dex_name, class).unwrap(); + apk.add_class("classes.dex", class).unwrap(); + apk.redistribute_classes(); + let mut dex_files = vec![]; let mut files = apk.gen_raw_dex().unwrap(); let mut i = 0; diff --git a/patcher/src/reflection_patcher.rs b/patcher/src/reflection_patcher.rs index 21b1d59..c6999b6 100644 --- a/patcher/src/reflection_patcher.rs +++ b/patcher/src/reflection_patcher.rs @@ -1346,7 +1346,7 @@ fn get_invoke_block( arg_arr, reg_inf.first_arg + if ref_data.is_static { 0 } else { 1 }, reg_inf, - )); + )?); if ref_data.is_static { insns.push(Instruction::InvokeStatic { method: ref_data.get_static_callee(), @@ -1375,7 +1375,7 @@ fn get_invoke_block( to: reg_inf.array_val, }); insns.push(Instruction::InvokeStatic { - method: get_scalar_to_obj_method(&ret_ty).unwrap(), + method: get_scalar_to_obj_method(&ret_ty)?, args: vec![reg_inf.array_val as u16, (reg_inf.array_val + 1) as u16], }); insns.push(move_result); @@ -1383,12 +1383,19 @@ fn get_invoke_block( reg: res_reg, lit: OBJECT_TY.clone(), }); + } else if ret_ty.is_void() { + // Void is represented by a null object + insns.push(Instruction::Const { + reg: res_reg, + lit: 0, + }); + insns.push(move_result); } else { insns.push(Instruction::MoveResult { to: reg_inf.array_val, }); insns.push(Instruction::InvokeStatic { - method: get_scalar_to_obj_method(&ret_ty).unwrap(), + method: get_scalar_to_obj_method(&ret_ty)?, args: vec![reg_inf.array_val as u16], }); insns.push(move_result); @@ -1415,7 +1422,7 @@ fn get_args_from_obj_arr( array_reg: u16, first_arg_reg: u16, reg_inf: &mut RegistersInfo, -) -> Vec { +) -> Result> { let mut insns = vec![]; let mut restore_array = vec![]; let mut reg_count = 0; @@ -1455,10 +1462,10 @@ fn get_args_from_obj_arr( } else if param.is_double() || param.is_long() { insns.push(Instruction::CheckCast { reg: reg_inf.array_val, - lit: get_obj_of_scalar(param).unwrap(), + lit: get_obj_of_scalar(param)?, }); insns.push(Instruction::InvokeVirtual { - method: get_obj_to_scalar_method(param).unwrap(), + method: get_obj_to_scalar_method(param)?, args: vec![reg_inf.array_val as u16], }); insns.push(Instruction::MoveResultWide { @@ -1472,10 +1479,10 @@ fn get_args_from_obj_arr( } else { insns.push(Instruction::CheckCast { reg: reg_inf.array_val, - lit: get_obj_of_scalar(param).unwrap(), + lit: get_obj_of_scalar(param)?, }); insns.push(Instruction::InvokeVirtual { - method: get_obj_to_scalar_method(param).unwrap(), + method: get_obj_to_scalar_method(param)?, args: vec![reg_inf.array_val as u16], }); insns.push(Instruction::MoveResult { @@ -1489,7 +1496,7 @@ fn get_args_from_obj_arr( } } insns.append(&mut restore_array); - insns + Ok(insns) } pub(crate) static ABORD_LABELS: std::sync::LazyLock< @@ -1557,7 +1564,7 @@ fn get_cnstr_new_inst_block( arg_arr, reg_inf.first_arg + 1, reg_inf, - )); + )?); if reg_inf.first_arg < u8::MAX as u16 { insns.push(Instruction::NewInstance { reg: reg_inf.first_arg as u8,