Add support for Android 9

This commit is contained in:
Romain Thomas 2018-08-10 16:10:51 +02:00
parent 04dddd3710
commit bce9ebe170
19 changed files with 279 additions and 12 deletions

View File

@ -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,

View File

@ -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@

View File

@ -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

View File

@ -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;
};

View File

@ -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@

View File

@ -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 ,
};
}

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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>();
}
}

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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):