add OS checksum computations

This commit is contained in:
Lephenixnoir 2022-03-06 22:50:48 +00:00
parent 4e76ff3a24
commit 2394725074
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
5 changed files with 132 additions and 14 deletions

View File

@ -34,6 +34,11 @@ public:
Addressable<std::string> timestamp;
Addressable<uint32_t> 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
//---

View File

@ -26,10 +26,14 @@ public:
/* Check if a full region is simulated */
virtual bool covers(MemoryRegion const &region) 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 &region) 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 &region, 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 &region) 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;

View File

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

View File

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

View File

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