add first draft of field value
This commit is contained in:
parent
68520d0c30
commit
c81a72ae36
3 changed files with 566 additions and 1 deletions
|
|
@ -90,6 +90,26 @@ impl Apk {
|
|||
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 {
|
||||
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 {
|
||||
name,
|
||||
superclass,
|
||||
|
|
@ -118,7 +138,7 @@ impl Apk {
|
|||
idx += field.field_idx_diff.0;
|
||||
|
||||
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: DexString = dex.get_string(class_ty.descriptor_idx)?.into();
|
||||
let class: String = class.into();
|
||||
|
|
@ -158,6 +178,7 @@ impl Apk {
|
|||
is_transient,
|
||||
is_synthetic,
|
||||
is_enum,
|
||||
value: None,
|
||||
})
|
||||
}
|
||||
Ok(fields)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//! Representation of the fields of a class.
|
||||
|
||||
use pyo3::exceptions::PyTypeError;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::DexString;
|
||||
|
|
@ -36,6 +37,8 @@ pub struct Field {
|
|||
/// If the field is an enumerated value
|
||||
#[pyo3(get, set)]
|
||||
pub is_enum: bool,
|
||||
/// The default value of this field
|
||||
pub value: Option<DexValue>,
|
||||
}
|
||||
|
||||
/// Represent the visibility of a field
|
||||
|
|
@ -62,6 +65,7 @@ impl Field {
|
|||
is_transient: false,
|
||||
is_synthetic: false,
|
||||
is_enum: false,
|
||||
value: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,4 +105,526 @@ impl Field {
|
|||
let ty: String = (&self.type_).into();
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,24 @@ impl DexString {
|
|||
#[pymodule]
|
||||
fn androscalpel(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
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::<FieldVisibility>()?;
|
||||
m.add_class::<Class>()?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue