add signatures and checksums

This commit is contained in:
Jean-Marie Mineau 2024-01-04 14:28:13 +01:00
parent d470881d98
commit e1f1d01e2c
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
3 changed files with 125 additions and 27 deletions

77
Cargo.lock generated
View file

@ -21,11 +21,13 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
name = "androscalpel" name = "androscalpel"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"adler",
"androscalpel_serializer", "androscalpel_serializer",
"anyhow", "anyhow",
"log", "log",
"pyo3 0.20.0", "pyo3 0.20.0",
"pyo3-log", "pyo3-log",
"sha1",
] ]
[[package]] [[package]]
@ -88,6 +90,15 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.83" version = "1.0.83"
@ -103,6 +114,45 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cpufeatures"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.28.1" version = "0.28.1"
@ -132,9 +182,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.147" version = "0.2.151"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -381,6 +431,17 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.11.0" version = "1.11.0"
@ -404,6 +465,12 @@ version = "0.12.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a"
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.11" version = "1.0.11"
@ -416,6 +483,12 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View file

@ -9,8 +9,10 @@ name = "androscalpel"
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
adler = "1.0.2"
androscalpel_serializer = { version = "0.1.0", path = "../androscalpel_serializer" } androscalpel_serializer = { version = "0.1.0", path = "../androscalpel_serializer" }
anyhow = { version = "1.0.75", features = ["backtrace"] } anyhow = { version = "1.0.75", features = ["backtrace"] }
log = "0.4.20" log = "0.4.20"
pyo3 = { version = "0.20.0", features = ["anyhow"] } pyo3 = { version = "0.20.0", features = ["anyhow"] }
pyo3-log = "0.8.3" pyo3-log = "0.8.3"
sha1 = "0.10.6"

View file

@ -1,11 +1,13 @@
//! The structure that generate a .dex from classes. //! The structure that generate a .dex from classes.
use std::collections::{HashMap, HashSet, VecDeque}; use std::collections::{HashMap, HashSet, VecDeque};
use std::io::{Cursor, Write}; use std::io;
use std::io::{Cursor, Seek, SeekFrom, Write};
use log::debug;
use adler::Adler32;
use anyhow::{anyhow, bail, Context}; use anyhow::{anyhow, bail, Context};
use log::debug;
use sha1::{Digest, Sha1};
use crate::Result; use crate::Result;
use crate::*; use crate::*;
@ -1898,7 +1900,7 @@ impl DexWriter {
annotation_off + 1 annotation_off + 1
} else { } else {
0 0
}, // TODO: link }, // linked in link_annotations()
}); });
} }
@ -2422,57 +2424,58 @@ impl DexWriter {
self.link_annotations(); self.link_annotations();
debug!("Serialize the dex file"); debug!("Serialize the dex file");
let mut buffer = Cursor::new(Vec::<u8>::new());
// TODO: compute checksum, hash, ect // TODO: compute checksum, hash, ect
self.header.serialize(writer)?; self.header.serialize(&mut buffer)?;
// StringIdItem section // StringIdItem section
let mut string_off = self.section_manager.get_offset(Section::StringDataItem); let mut string_off = self.section_manager.get_offset(Section::StringDataItem);
for string in self.string_data_list.iter() { for string in self.string_data_list.iter() {
let str_id = StringIdItem { let str_id = StringIdItem {
string_data_off: string_off, string_data_off: string_off,
}; };
str_id.serialize(writer)?; str_id.serialize(&mut buffer)?;
string_off += string.size() as u32; string_off += string.size() as u32;
} }
// TypeId section // TypeId section
for ty in &self.type_ids_list { for ty in &self.type_ids_list {
ty.serialize(writer)?; ty.serialize(&mut buffer)?;
} }
// ProtoId section // ProtoId section
for proto in &self.proto_ids_list { for proto in &self.proto_ids_list {
proto.serialize(writer)?; proto.serialize(&mut buffer)?;
} }
// FieldIdItem section // FieldIdItem section
for field_id in &self.field_ids_list { for field_id in &self.field_ids_list {
field_id.serialize(writer)?; field_id.serialize(&mut buffer)?;
} }
// MethodIdItem section // MethodIdItem section
for method_id in &self.method_ids_list { for method_id in &self.method_ids_list {
method_id.serialize(writer)?; method_id.serialize(&mut buffer)?;
} }
// ClassDefItem section // ClassDefItem section
for class_def in &self.class_defs_list { for class_def in &self.class_defs_list {
class_def.serialize(writer)?; class_def.serialize(&mut buffer)?;
} }
// CallSiteIdItem, data are inserted as encoded array item later // CallSiteIdItem, data are inserted as encoded array item later
for call_site_id in &self.call_site_ids { for call_site_id in &self.call_site_ids {
call_site_id.serialize(writer)?; call_site_id.serialize(&mut buffer)?;
} }
// MethodHandleItem section // MethodHandleItem section
for handle in &self.method_handles { for handle in &self.method_handles {
handle.serialize(writer)?; handle.serialize(&mut buffer)?;
} }
// MapList // MapList
self.map_list.serialize(writer)?; self.map_list.serialize(&mut buffer)?;
// TypeList, // TypeList,
let mut offset = 0; // the sections are always aligned until the type_lists let mut offset = 0; // the sections are always aligned until the type_lists
for (list, _) in &self.type_lists_with_offset { for (list, _) in &self.type_lists_with_offset {
while offset % 4 != 0 { while offset % 4 != 0 {
offset += 1; offset += 1;
0u8.serialize(writer)?; 0u8.serialize(&mut buffer)?;
} }
offset += list.size(); offset += list.size();
list.serialize(writer)?; list.serialize(&mut buffer)?;
} }
// The next section requires alignment to 4 // The next section requires alignment to 4
while offset % 4 != 0 { while offset % 4 != 0 {
@ -2482,41 +2485,61 @@ impl DexWriter {
} }
// AnnotationSetRefList section // AnnotationSetRefList section
for list in &self.annotation_set_lists { for list in &self.annotation_set_lists {
list.serialize(writer)?; list.serialize(&mut buffer)?;
} }
// AnnotationSetItem section // AnnotationSetItem section
for set in &self.annotation_set_items { for set in &self.annotation_set_items {
set.serialize(writer)?; set.serialize(&mut buffer)?;
} }
// ClassDataItem section // ClassDataItem section
for data in &self.class_data_list { for data in &self.class_data_list {
data.serialize(writer)?; data.serialize(&mut buffer)?;
} }
// CodeItem section // CodeItem section
for code_item in &self.code_items { for code_item in &self.code_items {
code_item.serialize(writer)? code_item.serialize(&mut buffer)?
} }
for string in &self.string_data_list { for string in &self.string_data_list {
string.serialize(writer)?; string.serialize(&mut buffer)?;
} }
// DebugInfoItem section // DebugInfoItem section
for debug_info in &self.debug_info_items { for debug_info in &self.debug_info_items {
debug_info.serialize(writer)?; debug_info.serialize(&mut buffer)?;
} }
// AnnotationItem section // AnnotationItem section
for annot in &self.annotation_items { for annot in &self.annotation_items {
annot.serialize(writer)?; annot.serialize(&mut buffer)?;
} }
// EncodedArrayItem section // EncodedArrayItem section
for array in &self.encoded_array_items { for array in &self.encoded_array_items {
array.serialize(writer)?; array.serialize(&mut buffer)?;
} }
// AnnotationsDirectoryItem section // AnnotationsDirectoryItem section
for dir in &self.annotations_directory_items { for dir in &self.annotations_directory_items {
dir.serialize(writer)?; dir.serialize(&mut buffer)?;
} }
// TODO: HiddenapiClassDataItem, // TODO: HiddenapiClassDataItem,
// compute signature
buffer.seek(SeekFrom::Start(8 + 4 + 20))?;
let mut hasher = Sha1::new();
io::copy(&mut buffer, &mut hasher)?;
self.header.signature = hasher.finalize().into();
buffer.rewind()?;
self.header.serialize(&mut buffer)?;
// Compute checksum
//buffer.seek(SeekFrom::Start(8 + 4))?;
let mut adler = Adler32::new();
adler.write_slice(&buffer.get_ref()[8 + 4..]);
self.header.checksum = adler.checksum();
buffer.rewind()?;
self.header.serialize(&mut buffer)?;
// copy buffer to output
buffer.rewind()?;
io::copy(&mut buffer, writer)?;
Ok(()) Ok(())
} }