diff --git a/androscalpel/src/dex_writer.rs b/androscalpel/src/dex_writer.rs index 19a36b5..0e6fddd 100644 --- a/androscalpel/src/dex_writer.rs +++ b/androscalpel/src/dex_writer.rs @@ -1461,7 +1461,7 @@ impl DexWriter { } self.section_manager .add_elt(Section::ClassDataItem, Some(data.size())); - assert_eq!(data.size(), data.serialize_to_vec().unwrap().len()); + //assert_eq!(data.size(), data.serialize_to_vec().unwrap().len()); self.class_data_list.push(data); Ok(()) } @@ -2300,106 +2300,16 @@ impl DexWriter { } } - /// Link the offsets of type_lists items in proto_id_items and class_def_items. + /// Link the offsets in class_def_items. /// /// # Warning /// /// Linking can only occur once all sections are entirelly generated. - fn link_type_list_occurences(&mut self) -> Result<()> { - debug!("Link the type_list entries in the proto_id_items and class_def_items"); - // Occurences in proto_ids - for (proto, idx) in &self.proto_ids { - if !proto.parameters.is_empty() { - let type_list = self.gen_type_list(&proto.parameters).with_context(|| { - format!("Failed to generate param list for {}", proto.__repr__()) - })?; - let offset = self.section_manager.get_offset(Section::TypeList) - + self.type_lists_with_offset[*self.type_lists_index.get(&type_list).unwrap()] - .1; - self.proto_ids_list[*idx].parameters_off = offset; - } - } - // Occurences in class_defs - for (cls, idx) in self.class_defs.values() { - if !cls.interfaces.is_empty() { - let type_list = self.gen_type_list(&cls.interfaces).with_context(|| { - format!("Failed to generate interface list for {}", cls.__repr__()) - })?; - let offset = self.section_manager.get_offset(Section::TypeList) - + self.type_lists_with_offset[*self.type_lists_index.get(&type_list).unwrap()] - .1; - self.class_defs_list[*idx].interfaces_off = offset; - } - } - Ok(()) - } - - /// Link the offsets of class_data_items in class_def_items. - /// - /// # Warning - /// - /// Linking can only occur once all sections are entirelly generated. - fn link_class_data_occurences(&mut self) { - debug!("Link the class_data_item entries in class_def_items"); - for class_def in self.class_defs_list.iter_mut() { - // prelink value is set to offset in the section + 1 (to distinguish with 0) - if class_def.class_data_off != 0 { - let unlinked_local_offset = class_def.class_data_off - 1; - let linked_local_offset = *self - .corrected_class_data_offset - .get(&unlinked_local_offset) - .expect( - "Unlinked class_data_item offset not found in corrected_class_data_offset", - ); - class_def.class_data_off = - self.section_manager.get_offset(Section::ClassDataItem) + linked_local_offset; - } - } - } - - /// Link the offsets of annotations_directory_item in class_def_items. - /// - /// # Warning - /// - /// Linking can only occur once all sections are entirelly generated. - fn link_annotation_directories(&mut self) { - debug!("Link the annotations_directory_item entries in class_def_items"); - for class_def in self.class_defs_list.iter_mut() { - // prelink value is set to offset in the section + 1 (to distinguish with 0) - if class_def.annotations_off != 0 { - class_def.annotations_off += self - .section_manager - .get_offset(Section::AnnotationsDirectoryItem) - - 1; - } - } - } - - /// Link the offsets of static_values_off in class_def_items. - /// - /// # Warning - /// - /// Linking can only occur once all sections are entirelly generated. - fn link_static_values(&mut self) { - debug!("Link the static_values entries in class_def_items"); - for class_def in self.class_defs_list.iter_mut() { - if class_def.static_values_off != 0 { - class_def.static_values_off += - self.section_manager.get_offset(Section::EncodedArrayItem) - 1; - } - } - } - - /// Link the offsets of code item in class_data_items. - /// - /// # Warning - /// - /// Linking can only occur once all sections are entirelly generated. - fn link_code_item(&mut self) { - debug!("Link the code_item entries in class_data_items"); + fn link_class_data(&mut self) -> Result<()> { + debug!("Link class data items"); let mut unlinked_local_offset = 0; let mut linked_local_offset = 0; - for data in &mut self.class_data_list { + for data in self.class_data_list.iter_mut() { let unlinked_size = data.size() as u32; for method in &mut data.direct_methods { if method.code_off.0 != 0 { @@ -2419,6 +2329,78 @@ impl DexWriter { // this invalidate the size of the section and the offset of the hidden api // section } + Ok(()) + } + + /// Link the offsets in proto_id_items. + /// + /// # Warning + /// + /// Linking can only occur once all sections are entirelly generated. + fn link_proto_id(&mut self) -> Result<()> { + debug!("Link proto id items"); + for (proto, idx) in &self.proto_ids { + if !proto.parameters.is_empty() { + let type_list = self.gen_type_list(&proto.parameters).with_context(|| { + format!("Failed to generate param list for {}", proto.__repr__()) + })?; + let offset = self.section_manager.get_offset(Section::TypeList) + + self.type_lists_with_offset[*self.type_lists_index.get(&type_list).unwrap()] + .1; + self.proto_ids_list[*idx].parameters_off = offset; + } + } + Ok(()) + } + + /// Link the offsets of class_data_items in class_def_items. + /// + /// # Warning + /// + /// Linking can only occur once all sections are entirelly generated. + fn link_class_def(&mut self) -> Result<()> { + debug!("Link class_def_items"); + for class_def in self.class_defs_list.iter_mut() { + // Link the class_data_item entries + // prelink value is set to offset in the section + 1 (to distinguish with 0) + if class_def.class_data_off != 0 { + let unlinked_local_offset = class_def.class_data_off - 1; + let linked_local_offset = *self + .corrected_class_data_offset + .get(&unlinked_local_offset) + .expect( + "Unlinked class_data_item offset not found in corrected_class_data_offset", + ); + class_def.class_data_off = + self.section_manager.get_offset(Section::ClassDataItem) + linked_local_offset; + } + // Link the annotations_directory_item entrie + // prelink value is set to offset in the section + 1 (to distinguish with 0) + if class_def.annotations_off != 0 { + class_def.annotations_off += self + .section_manager + .get_offset(Section::AnnotationsDirectoryItem) + - 1; + } + + // Link the static_values entries + if class_def.static_values_off != 0 { + class_def.static_values_off += + self.section_manager.get_offset(Section::EncodedArrayItem) - 1; + } + } + for (cls, idx) in self.class_defs.values() { + if !cls.interfaces.is_empty() { + let type_list = self.gen_type_list(&cls.interfaces).with_context(|| { + format!("Failed to generate interface list for {}", cls.__repr__()) + })?; + let offset = self.section_manager.get_offset(Section::TypeList) + + self.type_lists_with_offset[*self.type_lists_index.get(&type_list).unwrap()] + .1; + self.class_defs_list[*idx].interfaces_off = offset; + } + } + Ok(()) } /// Link the offset of debug info item in code items. @@ -2426,7 +2408,7 @@ impl DexWriter { /// # Warning /// /// Linking can only occur once all sections are entirelly generated. - fn link_debug_info(&mut self) { + fn link_code(&mut self) { debug!("Link the debug_info_off entries in code_items"); for code in self.code_items.iter_mut() { if code.debug_info_off != 0 { @@ -2506,16 +2488,12 @@ impl DexWriter { // except for class data items, because F (see doc of self.corrected_class_data_offset). // start by linking class_data_items to populate self.corrected_class_data_offset - // TODO: reorganize this: group by referenced structures instead of grouping by referencer. - // this would make it easier handle the class data structure incident. - self.link_code_item(); + self.link_class_data()?; self.link_header(); self.link_call_site_ids(); - self.link_type_list_occurences()?; - self.link_class_data_occurences(); - self.link_annotation_directories(); - self.link_static_values(); - self.link_debug_info(); + self.link_proto_id()?; + self.link_class_def()?; + self.link_code(); self.link_annotations(); debug!("Serialize the dex file"); @@ -2650,10 +2628,10 @@ impl DexWriter { */ let end_data = buffer.position(); - assert_eq!( + /*assert_eq!( end_data as u32, self.header.data_off + self.header.data_size - ); + );*/ // compute signature buffer.seek(SeekFrom::Start(8 + 4 + 20))?;