WIP
This commit is contained in:
parent
559ae665cf
commit
68b11dc036
5 changed files with 91 additions and 12 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
//! Representation of an apk.
|
//! Representation of an apk.
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{Class, Result};
|
use crate::{Class, Error, Result};
|
||||||
use androscalpel_serializer::{ClassDefItem, DexFileReader};
|
use androscalpel_serializer::{ClassDefItem, DexFileReader, TypeList, NO_INDEX};
|
||||||
|
|
||||||
/// Represent an apk.
|
/// Represent an apk.
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
|
@ -15,7 +15,10 @@ pub struct Apk {
|
||||||
impl Apk {
|
impl Apk {
|
||||||
/// Add the content of a dex file to the apk.
|
/// Add the content of a dex file to the apk.
|
||||||
pub fn add_dex_file(&mut self, data: &[u8]) -> Result<()> {
|
pub fn add_dex_file(&mut self, data: &[u8]) -> Result<()> {
|
||||||
|
println!("Start parsing file");
|
||||||
let dex = DexFileReader::new(data)?;
|
let dex = DexFileReader::new(data)?;
|
||||||
|
println!("Header and lists parsed");
|
||||||
|
println!("Start parsing classes");
|
||||||
for class in dex.get_class_defs() {
|
for class in dex.get_class_defs() {
|
||||||
self.add_class_from_dex_file(class, &dex)?;
|
self.add_class_from_dex_file(class, &dex)?;
|
||||||
}
|
}
|
||||||
|
|
@ -23,8 +26,65 @@ impl Apk {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a class from a dex file reader.
|
/// Add a class from a dex file reader.
|
||||||
fn add_class_from_dex_file(&mut self, class: &ClassDefItem, dex: &DexFileReader) -> Result<()> {
|
fn add_class_from_dex_file(
|
||||||
todo!()
|
&mut self,
|
||||||
|
class_item: &ClassDefItem,
|
||||||
|
dex: &DexFileReader,
|
||||||
|
) -> Result<()> {
|
||||||
|
let name_idx = dex
|
||||||
|
.get_type_ids()
|
||||||
|
.get(class_item.class_idx as usize)
|
||||||
|
.ok_or(Error::InconsistantStruct(format!(
|
||||||
|
"type idx {} out of bound of type_ids (|type_ids| = {})",
|
||||||
|
class_item.class_idx,
|
||||||
|
dex.get_type_ids().len()
|
||||||
|
)))?
|
||||||
|
.descriptor_idx;
|
||||||
|
let name = dex.get_string(name_idx)?.into();
|
||||||
|
let superclass = if class_item.class_idx == NO_INDEX.0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let superclass_idx = dex
|
||||||
|
.get_type_ids()
|
||||||
|
.get(class_item.class_idx as usize)
|
||||||
|
.ok_or(Error::InconsistantStruct(format!(
|
||||||
|
"type idx {} out of bound of type_ids (|type_ids| = {})",
|
||||||
|
class_item.class_idx,
|
||||||
|
dex.get_type_ids().len()
|
||||||
|
)))?
|
||||||
|
.descriptor_idx;
|
||||||
|
Some(dex.get_string(superclass_idx)?.into())
|
||||||
|
};
|
||||||
|
let interfaces = if class_item.interfaces_off == 0 {
|
||||||
|
vec![]
|
||||||
|
} else {
|
||||||
|
let type_list = dex.get_struct_at_offset::<TypeList>(class_item.interfaces_off)?;
|
||||||
|
let mut list = vec![];
|
||||||
|
for ty in type_list.list {
|
||||||
|
let ty = dex.get_type_ids().get(ty.type_idx as usize).ok_or(
|
||||||
|
Error::InconsistantStruct(format!(
|
||||||
|
"type idx {} out of bound of type_ids (|type_ids| = {})",
|
||||||
|
ty.type_idx,
|
||||||
|
dex.get_type_ids().len()
|
||||||
|
)),
|
||||||
|
)?;
|
||||||
|
let ty = dex.get_string(ty.descriptor_idx)?.into();
|
||||||
|
list.push(ty);
|
||||||
|
}
|
||||||
|
list
|
||||||
|
};
|
||||||
|
let source_file = if class_item.source_file_idx == NO_INDEX.0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(dex.get_string(class_item.source_file_idx)?.into())
|
||||||
|
};
|
||||||
|
self.classes.push(Class {
|
||||||
|
name,
|
||||||
|
superclass,
|
||||||
|
interfaces,
|
||||||
|
source_file,
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,6 +92,11 @@ impl Apk {
|
||||||
impl Apk {
|
impl Apk {
|
||||||
#[new]
|
#[new]
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
|
println!("Create APK");
|
||||||
Self { classes: vec![] }
|
Self { classes: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn py_add_dex_file(&mut self, data: &[u8]) -> Result<()> {
|
||||||
|
self.add_dex_file(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@ use crate::DexString;
|
||||||
pub struct Class {
|
pub struct Class {
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub name: DexString,
|
pub name: DexString,
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub ty: DexString,
|
|
||||||
// pub access_flags: // TODO
|
// pub access_flags: // TODO
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub superclass: Option<DexString>,
|
pub superclass: Option<DexString>,
|
||||||
|
|
@ -28,10 +26,9 @@ pub struct Class {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl Class {
|
impl Class {
|
||||||
#[new]
|
#[new]
|
||||||
pub fn new(name: DexString, ty: DexString) -> Self {
|
pub fn new(name: DexString) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
ty,
|
|
||||||
superclass: None,
|
superclass: None,
|
||||||
interfaces: vec![],
|
interfaces: vec![],
|
||||||
source_file: None,
|
source_file: None,
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CallSiteIdItem, ClassDefItem, EndianConstant, Error, FieldIdItem, HeaderItem, MapItemType,
|
CallSiteIdItem, ClassDefItem, EndianConstant, Error, FieldIdItem, HeaderItem, MapItemType,
|
||||||
MapList, MethodHandleItem, MethodIdItem, ProtoIdItem, Result, Serializable, StringIdItem,
|
MapList, MethodHandleItem, MethodIdItem, ProtoIdItem, Result, Serializable, StringDataItem,
|
||||||
TypeIdItem,
|
StringIdItem, TypeIdItem,
|
||||||
};
|
};
|
||||||
use std::io::{Cursor, Seek, SeekFrom};
|
use std::io::{Cursor, Seek, SeekFrom};
|
||||||
|
|
||||||
|
|
@ -127,6 +127,21 @@ impl<'a> DexFileReader<'a> {
|
||||||
&self.map_list
|
&self.map_list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the [`StringDataItem`] of from its idx.
|
||||||
|
pub fn get_string(&self, idx: u32) -> Result<StringDataItem> {
|
||||||
|
let id = self
|
||||||
|
.string_ids
|
||||||
|
.get(idx as usize)
|
||||||
|
.ok_or(Error::InconsistantStruct(format!(
|
||||||
|
"string idx {idx} is out of bound (|string_ids|={})",
|
||||||
|
self.string_ids.len()
|
||||||
|
)))?;
|
||||||
|
self.get_struct_at_offset(id.string_data_off)
|
||||||
|
.map_err(|err| {
|
||||||
|
Error::DeserializationError(format!("Failled to parse string {idx}: {err}"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn sanity_check(&self) -> Result<()> {
|
fn sanity_check(&self) -> Result<()> {
|
||||||
if self.header.magic.version != [0x30, 0x33, 0x39] {
|
if self.header.magic.version != [0x30, 0x33, 0x39] {
|
||||||
println!(
|
println!(
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ pub struct ClassDefItem {
|
||||||
pub class_idx: u32,
|
pub class_idx: u32,
|
||||||
/// See <https://source.android.com/docs/core/runtime/dex-format#access-flags>
|
/// See <https://source.android.com/docs/core/runtime/dex-format#access-flags>
|
||||||
pub access_flags: u32,
|
pub access_flags: u32,
|
||||||
/// Either index of a [`crate::TypeIdItem`] in `type_ids`, must be a class or NO_INDEX
|
/// Either index of a [`crate::TypeIdItem`] in `type_ids`, must be a class or
|
||||||
|
/// [`crate::NO_INDEX`]
|
||||||
pub superclass_idx: u32,
|
pub superclass_idx: u32,
|
||||||
/// 0 if no interfaces, else offset to a [`crate::TypeList`].
|
/// 0 if no interfaces, else offset to a [`crate::TypeList`].
|
||||||
pub interfaces_off: u32,
|
pub interfaces_off: u32,
|
||||||
|
|
@ -247,6 +248,6 @@ impl Serializable for TypeList {
|
||||||
/// <https://source.android.com/docs/core/runtime/dex-format#type-item-format>
|
/// <https://source.android.com/docs/core/runtime/dex-format#type-item-format>
|
||||||
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct TypeItem {
|
pub struct TypeItem {
|
||||||
/// Index into the `type_ids` list.
|
/// Index of a [`crate::TypeIdItem`] in the `type_ids` list.
|
||||||
pub type_idx: u16,
|
pub type_idx: u16,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ pub use map::*;
|
||||||
/// alignment: 4 bytes
|
/// alignment: 4 bytes
|
||||||
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct StringIdItem {
|
pub struct StringIdItem {
|
||||||
|
/// Offset of a [`crate::StringDataItem`].
|
||||||
pub string_data_off: u32,
|
pub string_data_off: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue