123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- #include "read_apk.h"
- #include <errno.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <memory>
- #include <android-base/file.h>
- #include <android-base/logging.h>
- #include <android-base/strings.h>
- #include <ziparchive/zip_archive.h>
- #include "read_elf.h"
- #include "utils.h"
- std::unordered_map<std::string, ApkInspector::ApkNode> ApkInspector::embedded_elf_cache_;
- EmbeddedElf* ApkInspector::FindElfInApkByOffset(const std::string& apk_path, uint64_t file_offset) {
-
- ApkNode& node = embedded_elf_cache_[apk_path];
- auto it = node.offset_map.find(file_offset);
- if (it != node.offset_map.end()) {
- return it->second.get();
- }
- std::unique_ptr<EmbeddedElf> elf = FindElfInApkByOffsetWithoutCache(apk_path, file_offset);
- EmbeddedElf* result = elf.get();
- node.offset_map[file_offset] = std::move(elf);
- if (result != nullptr) {
- node.name_map[result->entry_name()] = result;
- }
- return result;
- }
- EmbeddedElf* ApkInspector::FindElfInApkByName(const std::string& apk_path,
- const std::string& entry_name) {
- ApkNode& node = embedded_elf_cache_[apk_path];
- auto it = node.name_map.find(entry_name);
- if (it != node.name_map.end()) {
- return it->second;
- }
- std::unique_ptr<EmbeddedElf> elf = FindElfInApkByNameWithoutCache(apk_path, entry_name);
- EmbeddedElf* result = elf.get();
- node.name_map[entry_name] = result;
- if (result != nullptr) {
- node.offset_map[result->entry_offset()] = std::move(elf);
- }
- return result;
- }
- std::unique_ptr<EmbeddedElf> ApkInspector::FindElfInApkByOffsetWithoutCache(
- const std::string& apk_path, uint64_t file_offset) {
- std::unique_ptr<ArchiveHelper> ahelper = ArchiveHelper::CreateInstance(apk_path);
- if (!ahelper) {
- return nullptr;
- }
-
-
-
- bool found = false;
- ZipEntry found_entry;
- std::string found_entry_name;
- bool result = ahelper->IterateEntries([&](ZipEntry& entry, const std::string& name) {
- if (entry.method == kCompressStored &&
- file_offset >= static_cast<uint64_t>(entry.offset) &&
- file_offset < static_cast<uint64_t>(entry.offset) + entry.uncompressed_length) {
- found = true;
- found_entry = entry;
- found_entry_name = name;
- return false;
- }
- return true;
- });
- if (!result || !found) {
- return nullptr;
- }
-
- if (lseek(ahelper->GetFd(), found_entry.offset, SEEK_SET) != found_entry.offset) {
- PLOG(ERROR) << "lseek() failed in " << apk_path << " offset " << found_entry.offset;
- return nullptr;
- }
- if (IsValidElfFile(ahelper->GetFd()) != ElfStatus::NO_ERROR) {
-
- return nullptr;
- }
- return std::unique_ptr<EmbeddedElf>(new EmbeddedElf(apk_path, found_entry_name,
- found_entry.offset,
- found_entry.uncompressed_length));
- }
- std::unique_ptr<EmbeddedElf> ApkInspector::FindElfInApkByNameWithoutCache(
- const std::string& apk_path, const std::string& entry_name) {
- std::unique_ptr<ArchiveHelper> ahelper = ArchiveHelper::CreateInstance(apk_path);
- if (!ahelper) {
- return nullptr;
- }
- ZipEntry zentry;
- if (!ahelper->FindEntry(entry_name, &zentry)) {
- return nullptr;
- }
- if (zentry.method != kCompressStored || zentry.compressed_length != zentry.uncompressed_length) {
- return nullptr;
- }
- return std::unique_ptr<EmbeddedElf>(new EmbeddedElf(apk_path, entry_name, zentry.offset,
- zentry.uncompressed_length));
- }
- std::string GetUrlInApk(const std::string& apk_path, const std::string& elf_filename) {
- return apk_path + "!/" + elf_filename;
- }
- std::tuple<bool, std::string, std::string> SplitUrlInApk(const std::string& path) {
- size_t pos = path.find("!/");
- if (pos == std::string::npos) {
- return std::make_tuple(false, "", "");
- }
- return std::make_tuple(true, path.substr(0, pos), path.substr(pos + 2));
- }
- bool ParseExtractedInMemoryPath(const std::string& path, std::string* zip_path,
- std::string* entry_name) {
- const char* prefixes[2] = {"[anon:dalvik-", "/dev/ashmem/dalvik-"};
- const char* key = " extracted in memory from ";
- size_t pos = path.find(key);
- if (pos != std::string::npos) {
- for (const char* prefix : prefixes) {
- if (android::base::StartsWith(path, prefix)) {
- size_t entry_name_start = strlen(prefix);
- size_t entry_name_end = pos;
- size_t zip_path_start = pos + strlen(key);
- size_t zip_path_end = path.find_first_of(" ]", zip_path_start);
- if (zip_path_end == std::string::npos) {
- zip_path_end = path.size();
- }
- if (entry_name_start < entry_name_end && zip_path_start < zip_path_end) {
- *entry_name = path.substr(entry_name_start, entry_name_end - entry_name_start);
- *zip_path = path.substr(zip_path_start, zip_path_end - zip_path_start);
- size_t multidex_separator_pos = zip_path->find('!');
- if (multidex_separator_pos != std::string::npos) {
- zip_path->resize(multidex_separator_pos);
- }
- return true;
- }
- }
- }
- }
- return false;
- }
|