diff options
| author | Dennis Brentjes <d.brentjes@gmail.com> | 2016-06-27 01:33:02 +0200 |
|---|---|---|
| committer | Dennis Brentjes <d.brentjes@gmail.com> | 2016-06-27 15:23:06 +0200 |
| commit | b80a82fcc9edc73057796005cede4eea8380e193 (patch) | |
| tree | 2da5e7cddef0bc39b449410c9826680a3dd6ca9d | |
| parent | a7bcede17b4c10e172c7877fc2ce89862dc454af (diff) | |
| download | openwar-b80a82fcc9edc73057796005cede4eea8380e193.tar.gz openwar-b80a82fcc9edc73057796005cede4eea8380e193.tar.bz2 openwar-b80a82fcc9edc73057796005cede4eea8380e193.zip | |
Parses the fixup page and fixup record table.
| -rw-r--r-- | binparse/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | binparse/output.hpp | 4 | ||||
| -rw-r--r-- | binparse/parse.hpp | 6 | ||||
| -rw-r--r-- | binparse/variant_output_helper.hpp | 18 | ||||
| -rw-r--r-- | le/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | le/le_file.cpp | 17 | ||||
| -rw-r--r-- | le/le_file.hpp | 8 | ||||
| -rw-r--r-- | le/le_fixup_page_table.cpp | 33 | ||||
| -rw-r--r-- | le/le_fixup_page_table.hpp | 19 | ||||
| -rw-r--r-- | le/le_fixup_record_table.cpp | 237 | ||||
| -rw-r--r-- | le/le_fixup_record_table.hpp | 56 | ||||
| -rw-r--r-- | le/le_object_iterate_data_map_table.cpp | 18 | ||||
| -rw-r--r-- | le/le_object_iterate_data_map_table.hpp | 13 | ||||
| -rw-r--r-- | le/le_resource_table.cpp | 52 | ||||
| -rw-r--r-- | le/le_resource_table.hpp | 27 |
15 files changed, 508 insertions, 5 deletions
diff --git a/binparse/CMakeLists.txt b/binparse/CMakeLists.txt index c41a2b5..e436331 100644 --- a/binparse/CMakeLists.txt +++ b/binparse/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(binparse STATIC types.hpp + variant_output_helper.hpp parse.hpp parse.cpp output.hpp output.cpp otreestream.hpp otreestream.cpp diff --git a/binparse/output.hpp b/binparse/output.hpp index c5db2da..3919bef 100644 --- a/binparse/output.hpp +++ b/binparse/output.hpp @@ -42,6 +42,10 @@ std::ostream& operator<<(std::ostream& os, std::vector<uint8_t> vec); template <typename T, typename std::enable_if<boost::fusion::traits::is_sequence<T>::value>::type* = nullptr> std::ostream& operator<<(std::ostream&, T const&); + +template <typename ValueType> +std::ostream& operator<<(std::ostream& os, std::vector<ValueType> const& vec); + template <typename Key, typename Value> std::ostream& operator<<(std::ostream& os, std::map<Key, Value> const& map) { try { diff --git a/binparse/parse.hpp b/binparse/parse.hpp index 2103177..e02b230 100644 --- a/binparse/parse.hpp +++ b/binparse/parse.hpp @@ -12,9 +12,15 @@ #include <array> #include <vector> #include <string> +#include <cmath> namespace binparse { +template<typename T> +constexpr bool bit(unsigned char bit, T const& t) { + return t & T(std::pow(2, bit)); +} + struct UnexpectedEOS : public std::runtime_error { UnexpectedEOS(); diff --git a/binparse/variant_output_helper.hpp b/binparse/variant_output_helper.hpp new file mode 100644 index 0000000..7207a36 --- /dev/null +++ b/binparse/variant_output_helper.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "output.hpp" + +#include <boost/fusion/support/is_sequence.hpp> + +#include <ostream> + +namespace boost { namespace detail { namespace variant { + +template <typename T, typename std::enable_if<boost::fusion::traits::is_sequence<T>::value>::type* = nullptr> +std::ostream& operator<<(std::ostream& os, T const& t) { + return binparse::operator<<(os, t); +} + +} +} +}
\ No newline at end of file diff --git a/le/CMakeLists.txt b/le/CMakeLists.txt index a135f8b..a453669 100644 --- a/le/CMakeLists.txt +++ b/le/CMakeLists.txt @@ -6,10 +6,14 @@ add_library(le STATIC le_object_table_entry.hpp le_object_table_entry.cpp le_object_page_table.hpp le_object_page_table.cpp le_object_page_table_entry.hpp le_object_page_table_entry.cpp + le_object_iterate_data_map_table.hpp le_object_iterate_data_map_table.cpp + le_resource_table.hpp le_resource_table.cpp le_resident_name_table.hpp le_resident_name_table.cpp le_resident_name_table_entry.hpp le_resident_name_table_entry.cpp le_entry_table.hpp le_entry_table.cpp le_entry_table_entry.hpp le_entry_table_entry.cpp + le_fixup_page_table.hpp le_fixup_page_table.cpp + le_fixup_record_table.hpp le_fixup_record_table.cpp ) target_include_directories(le diff --git a/le/le_file.cpp b/le/le_file.cpp index b6aa54f..55478c8 100644 --- a/le/le_file.cpp +++ b/le/le_file.cpp @@ -19,8 +19,12 @@ BOOST_FUSION_ADAPT_STRUCT( (le::Header, le_header) (le::ObjectTable, object_table) (le::ObjectPageTable, object_page_table) + (le::ObjectIterateDataMapTable, object_iterate_data_map_table) + (le::ResourceTable, resource_table) (le::ResidentNameTable, resident_name_table) (le::EntryTable, entry_table) + (le::FixupPageTable, fixup_page_table) + (le::FixupRecordTable, fixup_record_table) ) namespace le { @@ -39,14 +43,13 @@ File parse_file(std::istream& is) { binparse::dump_bytes(is, dos_exe, "dos_exe"); auto le_h = le::parse_header(is); - auto object_table = parse_object_table(is, le_offset + le_h.object_table_offset, le_h.nr_objects_in_module); - auto object_page_table = parse_object_page_table(is, le_offset + le_h.object_page_table_offset, le_h.module_nr_of_pages); - auto resident_name_table = parse_resident_name_table(is, le_offset + le_h.resident_name_table_offset); - auto entry_table = parse_entry_table(is, le_offset + le_h.entry_table_offset); + auto resource_table = parse_resource_table(is, le_offset + le_h.resource_table_offset, le_h.nr_resource_table_entries); + auto fixup_page_table = parse_fixup_page_table(is, le_offset + le_h.fixup_page_table_offset, le_h.module_nr_of_pages + binparse::Value32(1)); + auto fixup_record_table = parse_fixup_record_table(is, le_offset + le_h.fixup_record_table_offset, fixup_page_table); return { mz_h, @@ -58,8 +61,12 @@ File parse_file(std::istream& is) { le_h, object_table, object_page_table, + {}, + resource_table, resident_name_table, - entry_table + entry_table, + fixup_page_table, + fixup_record_table }; } diff --git a/le/le_file.hpp b/le/le_file.hpp index f66bd36..09fc42d 100644 --- a/le/le_file.hpp +++ b/le/le_file.hpp @@ -6,8 +6,12 @@ #include "le_header.hpp" #include "le_object_table.hpp" #include "le_object_page_table.hpp" +#include "le_object_iterate_data_map_table.hpp" +#include "le_resource_table.hpp" #include "le_resident_name_table.hpp" #include "le_entry_table.hpp" +#include "le_fixup_page_table.hpp" +#include "le_fixup_record_table.hpp" #include <cstdint> #include <cstddef> @@ -31,8 +35,12 @@ struct File Header le_header; ObjectTable object_table; ObjectPageTable object_page_table; + ObjectIterateDataMapTable object_iterate_data_map_table; + ResourceTable resource_table; ResidentNameTable resident_name_table; EntryTable entry_table; + FixupPageTable fixup_page_table; + FixupRecordTable fixup_record_table; }; File parse_file(std::istream& is); diff --git a/le/le_fixup_page_table.cpp b/le/le_fixup_page_table.cpp new file mode 100644 index 0000000..c148fa6 --- /dev/null +++ b/le/le_fixup_page_table.cpp @@ -0,0 +1,33 @@ +#include "le_fixup_page_table.hpp" + +#include "parse.hpp" +#include "output.hpp" + +#include <boost/fusion/adapted/struct.hpp> + +BOOST_FUSION_ADAPT_STRUCT( + le::FixupPageTable, + (std::vector<binparse::Value32>, entries) +) + +namespace le { + +FixupPageTable parse_fixup_page_table(std::istream& is, binparse::Offset32 offset, binparse::Value32 nr_entries) +{ + is.seekg(offset, std::ios::beg); + + FixupPageTable table; + + for(binparse::Value32 i = binparse::Value32(0); i < nr_entries; i++) { + table.entries.push_back(binparse::parse<binparse::Value32>(is, "offset")); + } + + return table; +} + +std::ostream&operator<<(std::ostream& os, const FixupPageTable& table) +{ + return binparse::operator<<(os, table); +} + +} diff --git a/le/le_fixup_page_table.hpp b/le/le_fixup_page_table.hpp new file mode 100644 index 0000000..be44895 --- /dev/null +++ b/le/le_fixup_page_table.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "types.hpp" + +#include <iostream> +#include <vector> + +namespace le { + +struct FixupPageTable +{ + std::vector<binparse::Value32> entries; +}; + +FixupPageTable parse_fixup_page_table(std::istream& is, binparse::Offset32 offset, binparse::Value32 nr_entries); + +std::ostream& operator<<(std::ostream& os, FixupPageTable const& table); + +}
\ No newline at end of file diff --git a/le/le_fixup_record_table.cpp b/le/le_fixup_record_table.cpp new file mode 100644 index 0000000..9331626 --- /dev/null +++ b/le/le_fixup_record_table.cpp @@ -0,0 +1,237 @@ +#include "le_fixup_record_table.hpp" + +#include "parse.hpp" +#include "output.hpp" + +#include <boost/fusion/adapted/struct.hpp> +#include <bitset> + +typedef le::FixupRecordTable::Entry Entry; +typedef Entry::Internal Internal; +typedef Entry::ImportedOrdinal ImportedOrdinal; +typedef Entry::ImportedName ImportedName; +typedef Entry::InternalEntry InternalEntry; + +typedef binparse::Offset16 Offset16; +typedef binparse::Offset32 Offset32; +typedef binparse::Value8 Value8; +typedef binparse::Value16 Value16; + +typedef boost::variant<Offset16, Value8> ListOrOffsetT; +typedef boost::variant<Internal, ImportedOrdinal, ImportedName, InternalEntry> DataT; +typedef boost::optional<boost::variant<boost::variant<Offset16, Offset32>, std::vector<boost::variant<Offset16, Offset32>>>> AdditiveT; +typedef boost::optional<std::vector<Value16>> SourcesT; + +typedef boost::variant<Value8,Value16> V8orV16T; +typedef boost::variant<Offset16, Offset32> O16orO32T; + +BOOST_FUSION_ADAPT_STRUCT( + Internal, + (V8orV16T, object_number) + (O16orO32T, target_offset) +) + +BOOST_FUSION_ADAPT_STRUCT( + ImportedOrdinal, + (V8orV16T, ordinal_number) +) + +BOOST_FUSION_ADAPT_STRUCT( + ImportedName, + (V8orV16T, ordinal_number) + (O16orO32T, procedure_name_offset) +) + +BOOST_FUSION_ADAPT_STRUCT( + InternalEntry, + (V8orV16T, entry_number) +) + +BOOST_FUSION_ADAPT_STRUCT( + Entry, + (Value8, source_flags) + (Value8, target_flags) + (ListOrOffsetT, source_offset_or_source_list_count) + (DataT, data) + (AdditiveT, additive) + (SourcesT, sources) +) + +namespace le { + +using namespace binparse; + +FixupRecordTable::Entry::Internal parse_internal(std::istream& is, Value8 target_flags) { + using binparse::parse; + + FixupRecordTable::Entry::Internal internal; + + if(bit(6, target_flags)) { + internal.object_number = parse<Value16>(is, "segment_number"); + } else { + internal.object_number = parse<Value8>(is, "segment_number"); + } + + if(bit(4, target_flags)) { + internal.target_offset = parse<Offset32>(is, "target_offset"); + } else { + internal.target_offset = parse<Offset16>(is, "target_offset"); + } + + return internal; +} + +FixupRecordTable::Entry::ImportedOrdinal parse_imported_ordinal(std::istream& is, Value8 target_flags) { + using binparse::parse; + + FixupRecordTable::Entry::ImportedOrdinal ordinal; + + if(bit(6, target_flags)) { + ordinal.ordinal_number = parse<Value16>(is, "ordinal_value"); + } else { + ordinal.ordinal_number = parse<Value8>(is, "ordinal_value"); + } + + return ordinal; +} + +FixupRecordTable::Entry::ImportedName parse_imported_name(std::istream& is, Value8 target_flags) { + using binparse::parse; + + FixupRecordTable::Entry::ImportedName name; + + if(bit(6, target_flags)) { + name.ordinal_number = parse<Value16>(is, "ordinal_number"); + } else { + name.ordinal_number = parse<Value8>(is, "ordinal_number"); + } + + if(bit(4, target_flags)) { + name.procedure_name_offset = parse<Offset32>(is, "procedure_name_offset"); + } else { + name.procedure_name_offset = parse<Offset16>(is, "procedure_name_offset"); + } + + return name; +} + +FixupRecordTable::Entry::InternalEntry parse_internal_entry(std::istream& is, Value8 target_flags) { + using binparse::parse; + + FixupRecordTable::Entry::InternalEntry entry; + + if(bit(6, target_flags)) { + entry.entry_number = parse<Value16>(is, "entry_number"); + } else { + entry.entry_number = parse<Value8>(is, "entry_number"); + } + + return entry; +} + +FixupRecordTable::Entry parse(std::istream& is) +{ + using binparse::parse; + + FixupRecordTable::Entry entry; + + entry.source_flags = parse<Value8>(is, "source_flags"); + entry.target_flags = parse<Value8>(is, "target_flags"); + + bool has_lists = bit(6, entry.source_flags); + if(has_lists) { + entry.source_offset_or_source_list_count = parse<Value8>(is, "source_list_count"); + } else { + entry.source_offset_or_source_list_count = parse<Offset16>(is, "source_offset"); + } + + auto relevant_flags = entry.target_flags & 3; + + switch(relevant_flags) { + case 0: { + entry.data = parse_internal(is, entry.target_flags); + break; + } + case 1: { + entry.data = parse_imported_ordinal(is, entry.target_flags); + break; + } + case 2: { + entry.data = parse_imported_name(is, entry.target_flags); + break; + } + case 3: { + entry.data = parse_internal_entry(is, entry.target_flags); + break; + } + default: { + throw std::runtime_error("This cannot happen, value of relevant flags should be [0-3]"); + } + } + + if(relevant_flags == 0 or relevant_flags == 3) { + entry.additive.reset(); + } else { + if(bit(2, entry.target_flags)) { + std::vector<boost::variant<Offset16, Offset32>> vec; + for(int i = 0; i < int(boost::get<Value8>(entry.source_offset_or_source_list_count)); i++) { + if(bit(5, entry.target_flags)) { + vec.push_back(parse<Offset32>(is, "")); + } + else { + vec.push_back(parse<Offset16>(is, "")); + } + } + entry.additive = vec; + } else { + if(bit(5, entry.target_flags)) { + entry.additive = parse<Offset32>(is, ""); + } + else { + entry.additive = parse<Offset16>(is, ""); + } + } + } + + if(has_lists) { + std::vector<Value16> vec; + for(int i = 0; i < int(boost::get<Value8>(entry.source_offset_or_source_list_count)); i++) { + vec.push_back(parse<Value16>(is, "")); + } + entry.sources = vec; + } else { + entry.sources.reset(); + } + + return entry; +} + +FixupRecordTable parse_fixup_record_table(std::istream& is, Offset32 offset, FixupPageTable fixups) +{ + is.seekg(offset, std::ios::beg); + + FixupRecordTable table; + + binparse::otreestream otree(std::cout); + + for(int i = 1; i < fixups.entries.size(); i++) { + unsigned int current_pos = is.tellg(); + unsigned int endpos = current_pos + (fixups.entries[i] - fixups.entries[i-1]); + + while(current_pos = is.tellg(), current_pos < endpos) { + auto x = parse(is); + table.entries[Value32(i)].push_back(x); + } + + + } + + return table; +} + +std::ostream&operator<<(std::ostream& os, const FixupRecordTable& table) +{ + return binparse::operator<<(os, table.entries); +} + +} diff --git a/le/le_fixup_record_table.hpp b/le/le_fixup_record_table.hpp new file mode 100644 index 0000000..6a07da5 --- /dev/null +++ b/le/le_fixup_record_table.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "le_fixup_page_table.hpp" +#include "types.hpp" +#include "variant_output_helper.hpp" //include this before <boost/variant> + +#include <boost/variant.hpp> +#include <boost/optional.hpp> +#include <boost/optional/optional_io.hpp> + +#include <vector> +#include <map> + +namespace le { + +using namespace binparse; + +struct FixupRecordTable +{ + struct Entry { + struct Internal { + boost::variant<Value8,Value16> object_number; + boost::variant<Offset16, Offset32> target_offset; + }; + + struct ImportedOrdinal { + boost::variant<Value8, Value16> ordinal_number; + }; + + struct ImportedName { + boost::variant<Value8, Value16> ordinal_number; + boost::variant<Offset16, Offset32> procedure_name_offset; + }; + + struct InternalEntry { + boost::variant<Value8, Value16> entry_number; + }; + + Value8 source_flags; + Value8 target_flags; + boost::variant<Offset16, Value8> source_offset_or_source_list_count; + boost::variant<Internal, ImportedOrdinal, ImportedName, InternalEntry> data; + boost::optional<boost::variant<boost::variant<Offset16, Offset32>, std::vector<boost::variant<Offset16, Offset32>>>> additive; + boost::optional<std::vector<Value16>> sources; + }; + + std::map<Value32, std::vector<Entry>> entries; + +}; + +FixupRecordTable::Entry parse(std::istream& is); +FixupRecordTable parse_fixup_record_table(std::istream& is, Offset32 offset, FixupPageTable fixups); + +std::ostream& operator<<(std::ostream& os, FixupRecordTable const& table); + +}
\ No newline at end of file diff --git a/le/le_object_iterate_data_map_table.cpp b/le/le_object_iterate_data_map_table.cpp new file mode 100644 index 0000000..bc1b456 --- /dev/null +++ b/le/le_object_iterate_data_map_table.cpp @@ -0,0 +1,18 @@ +#include "le_object_iterate_data_map_table.hpp" + +#include "output.hpp" + +#include <boost/fusion/adapted/struct.hpp> + +BOOST_FUSION_ADAPT_STRUCT( + le::ObjectIterateDataMapTable, +) + +namespace le { + +std::ostream& operator<<(std::ostream& os, ObjectIterateDataMapTable const& table) +{ + return binparse::operator<<(os, table); +} + +}
\ No newline at end of file diff --git a/le/le_object_iterate_data_map_table.hpp b/le/le_object_iterate_data_map_table.hpp new file mode 100644 index 0000000..ef1a24d --- /dev/null +++ b/le/le_object_iterate_data_map_table.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include <ostream> + +namespace le { + +struct ObjectIterateDataMapTable +{ +}; + +std::ostream& operator<<(std::ostream& os, ObjectIterateDataMapTable const& table); + +} diff --git a/le/le_resource_table.cpp b/le/le_resource_table.cpp new file mode 100644 index 0000000..8b69733 --- /dev/null +++ b/le/le_resource_table.cpp @@ -0,0 +1,52 @@ +#include "le_resource_table.hpp" + +#include "parse.hpp" +#include "output.hpp" + +#include <boost/fusion/adapted/struct.hpp> + +BOOST_FUSION_ADAPT_STRUCT( + le::ResourceTable::Entry, + (binparse::Value16, type_id) + (binparse::Value16, name_id) + (binparse::Value32, resource_size) + (binparse::Value16, object_index) + (binparse::Offset32, offset) +) + +BOOST_FUSION_ADAPT_STRUCT( + le::ResourceTable, + (std::vector<le::ResourceTable::Entry>, entries) +) + +namespace le { + +ResourceTable::Entry parse_resource_table_entry(std::istream& is) +{ + return binparse::parse<ResourceTable::Entry>(is); +} + +ResourceTable parse_resource_table(std::istream& is, binparse::Offset32 offset, binparse::Value32 nr_entries) +{ + is.seekg(offset, std::ios::beg); + + ResourceTable table; + + for(binparse::Value32 i = binparse::Value32(0); i < nr_entries; i++) { + table.entries.push_back(parse_resource_table_entry(is)); + } + + return table; +} + +std::ostream&operator<<(std::ostream& os, const ResourceTable::Entry& entry) +{ + return binparse::operator<<(os, entry); +} + +std::ostream&operator<<(std::ostream& os, const ResourceTable& table) +{ + return binparse::operator<<(os, table.entries); +} + +}
\ No newline at end of file diff --git a/le/le_resource_table.hpp b/le/le_resource_table.hpp new file mode 100644 index 0000000..7590c6a --- /dev/null +++ b/le/le_resource_table.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "types.hpp" + +#include <vector> + +namespace le { + +struct ResourceTable +{ + struct Entry { + binparse::Value16 type_id; + binparse::Value16 name_id; + binparse::Value32 resource_size; + binparse::Value16 object_index; + binparse::Offset32 offset; + }; + std::vector<Entry> entries; +}; + +ResourceTable::Entry parse_resource_table_entry(std::istream& is); +ResourceTable parse_resource_table(std::istream& is, binparse::Offset32 offset, binparse::Value32 nr_entries); + +std::ostream& operator<<(std::ostream& os, ResourceTable::Entry const& entry); +std::ostream& operator<<(std::ostream& os, ResourceTable const& table); + +}
\ No newline at end of file |
