Skip to content

Commit

Permalink
Added parsing for the RICH header.
Browse files Browse the repository at this point in the history
  • Loading branch information
JusticeRage committed Feb 27, 2018
1 parent c2a1e68 commit 03c1ac7
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
9 changes: 9 additions & 0 deletions include/manape/pe.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,14 @@ class PE
*/
bool _parse_certificates();

/**
* @brief Parses the opaque RICH header.
*
* Included in the _parse_directories call.
* /!\ This relies on the information gathered in _parse_pe_header.
*/
bool _parse_rich_header();

/**
* @brief Translates a Virtual Address (*not relative to the image base*) into an offset in the file.
*
Expand Down Expand Up @@ -447,6 +455,7 @@ class PE
boost::optional<image_load_config_directory> _config;
boost::optional<delay_load_directory_table> _delay_load_directory_table;
std::vector<pwin_certificate> _certificates;
boost::optional<rich_header> _rich_header;
};


Expand Down
8 changes: 8 additions & 0 deletions include/manape/pe_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,4 +455,12 @@ typedef struct delay_load_directory_table_t
std::string NameStr; // Non-standard!
} delay_load_directory_table;

// ----------------------------------------------------------------------------

typedef struct rich_header_t
{
boost::uint32_t xor_key;
std::vector<std::tuple<boost::uint16_t, boost::uint16_t, boost::uint32_t> > values;
} rich_header;

} // !namespace mana
66 changes: 65 additions & 1 deletion manape/pe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,8 @@ bool PE::_parse_directories()
_parse_relocations() &&
_parse_tls() &&
_parse_config() &&
_parse_certificates();
_parse_certificates() &&
_parse_rich_header();
}

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -1024,4 +1025,67 @@ bool PE::_parse_certificates()
return true;
}

// ----------------------------------------------------------------------------

bool PE::_parse_rich_header()
{
if (!_h_dos || _file_handle == nullptr) {
return false;
}

// Star searching for the RICH header at offset 0, but before the PE header.
if (fseek(_file_handle.get(), 0, SEEK_SET)) {
return true;
}

unsigned int read;
int bytes_left = _h_dos->e_lfanew;

do
{
if (1 != fread(&read, 4, 1, _file_handle.get())) {
break;
}
bytes_left -= 4; // Stay between offset 0x80 and the PE header.
} while (read != 0x68636952 && bytes_left > 0);

if (read != 0x68636952) {
return true; // The RICH magic was not found.
}
rich_header h;
if (1 != fread(&h.xor_key, 4, 1, _file_handle.get()))
{
PRINT_WARNING << "XOR key absent after the RICH header!" << DEBUG_INFO_INSIDEPE << std::endl;
return true;
}

// Start parsing the values backwards.
while (true)
{
if (fseek(_file_handle.get(), -16, SEEK_CUR))
{
PRINT_WARNING << "Error while reading the RICH header!" << DEBUG_INFO_INSIDEPE << std::endl;
return true;
}
boost::uint64_t data;
if (1 != fread(&data, 8, 1, _file_handle.get()))
{
PRINT_WARNING << "Error while reading the RICH header!" << DEBUG_INFO_INSIDEPE << std::endl;
return true;
}
boost::uint32_t count = (data >> 32) ^ h.xor_key;
boost::uint32_t id_value = (data & 0xFFFFFFFF) ^ h.xor_key;

// Stop if we reach the start marker, "DanS".
if (id_value == 0x536E6144) {
break;
}
auto t = std::make_tuple(static_cast<boost::uint16_t>((id_value >> 16) & 0xFFFF), static_cast<boost::uint16_t>(id_value & 0xFFFF), count);
h.values.insert(h.values.begin(), t);
};

_rich_header.reset(h);
return true;
}

} // !namespace mana
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ bool parse_args(po::variables_map& vm, int argc, char**argv)
"Dump PE information. Available choices are any combination of: "
"all, summary, dos (dos header), pe (pe header), opt (pe optional header), sections, "
"imports, exports, resources, version, debug, tls, config (image load configuration), "
"delay (delay-load table")
"delay (delay-load table), rich")
("hashes", "Calculate various hashes of the file (may slow down the analysis!)")
("extract,x", po::value<std::string>(), "Extract the PE resources and authenticode certificates "
"to the target directory.")
Expand Down

0 comments on commit 03c1ac7

Please sign in to comment.