build cfg

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2025-02-20 18:29:19 +01:00
parent 23d1f51591
commit f9e8362671
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
4 changed files with 287 additions and 0 deletions

View file

@ -0,0 +1,33 @@
use std::fs::File;
use std::path::PathBuf;
use androscalpel::{Apk, IdMethod};
use patcher::code_analysis::CFG;
use clap::Parser;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None, arg_required_else_help = true)]
struct Cli {
#[arg(short, long)]
apk: PathBuf,
#[arg(short, long)]
method: String,
}
fn main() {
env_logger::init();
let cli = Cli::parse();
let mut apk = Apk::load_apk(File::open(&cli.apk).unwrap(), |_, _, _| None, false).unwrap();
let mid = IdMethod::from_smali(&cli.method).unwrap();
let class = apk.get_class_mut(&mid.class_).unwrap();
let method = if let Some(method) = class.virtual_methods.get(&mid) {
method
} else {
class.direct_methods.get(&mid).unwrap()
};
let code = method.code.as_ref().unwrap();
let cfg = CFG::new(code.ins_size.into(), &mid.proto, &code.insns).unwrap();
print!("{}", cfg.to_dot(&mid.__str__()));
}

151
patcher/src/bin/main.rs Normal file
View file

@ -0,0 +1,151 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::{Cursor, Read};
use std::path::PathBuf;
use androscalpel::Apk;
use patcher::{
labeling,
transform_method,
ReflectionData, // ReflectionInvokeData, ReflectionClassNewInstData, ReflectionCnstrNewInstData,
};
use clap::Parser;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None, arg_required_else_help = true)]
struct Cli {
#[arg(short, long)]
out: PathBuf,
#[arg(short, long)]
keystore: PathBuf,
#[arg(short, long)]
zipalign: Option<PathBuf>,
#[arg(short, long)]
apksigner: Option<PathBuf>,
#[arg(short, long)]
path: PathBuf,
#[arg(short, long)]
reflection_data: PathBuf,
}
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.reflection_data)
.unwrap()
.read_to_string(&mut json)
.unwrap();
let reflection_data: ReflectionData = serde_json::from_str(&json).unwrap();
/*
let reflection_data = ReflectionData {
invoke_data: vec![
ReflectionInvokeData {
method: IdMethod::from_smali(
"Lcom/example/theseus/reflection/Reflectee;\
->transfer\
(Ljava/lang/String;)Ljava/lang/String;",
)
.unwrap(),
caller_method: IdMethod::from_smali(
"Lcom/example/theseus/reflection/MainActivity;\
->callVirtualMethodReflectCall()V",
)
.unwrap(),
addr: 0x2B,
},
ReflectionInvokeData {
method: IdMethod::from_smali(
"Lcom/example/theseus/reflection/Reflectee;\
->transfer(Ljava/lang/String;)Ljava/lang/String;",
)
.unwrap(),
caller_method: IdMethod::from_smali(
"Lcom/example/theseus/reflection/MainActivity;\
->callConstructorVirtualMethodReflectConstr()V",
)
.unwrap(),
addr: 0x38,
},
ReflectionInvokeData {
method: IdMethod::from_smali(
"Lcom/example/theseus/reflection/Reflectee;\
->transfer(Ljava/lang/String;)Ljava/lang/String;",
)
.unwrap(),
caller_method: IdMethod::from_smali(
"Lcom/example/theseus/reflection/MainActivity;\
->callVirtualMethodReflectOldConst()V",
)
.unwrap(),
addr: 0x28,
},
],
class_new_inst_data: vec![ReflectionClassNewInstData {
constructor: IdMethod::from_smali(
"Lcom/example/theseus/reflection/Reflectee;\
-><init>()V",
)
.unwrap(),
caller_method: IdMethod::from_smali(
"Lcom/example/theseus/reflection/MainActivity;\
->callVirtualMethodReflectOldConst()V",
)
.unwrap(),
addr: 0x12,
}],
cnstr_new_inst_data: vec![ReflectionCnstrNewInstData {
constructor: IdMethod::from_smali(
"Lcom/example/theseus/reflection/Reflectee;\
-><init>(Ljava/lang/String;)V",
)
.unwrap(),
caller_method: IdMethod::from_smali(
"Lcom/example/theseus/reflection/MainActivity;\
->callConstructorVirtualMethodReflectConstr()V",
)
.unwrap(),
addr: 0x22,
}],
};
println!("{}", serde_json::to_string(&reflection_data).unwrap());
*/
for method in reflection_data.get_method_referenced().iter() {
if let Some(class) = apk.get_class_mut(&method.class_) {
//println!("{:#?}", class.direct_methods.keys());
//println!("{:#?}", class.virtual_methods.keys());
let method = class.virtual_methods.get_mut(method).unwrap();
transform_method(method, &reflection_data).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.path,
cli.out,
&mut dex_files,
cli.keystore,
cli.zipalign,
cli.apksigner,
None::<HashMap<_, Option<Cursor<&[u8]>>>>,
);
}