From db9e90822652b2fcd2c1c78f24be8eb27f3e61f6 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 13 Feb 2022 13:51:24 +0100 Subject: [PATCH] Read the payload.rpx with a properly aligned buffer, fix some missing free calls --- src/elfio/elfio.hpp | 27 ++++++++++++++ src/module/ModuleDataFactory.cpp | 23 ++++++++++-- src/utils/FileUtils.cpp | 62 ++++++++++++++++++++++++++++++++ src/utils/FileUtils.h | 3 ++ 4 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 src/utils/FileUtils.cpp create mode 100644 src/utils/FileUtils.h diff --git a/src/elfio/elfio.hpp b/src/elfio/elfio.hpp index 5381935..cb15769 100644 --- a/src/elfio/elfio.hpp +++ b/src/elfio/elfio.hpp @@ -68,6 +68,26 @@ set_##FNAME( TYPE val ) \ } \ } \ +struct membuf : std::streambuf { + membuf(char* begin, char* end) { + this->setg(begin, begin, end); + } + + pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override { + if (dir == std::ios_base::cur) + gbump(off); + else if (dir == std::ios_base::end) + setg(eback(), egptr() + off, egptr()); + else if (dir == std::ios_base::beg) + setg(eback(), eback() + off, egptr()); + return gptr() - eback(); + } + + pos_type seekpos(pos_type sp, std::ios_base::openmode which) override { + return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which); + } +}; + namespace ELFIO { //------------------------------------------------------------------------------ @@ -97,6 +117,13 @@ class elfio create_mandatory_sections(); } +//------------------------------------------------------------------------------ + bool load(char * buffer, size_t length) { + membuf sbuf(buffer, buffer + length); + std::istream in(&sbuf); + return load(in); + } + //------------------------------------------------------------------------------ bool load( const std::string& file_name ) { diff --git a/src/module/ModuleDataFactory.cpp b/src/module/ModuleDataFactory.cpp index f94754b..4d6f414 100644 --- a/src/module/ModuleDataFactory.cpp +++ b/src/module/ModuleDataFactory.cpp @@ -17,7 +17,7 @@ #include "ModuleDataFactory.h" #include "../ElfUtils.h" -#include "elfio/elfio.hpp" +#include "../utils/FileUtils.h" #include #include #include @@ -30,9 +30,17 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address, u elfio reader; ModuleData moduleData; + uint8_t *buffer = nullptr; + uint32_t fsize = 0; + if (LoadFileToMem(path.c_str(), &buffer, &fsize) < 0) { + DEBUG_FUNCTION_LINE("Failed to load file"); + return {}; + } + // Load ELF data - if (!reader.load(path)) { + if (!reader.load(reinterpret_cast(buffer), fsize)) { DEBUG_FUNCTION_LINE("Can't find or process %s", path.c_str()); + free(buffer); return {}; } @@ -40,6 +48,11 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address, u auto **destinations = (uint8_t **) malloc(sizeof(uint8_t *) * sec_num); + if (!destinations) { + DEBUG_FUNCTION_LINE("Failed to alloc memory for destinations"); + free(buffer); + } + uint32_t sizeOfModule = 0; for (uint32_t i = 0; i < sec_num; ++i) { section *psec = reader.sections[i]; @@ -54,6 +67,8 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address, u if (sizeOfModule > maximum_size) { DEBUG_FUNCTION_LINE("Module is too big."); + free(buffer); + free(destinations); return {}; } @@ -93,6 +108,7 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address, u } else { DEBUG_FUNCTION_LINE("Unhandled case"); free(destinations); + free(buffer); return {}; } @@ -130,6 +146,7 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address, u if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], offset_text, offset_data, trampolin_data, trampolin_data_length)) { DEBUG_FUNCTION_LINE("elfLink failed"); free(destinations); + free(buffer); return {}; } } @@ -146,6 +163,7 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address, u ICInvalidateRange((void *) baseOffset, totalSize); free(destinations); + free(buffer); moduleData.setEntrypoint(entrypoint); DEBUG_FUNCTION_LINE("Saved entrypoint as %08X", entrypoint); @@ -153,7 +171,6 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address, u return moduleData; } - std::vector ModuleDataFactory::getImportRelocationData(const elfio &reader, uint8_t **destinations) { std::vector result; std::map infoMap; diff --git a/src/utils/FileUtils.cpp b/src/utils/FileUtils.cpp new file mode 100644 index 0000000..8e80605 --- /dev/null +++ b/src/utils/FileUtils.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include + + +#define ROUNDDOWN(val, align) ((val) & ~(align - 1)) +#define ROUNDUP(val, align) ROUNDDOWN(((val) + (align - 1)), align) + +int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size) { + //! always initialze input + *inbuffer = nullptr; + if (size) { + *size = 0; + } + + int32_t iFd = open(filepath, O_RDONLY); + if (iFd < 0) { + return -1; + } + + uint32_t filesize = lseek(iFd, 0, SEEK_END); + lseek(iFd, 0, SEEK_SET); + + auto *buffer = (uint8_t *) malloc(ROUNDUP(filesize, 0x40)); + if (buffer == nullptr) { + close(iFd); + return -2; + } + + uint32_t blocksize = 0x20000; + uint32_t done = 0; + int32_t readBytes; + + while (done < filesize) { + if (done + blocksize > filesize) { + blocksize = filesize - done; + } + readBytes = read(iFd, buffer + done, blocksize); + if (readBytes <= 0) + break; + done += readBytes; + } + + ::close(iFd); + + if (done != filesize) { + free(buffer); + buffer = nullptr; + return -3; + } + + *inbuffer = buffer; + + //! sign is optional input + if (size) { + *size = filesize; + } + + return filesize; +} diff --git a/src/utils/FileUtils.h b/src/utils/FileUtils.h new file mode 100644 index 0000000..e9b0bc7 --- /dev/null +++ b/src/utils/FileUtils.h @@ -0,0 +1,3 @@ +#pragma once + +int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size); \ No newline at end of file