remove class now return the class

This commit is contained in:
Jean-Marie Mineau 2025-03-26 16:23:05 +01:00
parent e34415857d
commit 5c91adfe93
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
3 changed files with 60 additions and 17 deletions

8
patcher/Cargo.lock generated
View file

@ -35,7 +35,7 @@ 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=4c4940e6b1e1760617d2cb86f83a27a7a8e187da#4c4940e6b1e1760617d2cb86f83a27a7a8e187da" source = "git+ssh://git@git.mineau.eu/histausse/androscalpel.git?rev=5379c29#5379c29eb881bb2fbed9703206f01f4a9ec73ca3"
dependencies = [ dependencies = [
"adler", "adler",
"androscalpel_serializer", "androscalpel_serializer",
@ -51,7 +51,7 @@ 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=4c4940e6b1e1760617d2cb86f83a27a7a8e187da#4c4940e6b1e1760617d2cb86f83a27a7a8e187da" source = "git+ssh://git@git.mineau.eu/histausse/androscalpel.git?rev=5379c29#5379c29eb881bb2fbed9703206f01f4a9ec73ca3"
dependencies = [ dependencies = [
"androscalpel_serializer_derive", "androscalpel_serializer_derive",
"log", "log",
@ -60,7 +60,7 @@ 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=4c4940e6b1e1760617d2cb86f83a27a7a8e187da#4c4940e6b1e1760617d2cb86f83a27a7a8e187da" source = "git+ssh://git@git.mineau.eu/histausse/androscalpel.git?rev=5379c29#5379c29eb881bb2fbed9703206f01f4a9ec73ca3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -129,7 +129,7 @@ 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=4c4940e6b1e1760617d2cb86f83a27a7a8e187da#4c4940e6b1e1760617d2cb86f83a27a7a8e187da" source = "git+ssh://git@git.mineau.eu/histausse/androscalpel.git?rev=5379c29#5379c29eb881bb2fbed9703206f01f4a9ec73ca3"
dependencies = [ dependencies = [
"androscalpel_serializer", "androscalpel_serializer",
"flate2", "flate2",

View file

@ -6,8 +6,8 @@ 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 = "4c4940e6b1e1760617d2cb86f83a27a7a8e187da", features = ["code-analysis"] } androscalpel = { git = "ssh://git@git.mineau.eu/histausse/androscalpel.git", rev = "5379c29", features = ["code-analysis"] }
apk_frauder = { git = "ssh://git@git.mineau.eu/histausse/androscalpel.git", rev = "4c4940e6b1e1760617d2cb86f83a27a7a8e187da"} apk_frauder = { git = "ssh://git@git.mineau.eu/histausse/androscalpel.git", rev = "5379c29"}
anyhow = { version = "1.0.95", features = ["backtrace"] } 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"

View file

@ -1,8 +1,8 @@
use std::collections::{HashMap, HashSet}; use std::collections::HashMap;
use std::fs::File; use std::fs::File;
use androscalpel::{Apk, IdType}; use androscalpel::{Apk, DexString, IdType, VisitableMut, VisitorMut};
use anyhow::Result; use anyhow::{Context, Result};
use clap::ValueEnum; use clap::ValueEnum;
use crate::runtime_data::RuntimeData; use crate::runtime_data::RuntimeData;
@ -47,7 +47,7 @@ fn insert_code_model_class_loaders(apk: &mut Apk, data: &RuntimeData) -> Result<
parent: None, parent: None,
class: IdType::from_smali("Ljava/lang/Boolean;").unwrap(), class: IdType::from_smali("Ljava/lang/Boolean;").unwrap(),
apk: ApkOrRef::Ref(apk), apk: ApkOrRef::Ref(apk),
renamed_classes: HashSet::new(), renamed_classes: HashMap::new(),
}, },
); );
for dyn_data in &data.dyn_code_load { for dyn_data in &data.dyn_code_load {
@ -66,7 +66,7 @@ fn insert_code_model_class_loaders(apk: &mut Apk, data: &RuntimeData) -> Result<
parent: None, parent: None,
class, class,
apk: ApkOrRef::Owned(apk), apk: ApkOrRef::Owned(apk),
renamed_classes: HashSet::new(), renamed_classes: HashMap::new(),
}; };
let collisions = class_defined.intersection(&classes); let collisions = class_defined.intersection(&classes);
for cls in collisions { for cls in collisions {
@ -90,25 +90,68 @@ struct ClassLoader<'a> {
pub parent: Option<String>, pub parent: Option<String>,
pub class: IdType, pub class: IdType,
pub apk: ApkOrRef<'a>, pub apk: ApkOrRef<'a>,
pub renamed_classes: HashSet<IdType>, pub renamed_classes: HashMap<IdType, IdType>,
} }
impl ClassLoader<'_> { impl ClassLoader<'_> {
pub fn _apk(&mut self) -> &mut Apk { pub fn apk(&mut self) -> &mut Apk {
match &mut self.apk { match &mut self.apk {
ApkOrRef::Owned(ref mut apk) => apk, ApkOrRef::Owned(ref mut apk) => apk,
ApkOrRef::Ref(ref mut apk) => apk, ApkOrRef::Ref(ref mut apk) => apk,
} }
} }
pub fn rename_classdef(&mut self, cls: &IdType) { pub fn rename_classdef(&mut self, cls: &IdType) -> Result<()> {
use androscalpel::SmaliName; use androscalpel::SmaliName;
let id = self.id.clone();
let mut i = 0;
let name = if let Some(name) = cls.get_class_name() {
name
} else {
log::warn!("Tried to rename non class type {}", cls.__str__());
return Ok(());
};
let new_name = loop {
let prefix: DexString = if i == 0 {
format!("theseus-dedup/{}/", self.id).into()
} else {
format!("theseus-dedup/{}-{i}/", self.id).into()
};
let new_name = IdType::class_from_dex_string(&prefix.concatenate(&name));
if self.apk().get_class(&new_name).is_none() {
break new_name;
}
i += 1;
};
println!( println!(
"TODO: rename {} -> {}_{}", "TODO: rename {} -> {}",
cls.try_to_smali().unwrap(), cls.try_to_smali().unwrap(),
cls.try_to_smali().unwrap(), new_name.try_to_smali().unwrap(),
self.id
); );
let class = self.apk().remove_class(cls, None).with_context(|| {
format!(
"Try to rename classdef of {} in class loader {}, but classdef not found",
cls.__str__(),
&id
)
})?;
self.renamed_classes.insert(cls.clone(), new_name);
Ok(())
}
}
struct RenameTypeVisitor {
pub new_names: HashMap<IdType, IdType>,
}
impl VisitorMut for RenameTypeVisitor {
fn visit_type(&mut self, id: IdType) -> Result<IdType> {
match self.new_names.get(&id) {
Some(newid) => Ok(newid.clone()),
None => Ok(id.clone()),
}
} }
} }