debugging
This commit is contained in:
parent
e16252907a
commit
ed3385e611
5 changed files with 105 additions and 18 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
demo_env.sh
|
demo_env.sh
|
||||||
|
test
|
||||||
|
|
|
||||||
4
patcher/Cargo.lock
generated
4
patcher/Cargo.lock
generated
|
|
@ -35,7 +35,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "androscalpel"
|
name = "androscalpel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+ssh://git@git.mineau.eu/histausse/androscalpel.git?rev=f15ad78#f15ad78d44d78d188580698a2cfd3da1b0f4389d"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
"androscalpel_serializer",
|
"androscalpel_serializer",
|
||||||
|
|
@ -51,7 +50,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "androscalpel_serializer"
|
name = "androscalpel_serializer"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+ssh://git@git.mineau.eu/histausse/androscalpel.git?rev=f15ad78#f15ad78d44d78d188580698a2cfd3da1b0f4389d"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"androscalpel_serializer_derive",
|
"androscalpel_serializer_derive",
|
||||||
"log",
|
"log",
|
||||||
|
|
@ -60,7 +58,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "androscalpel_serializer_derive"
|
name = "androscalpel_serializer_derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+ssh://git@git.mineau.eu/histausse/androscalpel.git?rev=f15ad78#f15ad78d44d78d188580698a2cfd3da1b0f4389d"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -129,7 +126,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "apk_frauder"
|
name = "apk_frauder"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+ssh://git@git.mineau.eu/histausse/androscalpel.git?rev=f15ad78#f15ad78d44d78d188580698a2cfd3da1b0f4389d"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"androscalpel_serializer",
|
"androscalpel_serializer",
|
||||||
"flate2",
|
"flate2",
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
androscalpel = { git = "ssh://git@git.mineau.eu/histausse/androscalpel.git", rev = "f15ad78", features = ["code-analysis"] }
|
androscalpel = { git = "ssh://git@git.mineau.eu/histausse/androscalpel.git", rev = "ff2d630", features = ["code-analysis"] }
|
||||||
apk_frauder = { git = "ssh://git@git.mineau.eu/histausse/androscalpel.git", rev = "f15ad78"}
|
apk_frauder = { git = "ssh://git@git.mineau.eu/histausse/androscalpel.git", rev = "ff2d630"}
|
||||||
anyhow = "1.0.95"
|
anyhow = { version = "1.0.95", features = ["backtrace"] }
|
||||||
clap = { version = "4.5.27", features = ["derive"] }
|
clap = { version = "4.5.27", features = ["derive"] }
|
||||||
env_logger = "0.11.6"
|
env_logger = "0.11.6"
|
||||||
reqwest = { version = "0.12.12", default-features = false, features = ["blocking", "rustls-tls"] }
|
reqwest = { version = "0.12.12", default-features = false, features = ["blocking", "rustls-tls"] }
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ impl RegistersInfo {
|
||||||
from: reg_save,
|
from: reg_save,
|
||||||
to: i as u16,
|
to: i as u16,
|
||||||
});
|
});
|
||||||
}
|
} // else RegType::Undefined, do nothing, just use it
|
||||||
if regs_type[i + 1] == RegType::Object {
|
if regs_type[i + 1] == RegType::Object {
|
||||||
save_reg_insns.push(Instruction::MoveObject {
|
save_reg_insns.push(Instruction::MoveObject {
|
||||||
from: (i + 1) as u16,
|
from: (i + 1) as u16,
|
||||||
|
|
@ -284,7 +284,7 @@ impl RegistersInfo {
|
||||||
from: reg_save,
|
from: reg_save,
|
||||||
to: (i + 1) as u16,
|
to: (i + 1) as u16,
|
||||||
});
|
});
|
||||||
}
|
} // else RegType::Undefined, do nothing, just use it
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -336,7 +336,7 @@ impl RegistersInfo {
|
||||||
from: reg_save,
|
from: reg_save,
|
||||||
to: i as u16,
|
to: i as u16,
|
||||||
});
|
});
|
||||||
}
|
} // else RegType::Undefined, do nothing, just use it
|
||||||
if regs_type[i + 1] == RegType::Object {
|
if regs_type[i + 1] == RegType::Object {
|
||||||
save_reg_insns.push(Instruction::MoveObject {
|
save_reg_insns.push(Instruction::MoveObject {
|
||||||
from: (i + 1) as u16,
|
from: (i + 1) as u16,
|
||||||
|
|
@ -358,7 +358,7 @@ impl RegistersInfo {
|
||||||
from: reg_save,
|
from: reg_save,
|
||||||
to: (i + 1) as u16,
|
to: (i + 1) as u16,
|
||||||
});
|
});
|
||||||
}
|
} // else RegType::Undefined, do nothing, just use it
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -428,7 +428,7 @@ impl RegistersInfo {
|
||||||
from: reg_save,
|
from: reg_save,
|
||||||
to: i as u16,
|
to: i as u16,
|
||||||
});
|
});
|
||||||
}
|
} // else RegType::Undefined, do nothing, just use it
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -502,6 +502,7 @@ impl RegistersInfo {
|
||||||
used_reg.push(i as u16);
|
used_reg.push(i as u16);
|
||||||
if regs_type[i] == RegType::FirstWideScalar
|
if regs_type[i] == RegType::FirstWideScalar
|
||||||
|| regs_type[i] == RegType::SecondWideScalar
|
|| regs_type[i] == RegType::SecondWideScalar
|
||||||
|
|| regs_type[i] == RegType::SimpleScalar
|
||||||
{
|
{
|
||||||
save_reg_insns.push(Instruction::Move {
|
save_reg_insns.push(Instruction::Move {
|
||||||
from: i as u16,
|
from: i as u16,
|
||||||
|
|
@ -511,7 +512,7 @@ impl RegistersInfo {
|
||||||
from: reg_save,
|
from: reg_save,
|
||||||
to: i as u16,
|
to: i as u16,
|
||||||
});
|
});
|
||||||
}
|
} // else RegType::Undefined, do nothing, just use it
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -604,6 +605,22 @@ static OBJ_TO_SCAL_FLOAT: LazyLock<IdMethod> =
|
||||||
LazyLock::new(|| IdMethod::from_smali("Ljava/lang/Float;->floatValue()F").unwrap());
|
LazyLock::new(|| IdMethod::from_smali("Ljava/lang/Float;->floatValue()F").unwrap());
|
||||||
static OBJ_TO_SCAL_DOUBLE: LazyLock<IdMethod> =
|
static OBJ_TO_SCAL_DOUBLE: LazyLock<IdMethod> =
|
||||||
LazyLock::new(|| IdMethod::from_smali("Ljava/lang/Double;->doubleValue()D").unwrap());
|
LazyLock::new(|| IdMethod::from_smali("Ljava/lang/Double;->doubleValue()D").unwrap());
|
||||||
|
static OBJ_OF_SCAL_BOOL: LazyLock<IdType> =
|
||||||
|
LazyLock::new(|| IdType::from_smali("Ljava/lang/Boolean;").unwrap());
|
||||||
|
static OBJ_OF_SCAL_BYTE: LazyLock<IdType> =
|
||||||
|
LazyLock::new(|| IdType::from_smali("Ljava/lang/Byte;").unwrap());
|
||||||
|
static OBJ_OF_SCAL_SHORT: LazyLock<IdType> =
|
||||||
|
LazyLock::new(|| IdType::from_smali("Ljava/lang/Short;").unwrap());
|
||||||
|
static OBJ_OF_SCAL_CHAR: LazyLock<IdType> =
|
||||||
|
LazyLock::new(|| IdType::from_smali("Ljava/lang/Character;").unwrap());
|
||||||
|
static OBJ_OF_SCAL_INT: LazyLock<IdType> =
|
||||||
|
LazyLock::new(|| IdType::from_smali("Ljava/lang/Integer;").unwrap());
|
||||||
|
static OBJ_OF_SCAL_LONG: LazyLock<IdType> =
|
||||||
|
LazyLock::new(|| IdType::from_smali("Ljava/lang/Long;").unwrap());
|
||||||
|
static OBJ_OF_SCAL_FLOAT: LazyLock<IdType> =
|
||||||
|
LazyLock::new(|| IdType::from_smali("Ljava/lang/Float;").unwrap());
|
||||||
|
static OBJ_OF_SCAL_DOUBLE: LazyLock<IdType> =
|
||||||
|
LazyLock::new(|| IdType::from_smali("Ljava/lang/Double;").unwrap());
|
||||||
static SCAL_TO_OBJ_BOOL: LazyLock<IdMethod> = LazyLock::new(|| {
|
static SCAL_TO_OBJ_BOOL: LazyLock<IdMethod> = LazyLock::new(|| {
|
||||||
IdMethod::from_smali("Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;").unwrap()
|
IdMethod::from_smali("Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;").unwrap()
|
||||||
});
|
});
|
||||||
|
|
@ -640,7 +657,13 @@ pub fn labeling(_mth: &IdMethod, ins: &Instruction, addr: usize) -> Option<Strin
|
||||||
{
|
{
|
||||||
Some(format!("THESEUS_ADDR_{addr:08X}"))
|
Some(format!("THESEUS_ADDR_{addr:08X}"))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => {
|
||||||
|
if addr == 0 {
|
||||||
|
Some(format!("DEBUG_{addr:08X}"))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -682,9 +705,9 @@ pub fn transform_method(meth: &mut Method, ref_data: &ReflectionData) -> Result<
|
||||||
register_info.first_arg = code.registers_size + 4;
|
register_info.first_arg = code.registers_size + 4;
|
||||||
register_info.nb_arg_reg = 0;
|
register_info.nb_arg_reg = 0;
|
||||||
|
|
||||||
let regs_type = if register_info.array_val_save.is_none()
|
let regs_type = if register_info.array_val_save.is_some()
|
||||||
|| register_info.array_index_save.is_none()
|
|| register_info.array_index_save.is_some()
|
||||||
|| register_info.array_save.is_none()
|
|| register_info.array_save.is_some()
|
||||||
{
|
{
|
||||||
Some(meth.get_cfg()?.get_reg_types())
|
Some(meth.get_cfg()?.get_reg_types())
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -732,10 +755,32 @@ pub fn transform_method(meth: &mut Method, ref_data: &ReflectionData) -> Result<
|
||||||
}
|
}
|
||||||
match register_info.tmp_reserve_reg(&used_reg, regs_type) {
|
match register_info.tmp_reserve_reg(&used_reg, regs_type) {
|
||||||
Ok((mut save_insns, restore_insns)) => {
|
Ok((mut save_insns, restore_insns)) => {
|
||||||
|
new_insns
|
||||||
|
.append(&mut debug_info(&format!("Reg saved:\n{regs_type:?}")));
|
||||||
|
new_insns.append(&mut debug_info(&format!(
|
||||||
|
"Reg saved:\n{register_info:#?}"
|
||||||
|
)));
|
||||||
|
new_insns.append(&mut debug_info(&format!(
|
||||||
|
"save reg insns:\n{}",
|
||||||
|
save_insns
|
||||||
|
.iter()
|
||||||
|
.map(|i| " # ".to_string() + i.__str__().as_str())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
)));
|
||||||
|
new_insns.append(&mut debug_info(&format!(
|
||||||
|
"restore reg insns:\n{}",
|
||||||
|
restore_insns
|
||||||
|
.iter()
|
||||||
|
.map(|i| " # ".to_string() + i.__str__().as_str())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
)));
|
||||||
restore_reg = restore_insns;
|
restore_reg = restore_insns;
|
||||||
new_insns.append(&mut save_insns);
|
new_insns.append(&mut save_insns);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
new_insns.append(&mut debug_info(&format!("WTF?: {err}")));
|
||||||
warn!(
|
warn!(
|
||||||
"Failed to instrument reflection in {} at {}: {}",
|
"Failed to instrument reflection in {} at {}: {}",
|
||||||
method.__str__(),
|
method.__str__(),
|
||||||
|
|
@ -754,6 +799,11 @@ pub fn transform_method(meth: &mut Method, ref_data: &ReflectionData) -> Result<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
new_insns.append(&mut debug_info(&format!(
|
||||||
|
"regs_type is none: {regs_type:#?}"
|
||||||
|
)));
|
||||||
|
new_insns.append(&mut debug_info(&format!("Reg used:\n{register_info:#?}")));
|
||||||
}
|
}
|
||||||
// TODO: recover from failure
|
// TODO: recover from failure
|
||||||
if method == &*MTH_INVOKE {
|
if method == &*MTH_INVOKE {
|
||||||
|
|
@ -827,6 +877,14 @@ pub fn transform_method(meth: &mut Method, ref_data: &ReflectionData) -> Result<
|
||||||
code.insns = vec![];
|
code.insns = vec![];
|
||||||
// Start the method by moving the parameter to their registers pre-transformation.
|
// Start the method by moving the parameter to their registers pre-transformation.
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
if !meth.is_static {
|
||||||
|
// Non static method take 'this' as first argument
|
||||||
|
code.insns.push(Instruction::MoveObject {
|
||||||
|
from: code.registers_size - code.ins_size + i + register_info.get_nb_added_reg(),
|
||||||
|
to: code.registers_size - code.ins_size + i,
|
||||||
|
});
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
for arg in &meth.descriptor.proto.get_parameters() {
|
for arg in &meth.descriptor.proto.get_parameters() {
|
||||||
if arg.is_class() || arg.is_array() {
|
if arg.is_class() || arg.is_array() {
|
||||||
code.insns.push(Instruction::MoveObject {
|
code.insns.push(Instruction::MoveObject {
|
||||||
|
|
@ -1028,6 +1086,31 @@ pub fn get_obj_to_scalar_method(scalar_ty: &IdType) -> Result<IdMethod> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the object associated to a scalar (eg `java.lang.Integer` for `int`)
|
||||||
|
///
|
||||||
|
/// `scalar_ty` is the type of the scalar (eg `I`)
|
||||||
|
pub fn get_obj_of_scalar(scalar_ty: &IdType) -> Result<IdType> {
|
||||||
|
if scalar_ty == &IdType::boolean() {
|
||||||
|
Ok(OBJ_OF_SCAL_BOOL.clone())
|
||||||
|
} else if scalar_ty == &IdType::byte() {
|
||||||
|
Ok(OBJ_OF_SCAL_BYTE.clone())
|
||||||
|
} else if scalar_ty == &IdType::short() {
|
||||||
|
Ok(OBJ_OF_SCAL_SHORT.clone())
|
||||||
|
} else if scalar_ty == &IdType::char() {
|
||||||
|
Ok(OBJ_OF_SCAL_CHAR.clone())
|
||||||
|
} else if scalar_ty == &IdType::int() {
|
||||||
|
Ok(OBJ_OF_SCAL_INT.clone())
|
||||||
|
} else if scalar_ty == &IdType::long() {
|
||||||
|
Ok(OBJ_OF_SCAL_LONG.clone())
|
||||||
|
} else if scalar_ty == &IdType::float() {
|
||||||
|
Ok(OBJ_OF_SCAL_FLOAT.clone())
|
||||||
|
} else if scalar_ty == &IdType::double() {
|
||||||
|
Ok(OBJ_OF_SCAL_DOUBLE.clone())
|
||||||
|
} else {
|
||||||
|
bail!("{} is not a scalar", scalar_ty.__str__())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the method that convert a scalar to its object conterpart (eg `int` to `java.lang.Integer` with
|
/// Get the method that convert a scalar to its object conterpart (eg `int` to `java.lang.Integer` with
|
||||||
/// `Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;`)
|
/// `Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;`)
|
||||||
///
|
///
|
||||||
|
|
@ -1101,6 +1184,10 @@ fn get_args_from_obj_arr(
|
||||||
});
|
});
|
||||||
reg_count += 1;
|
reg_count += 1;
|
||||||
} else if param.is_double() || param.is_long() {
|
} else if param.is_double() || param.is_long() {
|
||||||
|
insns.push(Instruction::CheckCast {
|
||||||
|
reg: reg_inf.array_val,
|
||||||
|
lit: get_obj_of_scalar(param).unwrap(),
|
||||||
|
});
|
||||||
insns.push(Instruction::InvokeVirtual {
|
insns.push(Instruction::InvokeVirtual {
|
||||||
method: get_obj_to_scalar_method(param).unwrap(),
|
method: get_obj_to_scalar_method(param).unwrap(),
|
||||||
args: vec![reg_inf.array_val as u16],
|
args: vec![reg_inf.array_val as u16],
|
||||||
|
|
@ -1114,6 +1201,10 @@ fn get_args_from_obj_arr(
|
||||||
});
|
});
|
||||||
reg_count += 2;
|
reg_count += 2;
|
||||||
} else {
|
} else {
|
||||||
|
insns.push(Instruction::CheckCast {
|
||||||
|
reg: reg_inf.array_val,
|
||||||
|
lit: get_obj_of_scalar(param).unwrap(),
|
||||||
|
});
|
||||||
insns.push(Instruction::InvokeVirtual {
|
insns.push(Instruction::InvokeVirtual {
|
||||||
method: get_obj_to_scalar_method(param).unwrap(),
|
method: get_obj_to_scalar_method(param).unwrap(),
|
||||||
args: vec![reg_inf.array_val as u16],
|
args: vec![reg_inf.array_val as u16],
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
{"invoke_data": [{"method": "Lcom/example/theseus/reflection/Reflectee;->transfer(Ljava/lang/String;)Ljava/lang/String;", "caller_method": "Lcom/example/theseus/reflection/MainActivity;->callVirtualMethodReflectCall()V", "addr": 43}, {"method": "Lcom/example/theseus/reflection/Reflectee;->transfer(Ljava/lang/String;)Ljava/lang/String;", "caller_method": "Lcom/example/theseus/reflection/MainActivity;->callConstructorVirtualMethodReflectConstr()V", "addr": 56}, {"method": "Lcom/example/theseus/reflection/Reflectee;->transfer(Ljava/lang/String;)Ljava/lang/String;", "caller_method": "Lcom/example/theseus/reflection/MainActivity;->callVirtualMethodReflectOldConst()V", "addr": 40}, {"method": "Lcom/example/theseus/reflection/Reflectee;->transfer(ZBSCIJFDLjava/lang/String;)Ljava/lang/String;", "caller_method": "Lcom/example/theseus/reflection/MainActivity;->callVirtualMethodReflectCallAllScalar()V", "addr": 153}, {"method": "Lcom/example/theseus/reflection/Reflectee;->transfer(Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/String;", "caller_method": "Lcom/example/theseus/reflection/MainActivity;->callVirtualMethodReflectVarArg()V", "addr": 65}], "class_new_inst_data": [{"constructor": "Landroid/app/Application;-><init>()V", "caller_method": "Landroid/app/AppComponentFactory;->instantiateApplication(Ljava/lang/ClassLoader;Ljava/lang/String;)Landroid/app/Application;", "addr": 4}, {"constructor": "Lcom/example/theseus/reflection/MainActivity;-><init>()V", "caller_method": "Landroid/app/AppComponentFactory;->instantiateActivity(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Intent;)Landroid/app/Activity;", "addr": 4}, {"constructor": "Lcom/example/theseus/reflection/Reflectee;-><init>()V", "caller_method": "Lcom/example/theseus/reflection/MainActivity;->callVirtualMethodReflectOldConst()V", "addr": 18}], "cnstr_new_inst_data": [{"constructor": "Lcom/example/theseus/reflection/Reflectee;-><init>(Ljava/lang/String;)V", "caller_method": "Lcom/example/theseus/reflection/MainActivity;->callConstructorVirtualMethodReflectConstr()V", "addr": 34}]}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue