diff --git a/ElfReader.cpp b/ElfReader.cpp old mode 100644 new mode 100755 index 96d757b..b5670d2 --- a/ElfReader.cpp +++ b/ElfReader.cpp @@ -117,13 +117,13 @@ ElfReader::~ElfReader() { } } -bool ElfReader::Load() { +bool ElfReader::Load(size_t page_size) { // try open return ReadElfHeader() && VerifyElfHeader() && ReadProgramHeader() && // TODO READ dynamic from SECTION header (>= __ANDROID_API_O__) - ReserveAddressSpace() && + ReserveAddressSpace(page_size) && LoadSegments() && FindPhdr(); } @@ -212,6 +212,7 @@ bool ElfReader::ReadProgramHeader() { */ size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table, size_t phdr_count, + size_t page_size, Elf_Addr* out_min_vaddr, Elf_Addr* out_max_vaddr) { @@ -243,8 +244,8 @@ size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table, min_vaddr = 0x00000000U; } - min_vaddr = PAGE_START(min_vaddr); - max_vaddr = PAGE_END(max_vaddr); + min_vaddr = PAGE_START(min_vaddr, page_size); + max_vaddr = PAGE_END(max_vaddr, page_size); if (out_min_vaddr != NULL) { *out_min_vaddr = min_vaddr; @@ -258,9 +259,9 @@ size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table, // Reserve a virtual address range big enough to hold all loadable // segments of a program header table. This is done by creating a // private anonymous mmap() with PROT_NONE. -bool ElfReader::ReserveAddressSpace(uint32_t padding_size) { +bool ElfReader::ReserveAddressSpace(size_t page_size, uint32_t padding_size) { Elf_Addr min_vaddr; - load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr); + load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, page_size, &min_vaddr); if (load_size_ == 0) { FLOGE("\"%s\" has no loadable segments", name_); return false; @@ -325,7 +326,7 @@ bool ElfReader::LoadSegments() { // if the segment is writable, and does not end on a page boundary, // zero-fill it until the page limit. // if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) { -// memset(seg_file_end + reinterpret_cast(load_bias_), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end)); +// memset(seg_file_end + reinterpret_cast(load_bias_), 0, page_size - PAGE_OFFSET(seg_file_end)); // } // seg_file_end = PAGE_END(seg_file_end); @@ -351,7 +352,8 @@ static int _phdr_table_set_load_prot(const Elf_Phdr* phdr_table, int phdr_count, uint8_t *load_bias, - int extra_prot_flags) + int extra_prot_flags, + size_t page_size) { const Elf_Phdr* phdr = phdr_table; const Elf_Phdr* phdr_limit = phdr + phdr_count; @@ -360,8 +362,8 @@ _phdr_table_set_load_prot(const Elf_Phdr* phdr_table, if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) continue; - auto seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; - auto seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; + auto seg_page_start = PAGE_START(phdr->p_vaddr, page_size) + load_bias; + auto seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz, page_size) + load_bias; auto ret = 0; @@ -389,10 +391,11 @@ _phdr_table_set_load_prot(const Elf_Phdr* phdr_table, int phdr_table_protect_segments(const Elf_Phdr* phdr_table, int phdr_count, - uint8_t *load_bias) + uint8_t *load_bias, + size_t page_size) { return _phdr_table_set_load_prot(phdr_table, phdr_count, - load_bias, 0); + load_bias, 0, page_size); } /* Change the protection of all loaded segments in memory to writable. @@ -414,10 +417,11 @@ phdr_table_protect_segments(const Elf_Phdr* phdr_table, int phdr_table_unprotect_segments(const Elf_Phdr* phdr_table, int phdr_count, - uint8_t *load_bias) + uint8_t *load_bias, + size_t page_size) { return _phdr_table_set_load_prot(phdr_table, phdr_count, - load_bias, /*PROT_WRITE*/0); + load_bias, /*PROT_WRITE*/0, page_size); } /* Used internally by phdr_table_protect_gnu_relro and @@ -427,7 +431,8 @@ static int _phdr_table_set_gnu_relro_prot(const Elf_Phdr* phdr_table, int phdr_count, uint8_t *load_bias, - int prot_flags) + int prot_flags, + size_t page_size) { const Elf_Phdr* phdr = phdr_table; const Elf_Phdr* phdr_limit = phdr + phdr_count; @@ -453,8 +458,8 @@ _phdr_table_set_gnu_relro_prot(const Elf_Phdr* phdr_table, * linker must only emit a PT_GNU_RELRO segment if it ensures * that it starts on a page boundary. */ - auto seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; - auto seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; + auto seg_page_start = PAGE_START(phdr->p_vaddr, page_size) + load_bias; + auto seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz, page_size) + load_bias; auto ret = 0; // int ret = mprotect((void*)seg_page_start, @@ -486,12 +491,13 @@ _phdr_table_set_gnu_relro_prot(const Elf_Phdr* phdr_table, int phdr_table_protect_gnu_relro(const Elf_Phdr* phdr_table, int phdr_count, - uint8_t *load_bias) + uint8_t *load_bias, + size_t page_size) { return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, - /*PROT_READ*/0); + /*PROT_READ*/0, page_size); } diff --git a/ElfReader.h b/ElfReader.h old mode 100644 new mode 100755 index 2644445..38e08c2 --- a/ElfReader.h +++ b/ElfReader.h @@ -26,7 +26,7 @@ class ElfReader { ElfReader(); virtual ~ElfReader(); - virtual bool Load(); + virtual bool Load(size_t page_size); bool setSource(const char* source); size_t phdr_count() { return phdr_num_; } @@ -41,7 +41,7 @@ class ElfReader { bool ReadElfHeader(); bool VerifyElfHeader(); bool ReadProgramHeader(); - bool ReserveAddressSpace(uint32_t padding_size = 0); + bool ReserveAddressSpace(size_t page_size, uint32_t padding_size = 0); bool LoadSegments(); bool FindPhdr(); bool CheckPhdr(uint8_t *); @@ -85,6 +85,7 @@ class ElfReader { size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table, size_t phdr_count, + size_t page_size, Elf_Addr* min_vaddr = NULL, Elf_Addr* max_vaddr = NULL); diff --git a/ElfRebuilder.cpp b/ElfRebuilder.cpp old mode 100644 new mode 100755 index 6d21ece..635103a --- a/ElfRebuilder.cpp +++ b/ElfRebuilder.cpp @@ -21,7 +21,7 @@ ElfRebuilder::ElfRebuilder(ObElfReader *elf_reader) { elf_reader_ = elf_reader; } -bool ElfRebuilder::RebuildPhdr() { +bool ElfRebuilder::RebuildPhdr(size_t page_size) { FLOGD("=============LoadDynamicSectionFromBaseSource==========RebuildPhdr========================="); @@ -38,7 +38,7 @@ bool ElfRebuilder::RebuildPhdr() { return true; } -bool ElfRebuilder::RebuildShdr() { +bool ElfRebuilder::RebuildShdr(size_t page_size) { FLOGD("=======================RebuildShdr========================="); // rebuilding shdr, link information auto base = si.load_bias; @@ -361,12 +361,12 @@ bool ElfRebuilder::RebuildShdr() { // // global_offset_table // sGOT = shdrs.size(); // auto sLast = sGOT - 1; -// + // Elf_Shdr shdr; // shdr.sh_name = shstrtab.length(); // shstrtab.append(".got"); // shstrtab.push_back('\0'); -// + // shdr.sh_type = SHT_PROGBITS; // shdr.sh_flags = SHF_ALLOC | SHF_WRITE; // shdr.sh_addr = shdrs[sLast].sh_addr + shdrs[sLast].sh_size; @@ -374,18 +374,18 @@ bool ElfRebuilder::RebuildShdr() { // while (shdr.sh_addr & 0x7) { // shdr.sh_addr ++; // } -// + // shdr.sh_offset = shdr.sh_addr; // shdr.sh_size = (uintptr_t)(si.plt_got + si.plt_rel_count) - shdr.sh_addr - (uintptr_t)base + 3 * sizeof(Elf_Addr); // shdr.sh_link = 0; // shdr.sh_info = 0; -//#ifdef __SO64__ +// #ifdef __SO64__ // shdr.sh_addralign = 8; -//#else +// #else // shdr.sh_addralign = 4; -//#endif +// #endif // shdr.sh_entsize = 0x0; -// + // shdrs.push_back(shdr); // } @@ -415,12 +415,12 @@ bool ElfRebuilder::RebuildShdr() { // gen .bss // if(true) { // sBSS = shdrs.size(); -// + // Elf_Shdr shdr; // shdr.sh_name = shstrtab.length(); // shstrtab.append(".bss"); // shstrtab.push_back('\0'); -// + // shdr.sh_type = SHT_NOBITS; // shdr.sh_flags = SHF_ALLOC | SHF_WRITE; // shdr.sh_addr = si.max_load; @@ -430,7 +430,7 @@ bool ElfRebuilder::RebuildShdr() { // shdr.sh_info = 0; // shdr.sh_addralign = 8; // shdr.sh_entsize = 0x0; -// + // shdrs.push_back(shdr); // } @@ -537,21 +537,21 @@ bool ElfRebuilder::RebuildShdr() { return true; } -bool ElfRebuilder::Rebuild() { - return RebuildPhdr() && - ReadSoInfo() && - RebuildShdr() && - RebuildRelocs() && - RebuildFin(); +bool ElfRebuilder::Rebuild(size_t page_size) { + return RebuildPhdr(page_size) && + ReadSoInfo(page_size) && + RebuildShdr(page_size) && + RebuildRelocs(page_size) && + RebuildFin(page_size); } -bool ElfRebuilder::ReadSoInfo() { +bool ElfRebuilder::ReadSoInfo(size_t page_size) { FLOGD("=======================ReadSoInfo========================="); si.base = si.load_bias = elf_reader_->load_bias(); si.phdr = elf_reader_->loaded_phdr(); si.phnum = elf_reader_->phdr_count(); auto base = si.load_bias; - phdr_table_get_load_size(si.phdr, si.phnum, &si.min_load, &si.max_load); + phdr_table_get_load_size(si.phdr, si.phnum, page_size, &si.min_load, &si.max_load); si.max_load += elf_reader_->pad_size_; /* Extract dynamic section */ @@ -705,7 +705,7 @@ bool ElfRebuilder::ReadSoInfo() { } // Finally, generate rebuild_data -bool ElfRebuilder::RebuildFin() { +bool ElfRebuilder::RebuildFin(size_t page_size) { FLOGD("=======================try to finish file rebuild ========================="); auto load_size = si.max_load - si.min_load; rebuild_size = load_size + shstrtab.length() + @@ -778,7 +778,7 @@ void ElfRebuilder::relocate(uint8_t * base, Elf_Rel* rel, Elf_Addr dump_base) { }; -bool ElfRebuilder::RebuildRelocs() { +bool ElfRebuilder::RebuildRelocs(size_t page_size) { if(elf_reader_->dump_so_base_ == 0) return true; FLOGD("=======================RebuildRelocs========================="); if (si.plt_type == DT_REL) { diff --git a/ElfRebuilder.h b/ElfRebuilder.h old mode 100644 new mode 100755 index ff1455c..27c200b --- a/ElfRebuilder.h +++ b/ElfRebuilder.h @@ -92,16 +92,16 @@ class ElfRebuilder { public: ElfRebuilder(ObElfReader* elf_reader); ~ElfRebuilder() { if(rebuild_data != nullptr) delete []rebuild_data; } - bool Rebuild(); + bool Rebuild(size_t page_size); void* getRebuildData() { return rebuild_data; } size_t getRebuildSize() { return rebuild_size; } private: - bool RebuildPhdr(); - bool RebuildShdr(); - bool ReadSoInfo(); - bool RebuildRelocs(); - bool RebuildFin(); + bool RebuildPhdr(size_t page_size); + bool RebuildShdr(size_t page_size); + bool ReadSoInfo(size_t page_size); + bool RebuildRelocs(size_t page_size); + bool RebuildFin(size_t page_size); template void relocate(uint8_t * base, Elf_Rel* rel, Elf_Addr dump_base); diff --git a/ObElfReader.cpp b/ObElfReader.cpp old mode 100644 new mode 100755 index dc76e0e..ead7907 --- a/ObElfReader.cpp +++ b/ObElfReader.cpp @@ -48,7 +48,7 @@ void ObElfReader::FixDumpSoPhdr() { } } -bool ObElfReader::Load() { +bool ObElfReader::Load(size_t page_size) { // try open if (!ReadElfHeader() || !VerifyElfHeader() || !ReadProgramHeader()) return false; @@ -56,7 +56,7 @@ bool ObElfReader::Load() { bool has_base_dynamic_info = false; uint32_t base_dynamic_size = 0; - if (!haveDynamicSectionInLoadableSegment()) { + if (!haveDynamicSectionInLoadableSegment(page_size)) { // try to get dynamic information from base so file. // TODO fix bug in dynamic section rebuild. LoadDynamicSectionFromBaseSource(); @@ -69,7 +69,7 @@ bool ObElfReader::Load() { "argument baseso will be ignored."); } - if (!ReserveAddressSpace(base_dynamic_size) || + if (!ReserveAddressSpace(page_size, base_dynamic_size) || !LoadSegments() || !FindPhdr()) { return false; @@ -162,9 +162,9 @@ void ObElfReader::ApplyDynamicSection() { } } -bool ObElfReader::haveDynamicSectionInLoadableSegment() { +bool ObElfReader::haveDynamicSectionInLoadableSegment(size_t page_size) { Elf_Addr min_vaddr, max_vaddr; - phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr, &max_vaddr); + phdr_table_get_load_size(phdr_table_, phdr_num_, page_size, &min_vaddr, &max_vaddr); const Elf_Phdr* phdr = phdr_table_; const Elf_Phdr* phdr_limit = phdr + phdr_num_; diff --git a/ObElfReader.h b/ObElfReader.h old mode 100644 new mode 100755 index 6f53dd1..acba921 --- a/ObElfReader.h +++ b/ObElfReader.h @@ -17,7 +17,7 @@ class ObElfReader: public ElfReader { // try to fix it void FixDumpSoPhdr(); - bool Load() override; + bool Load(size_t page_size) override; bool LoadDynamicSectionFromBaseSource(); void setDumpSoBaseAddr(Elf_Addr base) { dump_so_base_ = base; } @@ -27,7 +27,7 @@ class ObElfReader: public ElfReader { } // void GetDynamicSection(Elf_Dyn** dynamic, size_t* dynamic_count, Elf_Word* dynamic_flags) override; - bool haveDynamicSectionInLoadableSegment(); + bool haveDynamicSectionInLoadableSegment(size_t page_size); private: void ApplyDynamicSection(); diff --git a/macros.h b/macros.h old mode 100644 new mode 100755 index 092d60a..1a610ea --- a/macros.h +++ b/macros.h @@ -35,19 +35,19 @@ typedef Elf64_Dyn Elf_Dyn; typedef Elf64_Word Elf_Word; #endif -#ifndef PAGE_SIZE -#define PAGE_SIZE 0x1000 +// #ifndef PAGE_SIZE +// #define PAGE_SIZE 0x1000 -#define PAGE_MASK (~(PAGE_SIZE-1)) +#define PAGE_MASK(page_size) (~(page_size-1)) // Returns the address of the page containing address 'x'. -#define PAGE_START(x) ((x) & PAGE_MASK) +#define PAGE_START(x, page_size) ((x) & PAGE_MASK(page_size)) // Returns the offset of address 'x' in its page. -#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK) +#define PAGE_OFFSET(x, page_size) ((x) & ~PAGE_MASK(page_size)) // Returns the address of the next page after address 'x', unless 'x' is // itself at the start of a page. -#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1)) +#define PAGE_END(x, page_size) PAGE_START((x) + (page_size-1), page_size) #endif #ifndef TEMP_FAILURE_RETRY @@ -60,4 +60,4 @@ typedef Elf64_Word Elf_Word; #endif -#endif //FAOATDUMP_EXELF_H +//#endif //FAOATDUMP_EXELF_H diff --git a/main.cpp b/main.cpp old mode 100644 new mode 100755 index 114ee00..ffa28ed --- a/main.cpp +++ b/main.cpp @@ -12,7 +12,7 @@ #endif -const char* short_options = "hdm:s:o:b:"; +const char* short_options = "hdm:s:o:b:a:"; const struct option long_options[] = { {"help", 0, NULL, 'h'}, {"debug", 0, NULL, 'd'}, @@ -20,10 +20,28 @@ const struct option long_options[] = { {"source", 1, NULL, 's'}, {"baseso", 1, NULL, 'b'}, {"output", 1, NULL, 'o'}, + {"align", 1, NULL, 'a'}, {nullptr, 0, nullptr, 0} }; void useage(); +auto is16Bit = [](const char* c) { + auto len = strlen(c); + if(len > 2) { + if(c[0] == '0' & c[1] == 'x') return true; + } + bool is10bit = true; + for(auto i = 0; i < len; i++) { + if((c[i] > 'a' && c[i] < 'f') || + (c[i] > 'A' && c[i] < 'F')) { + is10bit = false; + } + } + return !is10bit; +}; + + + bool main_loop(int argc, char* argv[]) { int c; @@ -31,6 +49,7 @@ bool main_loop(int argc, char* argv[]) { ObElfReader elf_reader; std::string source, output, baseso; + size_t page_size = -1; while((c = getopt_long(argc, argv, short_options, long_options, nullptr)) != -1) { switch (c) { case 'd': @@ -45,29 +64,24 @@ bool main_loop(int argc, char* argv[]) { case 'b': baseso = optarg; break; + case 'a': { + #ifndef __SO64__ + page_size = strtoul(optarg, 0, is16Bit(optarg) ? 16: 10); + #else + page_size = strtoull(optarg, 0, is16Bit(optarg) ? 16: 10); + #endif + } + break; case 'm': { - auto is16Bit = [](const char* c) { - auto len = strlen(c); - if(len > 2) { - if(c[0] == '0' & c[1] == 'x') return true; - } - bool is10bit = true; - for(auto i = 0; i < len; i++) { - if((c[i] > 'a' && c[i] < 'f') || - (c[i] > 'A' && c[i] < 'F')) { - is10bit = false; - } - } - return !is10bit; - }; -#ifndef __SO64__ - auto base = strtoul(optarg, 0, is16Bit(optarg) ? 16: 10); -#else - auto base = strtoull(optarg, 0, is16Bit(optarg) ? 16: 10); -#endif - elf_reader.setDumpSoBaseAddr(base); - } + #ifndef __SO64__ + auto base = strtoul(optarg, 0, is16Bit(optarg) ? 16: 10); + #else + auto base = strtoull(optarg, 0, is16Bit(optarg) ? 16: 10); + #endif + elf_reader.setDumpSoBaseAddr(base); + } break; + default: return false; } @@ -93,13 +107,18 @@ bool main_loop(int argc, char* argv[]) { elf_reader.setBaseSoName(baseso.c_str()); } - if(!elf_reader.Load()) { + if (page_size == -1) { + FLOGE("page size value is not found"); + return false; + } + + if(!elf_reader.Load(page_size)) { FLOGE("source so file is invalid"); return false; } ElfRebuilder elf_rebuilder(&elf_reader); - if(!elf_rebuilder.Rebuild()) { + if(!elf_rebuilder.Rebuild(page_size)) { FLOGE("error occured in rebuilding elf file"); return false; } @@ -139,4 +158,5 @@ void useage() { FLOGI(" -b --baseso baseFilePath Original so file path.(used to get base information)(experimental)"); FLOGI(" -o --output generateFilePath Generate file path"); FLOGI(" -h --help Display this information"); + FLOGI(" -a --align Set the page size for alignment"); }