This commit is contained in:
Jean-Marie 'Histausse' Mineau 2024-02-15 23:13:26 +01:00
parent 3a7208f1b5
commit cd6c638080
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
3 changed files with 48 additions and 115 deletions

88
TODO.md
View file

@ -1,92 +1,8 @@
- generate .dex
- edditable code format
- json serialize with serde
- sanity checks
- tests
- https://source.android.com/docs/core/runtime/dex-format#system-annotation
-
- Caused by: java.lang.VerifyError: Verifier rejected class androidx.appcompat.app.AppCompatViewInflater: android.view.View androidx.appcompat.app.AppCompatViewInflater.createView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet, boolean, boolean, boolean, boolean): [0xFFFFFFFF] unaligned switch table: at 32, switch offset 319 (declaration of 'androidx.appcompat.app.AppCompatViewInflater' appears in /data/app/~~P3In-lzdBi-g5oUouTDKsA==/com.example.testapplication-rXxXwHN5Yo2wxHAcnkq7iw==/base.apk
```
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::hash::Hash;
pub mod vectorize {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::iter::FromIterator;
pub fn serialize<'a, T, K, V, S>(target: T, ser: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: IntoIterator<Item = (&'a K, &'a V)>,
K: Serialize + 'a,
V: Serialize + 'a,
{
let container: Vec<_> = target.into_iter().collect();
serde::Serialize::serialize(&container, ser)
}
pub fn deserialize<'de, T, K, V, D>(des: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: FromIterator<(K, V)>,
K: Deserialize<'de>,
V: Deserialize<'de>,
{
let container: Vec<_> = serde::Deserialize::deserialize(des)?;
Ok(T::from_iter(container.into_iter()))
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
struct KeyItem {
name: String,
len: u32,
}
impl KeyItem {
fn new(s: &str) -> Self {
Self {
name: s.into(),
len: s.len() as u32,
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
enum ValueItem {
String1(String),
String2(String),
Int(u32),
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
struct ToSerialize {
#[serde(with = "vectorize")]
map1: HashMap<KeyItem, ValueItem>,
#[serde(with = "vectorize")]
map2: HashMap<KeyItem, ValueItem>,
}
fn main() {
let value = ToSerialize {
map1: HashMap::from([
(KeyItem::new("plop"), ValueItem::String1("Plop".into())),
(KeyItem::new("plip"), ValueItem::String2("Plip".into())),
(KeyItem::new("lop"), ValueItem::Int(109)),
]),
map2: HashMap::from([(
KeyItem::new("run"),
ValueItem::String1("Demons run when a good man goes to war".into()),
)]),
};
let serialized = serde_json::to_string(&value).unwrap();
println!("{serialized}");
assert_eq!(
serde_json::from_str::<ToSerialize>(&serialized).unwrap(),
value
);
}
```
`cargo add serde -F derive && cargo add serde_json`

View file

@ -721,6 +721,22 @@ impl Apk {
let code = if code_off == 0 {
None
} else {
if descriptor
== IdMethod::from_smali(
"Landroidx/appcompat/app/AppCompatViewInflater;\
->createView(Landroid/view/View;Ljava/lang/String;\
Landroid/content/Context;Landroid/util/AttributeSet;\
ZZZZ)Landroid/view/View;",
)
.unwrap()
{
let code_item = dex.get_struct_at_offset::<CodeItem>(code_off)?;
let mut off = 0;
for ins in &code_item.insns {
println!("INS 0x{off:x}: {ins:x?}");
off += ins.size();
}
}
Some(Self::get_code_from_off(code_off, dex).with_context(|| {
format!("Failed to parse code of method {}", descriptor.__str__())
})?)

49
test.py
View file

@ -59,42 +59,43 @@ print(f"[+] New code of {method_id} ")
for i in code.insns:
print(f" {i}")
# # Strip class for debugging
# classes = list(
# filter(
# lambda x: x
# not in [
# Strip class for debugging
classes = list(
filter(
lambda x: x
not in [
# IdType("Lcom/example/testapplication/ui/home/HomeViewModel;"),
# IdType("Landroidx/navigation/NavDeepLink$Builder;"),
# IdType("Landroidx/constraintlayout/core/widgets/ConstraintWidget$1;"),
# IdType("Landroidx/appcompat/app/ActionBar;"),
# IdType("Landroidx/constraintlayout/core/state/WidgetFrame;"),
# ],
# apk.classes.keys(),
# )
# )
# # for cls in classes:
# # apk.remove_class(cls)
IdType("Landroidx/appcompat/app/AppCompatViewInflater;"),
],
apk.classes.keys(),
)
)
for cls in classes:
apk.remove_class(cls)
print("[+] Recompile")
dex_raw = apk.gen_raw_dex()
# new_apk = Apk()
# for dex in dex_raw:
# new_apk.add_dex_file(dex)
new_apk = Apk()
for dex in dex_raw:
new_apk.add_dex_file(dex)
print("[+] Repackage")
utils.replace_dex(
APK_NAME,
APK_NAME.parent / (APK_NAME.name.removesuffix(".apk") + "-instrumented.apk"),
dex_raw,
Path().parent / "my-release-key.jks",
zipalign=Path.home() / "Android" / "Sdk" / "build-tools" / "34.0.0" / "zipalign",
apksigner=Path.home() / "Android" / "Sdk" / "build-tools" / "34.0.0" / "apksigner",
)
# print("[+] Repackage")
#
# utils.replace_dex(
# APK_NAME,
# APK_NAME.parent / (APK_NAME.name.removesuffix(".apk") + "-instrumented.apk"),
# dex_raw,
# Path().parent / "my-release-key.jks",
# zipalign=Path.home() / "Android" / "Sdk" / "build-tools" / "34.0.0" / "zipalign",
# apksigner=Path.home() / "Android" / "Sdk" / "build-tools" / "34.0.0" / "apksigner",
# )
last_id = None