some work on DexType and DexMethodType
This commit is contained in:
parent
cc6ce1c625
commit
2ec3fe2c9d
4 changed files with 127 additions and 28 deletions
|
|
@ -2,9 +2,13 @@
|
|||
use log::info;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::{Class, DexString, Error, Field, FieldVisibility, Result};
|
||||
use crate::*;
|
||||
use androscalpel_serializer::*;
|
||||
|
||||
// Prioritize Results from this crate
|
||||
use crate::Error;
|
||||
use crate::Result;
|
||||
|
||||
/// Represent an apk.
|
||||
#[pyclass]
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -87,8 +91,8 @@ impl Apk {
|
|||
let data_off = class_item.class_data_off;
|
||||
if data_off != 0 {
|
||||
let data = dex.get_struct_at_offset::<ClassDataItem>(data_off)?;
|
||||
static_fields = self.get_field_list_from_dex(&data.static_fields, dex)?;
|
||||
instance_fields = self.get_field_list_from_dex(&data.instance_fields, dex)?;
|
||||
static_fields = Self::get_field_list_from_dex(&data.static_fields, dex)?;
|
||||
instance_fields = Self::get_field_list_from_dex(&data.instance_fields, dex)?;
|
||||
}
|
||||
|
||||
if class_item.static_values_off != 0 {
|
||||
|
|
@ -105,7 +109,9 @@ impl Apk {
|
|||
static_fields.len()
|
||||
)));
|
||||
}
|
||||
//for (i, value) in values.iter().enumerate() {}
|
||||
for (i, value) in values.iter().enumerate() {
|
||||
static_fields[i].value = Some(Self::encoded_value_to_dex_value(value, dex)?);
|
||||
}
|
||||
for field in static_fields.iter_mut().skip(values.len()) {
|
||||
field.value = None;
|
||||
}
|
||||
|
|
@ -127,8 +133,64 @@ impl Apk {
|
|||
})
|
||||
}
|
||||
|
||||
fn get_field_list_from_dex(
|
||||
&self,
|
||||
pub fn encoded_value_to_dex_value(
|
||||
encoded_value: &EncodedValue,
|
||||
dex: &DexFileReader,
|
||||
) -> Result<DexValue> {
|
||||
match encoded_value {
|
||||
EncodedValue::Byte(val) => Ok(DexValue::Byte(DexByte(*val))),
|
||||
EncodedValue::Short(val) => Ok(DexValue::Short(DexShort(*val))),
|
||||
EncodedValue::Char(val) => Ok(DexValue::Char(DexChar(*val))),
|
||||
EncodedValue::Int(val) => Ok(DexValue::Int(DexInt(*val))),
|
||||
EncodedValue::Long(val) => Ok(DexValue::Long(DexLong(*val))),
|
||||
EncodedValue::Float(val) => Ok(DexValue::Float(DexFloat(*val))),
|
||||
EncodedValue::Double(val) => Ok(DexValue::Double(DexDouble(*val))),
|
||||
EncodedValue::MethodType(val) => {
|
||||
let proto = dex.get_proto_id(*val as usize)?;
|
||||
let shorty: DexString = dex.get_string(proto.shorty_idx)?.into();
|
||||
let return_type: DexType = DexType(
|
||||
dex.get_string(
|
||||
dex.get_type_id(proto.return_type_idx as usize)?
|
||||
.descriptor_idx,
|
||||
)?
|
||||
.into(),
|
||||
);
|
||||
let parameters = if proto.parameters_off == 0 {
|
||||
vec![]
|
||||
} else {
|
||||
let type_list = dex.get_struct_at_offset::<TypeList>(proto.parameters_off)?;
|
||||
let mut parameters: Vec<DexType> = vec![];
|
||||
for ty in type_list.list {
|
||||
parameters.push(DexType(
|
||||
dex.get_string(dex.get_type_id(ty.type_idx as usize)?.descriptor_idx)?
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
parameters
|
||||
};
|
||||
Ok(DexValue::MethodType(DexMethodType {
|
||||
shorty,
|
||||
return_type,
|
||||
parameters,
|
||||
}))
|
||||
}
|
||||
EncodedValue::MethodHandle(_val) => todo!(), //Ok(DexValue::MethodHandle(DexMethodHandle(*val))),
|
||||
EncodedValue::String(val) => Ok(DexValue::String(dex.get_string(*val)?.into())),
|
||||
EncodedValue::Type(val) => Ok(DexValue::Type(DexType(
|
||||
dex.get_string(dex.get_type_id(*val as usize)?.descriptor_idx)?
|
||||
.into(),
|
||||
))),
|
||||
EncodedValue::Field(val) => Ok(DexValue::Field(DexField(*val))),
|
||||
EncodedValue::Method(val) => Ok(DexValue::Method(DexMethod(*val))),
|
||||
EncodedValue::Enum(val) => Ok(DexValue::Enum(DexEnum(*val))),
|
||||
EncodedValue::Array(_val) => todo!(), //Ok(DexValue::Array(DexArray(*val))),
|
||||
EncodedValue::Annotation(_val) => todo!(), //Ok(DexValue::Annotation(DexAnnotation(*val))),
|
||||
EncodedValue::Null => Ok(DexValue::Null(DexNull)),
|
||||
EncodedValue::Boolean(val) => Ok(DexValue::Boolean(DexBoolean(*val))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_field_list_from_dex(
|
||||
encoded_fields: &[EncodedField],
|
||||
dex: &DexFileReader,
|
||||
) -> Result<Vec<Field>> {
|
||||
|
|
|
|||
|
|
@ -282,19 +282,27 @@ impl DexDouble {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[pyclass]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct DexMethodType(pub u32);
|
||||
#[pymethods]
|
||||
impl DexMethodType {
|
||||
#[new]
|
||||
pub fn new(val: u32) -> Self {
|
||||
Self(val)
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct DexMethodType {
|
||||
/// Type formated as described by <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
||||
shorty: DexString,
|
||||
return_type: DexType,
|
||||
parameters: Vec<DexType>,
|
||||
}
|
||||
|
||||
pub fn get_value(&self) -> u32 {
|
||||
self.0
|
||||
#[pymethods]
|
||||
/// The type of a method. The shorty is formated as described in
|
||||
/// <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
||||
impl DexMethodType {
|
||||
#[new]
|
||||
pub fn new(return_type: DexType, parameters: Vec<DexType>) -> Self {
|
||||
// TODO: check format
|
||||
Self {
|
||||
shorty: Self::get_shorty(&return_type, ¶meters),
|
||||
return_type,
|
||||
parameters,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __str__(&self) -> String {
|
||||
|
|
@ -302,10 +310,16 @@ impl DexMethodType {
|
|||
}
|
||||
|
||||
pub fn __repr__(&self) -> String {
|
||||
format!("DexMethodType({})", self.0)
|
||||
let repr: String = (&self.shorty).into();
|
||||
format!("DexMethodType({repr})")
|
||||
}
|
||||
}
|
||||
|
||||
impl DexMethodType {
|
||||
pub fn get_shorty(return_type: &DexType, parameters: &[DexType]) -> DexString {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
#[pyclass]
|
||||
|
|
@ -357,26 +371,31 @@ impl DexString {
|
|||
}
|
||||
*/
|
||||
|
||||
/// A type.
|
||||
/// Type a represented by [`DexString`] that follow the TypeDescriptor format
|
||||
/// as described here <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||
#[pyclass]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct DexType(pub u32);
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct DexType(pub(crate) DexString);
|
||||
#[pymethods]
|
||||
impl DexType {
|
||||
#[new]
|
||||
pub fn new(val: u32) -> Self {
|
||||
Self(val)
|
||||
pub fn _new(ty: DexString) -> Self {
|
||||
// TODO: check format
|
||||
Self(ty)
|
||||
}
|
||||
|
||||
pub fn get_value(&self) -> u32 {
|
||||
pub fn get_name(&self) -> DexString {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn __str__(&self) -> String {
|
||||
self.__repr__()
|
||||
self.0.into()
|
||||
}
|
||||
|
||||
pub fn __repr__(&self) -> String {
|
||||
format!("DexType({})", self.0)
|
||||
let name: String = self.0.into();
|
||||
format!("DexType({name})")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -546,7 +565,7 @@ pub enum DexValue {
|
|||
Long(DexLong),
|
||||
Float(DexFloat),
|
||||
Double(DexDouble),
|
||||
//MethodType(DexMethodType),
|
||||
MethodType(DexMethodType),
|
||||
//MethodHandle(DexMethodHandle),
|
||||
String(DexString),
|
||||
Type(DexType),
|
||||
|
|
@ -593,7 +612,8 @@ impl<'source> FromPyObject<'source> for DexValue {
|
|||
Ok(Self::Null(val))
|
||||
} else if let Ok(val) = DexBoolean::extract(ob) {
|
||||
Ok(Self::Boolean(val))
|
||||
// } else if let Ok(val) = DexMethodType::extract(ob) { Ok(Self::MethodType(val))
|
||||
} else if let Ok(val) = DexMethodType::extract(ob) {
|
||||
Ok(Self::MethodType(val))
|
||||
// } else if let Ok(val) = DexMethodHandle::extract(ob) { Ok(Self::MethodHandle(val))
|
||||
} else {
|
||||
Err(PyErr::new::<PyTypeError, _>(format!(
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ impl<'a> DexFileReader<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Return a [`&TypeIdItem`] from its idx.
|
||||
/// Return a [`TypeIdItem`] reference from its idx.
|
||||
pub fn get_type_id(&self, idx: usize) -> Result<&TypeIdItem> {
|
||||
self.type_ids
|
||||
.get(idx)
|
||||
|
|
@ -154,7 +154,7 @@ impl<'a> DexFileReader<'a> {
|
|||
)))
|
||||
}
|
||||
|
||||
/// Return a [`&FieldIdItem`] from its idx.
|
||||
/// Return a [`FieldIdItem`] reference from its idx.
|
||||
pub fn get_field_id(&self, idx: usize) -> Result<&FieldIdItem> {
|
||||
self.field_ids
|
||||
.get(idx)
|
||||
|
|
@ -164,6 +164,16 @@ impl<'a> DexFileReader<'a> {
|
|||
)))
|
||||
}
|
||||
|
||||
/// Return a [`ProtoIdItem`] reference from its idx.
|
||||
pub fn get_proto_id(&self, idx: usize) -> Result<&ProtoIdItem> {
|
||||
self.proto_ids
|
||||
.get(idx)
|
||||
.ok_or(Error::InconsistantStruct(format!(
|
||||
"prototype idx {idx} is out of bound (|proto_ids|={})",
|
||||
self.proto_ids.len()
|
||||
)))
|
||||
}
|
||||
|
||||
fn sanity_check(&self) -> Result<()> {
|
||||
if self.header.magic.version != [0x30, 0x33, 0x39] {
|
||||
warn!(
|
||||
|
|
|
|||
|
|
@ -14,12 +14,19 @@ pub enum EncodedValue {
|
|||
Long(i64),
|
||||
Float(f32),
|
||||
Double(f64),
|
||||
/// Index of a [`crate::ProtoIdItem`] in `proto_ids`
|
||||
MethodType(u32),
|
||||
/// Index of a [`crate::MethodHandleItem`] in `method_handles`
|
||||
MethodHandle(u32),
|
||||
/// Index of a [`crate::StringIdItem`] in `string_ids`
|
||||
String(u32),
|
||||
/// Index of a [`crate::TypeIdItem`] in `type_ids`
|
||||
Type(u32),
|
||||
/// Index of a [`crate::FieldIdItem`] in `field_ids`
|
||||
Field(u32),
|
||||
/// Index of a [`crate::MethodIdItem`] in `method_ids`
|
||||
Method(u32),
|
||||
/// Index of a [`crate::FieldIdItem`] in `field_ids` representing an enum.
|
||||
Enum(u32),
|
||||
Array(EncodedArray),
|
||||
Annotation(EncodedAnnotation),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue