remove setter to limit confusion

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2024-01-23 20:19:28 +01:00
parent 3a6edf1aa2
commit ebaeaef877
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
10 changed files with 305 additions and 294 deletions

View file

@ -1,11 +1,8 @@
- method (what's left to do except code?)
- generate .dex - generate .dex
- code
- edditable code format - edditable code format
- json serialize with serde - json serialize with serde
- sanity checks - sanity checks
- tests - tests
- PyRef https://pyo3.rs/v0.20.0/faq.html#pyo3get-clones-my-field
- https://source.android.com/docs/core/runtime/dex-format#system-annotation - https://source.android.com/docs/core/runtime/dex-format#system-annotation

View file

@ -13,17 +13,17 @@ use crate::{
pub struct DexAnnotationItem { pub struct DexAnnotationItem {
// TODO: the get/set will probably be wonky on the python side when edditing // TODO: the get/set will probably be wonky on the python side when edditing
/// The actual annotation /// The actual annotation
#[pyo3(get, set)] #[pyo3(get)]
pub annotation: DexAnnotation, pub annotation: DexAnnotation,
// TODO: enforce exclusivity // TODO: enforce exclusivity
/// If the annotation visibility is set to build /// If the annotation visibility is set to build
#[pyo3(get, set)] #[pyo3(get)]
pub visibility_build: bool, pub visibility_build: bool,
/// If the annotation visibility is set to runtime /// If the annotation visibility is set to runtime
#[pyo3(get, set)] #[pyo3(get)]
pub visibility_runtime: bool, pub visibility_runtime: bool,
/// If the annotation visibility is set to system /// If the annotation visibility is set to system
#[pyo3(get, set)] #[pyo3(get)]
pub visibility_system: bool, pub visibility_system: bool,
} }
@ -101,11 +101,11 @@ impl DexAnnotationItem {
pub struct DexAnnotation { pub struct DexAnnotation {
// TODO: check the relation between type and encoded_value. // TODO: check the relation between type and encoded_value.
/// The type of the annotation. /// The type of the annotation.
#[pyo3(get, set)] #[pyo3(get)]
pub type_: IdType, pub type_: IdType,
// TODO: the get/set will probably be wonky on the python side when edditing // TODO: the get/set will probably be wonky on the python side when edditing
/// The annotation elements. /// The annotation elements.
#[pyo3(get, set)] #[pyo3(get)]
pub elements: HashMap<DexString, DexValue>, // TODO: check MemberName syntax? pub elements: HashMap<DexString, DexValue>, // TODO: check MemberName syntax?
} }

View file

@ -17,7 +17,7 @@ use androscalpel_serializer::*;
#[pyclass] #[pyclass]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Apk { pub struct Apk {
#[pyo3(get, set)] #[pyo3(get)]
pub classes: HashMap<IdType, Class>, pub classes: HashMap<IdType, Class>,
} }

View file

@ -16,60 +16,60 @@ use androscalpel_serializer::consts::*;
pub struct Class { pub struct Class {
/// Type, format described at /// Type, format described at
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor> /// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
#[pyo3(get, set)] #[pyo3(get)]
pub descriptor: IdType, pub descriptor: IdType,
/// If the class is visible everywhere /// If the class is visible everywhere
#[pyo3(get, set)] #[pyo3(get)]
pub is_public: bool, pub is_public: bool,
/// If the class is subclassable /// If the class is subclassable
#[pyo3(get, set)] #[pyo3(get)]
pub is_final: bool, pub is_final: bool,
/// If the class is a 'multipy-implementable abstract class' AKA an interface /// If the class is a 'multipy-implementable abstract class' AKA an interface
#[pyo3(get, set)] #[pyo3(get)]
pub is_interface: bool, pub is_interface: bool,
/// If the class is instanciable /// If the class is instanciable
#[pyo3(get, set)] #[pyo3(get)]
pub is_abstract: bool, pub is_abstract: bool,
/// If the class is not directly defined in the source code /// If the class is not directly defined in the source code
#[pyo3(get, set)] #[pyo3(get)]
pub is_synthetic: bool, pub is_synthetic: bool,
/// If the class is an annotation /// If the class is an annotation
#[pyo3(get, set)] #[pyo3(get)]
pub is_annotation: bool, pub is_annotation: bool,
/// If the class is an enum /// If the class is an enum
#[pyo3(get, set)] #[pyo3(get)]
pub is_enum: bool, pub is_enum: bool,
/// Name of the superclass, format described at /// Name of the superclass, format described at
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor> /// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
#[pyo3(get, set)] #[pyo3(get)]
pub superclass: Option<IdType>, pub superclass: Option<IdType>,
/// List of the interfaces that class implement, format of the interfaces /// List of the interfaces that class implement, format of the interfaces
/// name is discribed at /// name is discribed at
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor> /// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
#[pyo3(get, set)] #[pyo3(get)]
pub interfaces: Vec<IdType>, pub interfaces: Vec<IdType>,
/// Name of the source file where this class is defined. /// Name of the source file where this class is defined.
#[pyo3(get, set)] #[pyo3(get)]
pub source_file: Option<DexString>, pub source_file: Option<DexString>,
/// The static fields /// The static fields
#[pyo3(get, set)] #[pyo3(get)]
pub static_fields: HashMap<IdField, Field>, pub static_fields: HashMap<IdField, Field>,
/// The instance fields /// The instance fields
#[pyo3(get, set)] #[pyo3(get)]
pub instance_fields: HashMap<IdField, Field>, pub instance_fields: HashMap<IdField, Field>,
/// The direct (static, private or constructor) methods of the class /// The direct (static, private or constructor) methods of the class
#[pyo3(get, set)] #[pyo3(get)]
pub direct_methods: HashMap<IdMethod, Method>, pub direct_methods: HashMap<IdMethod, Method>,
/// The virtual (ie non direct) methods of the class /// The virtual (ie non direct) methods of the class
#[pyo3(get, set)] #[pyo3(get)]
pub virtual_methods: HashMap<IdMethod, Method>, pub virtual_methods: HashMap<IdMethod, Method>,
// Do we need to distinguish direct and virtual (all the other) methods? // Do we need to distinguish direct and virtual (all the other) methods?
// Maybe overlapping descriptor (same name, class and proto?) // Maybe overlapping descriptor (same name, class and proto?)
/// The annotation related to this class (note: this does not include the /// The annotation related to this class (note: this does not include the
/// methods/field/parameters annotations, they are stored in the methods and fields /// methods/field/parameters annotations, they are stored in the methods and fields
/// structutres) /// structutres)
#[pyo3(get, set)] #[pyo3(get)]
pub annotations: Vec<DexAnnotationItem>, pub annotations: Vec<DexAnnotationItem>,
} }

View file

@ -16,22 +16,22 @@ use crate::{ins::Instruction, DexString, IdField, IdMethod, IdMethodType, IdType
pub struct Code { pub struct Code {
// TODO: remove and compute this value from code? // TODO: remove and compute this value from code?
/// The number of registers used by the code /// The number of registers used by the code
#[pyo3(get, set)] #[pyo3(get)]
pub registers_size: u16, pub registers_size: u16,
// TODO: what does it means? is it computable? // TODO: what does it means? is it computable?
/// The number of words of incoming arguments to the method /// The number of words of incoming arguments to the method
#[pyo3(get, set)] #[pyo3(get)]
pub ins_size: u16, pub ins_size: u16,
// TODO: what does it means? is it computable? // TODO: what does it means? is it computable?
/// The number of words of outgoing argument space /// The number of words of outgoing argument space
#[pyo3(get, set)] #[pyo3(get)]
pub outs_size: u16, pub outs_size: u16,
// TODO: implement // TODO: implement
/// The debug info /// The debug info
#[pyo3(get, set)] #[pyo3(get)]
pub debug_info: Vec<u8>, pub debug_info: Vec<u8>,
/// The instructions. /// The instructions.
#[pyo3(get, set)] #[pyo3(get)]
pub insns: Vec<Instruction>, pub insns: Vec<Instruction>,
} }

View file

@ -430,13 +430,13 @@ impl IdType {
pub struct IdField { pub struct IdField {
/// The name of the field, format described at /// The name of the field, format described at
/// <https://source.android.com/docs/core/runtime/dex-format#membername> /// <https://source.android.com/docs/core/runtime/dex-format#membername>
#[pyo3(get, set)] #[pyo3(get)]
pub name: DexString, pub name: DexString,
/// The type of the field. /// The type of the field.
#[pyo3(get, set)] #[pyo3(get)]
pub type_: IdType, pub type_: IdType,
/// The class that own the field. /// The class that own the field.
#[pyo3(get, set)] #[pyo3(get)]
pub class_: IdType, pub class_: IdType,
} }
@ -525,13 +525,13 @@ impl PartialOrd for IdField {
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct IdMethod { pub struct IdMethod {
/// The class containing the method. /// The class containing the method.
#[pyo3(get, set)] #[pyo3(get)]
pub class_: IdType, pub class_: IdType,
/// The prototype (aka type or signature) of the method. /// The prototype (aka type or signature) of the method.
#[pyo3(get, set)] #[pyo3(get)]
pub proto: IdMethodType, pub proto: IdMethodType,
/// The name of the method. /// The name of the method.
#[pyo3(get, set)] #[pyo3(get)]
pub name: DexString, pub name: DexString,
} }

View file

@ -14,33 +14,33 @@ use androscalpel_serializer::consts::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Field { pub struct Field {
/// The structure used to reference this field. /// The structure used to reference this field.
#[pyo3(get, set)] #[pyo3(get)]
pub descriptor: IdField, pub descriptor: IdField,
/// The field visibility /// The field visibility
#[pyo3(get, set)] #[pyo3(get)]
pub visibility: FieldVisibility, pub visibility: FieldVisibility,
/// If the field is defined for the class globally /// If the field is defined for the class globally
#[pyo3(get, set)] #[pyo3(get)]
pub is_static: bool, pub is_static: bool,
/// If the field is immutable after construction /// If the field is immutable after construction
#[pyo3(get, set)] #[pyo3(get)]
pub is_final: bool, pub is_final: bool,
/// For thread safety /// For thread safety
#[pyo3(get, set)] #[pyo3(get)]
pub is_volatile: bool, pub is_volatile: bool,
/// If the field should **not** be saved by default serialization /// If the field should **not** be saved by default serialization
#[pyo3(get, set)] #[pyo3(get)]
pub is_transient: bool, pub is_transient: bool,
/// If the field is not defined in the source code /// If the field is not defined in the source code
#[pyo3(get, set)] #[pyo3(get)]
pub is_synthetic: bool, pub is_synthetic: bool,
/// If the field is an enumerated value /// If the field is an enumerated value
#[pyo3(get, set)] #[pyo3(get)]
pub is_enum: bool, pub is_enum: bool,
/// The default value of this field /// The default value of this field
pub value: Option<DexValue>, pub value: Option<DexValue>,
/// The annotations for this field /// The annotations for this field
#[pyo3(get, set)] #[pyo3(get)]
pub annotations: Vec<DexAnnotationItem>, pub annotations: Vec<DexAnnotationItem>,
} }

File diff suppressed because it is too large Load diff

View file

@ -14,55 +14,55 @@ use androscalpel_serializer::consts::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Method { pub struct Method {
/// The structure used to reference this method. /// The structure used to reference this method.
#[pyo3(get, set)] #[pyo3(get)]
pub descriptor: IdMethod, pub descriptor: IdMethod,
/// The field visibility. /// The field visibility.
#[pyo3(get, set)] #[pyo3(get)]
pub visibility: MethodVisibility, pub visibility: MethodVisibility,
/// Static methods do not take this in argument. /// Static methods do not take this in argument.
#[pyo3(get, set)] #[pyo3(get)]
pub is_static: bool, pub is_static: bool,
/// Final methods are not averridable. /// Final methods are not averridable.
#[pyo3(get, set)] #[pyo3(get)]
pub is_final: bool, pub is_final: bool,
/// Synchronized method automatically acquire their associated lock around call. /// Synchronized method automatically acquire their associated lock around call.
/// Can only be set in native method, (`[Self::is_native] = true`). /// Can only be set in native method, (`[Self::is_native] = true`).
#[pyo3(get, set)] #[pyo3(get)]
pub is_synchronized: bool, pub is_synchronized: bool,
/// Bridge are automatically added by the compiler as a type-safe bridge. /// Bridge are automatically added by the compiler as a type-safe bridge.
#[pyo3(get, set)] #[pyo3(get)]
pub is_bridge: bool, pub is_bridge: bool,
/// If the last argument should be treated as a "rest" argument by compiler /// If the last argument should be treated as a "rest" argument by compiler
/// (for method of variable number of argument). /// (for method of variable number of argument).
#[pyo3(get, set)] #[pyo3(get)]
pub is_varargs: bool, pub is_varargs: bool,
/// If the method is a native method. /// If the method is a native method.
#[pyo3(get, set)] #[pyo3(get)]
pub is_native: bool, pub is_native: bool,
/// Abstract methods are not implemented by the class. /// Abstract methods are not implemented by the class.
#[pyo3(get, set)] #[pyo3(get)]
pub is_abstract: bool, pub is_abstract: bool,
/// If the method must use strict rules for floating point arithmetic. /// If the method must use strict rules for floating point arithmetic.
#[pyo3(get, set)] #[pyo3(get)]
pub is_strictfp: bool, pub is_strictfp: bool,
/// Synthetic method are not directly defined in the source code. /// Synthetic method are not directly defined in the source code.
#[pyo3(get, set)] #[pyo3(get)]
pub is_synthetic: bool, pub is_synthetic: bool,
/// If the method is a constructor. /// If the method is a constructor.
#[pyo3(get, set)] #[pyo3(get)]
pub is_constructor: bool, pub is_constructor: bool,
/// If the method is declared as synchronize (just indicatif) /// If the method is declared as synchronize (just indicatif)
#[pyo3(get, set)] #[pyo3(get)]
pub is_declared_syncrhonized: bool, pub is_declared_syncrhonized: bool,
/// The annotations for this method /// The annotations for this method
#[pyo3(get, set)] #[pyo3(get)]
pub annotations: Vec<DexAnnotationItem>, pub annotations: Vec<DexAnnotationItem>,
/// The annotations for the parameters of this method method /// The annotations for the parameters of this method method
#[pyo3(get, set)] #[pyo3(get)]
pub parameters_annotations: Vec<Vec<DexAnnotationItem>>, pub parameters_annotations: Vec<Vec<DexAnnotationItem>>,
/// The code of the method /// The code of the method
#[pyo3(get, set)] #[pyo3(get)]
pub code: Option<Code>, pub code: Option<Code>,
} }

22
test.py
View file

@ -37,13 +37,13 @@ new_insns = []
for i in code.insns: for i in code.insns:
if isinstance(i, asc.ins.ConstString): if isinstance(i, asc.ins.ConstString):
if i.lit == "Hello": if i.lit == "Hello":
i.lit = DexString("Degemer Mat") i = asc.ins.ConstString(i.reg, DexString("Degemer Mat"))
elif i.lit == "Bye": elif i.lit == "Bye":
i.lit = DexString("Kenavo") i = asc.ins.ConstString(i.reg, DexString("Kenavo"))
new_insns.append(i) new_insns.append(i)
# This need improving! # This need improving!
code.insns = new_insns code = asc.Code(code.registers_size, code.ins_size, code.outs_size, new_insns)
apk.set_method_code(method_id, code) apk.set_method_code(method_id, code)
# apk.set_method_code(method.descriptor, code) # apk.set_method_code(method.descriptor, code)
@ -57,5 +57,19 @@ for i in code.insns:
dex_raw = apk.gen_raw_dex() dex_raw = apk.gen_raw_dex()
assert len(dex_raw) == 1 assert len(dex_raw) == 1
with open(DEX_NAME + ".out", "wb") as file: with open(DEX_NAME, "wb") as file:
file.write(dex_raw[0]) file.write(dex_raw[0])
with open(DEX_NAME, "rb") as file:
dex = file.read()
new_apk = asc.Apk()
new_apk.add_dex_file(dex)
clazz = new_apk.classes[clazz_id]
method = clazz.virtual_methods[method_id]
code = method.code
print(f"Code of {method_id} in new apk")
for i in code.insns:
print(i)