add repackaging to utils

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2024-02-01 23:37:26 +01:00
parent cb34f76063
commit 2cf3963532
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
5 changed files with 52 additions and 8 deletions

4
.gitignore vendored
View file

@ -3,3 +3,7 @@
/venv_test
/test.apk
/androguard_test.py
*.apk
*.dex
*.idsig
*.jks

1
Cargo.lock generated
View file

@ -24,6 +24,7 @@ dependencies = [
"adler",
"androscalpel_serializer",
"anyhow",
"apk_frauder",
"log",
"pyo3 0.20.0",
"pyo3-log",

View file

@ -12,6 +12,7 @@ crate-type = ["cdylib"]
adler = "1.0.2"
androscalpel_serializer = { version = "0.1.0", path = "../androscalpel_serializer" }
anyhow = { version = "1.0.75", features = ["backtrace"] }
apk_frauder = { version = "0.1.0", path = "../apk_frauder" }
log = "0.4.20"
pyo3 = { version = "0.20.0", features = ["anyhow"] }
pyo3-log = "0.8.3"

View file

@ -3,6 +3,9 @@
use pyo3::prelude::*;
use pyo3::types::PyBytes;
use std::io::Cursor;
use std::path::PathBuf;
use crate::Result;
use androscalpel_serializer::{Serializable, Sleb128, Uleb128, Uleb128p1};
@ -41,6 +44,27 @@ pub fn sleb128_to_int(b: &[u8]) -> Result<i32> {
Ok(Sleb128::deserialize_from_slice(b)?.0)
}
/// Replace the dex files a an apk an resigned the apk.
///
/// # Warning
///
/// For now, only jks keystore are allowed.
///
/// The `zipalign` and `apksigner` args allow to use a specific version of the
/// tools instead of the one in the PATH (if it even exist)
#[pyfunction]
pub fn replace_dex(
apk: PathBuf,
dst: PathBuf,
dexfiles: Vec<&[u8]>,
keystore: PathBuf,
zipalign: Option<PathBuf>,
apksigner: Option<PathBuf>,
) {
let mut dexfiles: Vec<_> = dexfiles.iter().map(Cursor::new).collect();
apk_frauder::replace_dex(apk, dst, &mut dexfiles, keystore, zipalign, apksigner)
}
/// export the function in a python module
pub(crate) fn export_module(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(int_to_uleb128, m)?)?;
@ -49,5 +73,6 @@ pub(crate) fn export_module(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(uleb128_to_int, m)?)?;
m.add_function(wrap_pyfunction!(uleb128p1_to_int, m)?)?;
m.add_function(wrap_pyfunction!(sleb128_to_int, m)?)?;
m.add_function(wrap_pyfunction!(replace_dex, m)?)?;
Ok(())
}

29
test.py
View file

@ -8,9 +8,10 @@ import json
import androscalpel as asc
import zipfile as z
from androscalpel import *
from pathlib import Path
# APK_NAME = "test.apk"
APK_NAME = __file__.removesuffix("test.py") + "/apk_frauder/app-release.apk"
# APK_NAME = Path(__file__).parent / "test.apk"
APK_NAME = Path(__file__).parent / "app-release.apk"
DEX_NAME = "classes.dex"
with z.ZipFile(APK_NAME) as zipf:
@ -74,15 +75,27 @@ for i in code.insns:
print("[+] Recompile")
dex_raw = apk.gen_raw_dex()
assert len(dex_raw) == 1
with open(DEX_NAME, "wb") as file:
file.write(dex_raw[0])
utils.replace_dex(
APK_NAME,
APK_NAME.parent / "app-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",
)
# assert len(dex_raw) == 1
# with open(DEX_NAME, "wb") as file:
# file.write(dex_raw[0])
#
# with open(DEX_NAME, "rb") as file:
# dex = file.read()
print("[+] Load new dex")
with open(DEX_NAME, "rb") as file:
dex = file.read()
new_apk = asc.Apk()
new_apk.add_dex_file(dex)
for dex in dex_raw:
new_apk.add_dex_file(dex)
clazz = new_apk.classes[clazz_id]
method = clazz.virtual_methods[method_id]