From fb2ba61d21553f98d994d3493c482105f72977aa Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Fri, 26 Apr 2024 13:30:19 +0200 Subject: [PATCH] clean json format --- androscalpel/src/apk.rs | 2 - androscalpel/src/class.rs | 5 - androscalpel/src/dex_id.rs | 130 ++++- androscalpel/src/py_utils.rs | 21 +- androscalpel/src/tests/app1.json | 673 +++++++++++++++++++++++- androscalpel/src/tests/test_class1.json | 484 +++++++---------- 6 files changed, 990 insertions(+), 325 deletions(-) diff --git a/androscalpel/src/apk.rs b/androscalpel/src/apk.rs index 823789c..0c477e2 100644 --- a/androscalpel/src/apk.rs +++ b/androscalpel/src/apk.rs @@ -8,7 +8,6 @@ use log::info; use pyo3::prelude::*; use pyo3::types::PyBytes; -use crate::hashmap_vectorize; use crate::ins::CallSite; use crate::instructions; use crate::Result; @@ -22,7 +21,6 @@ use rayon::prelude::*; #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Default)] pub struct Apk { #[pyo3(get)] - #[serde(with = "hashmap_vectorize")] pub classes: HashMap, #[pyo3(get)] pub not_referenced_strings: HashSet, diff --git a/androscalpel/src/class.rs b/androscalpel/src/class.rs index 0b3745d..de058b9 100644 --- a/androscalpel/src/class.rs +++ b/androscalpel/src/class.rs @@ -5,7 +5,6 @@ use std::collections::{HashMap, HashSet}; use pyo3::prelude::*; -use crate::hashmap_vectorize; use crate::{ DexAnnotationItem, DexString, Field, IdField, IdMethod, IdMethodType, IdType, Method, MethodHandle, Result, @@ -56,19 +55,15 @@ pub struct Class { /// The static fields #[pyo3(get)] - #[serde(with = "hashmap_vectorize")] pub static_fields: HashMap, /// The instance fields #[pyo3(get)] - #[serde(with = "hashmap_vectorize")] pub instance_fields: HashMap, /// The direct (static, private or constructor) methods of the class #[pyo3(get)] - #[serde(with = "hashmap_vectorize")] pub direct_methods: HashMap, /// The virtual (ie non direct) methods of the class #[pyo3(get)] - #[serde(with = "hashmap_vectorize")] pub virtual_methods: HashMap, // Do we need to distinguish direct and virtual (all the other) methods? // Maybe overlapping descriptor (same name, class and proto?) diff --git a/androscalpel/src/dex_id.rs b/androscalpel/src/dex_id.rs index 21d3e73..093e7cb 100644 --- a/androscalpel/src/dex_id.rs +++ b/androscalpel/src/dex_id.rs @@ -16,7 +16,7 @@ use androscalpel_serializer::{StringDataItem, Uleb128}; /// The type of a method. The shorty is formated as described in /// #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IdMethodType { /// Type formated as described by pub(crate) shorty: DexString, // Redondant, but same as in the encoding, keep it in case we ever @@ -180,6 +180,25 @@ impl IdMethodType { } } +impl SmaliName for IdMethodType { + /// Convert a descriptor to its smali representation. + fn try_to_smali(&self) -> Result { + Ok(format!( + "({}){}", + self.parameters + .iter() + .map(|param| param.try_to_smali()) + .collect::>>()? + .join(""), + self.return_type.try_to_smali()? + )) + } + /// Convert a smali representation to its descriptor. + fn try_from_smali(smali: &str) -> Result { + Self::from_smali(smali) + } +} + impl IdMethodType { /// Compute the format for the shorty as described in /// @@ -199,7 +218,7 @@ impl IdMethodType { // Not a clean rust enum because we want to be compatible with python, and maybe support strange // malware edge case? #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Deserialize, Serialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct IdType(pub(crate) DexString); #[pymethods] impl IdType { @@ -591,8 +610,20 @@ impl IdType { // TODO: TESTS } +impl SmaliName for IdType { + /// Convert a descriptor to its smali representation. + fn try_to_smali(&self) -> Result { + let r = (&self.0 .0).try_into()?; // Anyhow conversion stuff + Ok(r) + } + /// Convert a smali representation to its descriptor. + fn try_from_smali(smali: &str) -> Result { + Self::from_smali(smali) + } +} + #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IdField { /// The name of the field, format described at /// @@ -735,9 +766,23 @@ impl PartialOrd for IdField { } } +impl SmaliName for IdField { + /// Convert a descriptor to its smali representation. + fn try_to_smali(&self) -> Result { + let class: String = self.class_.try_to_smali()?; + let name: String = (&self.name.0).try_into()?; + let ty: String = self.type_.try_to_smali()?; + Ok(format!("{class}->{name}:{ty}")) + } + /// Convert a smali representation to its descriptor. + fn try_from_smali(smali: &str) -> Result { + Self::from_smali(smali) + } +} + /// The Id of a method. #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IdMethod { /// The class containing the method. #[pyo3(get)] @@ -906,8 +951,25 @@ impl PartialOrd for IdMethod { } } +impl SmaliName for IdMethod { + /// Convert a descriptor to its smali representation. + fn try_to_smali(&self) -> Result { + let name: String = (&self.name.0).try_into()?; + Ok(format!( + "{}->{}{}", + self.class_.try_to_smali()?, + name, + self.proto.try_to_smali()?, + )) + } + /// Convert a smali representation to its descriptor. + fn try_from_smali(smali: &str) -> Result { + Self::from_smali(smali) + } +} + #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Ord, PartialOrd)] +#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)] pub struct IdEnum(pub IdField); #[pymethods] @@ -957,3 +1019,61 @@ impl IdEnum { op.matches(self.cmp(other)) } } + +// Not to sure about this one +impl SmaliName for IdEnum { + /// Convert a descriptor to its smali representation. + fn try_to_smali(&self) -> Result { + self.0.try_to_smali() + } + /// Convert a smali representation to its descriptor. + fn try_from_smali(smali: &str) -> Result { + Ok(Self(IdField::from_smali(smali)?)) + } +} + +pub trait SmaliName: Sized { + /// Convert a descriptor to its smali representation. + fn try_to_smali(&self) -> Result; + /// Convert a smali representation to its descriptor. + fn try_from_smali(smali: &str) -> Result; +} + +macro_rules! serde_serialize_to_smali { + // This macro takes an argument of designator `ident` and + // implement Serialize and Deserialize for the type, assuming + // it implement SmaliName. + ($type_name:ident) => { + impl serde::Serialize for $type_name { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + Serialize::serialize( + &self + .try_to_smali() + .expect(&format!("Failed to convert {} to smali", self.__str__())), + serializer, + ) + } + } + + impl<'de> serde::Deserialize<'de> for $type_name { + fn deserialize(deserializer: D) -> Result<$type_name, D::Error> + where + D: serde::Deserializer<'de>, + { + ::deserialize(deserializer).map(|string| { + $type_name::try_from_smali(&string) + .expect(&format!("Failed to convert {string} as smali")) + }) + } + } + }; +} + +serde_serialize_to_smali!(IdMethodType); +serde_serialize_to_smali!(IdType); +serde_serialize_to_smali!(IdMethod); +serde_serialize_to_smali!(IdField); +serde_serialize_to_smali!(IdEnum); diff --git a/androscalpel/src/py_utils.rs b/androscalpel/src/py_utils.rs index 9a641a1..d32cb9c 100644 --- a/androscalpel/src/py_utils.rs +++ b/androscalpel/src/py_utils.rs @@ -4,6 +4,7 @@ use pyo3::prelude::*; use pyo3::types::PyBytes; use std::collections::HashSet; +use std::fs::File; use std::io::{Cursor, Seek, SeekFrom}; use std::path::PathBuf; @@ -48,7 +49,7 @@ pub fn sleb128_to_int(b: &[u8]) -> Result { Ok(Sleb128::deserialize_from_slice(b)?.0) } -// TODO: list_defined_classes, is_dex, is_zip take &[u8], but should allow to also read from file +// TODO: list_defined_classes, is_dex, is_zip take only &[u8] or file, but should allow to also read from both /// List all classes defined in a dex file. #[pyfunction] @@ -62,8 +63,12 @@ pub fn list_defined_classes(dex: &[u8]) -> Result> { /// Test if a file is as .dex file an return the dex version if it is, else return None. #[pyfunction] -pub fn is_dex(file: &[u8]) -> Option { - HeaderItem::deserialize_from_slice(file) +pub fn is_dex(file: PathBuf) -> Option { + let mut file = match File::open(file) { + Ok(file) => file, + Err(_) => return None, + }; + HeaderItem::deserialize(&mut file) .ok() .and_then(|header| String::from_utf8(header.magic.version.to_vec()).ok()) .and_then(|version| version.parse::().ok()) @@ -71,8 +76,11 @@ pub fn is_dex(file: &[u8]) -> Option { /// Test if a file is a zip file. #[pyfunction] -pub fn is_zip(file: &[u8]) -> bool { - let mut file = Cursor::new(file); +pub fn is_zip(file: PathBuf) -> bool { + let mut file = match File::open(file) { + Ok(file) => file, + Err(_) => return false, + }; let ecd_off = if let Some(off) = ZipFileReader::get_end_of_central_directory_offset(&mut file) { off } else { @@ -117,6 +125,9 @@ pub(crate) fn export_module(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(uleb128_to_int, m)?)?; m.add_function(wrap_pyfunction!(uleb128p1_to_int, m)?)?; m.add_function(wrap_pyfunction!(sleb128_to_int, m)?)?; + m.add_function(wrap_pyfunction!(list_defined_classes, m)?)?; + m.add_function(wrap_pyfunction!(is_dex, m)?)?; + m.add_function(wrap_pyfunction!(is_zip, m)?)?; m.add_function(wrap_pyfunction!(replace_dex, m)?)?; Ok(()) } diff --git a/androscalpel/src/tests/app1.json b/androscalpel/src/tests/app1.json index 976a713..73ca654 100644 --- a/androscalpel/src/tests/app1.json +++ b/androscalpel/src/tests/app1.json @@ -1 +1,672 @@ -{"classes":[[{"String":"Lcom/example/testclassloader/TestB;"},{"descriptor":{"String":"Lcom/example/testclassloader/TestB;"},"is_public":true,"is_final":false,"is_interface":false,"is_abstract":false,"is_synthetic":false,"is_annotation":false,"is_enum":false,"superclass":{"String":"Ljava/lang/Object;"},"interfaces":[],"source_file":{"String":"TestB.java"},"static_fields":[],"instance_fields":[],"direct_methods":[[{"class_":{"String":"Lcom/example/testclassloader/TestB;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},{"descriptor":{"class_":{"String":"Lcom/example/testclassloader/TestB;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},"visibility":"Public","is_static":false,"is_final":false,"is_synchronized":false,"is_bridge":false,"is_varargs":false,"is_native":false,"is_abstract":false,"is_strictfp":false,"is_synthetic":false,"is_constructor":true,"is_declared_syncrhonized":false,"annotations":[],"parameters_annotations":[],"code":{"registers_size":1,"ins_size":1,"outs_size":1,"debug_info":[3,[14,0]],"parameter_names":[],"insns":[{"Label":{"name":"label_00000000"}},{"InvokeDirect":{"method":{"class_":{"String":"Ljava/lang/Object;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},"args":[0]}},{"Label":{"name":"label_00000003"}},{"ReturnVoid":null}]}}],[{"class_":{"String":"Lcom/example/testclassloader/TestB;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},{"descriptor":{"class_":{"String":"Lcom/example/testclassloader/TestB;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},"visibility":"None_","is_static":true,"is_final":false,"is_synchronized":false,"is_bridge":false,"is_varargs":false,"is_native":false,"is_abstract":false,"is_strictfp":false,"is_synthetic":false,"is_constructor":true,"is_declared_syncrhonized":false,"annotations":[],"parameters_annotations":[],"code":{"registers_size":1,"ins_size":0,"outs_size":0,"debug_info":[5,[14,0]],"parameter_names":[],"insns":[{"Label":{"name":"label_00000000"}},{"ConstString":{"reg":0,"lit":{"String":"Plopliplop"}}},{"Label":{"name":"label_00000002"}},{"SPutObject":{"from":0,"field":{"name":{"String":"value"},"type_":{"String":"Ljava/lang/String;"},"class_":{"String":"Lcom/example/testclassloader/TestB;"}}}},{"Label":{"name":"label_00000004"}},{"ReturnVoid":null}]}}]],"virtual_methods":[[{"class_":{"String":"Lcom/example/testclassloader/TestB;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"get_cl"}},{"descriptor":{"class_":{"String":"Lcom/example/testclassloader/TestB;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"get_cl"}},"visibility":"Public","is_static":false,"is_final":false,"is_synchronized":false,"is_bridge":false,"is_varargs":false,"is_native":false,"is_abstract":false,"is_strictfp":false,"is_synthetic":false,"is_constructor":false,"is_declared_syncrhonized":false,"annotations":[],"parameters_annotations":[],"code":{"registers_size":2,"ins_size":1,"outs_size":1,"debug_info":[7,[14,0]],"parameter_names":[],"insns":[{"Label":{"name":"label_00000000"}},{"InvokeVirtual":{"method":{"class_":{"String":"Ljava/lang/Object;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/Class;"},"parameters":[]},"name":{"String":"getClass"}},"args":[1]}},{"Label":{"name":"label_00000003"}},{"MoveResultObject":{"to":0}},{"Label":{"name":"label_00000004"}},{"InvokeVirtual":{"method":{"class_":{"String":"Ljava/lang/Class;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/ClassLoader;"},"parameters":[]},"name":{"String":"getClassLoader"}},"args":[0]}},{"Label":{"name":"label_00000007"}},{"MoveResultObject":{"to":0}},{"Label":{"name":"label_00000008"}},{"InvokeVirtual":{"method":{"class_":{"String":"Ljava/lang/Object;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"toString"}},"args":[0]}},{"Label":{"name":"label_0000000B"}},{"MoveResultObject":{"to":0}},{"Label":{"name":"label_0000000C"}},{"ReturnObject":{"reg":0}}]}}],[{"class_":{"String":"Lcom/example/testclassloader/TestB;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"get_value"}},{"descriptor":{"class_":{"String":"Lcom/example/testclassloader/TestB;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"get_value"}},"visibility":"Public","is_static":false,"is_final":false,"is_synchronized":false,"is_bridge":false,"is_varargs":false,"is_native":false,"is_abstract":false,"is_strictfp":false,"is_synthetic":false,"is_constructor":false,"is_declared_syncrhonized":false,"annotations":[],"parameters_annotations":[],"code":{"registers_size":2,"ins_size":1,"outs_size":0,"debug_info":[11,[14,0]],"parameter_names":[],"insns":[{"SGetObject":{"to":0,"field":{"name":{"String":"value"},"type_":{"String":"Ljava/lang/String;"},"class_":{"String":"Lcom/example/testclassloader/TestA;"}}}},{"ReturnObject":{"reg":0}}]}}]],"annotations":[]}],[{"String":"Lcom/example/testclassloader/TestA;"},{"descriptor":{"String":"Lcom/example/testclassloader/TestA;"},"is_public":true,"is_final":false,"is_interface":false,"is_abstract":false,"is_synthetic":false,"is_annotation":false,"is_enum":false,"superclass":{"String":"Ljava/lang/Object;"},"interfaces":[],"source_file":{"String":"TestA.java"},"static_fields":[[{"name":{"String":"value"},"type_":{"String":"Ljava/lang/String;"},"class_":{"String":"Lcom/example/testclassloader/TestA;"}},{"descriptor":{"name":{"String":"value"},"type_":{"String":"Ljava/lang/String;"},"class_":{"String":"Lcom/example/testclassloader/TestA;"}},"visibility":"Public","is_static":true,"is_final":false,"is_volatile":false,"is_transient":false,"is_synthetic":false,"is_enum":false,"value":null,"annotations":[]}]],"instance_fields":[],"direct_methods":[[{"class_":{"String":"Lcom/example/testclassloader/TestA;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},{"descriptor":{"class_":{"String":"Lcom/example/testclassloader/TestA;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},"visibility":"None_","is_static":true,"is_final":false,"is_synchronized":false,"is_bridge":false,"is_varargs":false,"is_native":false,"is_abstract":false,"is_strictfp":false,"is_synthetic":false,"is_constructor":true,"is_declared_syncrhonized":false,"annotations":[],"parameters_annotations":[],"code":{"registers_size":1,"ins_size":0,"outs_size":0,"debug_info":[5,[14,0]],"parameter_names":[],"insns":[{"Label":{"name":"label_00000000"}},{"ConstString":{"reg":0,"lit":{"String":"Pirat\\')"}}},{"Label":{"name":"label_00000002"}},{"SPutObject":{"from":0,"field":{"name":{"String":"value"},"type_":{"String":"Ljava/lang/String;"},"class_":{"String":"Lcom/example/testclassloader/TestA;"}}}},{"Label":{"name":"label_00000004"}},{"ReturnVoid":null}]}}],[{"class_":{"String":"Lcom/example/testclassloader/TestA;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},{"descriptor":{"class_":{"String":"Lcom/example/testclassloader/TestA;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},"visibility":"Public","is_static":false,"is_final":false,"is_synchronized":false,"is_bridge":false,"is_varargs":false,"is_native":false,"is_abstract":false,"is_strictfp":false,"is_synthetic":false,"is_constructor":true,"is_declared_syncrhonized":false,"annotations":[],"parameters_annotations":[],"code":{"registers_size":1,"ins_size":1,"outs_size":1,"debug_info":[3,[14,0]],"parameter_names":[],"insns":[{"Label":{"name":"label_00000000"}},{"InvokeDirect":{"method":{"class_":{"String":"Ljava/lang/Object;"},"proto":{"shorty":{"String":"V"},"return_type":{"String":"V"},"parameters":[]},"name":{"String":""}},"args":[0]}},{"Label":{"name":"label_00000003"}},{"ReturnVoid":null}]}}]],"virtual_methods":[[{"class_":{"String":"Lcom/example/testclassloader/TestA;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"get_cl"}},{"descriptor":{"class_":{"String":"Lcom/example/testclassloader/TestA;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"get_cl"}},"visibility":"Public","is_static":false,"is_final":false,"is_synchronized":false,"is_bridge":false,"is_varargs":false,"is_native":false,"is_abstract":false,"is_strictfp":false,"is_synthetic":false,"is_constructor":false,"is_declared_syncrhonized":false,"annotations":[],"parameters_annotations":[],"code":{"registers_size":2,"ins_size":1,"outs_size":1,"debug_info":[7,[14,0]],"parameter_names":[],"insns":[{"Label":{"name":"label_00000000"}},{"InvokeVirtual":{"method":{"class_":{"String":"Ljava/lang/Object;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/Class;"},"parameters":[]},"name":{"String":"getClass"}},"args":[1]}},{"Label":{"name":"label_00000003"}},{"MoveResultObject":{"to":0}},{"Label":{"name":"label_00000004"}},{"InvokeVirtual":{"method":{"class_":{"String":"Ljava/lang/Class;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/ClassLoader;"},"parameters":[]},"name":{"String":"getClassLoader"}},"args":[0]}},{"Label":{"name":"label_00000007"}},{"MoveResultObject":{"to":0}},{"Label":{"name":"label_00000008"}},{"InvokeVirtual":{"method":{"class_":{"String":"Ljava/lang/Object;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"toString"}},"args":[0]}},{"Label":{"name":"label_0000000B"}},{"MoveResultObject":{"to":0}},{"Label":{"name":"label_0000000C"}},{"ReturnObject":{"reg":0}}]}}],[{"class_":{"String":"Lcom/example/testclassloader/TestA;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"get_value"}},{"descriptor":{"class_":{"String":"Lcom/example/testclassloader/TestA;"},"proto":{"shorty":{"String":"L"},"return_type":{"String":"Ljava/lang/String;"},"parameters":[]},"name":{"String":"get_value"}},"visibility":"Public","is_static":false,"is_final":false,"is_synchronized":false,"is_bridge":false,"is_varargs":false,"is_native":false,"is_abstract":false,"is_strictfp":false,"is_synthetic":false,"is_constructor":false,"is_declared_syncrhonized":false,"annotations":[],"parameters_annotations":[],"code":{"registers_size":2,"ins_size":1,"outs_size":0,"debug_info":[11,[14,0]],"parameter_names":[],"insns":[{"Label":{"name":"label_00000000"}},{"SGetObject":{"to":0,"field":{"name":{"String":"value"},"type_":{"String":"Ljava/lang/String;"},"class_":{"String":"Lcom/example/testclassloader/TestA;"}}}},{"Label":{"name":"label_00000002"}},{"ReturnObject":{"reg":0}}]}}]],"annotations":[]}]],"not_referenced_strings":[]} \ No newline at end of file +{ + "classes": { + "Lcom/example/testclassloader/TestA;": { + "descriptor": "Lcom/example/testclassloader/TestA;", + "is_public": true, + "is_final": false, + "is_interface": false, + "is_abstract": false, + "is_synthetic": false, + "is_annotation": false, + "is_enum": false, + "superclass": "Ljava/lang/Object;", + "interfaces": [], + "source_file": { + "String": "TestA.java" + }, + "static_fields": { + "Lcom/example/testclassloader/TestA;->value:Ljava/lang/String;": { + "descriptor": "Lcom/example/testclassloader/TestA;->value:Ljava/lang/String;", + "visibility": "Public", + "is_static": true, + "is_final": false, + "is_volatile": false, + "is_transient": false, + "is_synthetic": false, + "is_enum": false, + "value": null, + "annotations": [] + } + }, + "instance_fields": {}, + "direct_methods": { + "Lcom/example/testclassloader/TestA;->()V": { + "descriptor": "Lcom/example/testclassloader/TestA;->()V", + "visibility": "Public", + "is_static": false, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": true, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 1, + "ins_size": 1, + "outs_size": 1, + "debug_info": [ + 3, + [ + 14, + 0 + ] + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" + } + }, + { + "InvokeDirect": { + "method": "Ljava/lang/Object;->()V", + "args": [ + 0 + ] + } + }, + { + "Label": { + "name": "label_00000003" + } + }, + { + "ReturnVoid": null + } + ] + } + }, + "Lcom/example/testclassloader/TestA;->()V": { + "descriptor": "Lcom/example/testclassloader/TestA;->()V", + "visibility": "None_", + "is_static": true, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": true, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 1, + "ins_size": 0, + "outs_size": 0, + "debug_info": [ + 5, + [ + 14, + 0 + ] + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" + } + }, + { + "ConstString": { + "reg": 0, + "lit": { + "String": "Pirat\\')" + } + } + }, + { + "Label": { + "name": "label_00000002" + } + }, + { + "SPutObject": { + "from": 0, + "field": "Lcom/example/testclassloader/TestA;->value:Ljava/lang/String;" + } + }, + { + "Label": { + "name": "label_00000004" + } + }, + { + "ReturnVoid": null + }, + { + "Label": { + "name": "label_00000005" + } + }, + { + "Nop": null + } + ] + } + } + }, + "virtual_methods": { + "Lcom/example/testclassloader/TestA;->get_value()Ljava/lang/String;": { + "descriptor": "Lcom/example/testclassloader/TestA;->get_value()Ljava/lang/String;", + "visibility": "Public", + "is_static": false, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": false, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 2, + "ins_size": 1, + "outs_size": 0, + "debug_info": [ + 11, + [ + 14, + 0 + ] + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" + } + }, + { + "SGetObject": { + "to": 0, + "field": "Lcom/example/testclassloader/TestA;->value:Ljava/lang/String;" + } + }, + { + "Label": { + "name": "label_00000002" + } + }, + { + "ReturnObject": { + "reg": 0 + } + }, + { + "Label": { + "name": "label_00000003" + } + }, + { + "Nop": null + } + ] + } + }, + "Lcom/example/testclassloader/TestA;->get_cl()Ljava/lang/String;": { + "descriptor": "Lcom/example/testclassloader/TestA;->get_cl()Ljava/lang/String;", + "visibility": "Public", + "is_static": false, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": false, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 2, + "ins_size": 1, + "outs_size": 1, + "debug_info": [ + 7, + [ + 14, + 0 + ] + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" + } + }, + { + "InvokeVirtual": { + "method": "Ljava/lang/Object;->getClass()Ljava/lang/Class;", + "args": [ + 1 + ] + } + }, + { + "Label": { + "name": "label_00000003" + } + }, + { + "MoveResultObject": { + "to": 0 + } + }, + { + "Label": { + "name": "label_00000004" + } + }, + { + "InvokeVirtual": { + "method": "Ljava/lang/Class;->getClassLoader()Ljava/lang/ClassLoader;", + "args": [ + 0 + ] + } + }, + { + "Label": { + "name": "label_00000007" + } + }, + { + "MoveResultObject": { + "to": 0 + } + }, + { + "Label": { + "name": "label_00000008" + } + }, + { + "InvokeVirtual": { + "method": "Ljava/lang/Object;->toString()Ljava/lang/String;", + "args": [ + 0 + ] + } + }, + { + "Label": { + "name": "label_0000000B" + } + }, + { + "MoveResultObject": { + "to": 0 + } + }, + { + "Label": { + "name": "label_0000000C" + } + }, + { + "ReturnObject": { + "reg": 0 + } + }, + { + "Label": { + "name": "label_0000000D" + } + }, + { + "Nop": null + } + ] + } + } + }, + "annotations": [] + }, + "Lcom/example/testclassloader/TestB;": { + "descriptor": "Lcom/example/testclassloader/TestB;", + "is_public": true, + "is_final": false, + "is_interface": false, + "is_abstract": false, + "is_synthetic": false, + "is_annotation": false, + "is_enum": false, + "superclass": "Ljava/lang/Object;", + "interfaces": [], + "source_file": { + "String": "TestB.java" + }, + "static_fields": {}, + "instance_fields": {}, + "direct_methods": { + "Lcom/example/testclassloader/TestB;->()V": { + "descriptor": "Lcom/example/testclassloader/TestB;->()V", + "visibility": "Public", + "is_static": false, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": true, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 1, + "ins_size": 1, + "outs_size": 1, + "debug_info": [ + 3, + [ + 14, + 0 + ] + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" + } + }, + { + "InvokeDirect": { + "method": "Ljava/lang/Object;->()V", + "args": [ + 0 + ] + } + }, + { + "Label": { + "name": "label_00000003" + } + }, + { + "ReturnVoid": null + } + ] + } + }, + "Lcom/example/testclassloader/TestB;->()V": { + "descriptor": "Lcom/example/testclassloader/TestB;->()V", + "visibility": "None_", + "is_static": true, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": true, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 1, + "ins_size": 0, + "outs_size": 0, + "debug_info": [ + 5, + [ + 14, + 0 + ] + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" + } + }, + { + "ConstString": { + "reg": 0, + "lit": { + "String": "Plopliplop" + } + } + }, + { + "Label": { + "name": "label_00000002" + } + }, + { + "SPutObject": { + "from": 0, + "field": "Lcom/example/testclassloader/TestB;->value:Ljava/lang/String;" + } + }, + { + "Label": { + "name": "label_00000004" + } + }, + { + "ReturnVoid": null + }, + { + "Label": { + "name": "label_00000005" + } + }, + { + "Nop": null + } + ] + } + } + }, + "virtual_methods": { + "Lcom/example/testclassloader/TestB;->get_cl()Ljava/lang/String;": { + "descriptor": "Lcom/example/testclassloader/TestB;->get_cl()Ljava/lang/String;", + "visibility": "Public", + "is_static": false, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": false, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 2, + "ins_size": 1, + "outs_size": 1, + "debug_info": [ + 7, + [ + 14, + 0 + ] + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" + } + }, + { + "InvokeVirtual": { + "method": "Ljava/lang/Object;->getClass()Ljava/lang/Class;", + "args": [ + 1 + ] + } + }, + { + "Label": { + "name": "label_00000003" + } + }, + { + "MoveResultObject": { + "to": 0 + } + }, + { + "Label": { + "name": "label_00000004" + } + }, + { + "InvokeVirtual": { + "method": "Ljava/lang/Class;->getClassLoader()Ljava/lang/ClassLoader;", + "args": [ + 0 + ] + } + }, + { + "Label": { + "name": "label_00000007" + } + }, + { + "MoveResultObject": { + "to": 0 + } + }, + { + "Label": { + "name": "label_00000008" + } + }, + { + "InvokeVirtual": { + "method": "Ljava/lang/Object;->toString()Ljava/lang/String;", + "args": [ + 0 + ] + } + }, + { + "Label": { + "name": "label_0000000B" + } + }, + { + "MoveResultObject": { + "to": 0 + } + }, + { + "Label": { + "name": "label_0000000C" + } + }, + { + "ReturnObject": { + "reg": 0 + } + }, + { + "Label": { + "name": "label_0000000D" + } + }, + { + "Nop": null + } + ] + } + }, + "Lcom/example/testclassloader/TestB;->get_value()Ljava/lang/String;": { + "descriptor": "Lcom/example/testclassloader/TestB;->get_value()Ljava/lang/String;", + "visibility": "Public", + "is_static": false, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": false, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 2, + "ins_size": 1, + "outs_size": 0, + "debug_info": [ + 11, + [ + 14, + 0 + ] + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" + } + }, + { + "SGetObject": { + "to": 0, + "field": "Lcom/example/testclassloader/TestA;->value:Ljava/lang/String;" + } + }, + { + "Label": { + "name": "label_00000002" + } + }, + { + "ReturnObject": { + "reg": 0 + } + }, + { + "Label": { + "name": "label_00000003" + } + }, + { + "Nop": null + } + ] + } + } + }, + "annotations": [] + } + }, + "not_referenced_strings": [] +} diff --git a/androscalpel/src/tests/test_class1.json b/androscalpel/src/tests/test_class1.json index 46f88b8..705b43f 100644 --- a/androscalpel/src/tests/test_class1.json +++ b/androscalpel/src/tests/test_class1.json @@ -1,7 +1,5 @@ { - "descriptor": { - "String": "Lcom/example/testclassloader/TestB;" - }, + "descriptor": "Lcom/example/testclassloader/TestB;", "is_public": true, "is_final": false, "is_interface": false, @@ -9,316 +7,188 @@ "is_synthetic": false, "is_annotation": false, "is_enum": false, - "superclass": { - "String": "Ljava/lang/Object;" - }, + "superclass": "Ljava/lang/Object;", "interfaces": [], "source_file": { "String": "TestB.java" }, - "static_fields": [], - "instance_fields": [], - "direct_methods": [ - [ - { - "class_": { - "String": "Lcom/example/testclassloader/TestB;" - }, - "proto": { - "shorty": { - "String": "V" - }, - "return_type": { - "String": "V" - }, - "parameters": [] - }, - "name": { - "String": "" - } - }, - { - "descriptor": { - "class_": { - "String": "Lcom/example/testclassloader/TestB;" - }, - "proto": { - "shorty": { - "String": "V" - }, - "return_type": { - "String": "V" - }, - "parameters": [] - }, - "name": { - "String": "" - } - }, - "visibility": "Public", - "is_static": false, - "is_final": false, - "is_synchronized": false, - "is_bridge": false, - "is_varargs": false, - "is_native": false, - "is_abstract": false, - "is_strictfp": false, - "is_synthetic": false, - "is_constructor": true, - "is_declared_syncrhonized": false, - "annotations": [], - "parameters_annotations": [], - "code": { - "registers_size": 1, - "ins_size": 1, - "outs_size": 1, - "debug_info": [ - 3, - [ - 14, - 0 - ] - ], - "parameter_names": [], - "insns": [ - { - "Label": { - "name": "label_00000000" - } - }, - { - "InvokeDirect": { - "method": { - "class_": { - "String": "Ljava/lang/Object;" - }, - "proto": { - "shorty": { - "String": "V" - }, - "return_type": { - "String": "V" - }, - "parameters": [] - }, - "name": { - "String": "" - } - }, - "args": [ - 0 - ] - } - }, - { - "Label": { - "name": "label_00000003" - } - }, - { - "ReturnVoid": null - } + "static_fields": {}, + "instance_fields": {}, + "direct_methods": { + "Lcom/example/testclassloader/TestB;->()V": { + "descriptor": "Lcom/example/testclassloader/TestB;->()V", + "visibility": "Public", + "is_static": false, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": true, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 1, + "ins_size": 1, + "outs_size": 1, + "debug_info": [ + 3, + [ + 14, + 0 ] - } - } - ] - ], - "virtual_methods": [ - [ - { - "class_": { - "String": "Lcom/example/testclassloader/TestB;" - }, - "proto": { - "shorty": { - "String": "L" - }, - "return_type": { - "String": "Ljava/lang/String;" - }, - "parameters": [] - }, - "name": { - "String": "val" - } - }, - { - "descriptor": { - "class_": { - "String": "Lcom/example/testclassloader/TestB;" - }, - "proto": { - "shorty": { - "String": "L" - }, - "return_type": { - "String": "Ljava/lang/String;" - }, - "parameters": [] - }, - "name": { - "String": "val" - } - }, - "visibility": "Public", - "is_static": false, - "is_final": false, - "is_synchronized": false, - "is_bridge": false, - "is_varargs": false, - "is_native": false, - "is_abstract": false, - "is_strictfp": false, - "is_synthetic": false, - "is_constructor": false, - "is_declared_syncrhonized": false, - "annotations": [], - "parameters_annotations": [], - "code": { - "registers_size": 2, - "ins_size": 1, - "outs_size": 1, - "debug_info": [ - 6, - [ - 14, - 0 - ] - ], - "parameter_names": [], - "insns": [ - { - "Label": { - "name": "label_00000000" - } - }, - { - "InvokeVirtual": { - "method": { - "class_": { - "String": "Ljava/lang/Object;" - }, - "proto": { - "shorty": { - "String": "L" - }, - "return_type": { - "String": "Ljava/lang/Class;" - }, - "parameters": [] - }, - "name": { - "String": "getClass" - } - }, - "args": [ - 1 - ] - } - }, - { - "Label": { - "name": "label_00000003" - } - }, - { - "MoveResultObject": { - "to": 0 - } - }, - { - "Label": { - "name": "label_00000004" - } - }, - { - "InvokeVirtual": { - "method": { - "class_": { - "String": "Ljava/lang/Class;" - }, - "proto": { - "shorty": { - "String": "L" - }, - "return_type": { - "String": "Ljava/lang/ClassLoader;" - }, - "parameters": [] - }, - "name": { - "String": "getClassLoader" - } - }, - "args": [ - 0 - ] - } - }, - { - "Label": { - "name": "label_00000007" - } - }, - { - "MoveResultObject": { - "to": 0 - } - }, - { - "Label": { - "name": "label_00000008" - } - }, - { - "InvokeVirtual": { - "method": { - "class_": { - "String": "Ljava/lang/Object;" - }, - "proto": { - "shorty": { - "String": "L" - }, - "return_type": { - "String": "Ljava/lang/String;" - }, - "parameters": [] - }, - "name": { - "String": "toString" - } - }, - "args": [ - 0 - ] - } - }, - { - "Label": { - "name": "label_0000000B" - } - }, - { - "MoveResultObject": { - "to": 0 - } - }, - { - "Label": { - "name": "label_0000000C" - } - }, - { - "ReturnObject": { - "reg": 0 - } + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" } - ] - } + }, + { + "InvokeDirect": { + "method": "Ljava/lang/Object;->()V", + "args": [ + 0 + ] + } + }, + { + "Label": { + "name": "label_00000003" + } + }, + { + "ReturnVoid": null + } + ] } - ] - ], + } + }, + "virtual_methods": { + "Lcom/example/testclassloader/TestB;->val()Ljava/lang/String;": { + "descriptor": "Lcom/example/testclassloader/TestB;->val()Ljava/lang/String;", + "visibility": "Public", + "is_static": false, + "is_final": false, + "is_synchronized": false, + "is_bridge": false, + "is_varargs": false, + "is_native": false, + "is_abstract": false, + "is_strictfp": false, + "is_synthetic": false, + "is_constructor": false, + "is_declared_syncrhonized": false, + "annotations": [], + "parameters_annotations": [], + "code": { + "registers_size": 2, + "ins_size": 1, + "outs_size": 1, + "debug_info": [ + 6, + [ + 14, + 0 + ] + ], + "parameter_names": [], + "insns": [ + { + "Label": { + "name": "label_00000000" + } + }, + { + "InvokeVirtual": { + "method": "Ljava/lang/Object;->getClass()Ljava/lang/Class;", + "args": [ + 1 + ] + } + }, + { + "Label": { + "name": "label_00000003" + } + }, + { + "MoveResultObject": { + "to": 0 + } + }, + { + "Label": { + "name": "label_00000004" + } + }, + { + "InvokeVirtual": { + "method": "Ljava/lang/Class;->getClassLoader()Ljava/lang/ClassLoader;", + "args": [ + 0 + ] + } + }, + { + "Label": { + "name": "label_00000007" + } + }, + { + "MoveResultObject": { + "to": 0 + } + }, + { + "Label": { + "name": "label_00000008" + } + }, + { + "InvokeVirtual": { + "method": "Ljava/lang/Object;->toString()Ljava/lang/String;", + "args": [ + 0 + ] + } + }, + { + "Label": { + "name": "label_0000000B" + } + }, + { + "MoveResultObject": { + "to": 0 + } + }, + { + "Label": { + "name": "label_0000000C" + } + }, + { + "ReturnObject": { + "reg": 0 + } + }, + { + "Label": { + "name": "label_0000000D" + } + }, + { + "Nop": null + } + ] + } + } + }, "annotations": [] }