mirror of
https://github.com/QuasarApp/LIEF.git
synced 2025-04-28 05:14:33 +00:00
Add support for Android 9
This commit is contained in:
parent
04dddd3710
commit
bce9ebe170
@ -29,7 +29,8 @@ void init_versions(py::module& m) {
|
||||
.value(PY_ENUM(ANDROID_VERSIONS::VERSION_710))
|
||||
.value(PY_ENUM(ANDROID_VERSIONS::VERSION_712))
|
||||
.value(PY_ENUM(ANDROID_VERSIONS::VERSION_800))
|
||||
.value(PY_ENUM(ANDROID_VERSIONS::VERSION_810));
|
||||
.value(PY_ENUM(ANDROID_VERSIONS::VERSION_810))
|
||||
.value(PY_ENUM(ANDROID_VERSIONS::VERSION_900));
|
||||
|
||||
m.def("code_name",
|
||||
&code_name,
|
||||
|
@ -37,6 +37,8 @@
|
||||
//
|
||||
// Android 8.0.0: ART 44
|
||||
// Android 8.1.0: ART 46
|
||||
//
|
||||
// Android 9.0.0 ART 56
|
||||
// ======================
|
||||
|
||||
namespace LIEF {
|
||||
@ -375,6 +377,86 @@ using header = ART_44::header;
|
||||
|
||||
} // Namespace ART_46
|
||||
|
||||
// ==============================
|
||||
// ART 56
|
||||
// - Android 9.0.0
|
||||
// ==============================
|
||||
namespace ART_56 {
|
||||
|
||||
static constexpr art_version_t art_version = 56;
|
||||
static constexpr uint32_t nb_sections = 10;
|
||||
static constexpr uint32_t nb_image_roots = 3;
|
||||
static constexpr uint32_t nb_image_methods = 9; // Android 9.0.0 - +=2
|
||||
struct ALIGNED_(4) header {
|
||||
|
||||
uint8_t magic[4];
|
||||
uint8_t version[4];
|
||||
|
||||
// Required base address for mapping the image.
|
||||
uint32_t image_begin;
|
||||
|
||||
// Image size, not page aligned.
|
||||
uint32_t image_size;
|
||||
|
||||
// Checksum of the oat file we link to for load time sanity check.
|
||||
uint32_t oat_checksum;
|
||||
|
||||
// Start address for oat file. Will be before oat_data_begin_ for .so files.
|
||||
uint32_t oat_file_begin;
|
||||
|
||||
// Required oat address expected by image Method::GetCode() pointers.
|
||||
uint32_t oat_data_begin;
|
||||
|
||||
// End of oat data address range for this image file.
|
||||
uint32_t oat_data_end;
|
||||
|
||||
// End of oat file address range. will be after oat_data_end_ for
|
||||
// .so files. Used for positioning a following alloc spaces.
|
||||
uint32_t oat_file_end;
|
||||
|
||||
// Boot image begin and end (app image headers only).
|
||||
uint32_t boot_image_begin;
|
||||
uint32_t boot_image_size;
|
||||
|
||||
// Boot oat begin and end (app image headers only).
|
||||
uint32_t boot_oat_begin;
|
||||
uint32_t boot_oat_size;
|
||||
|
||||
// The total delta that this image has been patched.
|
||||
int32_t patch_delta;
|
||||
|
||||
// Absolute address of an Object[] of objects needed to reinitialize from an image.
|
||||
uint32_t image_roots;
|
||||
|
||||
// Pointer size, this affects the size of the ArtMethods.
|
||||
uint32_t pointer_size;
|
||||
|
||||
// Boolean (0 or 1) to denote if the image was compiled with --compile-pic option
|
||||
uint32_t compile_pic;
|
||||
|
||||
// Boolean (0 or 1) to denote if the image can be mapped at a random address, this only refers to
|
||||
// the .art file. Currently, app oat files do not depend on their app image. There are no pointers
|
||||
// from the app oat code to the app image.
|
||||
uint32_t is_pic;
|
||||
|
||||
// Image sections
|
||||
image_section_t sections[nb_sections];
|
||||
|
||||
// Image methods.
|
||||
uint64_t image_methods[nb_image_methods];
|
||||
|
||||
// Storage method for the image, the image may be compressed.
|
||||
uint32_t storage_mode;
|
||||
|
||||
// Data size for the image data excluding the bitmap and the header. For compressed images, this
|
||||
// is the compressed size in the file.
|
||||
uint32_t data_size;
|
||||
};
|
||||
|
||||
|
||||
} // Namespace ART_56
|
||||
|
||||
|
||||
class ART17 {
|
||||
public:
|
||||
using art_header_t = ART_17::header;
|
||||
@ -520,6 +602,36 @@ class ART46 {
|
||||
using jdex_cache_t = ART_46::Java::jdex_cache_t<T>;
|
||||
};
|
||||
|
||||
class ART56 {
|
||||
public:
|
||||
using art_header_t = ART_56::header;
|
||||
static constexpr art_version_t art_version = ART_56::art_version;
|
||||
static constexpr uint32_t nb_image_roots = ART_56::nb_image_roots;
|
||||
|
||||
using IMAGE_SECTIONS = ART_46::IMAGE_SECTIONS;
|
||||
using IMAGE_METHODS = ART_46::IMAGE_METHODS;
|
||||
using IMAGE_ROOTS = ART_46::IMAGE_ROOTS;
|
||||
|
||||
// =====================
|
||||
// Java
|
||||
// =====================
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jobject_t = ART_56::Java::jobject_t<T>;
|
||||
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jarray_t = ART_56::Java::jarray_t<T>;
|
||||
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jclass_t = ART_56::Java::jclass_t<T>;
|
||||
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jstring_t = ART_56::Java::jstring_t<T>;
|
||||
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jdex_cache_t = ART_56::Java::jdex_cache_t<T>;
|
||||
};
|
||||
|
||||
|
||||
@LIEF_ART_STRUCTURES@
|
||||
|
||||
|
||||
|
@ -357,6 +357,35 @@ using jdex_cache_t = ART_44::Java::jdex_cache_t<T>;
|
||||
} // Namespace Java
|
||||
} // Namespace ART_46
|
||||
|
||||
// ======================
|
||||
// Android 9.0.0 - ART 66
|
||||
// ======================
|
||||
namespace ART_56 {
|
||||
|
||||
//! @brief Namespace related to the Java part of ART 46
|
||||
namespace Java {
|
||||
|
||||
using heap_reference_t = ART_46::Java::heap_reference_t;
|
||||
using brooks_read_barrier_t = ART_46::Java::brooks_read_barrier_t;
|
||||
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jobject_t = ART_46::Java::jobject_t<T>;
|
||||
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jarray_t = ART_46::Java::jarray_t<T>;
|
||||
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jclass_t = ART_46::Java::jclass_t<T>;
|
||||
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jstring_t = ART_46::Java::jstring_t<T>;
|
||||
|
||||
template<class T = no_brooks_read_barrier_t>
|
||||
using jdex_cache_t = ART_46::Java::jdex_cache_t<T>;
|
||||
|
||||
} // Namespace Java
|
||||
} // Namespace ART_56
|
||||
|
||||
} // Namespace ART
|
||||
} // Namespace LIEF
|
||||
|
||||
|
@ -164,6 +164,23 @@ static constexpr uint8_t magic[] = { 'd', 'e', 'x', '\n', '0', '3', '8', '\0' };
|
||||
|
||||
}
|
||||
|
||||
namespace DEX_39 {
|
||||
|
||||
using header = DEX::header;
|
||||
using class_def_item = DEX::class_def_item;
|
||||
using method_id_item = DEX::method_id_item;
|
||||
using field_id_item = DEX::field_id_item;
|
||||
using string_data_item = DEX::string_data_item;
|
||||
using map_items = DEX::map_items;
|
||||
using map = DEX::map;
|
||||
using proto_id_item = DEX::proto_id_item;
|
||||
using code_item = DEX::code_item;
|
||||
|
||||
static constexpr dex_version_t dex_version = 39;
|
||||
static constexpr uint8_t magic[] = { 'd', 'e', 'x', '\n', '0', '3', '9', '\0' };
|
||||
|
||||
}
|
||||
|
||||
|
||||
class DEX35 {
|
||||
public:
|
||||
@ -210,6 +227,22 @@ class DEX38 {
|
||||
static constexpr dex_version_t dex_version = DEX_38::dex_version;
|
||||
};
|
||||
|
||||
class DEX39 {
|
||||
public:
|
||||
using dex_header = DEX_39::header;
|
||||
using class_def_item = DEX_39::class_def_item;
|
||||
using method_id_item = DEX_39::method_id_item;
|
||||
using field_id_item = DEX_39::field_id_item;
|
||||
using string_data_item = DEX_39::string_data_item;
|
||||
using map_items = DEX_39::map_items;
|
||||
using map = DEX_39::map;
|
||||
using proto_id_item = DEX_39::proto_id_item;
|
||||
using code_item = DEX_39::code_item;
|
||||
|
||||
static constexpr dex_version_t dex_version = DEX_39::dex_version;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -34,6 +34,8 @@
|
||||
//
|
||||
// Android 8.0.0: OAT 126
|
||||
// Android 8.1.0: OAT 131
|
||||
//
|
||||
// Android 9.0.0 OAT 138
|
||||
// ======================
|
||||
|
||||
namespace LIEF {
|
||||
@ -233,6 +235,18 @@ using OAT_124::oat_quick_method_header;
|
||||
using OAT_124::lookup_table_entry_t;
|
||||
}
|
||||
|
||||
|
||||
// OAT 138 - Android 9.0.0
|
||||
namespace OAT_138 {
|
||||
static constexpr oat_version_t oat_version = 138;
|
||||
using OAT_131::oat_header;
|
||||
using OAT_131::oat_dex_file;
|
||||
using OAT_131::dex_file;
|
||||
|
||||
using OAT_131::oat_quick_method_header;
|
||||
using OAT_131::lookup_table_entry_t;
|
||||
}
|
||||
|
||||
class OAT64_t {
|
||||
public:
|
||||
static constexpr oat_version_t oat_version = OAT_064::oat_version;
|
||||
@ -287,6 +301,16 @@ class OAT131_t {
|
||||
using lookup_table_entry_t = OAT_131::lookup_table_entry_t;
|
||||
};
|
||||
|
||||
class OAT138_t {
|
||||
public:
|
||||
static constexpr oat_version_t oat_version = OAT_138::oat_version;
|
||||
using oat_header = OAT_138::oat_header;
|
||||
using oat_dex_file = OAT_138::oat_dex_file;
|
||||
using dex_file = OAT_138::dex_file;
|
||||
using oat_quick_method_header = OAT_138::oat_quick_method_header;
|
||||
using lookup_table_entry_t = OAT_138::lookup_table_entry_t;
|
||||
};
|
||||
|
||||
@LIEF_OAT_STRUCTURES@
|
||||
|
||||
|
||||
|
@ -34,6 +34,7 @@ static const HEADER_KEYS header_keys_list[] = {
|
||||
HEADER_KEYS::KEY_CLASS_PATH ,
|
||||
HEADER_KEYS::KEY_BOOT_CLASS_PATH ,
|
||||
HEADER_KEYS::KEY_CONCURRENT_COPYING ,
|
||||
HEADER_KEYS::KE_COMPILATION_REASON ,
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ enum HEADER_KEYS {
|
||||
KEY_CLASS_PATH = 8,
|
||||
KEY_BOOT_CLASS_PATH = 9,
|
||||
KEY_CONCURRENT_COPYING = 10,
|
||||
KE_COMPILATION_REASON = 11,
|
||||
};
|
||||
|
||||
enum INSTRUCTION_SETS {
|
||||
|
@ -30,6 +30,8 @@ enum class ANDROID_VERSIONS {
|
||||
|
||||
VERSION_800 = 5,
|
||||
VERSION_810 = 6,
|
||||
|
||||
VERSION_900 = 7,
|
||||
};
|
||||
|
||||
LIEF_API const char* code_name(ANDROID_VERSIONS version);
|
||||
|
@ -94,6 +94,10 @@ void Parser::init(const std::string& name, art_version_t version) {
|
||||
if (version <= ART_46::art_version) {
|
||||
return this->parse_file<ART46>();
|
||||
}
|
||||
|
||||
if (version <= ART_56::art_version) {
|
||||
return this->parse_file<ART56>();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ART
|
||||
|
@ -23,12 +23,14 @@ constexpr art_version_t ART29::art_version;
|
||||
constexpr art_version_t ART30::art_version;
|
||||
constexpr art_version_t ART44::art_version;
|
||||
constexpr art_version_t ART46::art_version;
|
||||
constexpr art_version_t ART56::art_version;
|
||||
|
||||
constexpr uint32_t ART17::nb_image_roots;
|
||||
constexpr uint32_t ART29::nb_image_roots;
|
||||
constexpr uint32_t ART30::nb_image_roots;
|
||||
constexpr uint32_t ART44::nb_image_roots;
|
||||
constexpr uint32_t ART46::nb_image_roots;
|
||||
constexpr uint32_t ART56::nb_image_roots;
|
||||
|
||||
} // Namespace ART
|
||||
} // Namespace LIEF
|
||||
|
@ -101,6 +101,7 @@ LIEF::Android::ANDROID_VERSIONS android_version(art_version_t version) {
|
||||
{ 30, LIEF::Android::ANDROID_VERSIONS::VERSION_712 },
|
||||
{ 44, LIEF::Android::ANDROID_VERSIONS::VERSION_800 },
|
||||
{ 46, LIEF::Android::ANDROID_VERSIONS::VERSION_810 },
|
||||
{ 56, LIEF::Android::ANDROID_VERSIONS::VERSION_900 },
|
||||
|
||||
};
|
||||
auto it = oat2android.lower_bound(version);
|
||||
|
@ -87,6 +87,10 @@ void Parser::init(const std::string& name, dex_version_t version) {
|
||||
return this->parse_file<DEX38>();
|
||||
}
|
||||
|
||||
if (version == DEX_39::dex_version) {
|
||||
return this->parse_file<DEX39>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Parser::resolve_inheritance(void) {
|
||||
|
@ -36,17 +36,18 @@ Header::Header(void) :
|
||||
|
||||
std::string Header::key_to_string(HEADER_KEYS key) {
|
||||
const static std::map<HEADER_KEYS, const char*> keys2str = {
|
||||
{ HEADER_KEYS::KEY_IMAGE_LOCATION, "image-location" },
|
||||
{ HEADER_KEYS::KEY_DEX2OAT_CMD_LINE, "dex2oat-cmdline" },
|
||||
{ HEADER_KEYS::KEY_DEX2OAT_HOST, "dex2oat-host" },
|
||||
{ HEADER_KEYS::KEY_PIC, "pic" },
|
||||
{ HEADER_KEYS::KEY_HAS_PATCH_INFO, "has-patch-info" },
|
||||
{ HEADER_KEYS::KEY_DEBUGGABLE, "debuggable" },
|
||||
{ HEADER_KEYS::KEY_NATIVE_DEBUGGABLE, "native-debuggable" },
|
||||
{ HEADER_KEYS::KEY_COMPILER_FILTER, "compiler-filter" },
|
||||
{ HEADER_KEYS::KEY_CLASS_PATH, "classpath" },
|
||||
{ HEADER_KEYS::KEY_BOOT_CLASS_PATH, "bootclasspath" },
|
||||
{ HEADER_KEYS::KEY_CONCURRENT_COPYING, "concurrent-copying" },
|
||||
{ HEADER_KEYS::KEY_IMAGE_LOCATION, "image-location" },
|
||||
{ HEADER_KEYS::KEY_DEX2OAT_CMD_LINE, "dex2oat-cmdline" },
|
||||
{ HEADER_KEYS::KEY_DEX2OAT_HOST, "dex2oat-host" },
|
||||
{ HEADER_KEYS::KEY_PIC, "pic" },
|
||||
{ HEADER_KEYS::KEY_HAS_PATCH_INFO, "has-patch-info" },
|
||||
{ HEADER_KEYS::KEY_DEBUGGABLE, "debuggable" },
|
||||
{ HEADER_KEYS::KEY_NATIVE_DEBUGGABLE, "native-debuggable" },
|
||||
{ HEADER_KEYS::KEY_COMPILER_FILTER, "compiler-filter" },
|
||||
{ HEADER_KEYS::KEY_CLASS_PATH, "classpath" },
|
||||
{ HEADER_KEYS::KEY_BOOT_CLASS_PATH, "bootclasspath" },
|
||||
{ HEADER_KEYS::KEY_CONCURRENT_COPYING, "concurrent-copying" },
|
||||
{ HEADER_KEYS::KE_COMPILATION_REASON, "compilation-reason" },
|
||||
};
|
||||
|
||||
auto it = keys2str.find(key);
|
||||
|
@ -110,6 +110,10 @@ void Parser::init(const std::string& name) {
|
||||
return this->parse_binary<OAT131_t>();
|
||||
}
|
||||
|
||||
if (version <= OAT_138::oat_version) {
|
||||
return this->parse_binary<OAT138_t>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -274,6 +274,12 @@ void Parser::parse_binary<OAT131_t>(void) {
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void Parser::parse_binary<OAT138_t>(void) {
|
||||
return this->parse_binary<OAT131_t>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename OAT_T>
|
||||
void Parser::parse_header(void) {
|
||||
|
@ -136,6 +136,7 @@ LIEF::Android::ANDROID_VERSIONS android_version(oat_version_t version) {
|
||||
{ 88, LIEF::Android::ANDROID_VERSIONS::VERSION_712 },
|
||||
{ 124, LIEF::Android::ANDROID_VERSIONS::VERSION_800 },
|
||||
{ 131, LIEF::Android::ANDROID_VERSIONS::VERSION_810 },
|
||||
{ 138, LIEF::Android::ANDROID_VERSIONS::VERSION_900 },
|
||||
|
||||
};
|
||||
auto it = oat2android.lower_bound(version);
|
||||
|
@ -27,6 +27,7 @@ const char* code_name(ANDROID_VERSIONS version) {
|
||||
{ ANDROID_VERSIONS::VERSION_712, "Nougat" },
|
||||
{ ANDROID_VERSIONS::VERSION_800, "Oreo" },
|
||||
{ ANDROID_VERSIONS::VERSION_810, "Oreo" },
|
||||
{ ANDROID_VERSIONS::VERSION_900, "Pie" },
|
||||
|
||||
};
|
||||
auto it = version2code.find(version);
|
||||
@ -42,6 +43,7 @@ const char* version_string(ANDROID_VERSIONS version) {
|
||||
{ ANDROID_VERSIONS::VERSION_712, "7.1.2" },
|
||||
{ ANDROID_VERSIONS::VERSION_800, "8.0.0" },
|
||||
{ ANDROID_VERSIONS::VERSION_810, "8.1.0" },
|
||||
{ ANDROID_VERSIONS::VERSION_900, "9.0.0" },
|
||||
|
||||
};
|
||||
auto it = version2code.find(version);
|
||||
@ -57,6 +59,7 @@ const char* to_string(ANDROID_VERSIONS version) {
|
||||
{ ANDROID_VERSIONS::VERSION_712, "VERSION_712" },
|
||||
{ ANDROID_VERSIONS::VERSION_800, "VERSION_800" },
|
||||
{ ANDROID_VERSIONS::VERSION_810, "VERSION_810" },
|
||||
{ ANDROID_VERSIONS::VERSION_900, "VERSION_900" },
|
||||
|
||||
};
|
||||
auto it = enumStrings.find(version);
|
||||
|
@ -49,6 +49,12 @@ class TestART(TestCase):
|
||||
print(boot.header)
|
||||
return
|
||||
|
||||
def test_art56(self):
|
||||
boot = lief.ART.parse(get_sample("ART/ART_056_AArch64_boot.art"))
|
||||
|
||||
print(boot.header)
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -411,6 +411,38 @@ class TestOAT131(TestCase):
|
||||
self.assertEqual(method.name, "getIMEI")
|
||||
self.assertEqual(method.oat_class, CallDeviceId.get_class("Lre/android/art/CallDeviceId;"))
|
||||
|
||||
class TestOAT138(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
def test_header(self):
|
||||
CallDeviceId = lief.parse(get_sample("OAT/OAT_138_AArch64_android.uid.systemui.oat"))
|
||||
header = CallDeviceId.header
|
||||
|
||||
self.assertEqual(header.magic, [111, 97, 116, 10])
|
||||
self.assertEqual(header.version, 138)
|
||||
self.assertEqual(header.checksum, 0x5c64d148)
|
||||
self.assertEqual(header.instruction_set, lief.OAT.INSTRUCTION_SETS.ARM_64)
|
||||
self.assertEqual(header.nb_dex_files, 1)
|
||||
|
||||
self.assertEqual(header.oat_dex_files_offset, 3289146)
|
||||
|
||||
self.assertEqual(header.executable_offset, 0x324000)
|
||||
self.assertEqual(header.i2i_bridge_offset, 0)
|
||||
self.assertEqual(header.i2c_code_bridge_offset, 0)
|
||||
self.assertEqual(header.jni_dlsym_lookup_offset, 0)
|
||||
self.assertEqual(header.quick_generic_jni_trampoline_offset, 0)
|
||||
self.assertEqual(header.quick_imt_conflict_trampoline_offset, 0)
|
||||
self.assertEqual(header.quick_resolution_trampoline_offset, 0)
|
||||
self.assertEqual(header.quick_to_interpreter_bridge_offset, 0)
|
||||
|
||||
self.assertEqual(header.image_patch_delta, 0)
|
||||
|
||||
self.assertEqual(header.image_file_location_oat_checksum, 0x8eb74f9a)
|
||||
self.assertEqual(header.image_file_location_oat_data_begin, 0x71242000)
|
||||
|
||||
|
||||
|
||||
class TestOAT(TestCase):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user