From 559ae665cf87efeb6d3bea609e089216caad69fd Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Thu, 31 Aug 2023 14:02:04 +0200 Subject: [PATCH] WIP --- androscalpel/src/apk.rs | 10 +++++- androscalpel/src/class.rs | 29 ++++++++++++++--- androscalpel/src/lib.rs | 27 +++++++++++++--- androscalpel_serializer/src/core/string.rs | 2 +- androscalpel_serializer/src/file_reader.rs | 36 ++++++++++++++++++++++ 5 files changed, 92 insertions(+), 12 deletions(-) diff --git a/androscalpel/src/apk.rs b/androscalpel/src/apk.rs index 188a598..dc30bf3 100644 --- a/androscalpel/src/apk.rs +++ b/androscalpel/src/apk.rs @@ -2,7 +2,7 @@ use pyo3::prelude::*; use crate::{Class, Result}; -use androscalpel_serializer::DexFileReader; +use androscalpel_serializer::{ClassDefItem, DexFileReader}; /// Represent an apk. #[pyclass] @@ -16,8 +16,16 @@ impl Apk { /// Add the content of a dex file to the apk. pub fn add_dex_file(&mut self, data: &[u8]) -> Result<()> { let dex = DexFileReader::new(data)?; + for class in dex.get_class_defs() { + self.add_class_from_dex_file(class, &dex)?; + } Ok(()) } + + /// Add a class from a dex file reader. + fn add_class_from_dex_file(&mut self, class: &ClassDefItem, dex: &DexFileReader) -> Result<()> { + todo!() + } } #[pymethods] diff --git a/androscalpel/src/class.rs b/androscalpel/src/class.rs index 88df7ad..80d1600 100644 --- a/androscalpel/src/class.rs +++ b/androscalpel/src/class.rs @@ -2,28 +2,47 @@ use pyo3::prelude::*; +use crate::DexString; + /// Represent an apk #[pyclass] #[derive(Debug, Clone)] pub struct Class { #[pyo3(get, set)] - pub name: String, + pub name: DexString, + #[pyo3(get, set)] + pub ty: DexString, + // pub access_flags: // TODO + #[pyo3(get, set)] + pub superclass: Option, + #[pyo3(get, set)] + pub interfaces: Vec, + #[pyo3(get, set)] + pub source_file: Option, + // pub annotations: Option<()> // TODO + // pub data: Option<()> // TODO + // pub static_values: Option<()> // TODO + // TODO: mix annotation data and static values to make it more practical } #[pymethods] impl Class { #[new] - pub fn new() -> Self { + pub fn new(name: DexString, ty: DexString) -> Self { Self { - name: "plop".into(), + name, + ty, + superclass: None, + interfaces: vec![], + source_file: None, } } - pub fn __str__(&self) -> String { + pub fn __str__(&self) -> DexString { self.name.clone() } - pub fn __repr__(&self) -> String { + pub fn __repr__(&self) -> DexString { self.name.clone() } } diff --git a/androscalpel/src/lib.rs b/androscalpel/src/lib.rs index 644c3f4..f47f1a2 100644 --- a/androscalpel/src/lib.rs +++ b/androscalpel/src/lib.rs @@ -52,21 +52,38 @@ impl std::error::Error for Error {} impl From for PyErr { fn from(error: Error) -> Self { match error { - Error::InputTooSmall(err) => PyValueError::new_err(format!("{err}")), - Error::SerializationError(err) => PyValueError::new_err(format!("{err}")), - Error::DeserializationError(err) => PyValueError::new_err(format!("{err}")), - Error::InvalidStringEncoding(err) => PyValueError::new_err(format!("{err}")), - Error::InconsistantStruct(err) => PyValueError::new_err(format!("{err}")), + Error::InputTooSmall(err) => PyValueError::new_err(err.to_string()), + Error::SerializationError(err) => PyValueError::new_err(err.to_string()), + Error::DeserializationError(err) => PyValueError::new_err(err.to_string()), + Error::InvalidStringEncoding(err) => PyValueError::new_err(err.to_string()), + Error::InconsistantStruct(err) => PyValueError::new_err(err.to_string()), } } } pub type Result = core::result::Result; +#[pyclass] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct DexString(androscalpel_serializer::StringDataItem); + +impl From for androscalpel_serializer::StringDataItem { + fn from(DexString(string): DexString) -> Self { + string + } +} + +impl From for DexString { + fn from(string: androscalpel_serializer::StringDataItem) -> Self { + Self(string) + } +} + /// Androscalpel. #[pymodule] fn androscalpel(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/androscalpel_serializer/src/core/string.rs b/androscalpel_serializer/src/core/string.rs index a506373..13e4008 100644 --- a/androscalpel_serializer/src/core/string.rs +++ b/androscalpel_serializer/src/core/string.rs @@ -17,7 +17,7 @@ use crate::core::*; pub use androscalpel_serializer_derive::*; /// -#[derive(Serializable, PartialEq, Eq, Debug)] +#[derive(Serializable, Clone, PartialEq, Eq, Debug)] pub struct StringDataItem { pub utf16_size: Uleb128, #[until(u8, u8, 0x00u8)] diff --git a/androscalpel_serializer/src/file_reader.rs b/androscalpel_serializer/src/file_reader.rs index fd11285..91d7357 100644 --- a/androscalpel_serializer/src/file_reader.rs +++ b/androscalpel_serializer/src/file_reader.rs @@ -90,6 +90,42 @@ impl<'a> DexFileReader<'a> { pub fn get_header(&self) -> &HeaderItem { &self.header } + /// Retunr the file [`StringIdItem`] list. + pub fn get_string_ids(&self) -> &[StringIdItem] { + &self.string_ids + } + /// Retunr the file [`TypeIdItem`] list. + pub fn get_type_ids(&self) -> &[TypeIdItem] { + &self.type_ids + } + /// Retunr the file [`ProtoIdItem`] list. + pub fn get_proto_ids(&self) -> &[ProtoIdItem] { + &self.proto_ids + } + /// Retunr the file [`FieldIdItem`] list. + pub fn get_field_ids(&self) -> &[FieldIdItem] { + &self.field_ids + } + /// Retunr the file [`MethodIdItem`] list. + pub fn get_method_ids(&self) -> &[MethodIdItem] { + &self.method_ids + } + /// Retunr the file [`ClassDefItem`] list. + pub fn get_class_defs(&self) -> &[ClassDefItem] { + &self.class_defs + } + /// Retunr the file [`CallSiteIdItem`] list. + pub fn get_call_site_ids(&self) -> &[CallSiteIdItem] { + &self.call_site_ids + } + /// Retunr the file [`MethodHandleItem`] list. + pub fn get_method_handles(&self) -> &[MethodHandleItem] { + &self.method_handles + } + /// Retunr the file [`MapList`]. + pub fn get_map_list(&self) -> &MapList { + &self.map_list + } fn sanity_check(&self) -> Result<()> { if self.header.magic.version != [0x30, 0x33, 0x39] {