rizin/librz/bin/p/bin_pe.c

569 lines
23 KiB
C

// SPDX-FileCopyrightText: 2009-2019 nibble <nibble.ds@gmail.com>
// SPDX-FileCopyrightText: 2009-2019 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2009-2019 alvarofe <alvaro.felipe91@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include "bin_pe.inc"
static bool pe_check_buffer(RzBuffer *b) {
ut64 length = rz_buf_size(b);
if (length <= 0x3d) {
return false;
}
ut16 idx;
if (!rz_buf_read_le16_at(b, 0x3c, &idx)) {
return false;
}
if (idx + 26 < length) {
/* Here PE signature for usual PE files
* and PL signature for Phar Lap TNT DOS extender 32bit executables
*/
ut8 buf[2];
rz_buf_read_at(b, 0, buf, sizeof(buf));
if (!memcmp(buf, "MZ", 2)) {
rz_buf_read_at(b, idx, buf, sizeof(buf));
// TODO: Add one more indicator, to prevent false positives
if (!memcmp(buf, "PL", 2)) {
return true;
}
if (!memcmp(buf, "PE", 2)) {
rz_buf_read_at(b, idx + 0x18, buf, sizeof(buf));
return !memcmp(buf, "\x0b\x01", 2);
}
}
}
return false;
}
/* inspired in http://www.phreedom.org/solar/code/tinype/tiny.97/tiny.asm */
static RzBuffer *pe_create(RzBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RzBinArchOptions *opt) {
ut32 hdrsize, p_start, p_opthdr, p_sections, p_lsrlc, n;
ut32 baddr = 0x400000;
RzBuffer *buf = rz_buf_new_with_bytes(NULL, 0);
#define B(x, y) rz_buf_append_bytes(buf, (const ut8 *)(x), y)
#define H(x) rz_buf_append_ut16(buf, x)
#define D(x) rz_buf_append_ut32(buf, x)
#define Z(x) rz_buf_append_nbytes(buf, x)
#define W(x, y, z) rz_buf_write_at(buf, x, (const ut8 *)(y), z)
#define WZ(x, y) \
p_tmp = rz_buf_size(buf); \
Z(x); \
W(p_tmp, y, strlen(y))
B("MZ\x00\x00", 4); // MZ Header
B("PE\x00\x00", 4); // PE Signature
H(0x14c); // Machine
H(1); // Number of sections
D(0); // Timestamp (Unused)
D(0); // PointerToSymbolTable (Unused)
D(0); // NumberOfSymbols (Unused)
p_lsrlc = rz_buf_size(buf);
H(-1); // SizeOfOptionalHeader
H(0x103); // Characteristics
/* Optional Header */
p_opthdr = rz_buf_size(buf);
H(0x10b); // Magic
B("\x08\x00", 2); // (Major/Minor)LinkerVersion (Unused)
p_sections = rz_buf_size(buf);
n = p_sections - p_opthdr;
W(p_lsrlc, &n, 2); // Fix SizeOfOptionalHeader
/* Sections */
p_start = 0x7c; // HACK: Headersize
hdrsize = 0x7c;
D(RZ_ROUND(codelen, 4)); // SizeOfCode (Unused)
D(0); // SizeOfInitializedData (Unused)
D(codelen); // codesize
D(p_start);
D(codelen);
D(p_start);
D(baddr); // ImageBase
D(4); // SectionAlignment
D(4); // FileAlignment
H(4); // MajorOperatingSystemVersion (Unused)
H(0); // MinorOperatingSystemVersion (Unused)
H(0); // MajorImageVersion (Unused)
H(0); // MinorImageVersion (Unused)
H(4); // MajorSubsystemVersion
H(0); // MinorSubsystemVersion (Unused)
D(0); // Win32VersionValue (Unused)
D((RZ_ROUND(hdrsize, 4)) + (RZ_ROUND(codelen, 4))); // SizeOfImage
D(RZ_ROUND(hdrsize, 4)); // SizeOfHeaders
D(0); // CheckSum (Unused)
H(2); // Subsystem (Win32 GUI)
H(0x400); // DllCharacteristics (Unused)
D(0x100000); // SizeOfStackReserve (Unused)
D(0x1000); // SizeOfStackCommit
D(0x100000); // SizeOfHeapReserve
D(0x1000); // SizeOfHeapCommit (Unused)
D(0); // LoaderFlags (Unused)
D(0); // NumberOfRvaAndSizes (Unused)
B(code, codelen);
if (data && datalen > 0) {
// ut32 data_section = buf->length;
RZ_LOG_WARN("DATA section not support for PE yet\n");
B(data, datalen);
}
return buf;
}
static char *pe_signature(RzBinFile *bf, bool json) {
if (!bf || !bf->o || !bf->o->bin_obj) {
return NULL;
}
struct PE_(rz_bin_pe_obj_t) *bin = bf->o->bin_obj;
RzStructuredData *pe_cms = rz_pkcs7_cms_to_structure(bin->cms);
if (!pe_cms) {
return rz_str_dup(json ? "{}" : "");
}
char *value = NULL;
if (json) {
value = rz_structured_data_to_json(pe_cms);
} else {
value = rz_structured_data_to_yaml(pe_cms);
}
rz_structured_data_free(pe_cms);
return value;
}
static RzPVector /*<RzBinField *>*/ *pe_fields(RzBinFile *bf) {
RzPVector *ret = rz_pvector_new((RzPVectorFree)rz_bin_field_free);
if (!ret) {
return NULL;
}
#define ROWL(buf, nam, siz, val, fmt) \
rz_pvector_push(ret, rz_bin_field_new(addr, addr, siz, nam, rz_strf(buf, "0x%08x", val), fmt, false));
struct PE_(rz_bin_pe_obj_t) *bin = bf->o->bin_obj;
ut64 addr = bin->rich_header_offset ? bin->rich_header_offset : 128;
char tmpbuf[32];
RzListIter *it;
Pe_image_rich_entry *rich;
rz_list_foreach (bin->rich_entries, it, rich) {
rz_pvector_push(ret, rz_bin_field_new(addr, addr, 0, "RICH_ENTRY_NAME", rz_str_dup(rich->productName), "s", false));
ROWL(tmpbuf, "RICH_ENTRY_ID", 2, rich->productId, "x");
addr += 2;
ROWL(tmpbuf, "RICH_ENTRY_VERSION", 2, rich->minVersion, "x");
addr += 2;
ROWL(tmpbuf, "RICH_ENTRY_TIMES", 4, rich->timesUsed, "x");
addr += 4;
}
ROWL(tmpbuf, "Signature", 4, bin->nt_headers->Signature, "x");
addr += 4;
ROWL(tmpbuf, "Machine", 2, bin->nt_headers->file_header.Machine, "x");
addr += 2;
ROWL(tmpbuf, "NumberOfSections", 2, bin->nt_headers->file_header.NumberOfSections, "x");
addr += 2;
ROWL(tmpbuf, "TimeDateStamp", 4, bin->nt_headers->file_header.TimeDateStamp, "x");
addr += 4;
ROWL(tmpbuf, "PointerToSymbolTable", 4, bin->nt_headers->file_header.PointerToSymbolTable, "x");
addr += 4;
ROWL(tmpbuf, "NumberOfSymbols ", 4, bin->nt_headers->file_header.NumberOfSymbols, "x");
addr += 4;
ROWL(tmpbuf, "SizeOfOptionalHeader", 2, bin->nt_headers->file_header.SizeOfOptionalHeader, "x");
addr += 2;
ROWL(tmpbuf, "Characteristics", 2, bin->nt_headers->file_header.Characteristics, "x");
addr += 2;
ROWL(tmpbuf, "Magic", 2, bin->nt_headers->optional_header.Magic, "x");
addr += 2;
ROWL(tmpbuf, "MajorLinkerVersion", 1, bin->nt_headers->optional_header.MajorLinkerVersion, "x");
addr += 1;
ROWL(tmpbuf, "MinorLinkerVersion", 1, bin->nt_headers->optional_header.MinorLinkerVersion, "x");
addr += 1;
ROWL(tmpbuf, "SizeOfCode", 4, bin->nt_headers->optional_header.SizeOfCode, "x");
addr += 4;
ROWL(tmpbuf, "SizeOfInitializedData", 4, bin->nt_headers->optional_header.SizeOfInitializedData, "x");
addr += 4;
ROWL(tmpbuf, "SizeOfUninitializedData", 4, bin->nt_headers->optional_header.SizeOfUninitializedData, "x");
addr += 4;
ROWL(tmpbuf, "AddressOfEntryPoint", 4, bin->nt_headers->optional_header.AddressOfEntryPoint, "x");
addr += 4;
ROWL(tmpbuf, "BaseOfCode", 4, bin->nt_headers->optional_header.BaseOfCode, "x");
addr += 4;
ROWL(tmpbuf, "BaseOfData", 4, bin->nt_headers->optional_header.BaseOfData, "x");
addr += 4;
ROWL(tmpbuf, "ImageBase", 4, bin->nt_headers->optional_header.ImageBase, "x");
addr += 4;
ROWL(tmpbuf, "SectionAlignment", 4, bin->nt_headers->optional_header.SectionAlignment, "x");
addr += 4;
ROWL(tmpbuf, "FileAlignment", 4, bin->nt_headers->optional_header.FileAlignment, "x");
addr += 4;
ROWL(tmpbuf, "MajorOperatingSystemVersion", 2, bin->nt_headers->optional_header.MajorOperatingSystemVersion, "x");
addr += 2;
ROWL(tmpbuf, "MinorOperatingSystemVersion", 2, bin->nt_headers->optional_header.MinorOperatingSystemVersion, "x");
addr += 2;
ROWL(tmpbuf, "MajorImageVersion", 2, bin->nt_headers->optional_header.MajorImageVersion, "x");
addr += 2;
ROWL(tmpbuf, "MinorImageVersion", 2, bin->nt_headers->optional_header.MinorImageVersion, "x");
addr += 2;
ROWL(tmpbuf, "MajorSubsystemVersion", 2, bin->nt_headers->optional_header.MajorSubsystemVersion, "x");
addr += 2;
ROWL(tmpbuf, "MinorSubsystemVersion", 2, bin->nt_headers->optional_header.MinorSubsystemVersion, "x");
addr += 2;
ROWL(tmpbuf, "Win32VersionValue", 4, bin->nt_headers->optional_header.Win32VersionValue, "x");
addr += 4;
ROWL(tmpbuf, "SizeOfImage", 4, bin->nt_headers->optional_header.SizeOfImage, "x");
addr += 4;
ROWL(tmpbuf, "SizeOfHeaders", 4, bin->nt_headers->optional_header.SizeOfHeaders, "x");
addr += 4;
ROWL(tmpbuf, "CheckSum", 4, bin->nt_headers->optional_header.CheckSum, "x");
addr += 4;
ROWL(tmpbuf, "Subsystem", 24, bin->nt_headers->optional_header.Subsystem, "x");
addr += 2;
ROWL(tmpbuf, "DllCharacteristics", 2, bin->nt_headers->optional_header.DllCharacteristics, "x");
addr += 2;
ROWL(tmpbuf, "SizeOfStackReserve", 4, bin->nt_headers->optional_header.SizeOfStackReserve, "x");
addr += 4;
ROWL(tmpbuf, "SizeOfStackCommit", 4, bin->nt_headers->optional_header.SizeOfStackCommit, "x");
addr += 4;
ROWL(tmpbuf, "SizeOfHeapReserve", 4, bin->nt_headers->optional_header.SizeOfHeapReserve, "x");
addr += 4;
ROWL(tmpbuf, "SizeOfHeapCommit", 4, bin->nt_headers->optional_header.SizeOfHeapCommit, "x");
addr += 4;
ROWL(tmpbuf, "LoaderFlags", 4, bin->nt_headers->optional_header.LoaderFlags, "x");
addr += 4;
ROWL(tmpbuf, "NumberOfRvaAndSizes", 4, bin->nt_headers->optional_header.NumberOfRvaAndSizes, "x");
addr += 4;
int i;
ut64 tmp = addr;
for (i = 0; i < PE_IMAGE_DIRECTORY_ENTRIES - 1; i++) {
if (bin->nt_headers->optional_header.DataDirectory[i].Size > 0) {
addr = tmp + i * 8;
switch (i) {
case PE_IMAGE_DIRECTORY_ENTRY_EXPORT:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_EXPORT", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_EXPORT", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_IMPORT:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_IMPORT", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_IMPORT", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_RESOURCE:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_RESOURCE", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_RESOURCE", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_EXCEPTION", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_EXCEPTION", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_SECURITY:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_SECURITY", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_SECURITY", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_BASERELOC:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_BASERELOC", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_BASERELOC", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_DEBUG:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_DEBUG", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_DEBUG", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_COPYRIGHT:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_COPYRIGHT", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_COPYRIGHT", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_GLOBALPTR:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_GLOBALPTR", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_GLOBALPTR", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_TLS:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_TLS", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_TLS", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_IAT:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_IAT", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_IAT", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
case PE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:
ROWL(tmpbuf, "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", 4,
bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, "x");
addr += 4;
ROWL(tmpbuf, "SIZE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", 4,
bin->nt_headers->optional_header.DataDirectory[i].Size, "x");
break;
}
}
}
return ret;
}
static RzStructuredData *pe_structure(RzBinFile *bf) {
rz_return_val_if_fail(bf && bf->o && bf->o->bin_obj, NULL);
struct PE_(rz_bin_pe_obj_t) *bin = bf->o->bin_obj;
if (!bin) {
return NULL;
}
RzStructuredData *info = rz_structured_data_new_map();
if (!info) {
return NULL;
}
RzStructuredData *pe32 = rz_structured_data_map_add_map(info, "pe32");
if (!pe32) {
rz_structured_data_free(info);
return NULL;
}
RzStructuredData *image = rz_structured_data_map_add_map(pe32, "IMAGE_NT_HEADERS");
if (!image) {
rz_structured_data_free(info);
return NULL;
}
rz_structured_data_map_add_unsigned(image, "Signature", bin->nt_headers->Signature, true);
if (!(image = rz_structured_data_map_add_map(pe32, "IMAGE_FILE_HEADERS"))) {
rz_structured_data_free(info);
return NULL;
}
rz_structured_data_map_add_unsigned(image, "Machine", bin->nt_headers->file_header.Machine, true);
rz_structured_data_map_add_unsigned(image, "NumberOfSections", bin->nt_headers->file_header.NumberOfSections, false);
rz_structured_data_map_add_unsigned(image, "TimeDateStamp", bin->nt_headers->file_header.TimeDateStamp, false);
rz_structured_data_map_add_unsigned(image, "PointerToSymbolTable", bin->nt_headers->file_header.PointerToSymbolTable, true);
rz_structured_data_map_add_unsigned(image, "NumberOfSymbols", bin->nt_headers->file_header.NumberOfSymbols, false);
rz_structured_data_map_add_unsigned(image, "SizeOfOptionalHeader", bin->nt_headers->file_header.SizeOfOptionalHeader, false);
rz_structured_data_map_add_unsigned(image, "Characteristics", bin->nt_headers->file_header.Characteristics, true);
if (!(image = rz_structured_data_map_add_map(pe32, "IMAGE_OPTIONAL_HEADERS"))) {
rz_structured_data_free(info);
return NULL;
}
rz_structured_data_map_add_unsigned(image, "Magic", bin->nt_headers->optional_header.Magic, true);
rz_structured_data_map_add_unsigned(image, "MajorLinkerVersion", bin->nt_headers->optional_header.MajorLinkerVersion, false);
rz_structured_data_map_add_unsigned(image, "MinorLinkerVersion", bin->nt_headers->optional_header.MinorLinkerVersion, false);
rz_structured_data_map_add_unsigned(image, "SizeOfCode", bin->nt_headers->optional_header.SizeOfCode, false);
rz_structured_data_map_add_unsigned(image, "SizeOfInitializedData", bin->nt_headers->optional_header.SizeOfInitializedData, false);
rz_structured_data_map_add_unsigned(image, "SizeOfUninitializedData", bin->nt_headers->optional_header.SizeOfUninitializedData, false);
rz_structured_data_map_add_unsigned(image, "AddressOfEntryPoint", bin->nt_headers->optional_header.AddressOfEntryPoint, true);
rz_structured_data_map_add_unsigned(image, "BaseOfCode", bin->nt_headers->optional_header.BaseOfCode, true);
rz_structured_data_map_add_unsigned(image, "BaseOfData", bin->nt_headers->optional_header.BaseOfData, true);
rz_structured_data_map_add_unsigned(image, "ImageBase", bin->nt_headers->optional_header.ImageBase, true);
rz_structured_data_map_add_unsigned(image, "SectionAlignment", bin->nt_headers->optional_header.SectionAlignment, true);
rz_structured_data_map_add_unsigned(image, "FileAlignment", bin->nt_headers->optional_header.FileAlignment, true);
rz_structured_data_map_add_unsigned(image, "MajorOperatingSystemVersion", bin->nt_headers->optional_header.MajorOperatingSystemVersion, true);
rz_structured_data_map_add_unsigned(image, "MinorOperatingSystemVersion", bin->nt_headers->optional_header.MinorOperatingSystemVersion, true);
rz_structured_data_map_add_unsigned(image, "MajorImageVersion", bin->nt_headers->optional_header.MajorImageVersion, true);
rz_structured_data_map_add_unsigned(image, "MinorImageVersion", bin->nt_headers->optional_header.MinorImageVersion, true);
rz_structured_data_map_add_unsigned(image, "MajorSubsystemVersion", bin->nt_headers->optional_header.MajorSubsystemVersion, true);
rz_structured_data_map_add_unsigned(image, "MinorSubsystemVersion", bin->nt_headers->optional_header.MinorSubsystemVersion, true);
rz_structured_data_map_add_unsigned(image, "Win32VersionValue", bin->nt_headers->optional_header.Win32VersionValue, true);
rz_structured_data_map_add_unsigned(image, "SizeOfImage", bin->nt_headers->optional_header.SizeOfImage, false);
rz_structured_data_map_add_unsigned(image, "SizeOfHeaders", bin->nt_headers->optional_header.SizeOfHeaders, false);
rz_structured_data_map_add_unsigned(image, "CheckSum", bin->nt_headers->optional_header.CheckSum, true);
rz_structured_data_map_add_unsigned(image, "Subsystem", bin->nt_headers->optional_header.Subsystem, true);
rz_structured_data_map_add_unsigned(image, "DllCharacteristics", bin->nt_headers->optional_header.DllCharacteristics, true);
rz_structured_data_map_add_unsigned(image, "SizeOfStackReserve", bin->nt_headers->optional_header.SizeOfStackReserve, false);
rz_structured_data_map_add_unsigned(image, "SizeOfStackCommit", bin->nt_headers->optional_header.SizeOfStackCommit, false);
rz_structured_data_map_add_unsigned(image, "SizeOfHeapReserve", bin->nt_headers->optional_header.SizeOfHeapReserve, false);
rz_structured_data_map_add_unsigned(image, "SizeOfHeapCommit", bin->nt_headers->optional_header.SizeOfHeapCommit, false);
rz_structured_data_map_add_unsigned(image, "LoaderFlags", bin->nt_headers->optional_header.LoaderFlags, true);
rz_structured_data_map_add_unsigned(image, "NumberOfRvaAndSizes", bin->nt_headers->optional_header.NumberOfRvaAndSizes, false);
if (rz_list_length(bin->rich_entries) > 0) {
if (!(image = rz_structured_data_map_add_array(pe32, "RICH_FIELDS"))) {
rz_structured_data_free(info);
return NULL;
}
RzListIter *it;
Pe_image_rich_entry *entry;
rz_list_foreach (bin->rich_entries, it, entry) {
RzStructuredData *field = rz_structured_data_array_add_map(image);
if (!field) {
rz_structured_data_free(info);
return NULL;
}
rz_structured_data_map_add_unsigned(field, "Product", entry->productId, false);
rz_structured_data_map_add_string(field, "Name", entry->productName);
rz_structured_data_map_add_unsigned(field, "Version", entry->minVersion, false);
rz_structured_data_map_add_unsigned(field, "Times", entry->timesUsed, false);
}
}
for (size_t i = 0; i < PE_IMAGE_DIRECTORY_ENTRIES - 1; i++) {
if (bin->nt_headers->optional_header.DataDirectory[i].Size < 1) {
continue;
}
const char *name = "unknown";
switch (i) {
case PE_IMAGE_DIRECTORY_ENTRY_EXPORT:
name = "IMAGE_DIRECTORY_ENTRY_EXPORT";
break;
case PE_IMAGE_DIRECTORY_ENTRY_IMPORT:
name = "IMAGE_DIRECTORY_ENTRY_IMPORT";
break;
case PE_IMAGE_DIRECTORY_ENTRY_RESOURCE:
name = "IMAGE_DIRECTORY_ENTRY_RESOURCE";
break;
case PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION:
name = "IMAGE_DIRECTORY_ENTRY_EXCEPTION";
break;
case PE_IMAGE_DIRECTORY_ENTRY_SECURITY:
name = "IMAGE_DIRECTORY_ENTRY_SECURITY";
break;
case PE_IMAGE_DIRECTORY_ENTRY_BASERELOC:
name = "IMAGE_DIRECTORY_ENTRY_BASERELOC";
break;
case PE_IMAGE_DIRECTORY_ENTRY_DEBUG:
name = "IMAGE_DIRECTORY_ENTRY_DEBUG";
break;
case PE_IMAGE_DIRECTORY_ENTRY_COPYRIGHT:
name = "IMAGE_DIRECTORY_ENTRY_COPYRIGHT";
name = "IMAGE_DIRECTORY_ENTRY_ARCHITECTURE";
break;
case PE_IMAGE_DIRECTORY_ENTRY_GLOBALPTR:
name = "IMAGE_DIRECTORY_ENTRY_GLOBALPTR";
break;
case PE_IMAGE_DIRECTORY_ENTRY_TLS:
name = "IMAGE_DIRECTORY_ENTRY_TLS";
break;
case PE_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG:
name = "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG";
break;
case PE_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT:
name = "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT";
break;
case PE_IMAGE_DIRECTORY_ENTRY_IAT:
name = "IMAGE_DIRECTORY_ENTRY_IAT";
break;
case PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT:
name = "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT";
break;
case PE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:
name = "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR";
break;
}
if (!(image = rz_structured_data_map_add_map(pe32, name))) {
rz_structured_data_free(info);
return NULL;
}
rz_structured_data_map_add_unsigned(image, "VirtualAddress", bin->nt_headers->optional_header.DataDirectory[i].VirtualAddress, true);
rz_structured_data_map_add_unsigned(image, "Size", bin->nt_headers->optional_header.DataDirectory[i].Size, false);
}
if (bin->cms) {
RzStructuredData *pe_cms = rz_pkcs7_cms_to_structure(bin->cms);
rz_structured_data_map_add(pe32, "CryptographicMessageSyntax", pe_cms);
}
if (bin->spcinfo) {
RzStructuredData *pe_auth = rz_pkcs7_spcinfo_to_structure(bin->spcinfo);
rz_structured_data_map_add(pe32, "Authenticode", pe_auth);
}
return info;
}
RzBinPlugin rz_bin_plugin_pe = {
.name = "pe",
.desc = "PE (Portable Executable)",
.license = "LGPL3",
.author = "nibble",
.get_sdb = &pe_get_sdb,
.load_buffer = &pe_load_buffer,
.destroy = &pe_destroy,
.check_buffer = &pe_check_buffer,
.baddr = &pe_baddr,
.binsym = &pe_binsym,
.entries = &pe_entries,
.maps = &pe_maps,
.sections = &pe_sections,
.signature = &pe_signature,
.symbols = &pe_symbols,
.imports = &pe_imports,
.info = &pe_info,
.bin_structure = &pe_structure,
.fields = &pe_fields,
.libs = &pe_libs,
.relocs = &pe_relocs,
.create = &pe_create,
.get_offset = &pe_get_offset,
.get_vaddr = &pe_get_vaddr,
.hashes = &pe_compute_hashes,
.resources = &pe_resources,
.section_flag_to_rzlist = &PE_(section_flag_to_rzlist),
.strings = &pe_strings,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_BIN,
.data = &rz_bin_plugin_pe,
.version = RZ_VERSION
};
#endif