diff --git a/androscalpel/src/apk.rs b/androscalpel/src/apk.rs index 588bf34..8f588de 100644 --- a/androscalpel/src/apk.rs +++ b/androscalpel/src/apk.rs @@ -92,7 +92,7 @@ impl Apk { Some(dex.get_struct_at_offset::(class_item.annotations_off)?) }; let mut annotations = vec![]; - if let Some(annotations_directory) = annotations_directory { + if let Some(annotations_directory) = &annotations_directory { if annotations_directory.class_annotations_off != 0 { annotations = Self::get_annotation_items_from_annotation_set_off( annotations_directory.class_annotations_off, @@ -137,6 +137,134 @@ impl Apk { field.value = None; } } + if let Some(annotations_directory) = annotations_directory { + for field_annotation in annotations_directory.field_annotations { + let field_id = + Self::get_id_field_from_idx(field_annotation.field_idx as usize, dex)?; + let annotations = if field_annotation.annotations_off != 0 { + Self::get_annotation_items_from_annotation_set_off( + field_annotation.annotations_off, + dex, + )? + } else { + vec![] + }; + if field_id.class_.get_name() != name { + info!( + "Annotation for field {} found in class {}, dropping it", + field_id.__str__(), + name.__str__(), + ); + } + let mut found = false; + for field in &mut instance_fields { + if field.descriptor == field_id { + field.annotations.append(&mut (annotations.clone())); // the clone is prob + // unnecessary + found = true; + } + } + for field in &mut static_fields { + if field.descriptor == field_id { + field.annotations.append(&mut (annotations.clone())); // the clone is prob + // unnecessary + found = true; + } + } + if !found { + info!( + "Annotation found for field {} but could not find the field definition, dropping it", + field_id.__str__(), + ); + } + } + for method_annotation in annotations_directory.method_annotations { + let method_id = + Self::get_id_method_from_idx(method_annotation.method_idx as usize, dex)?; + let annotations = if method_annotation.annotations_off != 0 { + Self::get_annotation_items_from_annotation_set_off( + method_annotation.annotations_off, + dex, + )? + } else { + vec![] + }; + if method_id.class_.get_name() != name { + info!( + "Annotation for method {} found in class {}, dropping it", + method_id.__str__(), + name.__str__(), + ); + } + let mut found = false; + for method in &mut direct_methods { + if method.descriptor == method_id { + method.annotations.append(&mut (annotations.clone())); // the clone is prob + // unnecessary + found = true; + } + } + for method in &mut virtual_methods { + if method.descriptor == method_id { + method.annotations.append(&mut (annotations.clone())); // the clone is prob + // unnecessary + found = true; + } + } + if !found { + info!( + "Annotation found for method {} but could not find the method definition, dropping it", + method_id.__str__(), + ); + } + } + for parameter_annotation in annotations_directory.parameter_annotations { + let method_id = + Self::get_id_method_from_idx(parameter_annotation.method_idx as usize, dex)?; + let annotation_set_ref_list = dex.get_struct_at_offset::( + parameter_annotation.annotations_off, + )?; + let mut annotations_list = vec![]; + for annotation_set in annotation_set_ref_list.list { + if annotation_set.annotations_off != 0 { + annotations_list.push(Self::get_annotation_items_from_annotation_set_off( + annotation_set.annotations_off, + dex, + )?); + } else { + annotations_list.push(vec![]); + } + } + if method_id.class_.get_name() != name { + info!( + "Annotation for parameter of method {} found in class {}, dropping it", + method_id.__str__(), + name.__str__(), + ); + } + let mut found = false; + for method in &mut direct_methods { + if method.descriptor == method_id { + method.parameters_annotations = annotations_list.clone(); // the clone is prob + // unnecessary + found = true; + } + } + for method in &mut virtual_methods { + if method.descriptor == method_id { + method.parameters_annotations = annotations_list.clone(); // the clone is prob + // unnecessary + found = true; + } + } + if !found { + info!( + "Annotation found for parameter of method {} but could not find the method definition, dropping it", + method_id.__str__(), + ); + } + } + } Ok(Class { name, superclass, @@ -427,6 +555,7 @@ impl Apk { is_synthetic, is_enum, value: None, + annotations: vec![], }) } @@ -546,6 +675,8 @@ impl Apk { is_synthetic, is_constructor, is_declared_syncrhonized, + annotations: vec![], + parameters_annotations: vec![], code: (), }) } diff --git a/androscalpel/src/field.rs b/androscalpel/src/field.rs index 4f1ff52..05138ef 100644 --- a/androscalpel/src/field.rs +++ b/androscalpel/src/field.rs @@ -2,7 +2,7 @@ use pyo3::prelude::*; -use crate::{DexValue, IdField}; +use crate::{DexAnnotationItem, DexValue, IdField}; /// Represent a field. #[pyclass] @@ -34,6 +34,9 @@ pub struct Field { pub is_enum: bool, /// The default value of this field pub value: Option, + /// The annotations for this field + #[pyo3(get, set)] + pub annotations: Vec, } /// Represent the visibility of a field @@ -60,6 +63,7 @@ impl Field { is_synthetic: false, is_enum: false, value: None, + annotations: vec![], } } diff --git a/androscalpel/src/method.rs b/androscalpel/src/method.rs index 112562a..b1c4531 100644 --- a/androscalpel/src/method.rs +++ b/androscalpel/src/method.rs @@ -2,7 +2,7 @@ use pyo3::prelude::*; -use crate::IdMethod; +use crate::{DexAnnotationItem, IdMethod}; /// Represent a method. #[pyclass] @@ -49,6 +49,12 @@ pub struct Method { /// If the method is declared as synchronize (just indicatif) #[pyo3(get, set)] pub is_declared_syncrhonized: bool, + /// The annotations for this method + #[pyo3(get, set)] + pub annotations: Vec, + /// The annotations for the parameters of this method method + #[pyo3(get, set)] + pub parameters_annotations: Vec>, /// The code of the method pub code: (), @@ -82,6 +88,8 @@ impl Method { is_synthetic: false, is_constructor: false, is_declared_syncrhonized: false, + annotations: vec![], + parameters_annotations: vec![], code: (), } } diff --git a/androscalpel_serializer/src/annotation/mod.rs b/androscalpel_serializer/src/annotation/mod.rs index 5992cfe..83d8be2 100644 --- a/androscalpel_serializer/src/annotation/mod.rs +++ b/androscalpel_serializer/src/annotation/mod.rs @@ -21,7 +21,7 @@ pub struct AnnotationDirectoryItem { pub field_annotations: Vec, /// List of method annotation. The method annotations must be sorted by /// increasing order of [`crate::MethodAnnotation.method_idx`]. - pub method_annotation: Vec, + pub method_annotations: Vec, /// List of associated method parameter annotation. The parameter annotations /// must be sorted by increasing order of [`crate::ParameterAnnotation.parameter_size`]. pub parameter_annotations: Vec, @@ -32,7 +32,7 @@ impl AnnotationDirectoryItem { self.field_annotations.len() as u32 } pub fn annotated_methods_size_field(&self) -> u32 { - self.method_annotation.len() as u32 + self.method_annotations.len() as u32 } pub fn parameter_annotations_field(&self) -> u32 { self.parameter_annotations.len() as u32 @@ -49,7 +49,7 @@ impl Serializable for AnnotationDirectoryItem { for item in &self.field_annotations { item.serialize(output)?; } - for item in &self.method_annotation { + for item in &self.method_annotations { item.serialize(output)?; } for item in &self.parameter_annotations { @@ -66,9 +66,9 @@ impl Serializable for AnnotationDirectoryItem { for _ in 0..fields_size { field_annotations.push(FieldAnnotation::deserialize(input)?); } - let mut method_annotation = vec![]; + let mut method_annotations = vec![]; for _ in 0..annotated_methods_size { - method_annotation.push(MethodAnnotation::deserialize(input)?); + method_annotations.push(MethodAnnotation::deserialize(input)?); } let mut parameter_annotations = vec![]; for _ in 0..annotated_parameters_size { @@ -78,7 +78,7 @@ impl Serializable for AnnotationDirectoryItem { Ok(Self { class_annotations_off, field_annotations, - method_annotation, + method_annotations, parameter_annotations, }) } @@ -93,7 +93,7 @@ impl Serializable for AnnotationDirectoryItem { .map(|val| val.size()) .sum::() + self - .method_annotation + .method_annotations .iter() .map(|val| val.size()) .sum::() @@ -108,25 +108,28 @@ impl Serializable for AnnotationDirectoryItem { /// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct FieldAnnotation { + /// Index of the field annotated in `field_ids` pub field_idx: u32, /// Offset to a [`AnnotationSetItem`] - pub annotation_off: u32, + pub annotations_off: u32, } /// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct MethodAnnotation { + /// Index of the method annotated in `method_ids` pub method_idx: u32, /// Offset to a [`AnnotationSetItem`] - pub annotation_off: u32, + pub annotations_off: u32, } /// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct ParameterAnnotation { - pub field_idx: u32, + /// Index of the method whose parameters are annotated in `method_ids` + pub method_idx: u32, /// Offset of a [`AnnotationSetRefList`] - pub annotation_off: u32, + pub annotations_off: u32, } ///