add first draft of field value

This commit is contained in:
Jean-Marie Mineau 2023-09-04 14:52:15 +02:00
parent 68520d0c30
commit c81a72ae36
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
3 changed files with 566 additions and 1 deletions

View file

@ -90,6 +90,26 @@ impl Apk {
static_fields = self.get_field_list_from_dex(&data.static_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)?; instance_fields = self.get_field_list_from_dex(&data.instance_fields, dex)?;
} }
/*
if class_item.static_values_off != 0 {
let values = dex
.get_struct_at_offset::<EncodedArray>(class_item.static_values_off)?
.values;
if values.len() > static_fields.len() {
return Err(Error::InconsistantStruct(format!(
"Inconsistant static_values array found in {}: \
|static_values| = {}, |static_fields| = {}, \
|static_values| should be <= |static_fields|",
<&DexString as Into<String>>::into(&name),
values.len(),
static_fields.len()
)));
}
//for (i, value) in values.iter().enumerate() {}
for field in static_fields.iter_mut().skip(values.len()) {
field.value = None;
}
}*/
Ok(Class { Ok(Class {
name, name,
superclass, superclass,
@ -118,7 +138,7 @@ impl Apk {
idx += field.field_idx_diff.0; idx += field.field_idx_diff.0;
let id_item = dex.get_field_id(idx as usize)?; let id_item = dex.get_field_id(idx as usize)?;
// Check class_idx == class? ¯\_(ツ)/¯ at list it usefull for debug // Check class_idx == class? ¯\_(ツ)/¯ at least it usefull for debug
let class_ty = dex.get_type_id(id_item.class_idx as usize)?; let class_ty = dex.get_type_id(id_item.class_idx as usize)?;
let class: DexString = dex.get_string(class_ty.descriptor_idx)?.into(); let class: DexString = dex.get_string(class_ty.descriptor_idx)?.into();
let class: String = class.into(); let class: String = class.into();
@ -158,6 +178,7 @@ impl Apk {
is_transient, is_transient,
is_synthetic, is_synthetic,
is_enum, is_enum,
value: None,
}) })
} }
Ok(fields) Ok(fields)

View file

@ -1,5 +1,6 @@
//! Representation of the fields of a class. //! Representation of the fields of a class.
use pyo3::exceptions::PyTypeError;
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::DexString; use crate::DexString;
@ -36,6 +37,8 @@ pub struct Field {
/// If the field is an enumerated value /// If the field is an enumerated value
#[pyo3(get, set)] #[pyo3(get, set)]
pub is_enum: bool, pub is_enum: bool,
/// The default value of this field
pub value: Option<DexValue>,
} }
/// Represent the visibility of a field /// Represent the visibility of a field
@ -62,6 +65,7 @@ impl Field {
is_transient: false, is_transient: false,
is_synthetic: false, is_synthetic: false,
is_enum: false, is_enum: false,
value: None,
} }
} }
@ -101,4 +105,526 @@ impl Field {
let ty: String = (&self.type_).into(); let ty: String = (&self.type_).into();
format!("Field({name}, {ty})") format!("Field({name}, {ty})")
} }
/// Return the value as a python object
#[getter]
pub fn get_value(&self) -> Option<DexValue> {
self.value.clone()
}
/// Set the value from a python object
#[setter]
pub fn set_value(&mut self, ob: &PyAny) -> PyResult<()> {
self.value = Some(ob.extract()?);
// TODO: check type match
Ok(())
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexByte(pub i8);
#[pymethods]
impl DexByte {
#[new]
pub fn new(val: i8) -> Self {
Self(val)
}
pub fn get_value(&self) -> i8 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexByte({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexShort(pub i16);
#[pymethods]
impl DexShort {
#[new]
pub fn new(val: i16) -> Self {
Self(val)
}
pub fn get_value(&self) -> i16 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexShort({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexChar(pub u16);
#[pymethods]
impl DexChar {
#[new]
pub fn new(val: u16) -> Self {
Self(val)
}
pub fn get_value(&self) -> u16 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexChar({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexInt(pub i32);
#[pymethods]
impl DexInt {
#[new]
pub fn new(val: i32) -> Self {
Self(val)
}
pub fn get_value(&self) -> i32 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexInt({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexLong(pub i64);
#[pymethods]
impl DexLong {
#[new]
pub fn new(val: i64) -> Self {
Self(val)
}
pub fn get_value(&self) -> i64 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexLong({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy)]
pub struct DexFloat(pub f32);
#[pymethods]
impl DexFloat {
#[new]
pub fn new(val: f32) -> Self {
Self(val)
}
pub fn get_value(&self) -> f32 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexFloat({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy)]
pub struct DexDouble(pub f64);
#[pymethods]
impl DexDouble {
#[new]
pub fn new(val: f64) -> Self {
Self(val)
}
pub fn get_value(&self) -> f64 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexDouble({})", self.0)
}
}
/*
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexMethodType(pub u32);
#[pymethods]
impl DexMethodType {
#[new]
pub fn new(val: u32) -> Self {
Self(val)
}
pub fn get_value(&self) -> u32 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexMethodType({})", self.0)
}
}
*/
/*
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexMethodHandle(pub u32);
#[pymethods]
impl DexMethodHandle {
#[new]
pub fn new(val: u32) -> Self {
Self(val)
}
pub fn get_value(&self) -> u32 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexMethodHandle({})", self.0)
}
}
*/
/*
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexString(pub u32);
#[pymethods]
impl DexString {
#[new]
pub fn new(val: u32) -> Self {
Self(val)
}
pub fn get_value(&self) -> u32 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexString({})", self.0)
}
}
*/
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexType(pub u32);
#[pymethods]
impl DexType {
#[new]
pub fn new(val: u32) -> Self {
Self(val)
}
pub fn get_value(&self) -> u32 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexType({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexField(pub u32);
#[pymethods]
impl DexField {
#[new]
pub fn new(val: u32) -> Self {
Self(val)
}
pub fn get_value(&self) -> u32 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexField({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexMethod(pub u32);
#[pymethods]
impl DexMethod {
#[new]
pub fn new(val: u32) -> Self {
Self(val)
}
pub fn get_value(&self) -> u32 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexMethod({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexEnum(pub u32);
#[pymethods]
impl DexEnum {
#[new]
pub fn new(val: u32) -> Self {
Self(val)
}
pub fn get_value(&self) -> u32 {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexEnum({})", self.0)
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexArray;
#[pymethods]
impl DexArray {
#[new]
pub fn _new() -> Self {
Self
}
pub fn get_value(&self) {
todo!()
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
"DexArray".into()
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexAnnotation;
#[pymethods]
impl DexAnnotation {
#[new]
pub fn _new() -> Self {
Self
}
pub fn get_value(&self) {
todo!()
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
"DexAnnotation".into()
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexNull;
#[pymethods]
impl DexNull {
#[new]
pub fn _new() -> Self {
Self
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
"DexNull".into()
}
}
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DexBoolean(pub bool);
#[pymethods]
impl DexBoolean {
#[new]
pub fn new(val: bool) -> Self {
Self(val)
}
pub fn get_value(&self) -> bool {
self.0
}
pub fn __str__(&self) -> String {
self.__repr__()
}
pub fn __repr__(&self) -> String {
format!("DexBoolean({})", self.0)
}
}
#[derive(Debug, Clone)]
pub enum DexValue {
Byte(DexByte),
Short(DexShort),
Char(DexChar),
Int(DexInt),
Long(DexLong),
Float(DexFloat),
Double(DexDouble),
//MethodType(DexMethodType),
//MethodHandle(DexMethodHandle),
String(DexString),
Type(DexType),
Field(DexField),
Method(DexMethod),
Enum(DexEnum),
Array(DexArray),
Annotation(DexAnnotation),
Null(DexNull),
Boolean(DexBoolean),
}
impl<'source> FromPyObject<'source> for DexValue {
fn extract(ob: &'source PyAny) -> PyResult<Self> {
if let Ok(val) = DexByte::extract(ob) {
Ok(Self::Byte(val))
} else if let Ok(val) = DexShort::extract(ob) {
Ok(Self::Short(val))
} else if let Ok(val) = DexChar::extract(ob) {
Ok(Self::Char(val))
} else if let Ok(val) = DexInt::extract(ob) {
Ok(Self::Int(val))
} else if let Ok(val) = DexLong::extract(ob) {
Ok(Self::Long(val))
} else if let Ok(val) = DexFloat::extract(ob) {
Ok(Self::Float(val))
} else if let Ok(val) = DexDouble::extract(ob) {
Ok(Self::Double(val))
} else if let Ok(val) = DexString::extract(ob) {
Ok(Self::String(val))
} else if let Ok(val) = DexType::extract(ob) {
Ok(Self::Type(val))
} else if let Ok(val) = DexField::extract(ob) {
Ok(Self::Field(val))
} else if let Ok(val) = DexMethod::extract(ob) {
Ok(Self::Method(val))
} else if let Ok(val) = DexEnum::extract(ob) {
Ok(Self::Enum(val))
} else if let Ok(val) = DexArray::extract(ob) {
Ok(Self::Array(val))
} else if let Ok(val) = DexAnnotation::extract(ob) {
Ok(Self::Annotation(val))
} else if let Ok(val) = DexNull::extract(ob) {
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) = DexMethodHandle::extract(ob) { Ok(Self::MethodHandle(val))
} else {
Err(PyErr::new::<PyTypeError, _>(format!(
"{} is not a castable as a DexValue",
ob.repr()?
)))
}
}
}
impl IntoPy<PyObject> for DexValue {
fn into_py(self, py: Python<'_>) -> PyObject {
match self {
DexValue::Byte(val) => val.into_py(py),
DexValue::Short(val) => val.into_py(py),
DexValue::Char(val) => val.into_py(py),
DexValue::Int(val) => val.into_py(py),
DexValue::Long(val) => val.into_py(py),
DexValue::Float(val) => val.into_py(py),
DexValue::Double(val) => val.into_py(py),
//DexValue::MethodType(val) => val.into_py(py),
//DexValue::MethodHandle(val) => val.into_py(py),
DexValue::String(val) => val.into_py(py),
DexValue::Type(val) => val.into_py(py),
DexValue::Field(val) => val.into_py(py),
DexValue::Method(val) => val.into_py(py),
DexValue::Enum(val) => val.into_py(py),
DexValue::Array(val) => val.into_py(py),
DexValue::Annotation(val) => val.into_py(py),
DexValue::Null(val) => val.into_py(py),
DexValue::Boolean(val) => val.into_py(py),
}
}
} }

View file

@ -148,6 +148,24 @@ impl DexString {
#[pymodule] #[pymodule]
fn androscalpel(_py: Python, m: &PyModule) -> PyResult<()> { fn androscalpel(_py: Python, m: &PyModule) -> PyResult<()> {
pyo3_log::init(); pyo3_log::init();
m.add_class::<DexByte>()?;
m.add_class::<DexShort>()?;
m.add_class::<DexChar>()?;
m.add_class::<DexInt>()?;
m.add_class::<DexLong>()?;
m.add_class::<DexFloat>()?;
m.add_class::<DexDouble>()?;
// m.add_class::<DexMethodType>()?;
// m.add_class::<DexMethodHandle>()?;
m.add_class::<DexString>()?;
m.add_class::<DexType>()?;
m.add_class::<DexField>()?;
m.add_class::<DexMethod>()?;
m.add_class::<DexEnum>()?;
m.add_class::<DexArray>()?;
m.add_class::<DexAnnotation>()?;
m.add_class::<DexNull>()?;
m.add_class::<DexBoolean>()?;
m.add_class::<DexString>()?; m.add_class::<DexString>()?;
m.add_class::<FieldVisibility>()?; m.add_class::<FieldVisibility>()?;
m.add_class::<Class>()?; m.add_class::<Class>()?;