Populate Rich header version strings (#94)

This commit is contained in:
Stefan Siegfried 2019-11-17 01:45:55 +09:00 committed by William Woodruff
parent ea3970c9a0
commit bd68ba418f
4 changed files with 592 additions and 140 deletions

View File

@ -229,11 +229,12 @@ int printSymbols(void *N,
int printRich(void *N, rich_entry r) {
static_cast<void>(N);
std::cout << std::dec;
std::cout << std::setw(10) << "ProdId:" << std::setw(7) << r.ProductId;
std::cout << std::setw(10) << "Build:" << std::setw(7) << r.BuildNumber;
std::cout << std::setw(10) << "Name:" << std::setw(20)
<< GetRichProductName(r.ProductId, r.BuildNumber);
std::cout << std::setw(10) << "Name:" << std::setw(40)
<< GetRichProductName(r.BuildNumber) << " "
<< GetRichObjectType(r.ProductId);
std::cout << std::setw(10) << "Count:" << std::setw(7) << r.Count << "\n";
return 0;
}
@ -282,10 +283,13 @@ int printSecs(void *N,
#define DUMP_FIELD(x) \
std::cout << "" #x << ": 0x"; \
std::cout << std::hex << static_cast<std::uint64_t>(p->peHeader.nt.x) << "\n";
std::cout << std::hex << static_cast<std::uint64_t>(p->peHeader.x) << "\n";
#define DUMP_DEC_FIELD(x) \
std::cout << "" #x << ": "; \
std::cout << std::dec << static_cast<std::uint64_t>(p->peHeader.nt.x) << "\n";
std::cout << std::dec << static_cast<std::uint64_t>(p->peHeader.x) << "\n";
#define DUMP_BOOL_FIELD(x) \
std::cout << "" #x << ": "; \
std::cout << std::boolalpha << static_cast<bool>(p->peHeader.x) << "\n";
int main(int argc, char *argv[]) {
if (argc != 2 || (argc == 2 && std::strcmp(argv[1], "--help") == 0)) {
@ -303,120 +307,153 @@ int main(int argc, char *argv[]) {
return 1;
}
// Print Rich header info
if (p->peHeader.rich.isPresent) {
std::cout << "Rich header: present\n";
IterRich(p, printRich, NULL);
} else {
std::cout << "Rich header: not present\n";
}
// print out some things
DUMP_FIELD(Signature);
DUMP_FIELD(FileHeader.Machine);
DUMP_FIELD(FileHeader.NumberOfSections);
DUMP_DEC_FIELD(FileHeader.TimeDateStamp);
DUMP_FIELD(FileHeader.PointerToSymbolTable);
DUMP_DEC_FIELD(FileHeader.NumberOfSymbols);
DUMP_FIELD(FileHeader.SizeOfOptionalHeader);
DUMP_FIELD(FileHeader.Characteristics);
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
DUMP_FIELD(OptionalHeader.Magic);
DUMP_DEC_FIELD(OptionalHeader.MajorLinkerVersion);
DUMP_DEC_FIELD(OptionalHeader.MinorLinkerVersion);
DUMP_FIELD(OptionalHeader.SizeOfCode);
DUMP_FIELD(OptionalHeader.SizeOfInitializedData);
DUMP_FIELD(OptionalHeader.SizeOfUninitializedData);
DUMP_FIELD(OptionalHeader.AddressOfEntryPoint);
DUMP_FIELD(OptionalHeader.BaseOfCode);
DUMP_FIELD(OptionalHeader.BaseOfData);
DUMP_FIELD(OptionalHeader.ImageBase);
DUMP_FIELD(OptionalHeader.SectionAlignment);
DUMP_FIELD(OptionalHeader.FileAlignment);
DUMP_DEC_FIELD(OptionalHeader.MajorOperatingSystemVersion);
DUMP_DEC_FIELD(OptionalHeader.MinorOperatingSystemVersion);
DUMP_DEC_FIELD(OptionalHeader.Win32VersionValue);
DUMP_FIELD(OptionalHeader.SizeOfImage);
DUMP_FIELD(OptionalHeader.SizeOfHeaders);
DUMP_FIELD(OptionalHeader.CheckSum);
DUMP_FIELD(OptionalHeader.Subsystem);
DUMP_FIELD(OptionalHeader.DllCharacteristics);
DUMP_FIELD(OptionalHeader.SizeOfStackReserve);
DUMP_FIELD(OptionalHeader.SizeOfStackCommit);
DUMP_FIELD(OptionalHeader.SizeOfHeapReserve);
DUMP_FIELD(OptionalHeader.SizeOfHeapCommit);
DUMP_FIELD(OptionalHeader.LoaderFlags);
DUMP_DEC_FIELD(OptionalHeader.NumberOfRvaAndSizes);
} else {
DUMP_FIELD(OptionalHeader64.Magic);
DUMP_DEC_FIELD(OptionalHeader64.MajorLinkerVersion);
DUMP_DEC_FIELD(OptionalHeader64.MinorLinkerVersion);
DUMP_FIELD(OptionalHeader64.SizeOfCode);
DUMP_FIELD(OptionalHeader64.SizeOfInitializedData);
DUMP_FIELD(OptionalHeader64.SizeOfUninitializedData);
DUMP_FIELD(OptionalHeader64.AddressOfEntryPoint);
DUMP_FIELD(OptionalHeader64.BaseOfCode);
DUMP_FIELD(OptionalHeader64.ImageBase);
DUMP_FIELD(OptionalHeader64.SectionAlignment);
DUMP_FIELD(OptionalHeader64.FileAlignment);
DUMP_DEC_FIELD(OptionalHeader64.MajorOperatingSystemVersion);
DUMP_DEC_FIELD(OptionalHeader64.MinorOperatingSystemVersion);
DUMP_DEC_FIELD(OptionalHeader64.Win32VersionValue);
DUMP_FIELD(OptionalHeader64.SizeOfImage);
DUMP_FIELD(OptionalHeader64.SizeOfHeaders);
DUMP_FIELD(OptionalHeader64.CheckSum);
DUMP_FIELD(OptionalHeader64.Subsystem);
DUMP_FIELD(OptionalHeader64.DllCharacteristics);
DUMP_FIELD(OptionalHeader64.SizeOfStackReserve);
DUMP_FIELD(OptionalHeader64.SizeOfStackCommit);
DUMP_FIELD(OptionalHeader64.SizeOfHeapReserve);
DUMP_FIELD(OptionalHeader64.SizeOfHeapCommit);
DUMP_FIELD(OptionalHeader64.LoaderFlags);
DUMP_DEC_FIELD(OptionalHeader64.NumberOfRvaAndSizes);
}
if (p != NULL) {
// Print DOS header
DUMP_FIELD(dos.e_magic);
DUMP_FIELD(dos.e_cp);
DUMP_FIELD(dos.e_crlc);
DUMP_FIELD(dos.e_cparhdr);
DUMP_FIELD(dos.e_minalloc);
DUMP_FIELD(dos.e_maxalloc);
DUMP_FIELD(dos.e_ss);
DUMP_FIELD(dos.e_sp);
DUMP_FIELD(dos.e_csum);
DUMP_FIELD(dos.e_ip);
DUMP_FIELD(dos.e_cs);
DUMP_FIELD(dos.e_lfarlc);
DUMP_FIELD(dos.e_ovno);
DUMP_FIELD(dos.e_res[0]);
DUMP_FIELD(dos.e_res[1]);
DUMP_FIELD(dos.e_res[2]);
DUMP_FIELD(dos.e_res[3]);
DUMP_FIELD(dos.e_oemid);
DUMP_FIELD(dos.e_oeminfo);
DUMP_FIELD(dos.e_res2[0]);
DUMP_FIELD(dos.e_res2[1]);
DUMP_FIELD(dos.e_res2[2]);
DUMP_FIELD(dos.e_res2[3]);
DUMP_FIELD(dos.e_res2[4]);
DUMP_FIELD(dos.e_res2[5]);
DUMP_FIELD(dos.e_res2[6]);
DUMP_FIELD(dos.e_res2[7]);
DUMP_FIELD(dos.e_res2[8]);
DUMP_FIELD(dos.e_res2[9]);
DUMP_FIELD(dos.e_lfanew);
// Print Rich header info
DUMP_BOOL_FIELD(rich.isPresent);
if (p->peHeader.rich.isPresent) {
DUMP_FIELD(rich.DecryptionKey);
DUMP_FIELD(rich.Checksum);
DUMP_BOOL_FIELD(rich.isValid);
IterRich(p, printRich, NULL);
}
// print out some things
DUMP_FIELD(nt.Signature);
DUMP_FIELD(nt.FileHeader.Machine);
DUMP_FIELD(nt.FileHeader.NumberOfSections);
DUMP_DEC_FIELD(nt.FileHeader.TimeDateStamp);
DUMP_FIELD(nt.FileHeader.PointerToSymbolTable);
DUMP_DEC_FIELD(nt.FileHeader.NumberOfSymbols);
DUMP_FIELD(nt.FileHeader.SizeOfOptionalHeader);
DUMP_FIELD(nt.FileHeader.Characteristics);
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
DUMP_FIELD(nt.OptionalHeader.Magic);
DUMP_DEC_FIELD(nt.OptionalHeader.MajorLinkerVersion);
DUMP_DEC_FIELD(nt.OptionalHeader.MinorLinkerVersion);
DUMP_FIELD(nt.OptionalHeader.SizeOfCode);
DUMP_FIELD(nt.OptionalHeader.SizeOfInitializedData);
DUMP_FIELD(nt.OptionalHeader.SizeOfUninitializedData);
DUMP_FIELD(nt.OptionalHeader.AddressOfEntryPoint);
DUMP_FIELD(nt.OptionalHeader.BaseOfCode);
DUMP_FIELD(nt.OptionalHeader.BaseOfData);
DUMP_FIELD(nt.OptionalHeader.ImageBase);
DUMP_FIELD(nt.OptionalHeader.SectionAlignment);
DUMP_FIELD(nt.OptionalHeader.FileAlignment);
DUMP_DEC_FIELD(nt.OptionalHeader.MajorOperatingSystemVersion);
DUMP_DEC_FIELD(nt.OptionalHeader.MinorOperatingSystemVersion);
DUMP_DEC_FIELD(nt.OptionalHeader.Win32VersionValue);
DUMP_FIELD(nt.OptionalHeader.SizeOfImage);
DUMP_FIELD(nt.OptionalHeader.SizeOfHeaders);
DUMP_FIELD(nt.OptionalHeader.CheckSum);
DUMP_FIELD(nt.OptionalHeader.Subsystem);
DUMP_FIELD(nt.OptionalHeader.DllCharacteristics);
DUMP_FIELD(nt.OptionalHeader.SizeOfStackReserve);
DUMP_FIELD(nt.OptionalHeader.SizeOfStackCommit);
DUMP_FIELD(nt.OptionalHeader.SizeOfHeapReserve);
DUMP_FIELD(nt.OptionalHeader.SizeOfHeapCommit);
DUMP_FIELD(nt.OptionalHeader.LoaderFlags);
DUMP_DEC_FIELD(nt.OptionalHeader.NumberOfRvaAndSizes);
} else {
DUMP_FIELD(nt.OptionalHeader64.Magic);
DUMP_DEC_FIELD(nt.OptionalHeader64.MajorLinkerVersion);
DUMP_DEC_FIELD(nt.OptionalHeader64.MinorLinkerVersion);
DUMP_FIELD(nt.OptionalHeader64.SizeOfCode);
DUMP_FIELD(nt.OptionalHeader64.SizeOfInitializedData);
DUMP_FIELD(nt.OptionalHeader64.SizeOfUninitializedData);
DUMP_FIELD(nt.OptionalHeader64.AddressOfEntryPoint);
DUMP_FIELD(nt.OptionalHeader64.BaseOfCode);
DUMP_FIELD(nt.OptionalHeader64.ImageBase);
DUMP_FIELD(nt.OptionalHeader64.SectionAlignment);
DUMP_FIELD(nt.OptionalHeader64.FileAlignment);
DUMP_DEC_FIELD(nt.OptionalHeader64.MajorOperatingSystemVersion);
DUMP_DEC_FIELD(nt.OptionalHeader64.MinorOperatingSystemVersion);
DUMP_DEC_FIELD(nt.OptionalHeader64.Win32VersionValue);
DUMP_FIELD(nt.OptionalHeader64.SizeOfImage);
DUMP_FIELD(nt.OptionalHeader64.SizeOfHeaders);
DUMP_FIELD(nt.OptionalHeader64.CheckSum);
DUMP_FIELD(nt.OptionalHeader64.Subsystem);
DUMP_FIELD(nt.OptionalHeader64.DllCharacteristics);
DUMP_FIELD(nt.OptionalHeader64.SizeOfStackReserve);
DUMP_FIELD(nt.OptionalHeader64.SizeOfStackCommit);
DUMP_FIELD(nt.OptionalHeader64.SizeOfHeapReserve);
DUMP_FIELD(nt.OptionalHeader64.SizeOfHeapCommit);
DUMP_FIELD(nt.OptionalHeader64.LoaderFlags);
DUMP_DEC_FIELD(nt.OptionalHeader64.NumberOfRvaAndSizes);
}
#undef DUMP_FIELD
#undef DUMP_DEC_FIELD
std::cout << "Imports: "
<< "\n";
IterImpVAString(p, printImports, NULL);
std::cout << "Relocations: "
<< "\n";
IterRelocs(p, printRelocs, NULL);
std::cout << "Symbols (symbol table): "
<< "\n";
IterSymbols(p, printSymbols, NULL);
std::cout << "Sections: "
<< "\n";
IterSec(p, printSecs, NULL);
std::cout << "Exports: "
<< "\n";
IterExpVA(p, printExps, NULL);
// read the first 8 bytes from the entry point and print them
VA entryPoint;
if (GetEntryPoint(p, entryPoint)) {
std::cout << "First 8 bytes from entry point (0x";
std::cout << std::hex << entryPoint << "):"
std::cout << "Imports: "
<< "\n";
for (std::size_t i = 0; i < 8; i++) {
std::uint8_t b;
if (!ReadByteAtVA(p, i + entryPoint, b)) {
std::cout << " ERR";
} else {
std::cout << " 0x" << std::hex << static_cast<int>(b);
IterImpVAString(p, printImports, NULL);
std::cout << "Relocations: "
<< "\n";
IterRelocs(p, printRelocs, NULL);
std::cout << "Symbols (symbol table): "
<< "\n";
IterSymbols(p, printSymbols, NULL);
std::cout << "Sections: "
<< "\n";
IterSec(p, printSecs, NULL);
std::cout << "Exports: "
<< "\n";
IterExpVA(p, printExps, NULL);
// read the first 8 bytes from the entry point and print them
VA entryPoint;
if (GetEntryPoint(p, entryPoint)) {
std::cout << "First 8 bytes from entry point (0x";
std::cout << std::hex << entryPoint << "):"
<< "\n";
for (std::size_t i = 0; i < 8; i++) {
std::uint8_t b;
if (!ReadByteAtVA(p, i + entryPoint, b)) {
std::cout << " ERR";
} else {
std::cout << " 0x" << std::hex << static_cast<int>(b);
}
}
std::cout << "\n";
}
std::cout << "\n";
std::cout << "Resources: "
<< "\n";
IterRsrc(p, printRsrc, NULL);
DestructParsedPE(p);
return 0;
}
std::cout << "Resources: "
<< "\n";
IterRsrc(p, printRsrc, NULL);
DestructParsedPE(p);
return 0;
}

View File

@ -359,7 +359,9 @@ struct rich_header {
std::vector<rich_entry> Entries;
std::uint32_t EndSignature;
std::uint32_t DecryptionKey;
std::uint32_t Checksum;
bool isPresent;
bool isValid;
};
/*

View File

@ -157,6 +157,7 @@ uint64_t bufLen(bounded_buffer *b);
struct parsed_pe_internal;
typedef struct _pe_header {
dos_header dos;
rich_header rich;
nt_header_32 nt;
} pe_header;
@ -170,8 +171,8 @@ typedef struct _parsed_pe {
// Resolve a Rich header product id / build number pair to a known
// product name
typedef std::pair<std::uint16_t, std::uint16_t> ProductKey;
const std::string &GetRichProductName(std::uint16_t prodId,
std::uint16_t buildNum);
const std::string &GetRichObjectType(std::uint16_t prodId);
const std::string &GetRichProductName(std::uint16_t buildNum);
// get parser error status as integer
std::uint32_t GetPEErr();

View File

@ -123,20 +123,347 @@ struct parsed_pe_internal {
std::vector<symbol> symbols;
};
// The mapping of Rich header product id / build number pairs
// to strings
static const std::map<ProductKey, const std::string> ProductMap = {
{std::make_pair(static_cast<std::uint16_t>(1),
static_cast<std::uint16_t>(0)),
"Imported Functions"}};
// String representation of Rich header object types
static const std::string kProdId_C = "[ C ]";
static const std::string kProdId_CPP = "[C++]";
static const std::string kProdId_RES = "[RES]";
static const std::string kProdId_IMP = "[IMP]";
static const std::string kProdId_EXP = "[EXP]";
static const std::string kProdId_ASM = "[ASM]";
static const std::string kProdId_LNK = "[LNK]";
static const std::string kProdId_UNK = "[ ? ]";
// Mapping of Rich header Product ID to object type string
// Source: https://github.com/dishather/richprint/blob/master/comp_id.txt
static const std::map<std::uint16_t, std::string> ProductIdMap = {
{std::make_pair(static_cast<std::uint16_t>(0x0000), kProdId_UNK)},
{std::make_pair(static_cast<std::uint16_t>(0x0002), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x0004), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x0006), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x000A), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x000B), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x000F), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x0015), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x0016), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x0019), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x001C), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x001D), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x003D), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x003F), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x0040), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x0045), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x005A), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x005C), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x005D), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x005E), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x005F), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x0060), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x006D), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x006E), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x0078), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x007A), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x007B), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x007C), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x007D), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x0083), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x0084), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x0091), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x0092), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x0093), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x0094), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x0095), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x009A), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x009B), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x009C), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x009D), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x009E), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x00AA), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x00AB), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x00C9), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x00CA), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x00CB), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x00CC), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x00CD), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x00CE), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x00CF), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x00DB), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x00DC), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x00DD), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x00DE), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x00DF), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x00E0), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x00E1), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x00FF), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x0100), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x0101), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x0102), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x0103), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x0104), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x0105), kProdId_CPP)}};
// Mapping of Rich header build number to version strings
static const std::map<std::uint16_t, const std::string> ProductMap = {
// Source: https://github.com/dishather/richprint/blob/master/comp_id.txt
{std::make_pair(static_cast<std::uint16_t>(0x0000), "Imported Functions")},
{std::make_pair(static_cast<std::uint16_t>(0x0684),
"VS97 v5.0 SP3 cvtres 5.00.1668")},
{std::make_pair(static_cast<std::uint16_t>(0x06B8),
"VS98 v6.0 cvtres build 1720")},
{std::make_pair(static_cast<std::uint16_t>(0x06C8),
"VS98 v6.0 SP6 cvtres build 1736")},
{std::make_pair(static_cast<std::uint16_t>(0x1C87),
"VS97 v5.0 SP3 link 5.10.7303")},
{std::make_pair(static_cast<std::uint16_t>(0x5E92),
"VS2015 v14.0 UPD3 build 24210")},
{std::make_pair(static_cast<std::uint16_t>(0x5E95),
"VS2015 UPD3 build 24213")},
// http://bytepointer.com/articles/the_microsoft_rich_header.htm
{std::make_pair(static_cast<std::uint16_t>(0x0BEC),
"VS2003 v7.1 Free Toolkit .NET build 3052")},
{std::make_pair(static_cast<std::uint16_t>(0x0C05),
"VS2003 v7.1 .NET build 3077")},
{std::make_pair(static_cast<std::uint16_t>(0x0FC3),
"VS2003 v7.1 | Windows Server 2003 SP1 DDK build 4035")},
{std::make_pair(static_cast<std::uint16_t>(0x1C83), "MASM 6.13.7299")},
{std::make_pair(static_cast<std::uint16_t>(0x178E),
"VS2003 v7.1 SP1 .NET build 6030")},
{std::make_pair(static_cast<std::uint16_t>(0x1FE8),
"VS98 v6.0 RTM/SP1/SP2 build 8168")},
{std::make_pair(static_cast<std::uint16_t>(0x1FE9),
"VB 6.0/SP1/SP2 build 8169")},
{std::make_pair(static_cast<std::uint16_t>(0x20FC), "MASM 6.14.8444")},
{std::make_pair(static_cast<std::uint16_t>(0x20FF),
"VC++ 6.0 SP3 build 8447")},
{std::make_pair(static_cast<std::uint16_t>(0x212F),
"VB 6.0 SP3 build 8495")},
{std::make_pair(static_cast<std::uint16_t>(0x225F),
"VS 6.0 SP4 build 8799")},
{std::make_pair(static_cast<std::uint16_t>(0x2263), "MASM 6.15.8803")},
{std::make_pair(static_cast<std::uint16_t>(0x22AD),
"VB 6.0 SP4 build 8877")},
{std::make_pair(static_cast<std::uint16_t>(0x2304),
"VB 6.0 SP5 build 8964")},
{std::make_pair(static_cast<std::uint16_t>(0x2306),
"VS 6.0 SP5 build 8966")},
// {std::make_pair(static_cast<std::uint16_t>(0x2346), "MASM 6.15.9030
// (VS.NET 7.0 BETA 1)")},
{std::make_pair(static_cast<std::uint16_t>(0x2346),
"VS 7.0 2000 Beta 1 build 9030")},
{std::make_pair(static_cast<std::uint16_t>(0x2354),
"VS 6.0 SP5 Processor Pack build 9044")},
{std::make_pair(static_cast<std::uint16_t>(0x2426),
"VS2001 v7.0 Beta 2 build 9254")},
{std::make_pair(static_cast<std::uint16_t>(0x24FA),
"VS2002 v7.0 .NET build 9466")},
{std::make_pair(static_cast<std::uint16_t>(0x2636),
"VB 6.0 SP6 / VC++ build 9782")},
{std::make_pair(static_cast<std::uint16_t>(0x26E3),
"VS2002 v7.0 SP1 build 9955")},
{std::make_pair(static_cast<std::uint16_t>(0x520D),
"VS2013 v12.[0,1] build 21005")},
{std::make_pair(static_cast<std::uint16_t>(0x521E),
"VS2008 v9.0 build 21022")},
{std::make_pair(static_cast<std::uint16_t>(0x56C7),
"VS2015 v14.0 build 22215")},
{std::make_pair(static_cast<std::uint16_t>(0x59F2),
"VS2015 v14.0 build 23026")},
{std::make_pair(static_cast<std::uint16_t>(0x5BD2),
"VS2015 v14.0 UPD1 build 23506")},
{std::make_pair(static_cast<std::uint16_t>(0x5D10),
"VS2015 v14.0 UPD2 build 23824")},
{std::make_pair(static_cast<std::uint16_t>(0x5E97),
"VS2015 v14.0 UPD3.1 build 24215")},
{std::make_pair(static_cast<std::uint16_t>(0x7725),
"VS2013 v12.0 UPD2 build 30501")},
{std::make_pair(static_cast<std::uint16_t>(0x766F),
"VS2010 v10.0 build 30319")},
{std::make_pair(static_cast<std::uint16_t>(0x7809),
"VS2008 v9.0 SP1 build 30729")},
{std::make_pair(static_cast<std::uint16_t>(0x797D),
"VS2013 v12.0 UPD4 build 31101")},
{std::make_pair(static_cast<std::uint16_t>(0x9D1B),
"VS2010 v10.0 SP1 build 40219")},
{std::make_pair(static_cast<std::uint16_t>(0x9EB5),
"VS2013 v12.0 UPD5 build 40629")},
{std::make_pair(static_cast<std::uint16_t>(0xC497),
"VS2005 v8.0 (Beta) build 50327")},
{std::make_pair(static_cast<std::uint16_t>(0xC627),
"VS2005 v8.0 | VS2012 v11.0 build 50727")},
{std::make_pair(static_cast<std::uint16_t>(0xC751),
"VS2012 v11.0 Nov CTP build 51025")},
{std::make_pair(static_cast<std::uint16_t>(0xC7A2),
"VS2012 v11.0 UPD1 build 51106")},
{std::make_pair(static_cast<std::uint16_t>(0xEB9B),
"VS2012 v11.0 UPD2 build 60315")},
{std::make_pair(static_cast<std::uint16_t>(0xECC2),
"VS2012 v11.0 UPD3 build 60610")},
{std::make_pair(static_cast<std::uint16_t>(0xEE66),
"VS2012 v11.0 UPD4 build 61030")},
{std::make_pair(static_cast<std::uint16_t>(0x5E9A),
"VS2015 v14.0 build 24218")},
{std::make_pair(static_cast<std::uint16_t>(0x61BB),
"VS2017 v14.1 build 25019")},
// https://dev.to/yumetodo/list-of-mscver-and-mscfullver-8nd
{std::make_pair(static_cast<std::uint16_t>(0x2264),
"VS 6 [SP5,SP6] build 8804")},
{std::make_pair(static_cast<std::uint16_t>(0x23D8), "Windows XP SP1 DDK")},
{std::make_pair(static_cast<std::uint16_t>(0x0883),
"Windows Server 2003 DDK")},
{std::make_pair(static_cast<std::uint16_t>(0x08F4),
"VS2003 v7.1 .NET Beta build 2292")},
{std::make_pair(static_cast<std::uint16_t>(0x9D76),
"Windows Server 2003 SP1 DDK (for AMD64)")},
{std::make_pair(static_cast<std::uint16_t>(0x9E9F),
"VS2005 v8.0 Beta 1 build 40607")},
{std::make_pair(static_cast<std::uint16_t>(0xC427),
"VS2005 v8.0 Beta 2 build 50215")},
{std::make_pair(static_cast<std::uint16_t>(0xC490),
"VS2005 v8.0 build 50320")},
{std::make_pair(static_cast<std::uint16_t>(0x50E2),
"VS2008 v9.0 Beta 2 build 20706")},
{std::make_pair(static_cast<std::uint16_t>(0x501A),
"VS2010 v10.0 Beta 1 build 20506")},
{std::make_pair(static_cast<std::uint16_t>(0x520B),
"VS2010 v10.0 Beta 2 build 21003")},
{std::make_pair(static_cast<std::uint16_t>(0x5089),
"VS2013 v12.0 Preview build 20617")},
{std::make_pair(static_cast<std::uint16_t>(0x515B),
"VS2013 v12.0 RC build 20827")},
{std::make_pair(static_cast<std::uint16_t>(0x527A),
"VS2013 v12.0 Nov CTP build 21114")},
{std::make_pair(static_cast<std::uint16_t>(0x63A3),
"VS2017 v15.3.3 build 25507")},
{std::make_pair(static_cast<std::uint16_t>(0x63C6),
"VS2017 v15.4.4 build 25542")},
{std::make_pair(static_cast<std::uint16_t>(0x63CB),
"VS2017 v15.4.5 build 25547")},
{std::make_pair(static_cast<std::uint16_t>(0x7674),
"VS2013 v12.0 UPD2 RC build 30324")},
// https://walbourn.github.io/visual-studio-2015-update-2/
{std::make_pair(static_cast<std::uint16_t>(0x5D6E),
"VS2015 v14.0 UPD2 build 23918")},
// https://walbourn.github.io/visual-studio-2017/
{std::make_pair(static_cast<std::uint16_t>(0x61B9),
"VS2017 v15.[0,1] build 25017")},
{std::make_pair(static_cast<std::uint16_t>(0x63A2),
"VS2017 v15.2 build 25019")},
// https://walbourn.github.io/vs-2017-15-5-update/
{std::make_pair(static_cast<std::uint16_t>(0x64E6),
"VS2017 v15 build 25830")},
{std::make_pair(static_cast<std::uint16_t>(0x64E7),
"VS2017 v15.5.2 build 25831")},
{std::make_pair(static_cast<std::uint16_t>(0x64EA),
"VS2017 v15.5.[3,4] build 25834")},
{std::make_pair(static_cast<std::uint16_t>(0x64EB),
"VS2017 v15.5.[5,6,7] build 25835")},
// https://walbourn.github.io/vs-2017-15-6-update/
{std::make_pair(static_cast<std::uint16_t>(0x6610),
"VS2017 v15.6.[0,1,2] build 26128")},
{std::make_pair(static_cast<std::uint16_t>(0x6611),
"VS2017 v15.6.[3,4] build 26129")},
{std::make_pair(static_cast<std::uint16_t>(0x6613),
"VS2017 v15.6.6 build 26131")},
{std::make_pair(static_cast<std::uint16_t>(0x6614),
"VS2017 v15.6.7 build 26132")},
// https://devblogs.microsoft.com/visualstudio/visual-studio-2017-update/
{std::make_pair(static_cast<std::uint16_t>(0x6723),
"VS2017 v15.1 build 26403")},
// https://walbourn.github.io/vs-2017-15-7-update/
{std::make_pair(static_cast<std::uint16_t>(0x673C),
"VS2017 v15.7.[0,1] build 26428")},
{std::make_pair(static_cast<std::uint16_t>(0x673D),
"VS2017 v15.7.2 build 26429")},
{std::make_pair(static_cast<std::uint16_t>(0x673E),
"VS2017 v15.7.3 build 26430")},
{std::make_pair(static_cast<std::uint16_t>(0x673F),
"VS2017 v15.7.4 build 26431")},
{std::make_pair(static_cast<std::uint16_t>(0x6741),
"VS2017 v15.7.5 build 26433")},
// https://walbourn.github.io/visual-studio-2019/
{std::make_pair(static_cast<std::uint16_t>(0x6B74),
"VS2019 v16.0.0 build 27508")},
// https://walbourn.github.io/vs-2017-15-8-update/
{std::make_pair(static_cast<std::uint16_t>(0x6866),
"VS2017 v15.8.0 build 26726")},
{std::make_pair(static_cast<std::uint16_t>(0x6869),
"VS2017 v15.8.4 build 26729")},
{std::make_pair(static_cast<std::uint16_t>(0x686A),
"VS2017 v15.8.9 build 26730")},
{std::make_pair(static_cast<std::uint16_t>(0x686C),
"VS2017 v15.8.5 build 26732")},
// https://walbourn.github.io/vs-2017-15-9-update/
{std::make_pair(static_cast<std::uint16_t>(0x698F),
"VS2017 v15.9.[0,1] build 27023")},
{std::make_pair(static_cast<std::uint16_t>(0x6990),
"VS2017 v15.9.2 build 27024")},
{std::make_pair(static_cast<std::uint16_t>(0x6991),
"VS2017 v15.9.4 build 27025")},
{std::make_pair(static_cast<std::uint16_t>(0x6992),
"VS2017 v15.9.5 build 27026")},
{std::make_pair(static_cast<std::uint16_t>(0x6993),
"VS2017 v15.9.7 build 27027")},
{std::make_pair(static_cast<std::uint16_t>(0x6996),
"VS2017 v15.9.11 build 27030")},
{std::make_pair(static_cast<std::uint16_t>(0x6997),
"VS2017 v15.9.12 build 27031")},
{std::make_pair(static_cast<std::uint16_t>(0x6998),
"VS2017 v15.9.14 build 27032")},
{std::make_pair(static_cast<std::uint16_t>(0x699A),
"VS2017 v15.9.16 build 27034")},
// https://walbourn.github.io/visual-studio-2019/
{std::make_pair(static_cast<std::uint16_t>(0x6B74),
"VS2019 v16.0.0 RTM build 27508")},
// https://walbourn.github.io/vs-2019-update-1/
{std::make_pair(static_cast<std::uint16_t>(0x6C36),
"VS2019 v16.1.2 UPD1 build 27702")},
// https://walbourn.github.io/vs-2019-update-2/
{std::make_pair(static_cast<std::uint16_t>(0x6D01),
"VS2019 v16.2.3 UPD2 build 27905")},
// https://walbourn.github.io/vs-2019-update-3/
{std::make_pair(static_cast<std::uint16_t>(0x6DC9),
"VS2019 v16.3.2 UPD3 build 28105")},
// https://walbourn.github.io/visual-studio-2013-update-3/
{std::make_pair(static_cast<std::uint16_t>(0x7803),
"VS2013 v12.0 UPD3 build 30723")},
// experimentation
{std::make_pair(static_cast<std::uint16_t>(0x685B),
"VS2017 v15.8.? build 26715")},
};
static const std::string kUnknownProduct = "<unknown>";
// Resolve a Rich header product id / build number pair to a known
// product name
const std::string &GetRichProductName(std::uint16_t prodId,
std::uint16_t buildNum) {
auto it = ProductMap.find(std::make_pair(prodId, buildNum));
// Returns a stringified Rich header object type given a product id
const std::string &GetRichObjectType(std::uint16_t prodId) {
auto it = ProductIdMap.find(prodId);
if (it != ProductIdMap.end()) {
return it->second;
} else {
return kProdId_UNK;
}
}
// Returns a stringified Rich header product name given a build number
const std::string &GetRichProductName(std::uint16_t buildNum) {
auto it = ProductMap.find(buildNum);
if (it != ProductMap.end()) {
return it->second;
} else {
@ -836,6 +1163,41 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
return true;
}
// zero extends its first argument to 32 bits and then performs a rotate left
// operation equal to the second arguments value of the first arguments bits
static inline std::uint32_t rol(std::uint32_t val, std::uint32_t num) {
return ((val << num) & 0xffffffff) | (val >> (32 - num));
}
std::uint32_t calculateRichChecksum(const bounded_buffer *b, pe_header &p) {
// First, calculate the sum of the DOS header bytes each rotated left the
// number of times their position relative to the start of the DOS header e.g.
// second byte is rotated left 2x using rol operation
std::uint32_t checksum = 0;
for (uint8_t i = 0; i < RICH_OFFSET; i++) {
// skip over dos e_lfanew field at offset 0x3C
if (i >= 0x3C && i <= 0x3F) {
continue;
}
checksum += rol(b->buf[i], i);
}
// Next, take summation of each Rich header entry by combining its ProductId
// and BuildNumber into a single 32 bit number and rotating by its count.
for (rich_entry entry : p.rich.Entries) {
std::uint32_t num =
static_cast<std::uint32_t>((entry.ProductId << 16) | entry.BuildNumber);
checksum += rol(num, entry.Count & 0x1F);
}
checksum += RICH_OFFSET;
return checksum;
}
bool readRichHeader(bounded_buffer *rich_buf,
std::uint32_t key,
rich_header &rich_hdr) {
@ -914,30 +1276,62 @@ bool readRichHeader(bounded_buffer *rich_buf,
return true;
}
bool readDosHeader(bounded_buffer *file, dos_header &dos_hdr) {
if (file == nullptr) {
return false;
}
READ_WORD(file, 0, dos_hdr, e_magic);
READ_WORD(file, 0, dos_hdr, e_cblp);
READ_WORD(file, 0, dos_hdr, e_cp);
READ_WORD(file, 0, dos_hdr, e_crlc);
READ_WORD(file, 0, dos_hdr, e_cparhdr);
READ_WORD(file, 0, dos_hdr, e_minalloc);
READ_WORD(file, 0, dos_hdr, e_maxalloc);
READ_WORD(file, 0, dos_hdr, e_ss);
READ_WORD(file, 0, dos_hdr, e_sp);
READ_WORD(file, 0, dos_hdr, e_csum);
READ_WORD(file, 0, dos_hdr, e_ip);
READ_WORD(file, 0, dos_hdr, e_cs);
READ_WORD(file, 0, dos_hdr, e_lfarlc);
READ_WORD(file, 0, dos_hdr, e_ovno);
READ_WORD(file, 0, dos_hdr, e_res[0]);
READ_WORD(file, 0, dos_hdr, e_res[1]);
READ_WORD(file, 0, dos_hdr, e_res[2]);
READ_WORD(file, 0, dos_hdr, e_res[3]);
READ_WORD(file, 0, dos_hdr, e_oemid);
READ_WORD(file, 0, dos_hdr, e_oeminfo);
READ_WORD(file, 0, dos_hdr, e_res2[0]);
READ_WORD(file, 0, dos_hdr, e_res2[1]);
READ_WORD(file, 0, dos_hdr, e_res2[2]);
READ_WORD(file, 0, dos_hdr, e_res2[3]);
READ_WORD(file, 0, dos_hdr, e_res2[4]);
READ_WORD(file, 0, dos_hdr, e_res2[5]);
READ_WORD(file, 0, dos_hdr, e_res2[6]);
READ_WORD(file, 0, dos_hdr, e_res2[7]);
READ_WORD(file, 0, dos_hdr, e_res2[8]);
READ_WORD(file, 0, dos_hdr, e_res2[9]);
READ_DWORD(file, 0, dos_hdr, e_lfanew);
return true;
}
bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
if (file == nullptr) {
return false;
}
// start by reading MZ
std::uint16_t tmp = 0;
std::uint32_t curOffset = 0;
if (!readWord(file, curOffset, tmp)) {
PE_ERR(PEERR_READ);
return false;
}
if (tmp != MZ_MAGIC) {
// read the DOS header
readDosHeader(file, p.dos);
if (p.dos.e_magic != MZ_MAGIC) {
PE_ERR(PEERR_MAGIC);
return false;
}
// read the offset to the NT headers
std::uint32_t offset;
if (!readDword(file, _offset(dos_header, e_lfanew), offset)) {
PE_ERR(PEERR_READ);
return false;
}
curOffset += offset;
// get the offset to the NT headers
std::uint32_t offset = p.dos.e_lfanew;
std::uint32_t curOffset = offset;
// read rich header
std::uint32_t dword;
@ -983,6 +1377,24 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
deleteBuffer(richBuf);
}
// Split the DOS header into a separate buffer which
// starts at offset 0 and has length 0x80
bounded_buffer *dosBuf = splitBuffer(file, 0, RICH_OFFSET);
if (dosBuf == nullptr) {
return false;
}
// Calculate checksum
p.rich.Checksum = calculateRichChecksum(dosBuf, p);
if (p.rich.Checksum == p.rich.DecryptionKey) {
p.rich.isValid = true;
} else {
p.rich.isValid = false;
}
if (dosBuf != nullptr) {
deleteBuffer(dosBuf);
}
// Rich header not present
} else {
p.rich.isPresent = false;
}