remove setter to limit confusion
This commit is contained in:
parent
3a6edf1aa2
commit
ebaeaef877
10 changed files with 305 additions and 294 deletions
3
TODO.md
3
TODO.md
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
@ -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
22
test.py
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue