From 239472507497e680e6f3dc6a2f5bf338e055b535 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 6 Mar 2022 22:50:48 +0000 Subject: [PATCH] add OS checksum computations --- include/fxos/os.h | 14 +++++++ include/fxos/vspace.h | 19 ++++------ lib/os.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++ lib/vspace.cpp | 18 +++++++++ shell/i.cpp | 8 ++-- 5 files changed, 132 insertions(+), 14 deletions(-) diff --git a/include/fxos/os.h b/include/fxos/os.h index a36f96a..e8641ac 100644 --- a/include/fxos/os.h +++ b/include/fxos/os.h @@ -34,6 +34,11 @@ public: Addressable timestamp; Addressable checksum; + /* Separated version components */ + int version_major, version_minor, version_patch; + /* Recomputed checksum */ + uint32_t computed_checksum; + /* Get number of syscalls */ int syscall_count() const noexcept; /* Get a syscall entry */ @@ -43,6 +48,12 @@ public: /* Get address of syscall table */ uint32_t syscall_table_address() const noexcept; + /* Tests against the OS version */ + bool version_lt(int major, int minor, int patch) const noexcept; + bool version_le(int major, int minor, int patch) const noexcept; + bool version_gt(int major, int minor, int patch) const noexcept; + bool version_ge(int major, int minor, int patch) const noexcept; + /* Footer address, or -1 if not found */ uint32_t footer; /* Number of langdata entries */ @@ -64,6 +75,9 @@ private: /* Locate and parse the footer. */ void parse_footer(); + /* Compute OS checkum .*/ + uint32_t compute_checksum() const; + //--- // OS information //--- diff --git a/include/fxos/vspace.h b/include/fxos/vspace.h index e1b3606..72891db 100644 --- a/include/fxos/vspace.h +++ b/include/fxos/vspace.h @@ -26,10 +26,14 @@ public: /* Check if a full region is simulated */ virtual bool covers(MemoryRegion const ®ion) const noexcept; - /* Returns the data located at the provided virtual address. Throws - std::out_of_range if the interval is not entirely simulated */ + /* Returns the data located at the provided virtual address, nullptr if it + is not entirely covered. */ virtual char const *translate(uint32_t addr, int size=1) const = 0; + /* Returns the data located at the provided virtual address, and indicates + how much is available in *size. */ + virtual char const *translate_dynamic(uint32_t addr, int *size) const = 0; + /* Read data from the memory. The following methods read data of various types. (Not a template because of the restriction about template specialization in non-namespaces scopes still in g++.) @@ -77,16 +81,12 @@ struct Binding: public AbstractMemory /* Underlying buffer (copy of the original one) */ Buffer buffer; - /* Checks if an address is covered by the binding */ bool covers(uint32_t addr, int size=1) const noexcept override; - /* Check if a region is covered by the binding */ bool covers(MemoryRegion const ®ion) const noexcept override; - /* Returns this process' address (in [data]) corresponding to the - provided virtual address */ char const *translate(uint32_t addr, int size=1) const override; + char const *translate_dynamic(uint32_t addr, int *size) const override; - /* Search a pattern */ uint32_t search(uint32_t start, uint32_t end, void const *pattern, int size) const override; }; @@ -140,15 +140,12 @@ public: bound. */ void bind_region(MemoryRegion const ®ion, Buffer const &buffer); - /* Check if an address is bound */ bool covers(uint32_t addr, int size=1) const noexcept override; - /* Check if a full region is bound */ bool covers(MemoryRegion const ®ion) const noexcept override; - /* Returns the data at the provided virtual address */ char const *translate(uint32_t addr, int size=1) const override; + char const *translate_dynamic(uint32_t addr, int *size) const override; - /* Search a pattern */ uint32_t search(uint32_t start, uint32_t end, void const *pattern, int size) const override; diff --git a/lib/os.cpp b/lib/os.cpp index 1a479a3..de8fc14 100644 --- a/lib/os.cpp +++ b/lib/os.cpp @@ -47,6 +47,47 @@ void OS::parse_header() this->version = s.read_str(0x80020020, 10); this->serial_number = s.read_str(0x8001ffd0, 8); } + + /* Version has format MM.mm.pppp */ + version_major = std::stoi(this->version.value.substr(0, 2)); + version_minor = std::stoi(this->version.value.substr(3, 2)); + version_patch = std::stoi(this->version.value.substr(6, 4)); +} + +bool OS::version_lt(int major, int minor, int patch) const noexcept +{ + if(this->version_major < major) return true; + if(this->version_major > major) return false; + if(this->version_minor < minor) return true; + if(this->version_minor > minor) return false; + return (this->version_patch < patch); +} + +bool OS::version_le(int major, int minor, int patch) const noexcept +{ + if(this->version_major < major) return true; + if(this->version_major > major) return false; + if(this->version_minor < minor) return true; + if(this->version_minor > minor) return false; + return (this->version_patch <= patch); +} + +bool OS::version_gt(int major, int minor, int patch) const noexcept +{ + if(this->version_major < major) return false; + if(this->version_major > major) return true; + if(this->version_minor < minor) return false; + if(this->version_minor > minor) return true; + return (this->version_patch > patch); +} + +bool OS::version_ge(int major, int minor, int patch) const noexcept +{ + if(this->version_major < major) return false; + if(this->version_major > major) return true; + if(this->version_minor < minor) return false; + if(this->version_minor > minor) return true; + return (this->version_patch >= patch); } //--- @@ -117,6 +158,7 @@ void OS::parse_footer() this->footer = -1; this->timestamp = std::string(""); this->langdata = 0; + this->computed_checksum = -1; return; } @@ -131,6 +173,51 @@ void OS::parse_footer() this->timestamp = s.read_str(addr, 14); this->checksum = s.read_u32(addr + 0x18); + this->computed_checksum = this->compute_checksum(); +} + +//--- +// Checksum +//--- + +static uint32_t accumulate_range(VirtualSpace const &m_space, + uint32_t start, uint32_t end) +{ + uint32_t sum = 0; + + /* Read from dynamically-sized bindings; read_u8() would be too slow */ + while(start < end) { + int size; + uint8_t *buf = (uint8_t *)m_space.translate_dynamic(start, &size); + + if(start + size > end) + size = end - start; + + for(int i = 0; i < size; i++) + sum += buf[i]; + + start += size; + } + + return sum; +} + +uint32_t OS::compute_checksum() const +{ + if(this->type == FX) { + return accumulate_range(m_space, 0x80010000, &this->checksum); + } + else if(this->type == CG) { + if(this->version_lt(2, 2, 0)) { + return accumulate_range(m_space, 0x80020000, 0x80b5feb0) + + accumulate_range(m_space,0x80b5fef0, 0x80b5fff8); + } + else { + return accumulate_range(m_space, 0x80020000, 0x80b20000) + + accumulate_range(m_space, this->footer+8, &this->checksum); + } + } + return -1; } } /* namespace FxOS */ diff --git a/lib/vspace.cpp b/lib/vspace.cpp index 5cfae79..46a2df5 100644 --- a/lib/vspace.cpp +++ b/lib/vspace.cpp @@ -90,6 +90,13 @@ char const *Binding::translate(uint32_t addr, int size) const return buffer.data.get() + (addr - region.start); } +char const *Binding::translate_dynamic(uint32_t addr, int *size) const +{ + if(!covers(addr, 1)) return nullptr; + *size = region.end - addr; + return buffer.data.get() + (addr - region.start); +} + uint32_t Binding::search(uint32_t start, uint32_t end, void const *pattern, int size) const { @@ -169,6 +176,17 @@ char const *VirtualSpace::translate(uint32_t addr, int size) const throw AddressError(addr, size); } +char const *VirtualSpace::translate_dynamic(uint32_t addr, int *size) const +{ + for(auto it = m_bindings.crbegin(); it != m_bindings.crend(); it++) + { + char const *ptr = it->translate_dynamic(addr, size); + if(ptr) return ptr; + } + + throw AddressError(addr, 1); +} + uint32_t VirtualSpace::search(uint32_t start, uint32_t end,void const *pattern, int size) const { diff --git a/shell/i.cpp b/shell/i.cpp index de062a2..49802d3 100644 --- a/shell/i.cpp +++ b/shell/i.cpp @@ -12,7 +12,7 @@ //--- static char const *info_str = -"OS type: %s\n" +"OS: type %s version %02d.%02d.%04d\n" "\n" "Header information:\n" " Bootcode timestamp (DateA) (0x%000008x) : %s\n" @@ -25,7 +25,8 @@ static char const *footer_str = " Detected footer address : 0x%08x\n" " Langdata entries found : %d\n" " OS date (DateO) (0x%000008x) : %s\n" -" OS checksum (0x%000008x) : 0x%08x\n"; +" OS checksum (0x%000008x) : 0x%08x\n" +" Computed OS checksum : 0x%08x\n"; static char const *syscall_str = "\nSyscall information:\n" @@ -56,6 +57,7 @@ void _io(Session &session, std::string name) if(!os) throw CommandError("os analysis on '{}' failed", name); printf(info_str, (os->type == OS::FX ? "FX" : "CG"), + os->version_major, os->version_minor, os->version_patch, &os->bootcode_timestamp, os->bootcode_timestamp.value.c_str(), &os->bootcode_checksum, os->bootcode_checksum, &os->serial_number, os->serial_number.value.c_str(), @@ -69,7 +71,7 @@ void _io(Session &session, std::string name) { printf(footer_str, os->footer, os->langdata, &os->timestamp, os->timestamp.value.c_str(), - &os->checksum, os->checksum); + &os->checksum, os->checksum, os->computed_checksum); } uint32_t syscall_table = os->syscall_table_address();