add flags for fields

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2023-09-01 18:56:41 +02:00
parent c84e3e36cc
commit 68520d0c30
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
4 changed files with 88 additions and 10 deletions

View file

@ -2,7 +2,7 @@
use log::info; use log::info;
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::{Class, DexString, Field, Result}; use crate::{Class, DexString, Error, Field, FieldVisibility, Result};
use androscalpel_serializer::*; use androscalpel_serializer::*;
/// Represent an apk. /// Represent an apk.
@ -34,11 +34,11 @@ impl Apk {
.get_type_id(class_item.class_idx as usize)? .get_type_id(class_item.class_idx as usize)?
.descriptor_idx; .descriptor_idx;
let name: DexString = dex.get_string(name_idx)?.into(); let name: DexString = dex.get_string(name_idx)?.into();
let superclass = if class_item.class_idx == NO_INDEX.0 { let superclass = if class_item.superclass_idx == NO_INDEX.0 {
None None
} else { } else {
let superclass_idx = dex let superclass_idx = dex
.get_type_id(class_item.class_idx as usize)? .get_type_id(class_item.superclass_idx as usize)?
.descriptor_idx; .descriptor_idx;
Some(dex.get_string(superclass_idx)?.into()) Some(dex.get_string(superclass_idx)?.into())
}; };
@ -116,13 +116,49 @@ impl Apk {
let mut fields = vec![]; let mut fields = vec![];
for field in encoded_fields { for field in encoded_fields {
idx += field.field_idx_diff.0; idx += field.field_idx_diff.0;
// TODO: flags
let id_item = dex.get_field_id(idx as usize)?; let id_item = dex.get_field_id(idx as usize)?;
// Check class_idx == class? ¯\_(ツ)/¯ // Check class_idx == class? ¯\_(ツ)/¯ at list 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();
let ty = dex.get_type_id(id_item.type_idx as usize)?; let ty = dex.get_type_id(id_item.type_idx as usize)?;
let ty = dex.get_string(ty.descriptor_idx)?.into(); let ty = dex.get_string(ty.descriptor_idx)?.into();
let name = dex.get_string(id_item.name_idx)?.into(); let name: DexString = dex.get_string(id_item.name_idx)?.into();
fields.push(Field { name, type_: ty })
let is_public = (field.access_flags.0 & ACC_PUBLIC) != 0;
let is_private = (field.access_flags.0 & ACC_PRIVATE) != 0;
let is_protected = (field.access_flags.0 & ACC_PROTECTED) != 0;
let is_static = (field.access_flags.0 & ACC_STATIC) != 0;
let is_final = (field.access_flags.0 & ACC_FINAL) != 0;
let is_volatile = (field.access_flags.0 & ACC_VOLATILE) != 0;
let is_transient = (field.access_flags.0 & ACC_TRANSIENT) != 0;
let is_synthetic = (field.access_flags.0 & ACC_SYNTHETIC) != 0;
let is_enum = (field.access_flags.0 & ACC_ENUM) != 0;
let visibility = match (is_public, is_private, is_protected) {
(true, false, false) => FieldVisibility::Public,
(false, true, false) => FieldVisibility::Private,
(false, false, true) => FieldVisibility::Protected,
(false, false, false) => FieldVisibility::None_,
(pbl, prv, prt) => {
let name: String = name.into();
return Err(Error::InconsistantStruct(format!(
"Inconsistant visiblity found in {class}.{name}: \
(public: {pbl}, private: {prv}, protected: {prt})"
)));
}
};
fields.push(Field {
name,
type_: ty,
visibility,
is_static,
is_final,
is_volatile,
is_transient,
is_synthetic,
is_enum,
})
} }
Ok(fields) Ok(fields)
} }

View file

@ -69,7 +69,7 @@ impl Class {
pub fn new(name: DexString) -> Self { pub fn new(name: DexString) -> Self {
Self { Self {
name, name,
superclass: None, superclass: Some("Ljava/lang/Object;".into()),
interfaces: vec![], interfaces: vec![],
source_file: None, source_file: None,
is_public: true, is_public: true,

View file

@ -15,13 +15,54 @@ pub struct Field {
/// The type of the field, format described at <> /// The type of the field, format described at <>
#[pyo3(get, set)] #[pyo3(get, set)]
pub type_: DexString, pub type_: DexString,
/// The field visibility
#[pyo3(get, set)]
pub visibility: FieldVisibility,
/// If the field is defined for the class globally
#[pyo3(get, set)]
pub is_static: bool,
/// If the field is immutable after construction
#[pyo3(get, set)]
pub is_final: bool,
/// For thread safety
#[pyo3(get, set)]
pub is_volatile: bool,
/// If the field should **not** be saved by default serialization
#[pyo3(get, set)]
pub is_transient: bool,
/// If the field is not defined in the source code
#[pyo3(get, set)]
pub is_synthetic: bool,
/// If the field is an enumerated value
#[pyo3(get, set)]
pub is_enum: bool,
}
/// Represent the visibility of a field
#[pyclass]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FieldVisibility {
Public,
Private,
Protected,
None_, // Actually quite common
} }
#[pymethods] #[pymethods]
impl Field { impl Field {
#[new] #[new]
pub fn new(name: DexString, type_: DexString) -> Self { pub fn new(name: DexString, type_: DexString) -> Self {
Self { name, type_ } Self {
name,
type_,
visibility: FieldVisibility::Public,
is_static: false,
is_final: false,
is_volatile: false,
is_transient: false,
is_synthetic: false,
is_enum: false,
}
} }
pub fn __str__(&self) -> String { pub fn __str__(&self) -> String {

View file

@ -148,8 +148,9 @@ 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::<DexString>()?;
m.add_class::<FieldVisibility>()?;
m.add_class::<Class>()?; m.add_class::<Class>()?;
m.add_class::<Apk>()?; m.add_class::<Apk>()?;
m.add_class::<DexString>()?;
Ok(()) Ok(())
} }