* fix: format with clang-format-20 * fix: fix clang-format linter with rewrite '^#define.*/\*.*\\$' * fix: update clang-format to version 20 in workflows and documentation * fix: add SPDX license information to .git-blame-ignore-revs
290 lines
12 KiB
C
290 lines
12 KiB
C
// SPDX-FileCopyrightText: 2008 nibble <nibble.ds@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_types.h>
|
|
#include <rz_util.h>
|
|
#include <rz_lib.h>
|
|
#include <rz_bin.h>
|
|
#include <rz_vector.h>
|
|
|
|
#include "pe_specs.h"
|
|
#include "dotnet.h"
|
|
|
|
#ifndef _INCLUDE_RZ_BIN_PE_H_
|
|
#define _INCLUDE_RZ_BIN_PE_H_
|
|
|
|
#define PE_READ_STRUCT_FIELD(var, struct_type, field, size) var->field = rz_read_le##size(buf + offsetof(struct_type, field))
|
|
|
|
#define RZ_BIN_PE_SCN_IS_SHAREABLE(x) x &PE_IMAGE_SCN_MEM_SHARED
|
|
#define RZ_BIN_PE_SCN_IS_EXECUTABLE(x) x &PE_IMAGE_SCN_MEM_EXECUTE
|
|
#define RZ_BIN_PE_SCN_IS_READABLE(x) x &PE_IMAGE_SCN_MEM_READ
|
|
#define RZ_BIN_PE_SCN_IS_WRITABLE(x) x &PE_IMAGE_SCN_MEM_WRITE
|
|
|
|
// SECTION FLAGS FOR EXE/PE/DLL START
|
|
#define IMAGE_SCN_TYPE_REG 0x00000000 // Reserved
|
|
#define IMAGE_SCN_TYPE_D_SECT 0x00000001 // Reserved
|
|
#define IMAGE_SCN_TYPE_NO_LOAD 0x00000002 // Reserved
|
|
#define IMAGE_SCN_TYPE_GROUP 0x00000004 // Reserved
|
|
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // The section should not be padded to the next boundary. This flag is obsolete and is replaced by #define IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files.
|
|
#define IMAGE_SCN_TYPE_COPY 0x00000010 // Reserved
|
|
#define IMAGE_SCN_CNT_CODE 0x00000020 // The section contains executable code.
|
|
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // The section contains initialized data.
|
|
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // The section contains uninitialized data.
|
|
#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved for future use.
|
|
#define IMAGE_SCN_LNK_INFO 0x00000200 // The section contains comments or other information. The .drectve section has this type. This is valid for object files only.
|
|
#define IMAGE_SCN_TYPE_OVER 0x00000400 // Reserved
|
|
#define IMAGE_SCN_LNK_REMOVE 0x00000800 // The section will not become part of the image. This is valid only for object files.
|
|
#define IMAGE_SCN_LNK_COMDAT 0x00001000 // The section contains COMDAT data. For more information, see COMDAT Sections (Object Only). This is valid only for object files.
|
|
#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 // Reset speculative exceptions handling bits in the TLB entries for this section.
|
|
#define IMAGE_SCN_MEM_PROTECTED 0x00004000
|
|
#define IMAGE_SCN_GPREL 0x00008000 // The section contains data referenced through the global pointer (GP).
|
|
#define IMAGE_SCN_MEM_FARDATA 0x00008000
|
|
#define IMAGE_SCN_MEM_SYSHEAP 0x00010000
|
|
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 // Reserved for future use.
|
|
#define IMAGE_SCN_MEM_16BIT 0x00020000 // Reserved for future use.
|
|
#define IMAGE_SCN_MEM_LOCKED 0x00040000 // Reserved for future use.
|
|
#define IMAGE_SCN_MEM_PRELOAD 0x00080000 // Reserved for future use.
|
|
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // Align data on a 1-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // Align data on a 2-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // Align data on a 4-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // Align data on an 8-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Align data on a 16-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // Align data on a 32-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // Align data on a 64-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 // Align data on a 128-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 // Align data on a 256-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 // Align data on a 512-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 // Align data on a 1024-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 // Align data on a 2048-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 // Align data on a 4096-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 // Align data on an 8192-byte boundary. Valid only for object files.
|
|
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // The section contains extended relocations.
|
|
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // The section can be discarded as needed.
|
|
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // The section cannot be cached.
|
|
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // The section is not pageable.
|
|
#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable.
|
|
#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable.
|
|
#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable.
|
|
#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writable.
|
|
|
|
#define PE_SCN_ALIGN_MASK 0x00F00000
|
|
|
|
// For the following relocation structs,
|
|
// See: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#the-reloc-section-image-only
|
|
typedef struct rz_bin_pe_reloc_block_t {
|
|
ut32 page_rva; ///< RVA of the block
|
|
ut32 block_size; ///< Size of the block
|
|
} RzBinPeRelocBlock;
|
|
|
|
// encoding is 12 bits for type and 4 bits for offset.
|
|
#define PE_RELOC_ENT_TYPE(val) ((val) >> 12)
|
|
#define PE_RELOC_ENT_OFFSET(val) ((val) & 0xfff)
|
|
|
|
typedef struct rz_bin_pe_reloc_ent_t {
|
|
ut16 raw_val; ///< Type + Offset of the relocation entry
|
|
ut32 page_rva; ///< RVA of the block to which the relocation entry belongs
|
|
} RzBinPeRelocEnt;
|
|
|
|
struct rz_bin_pe_addr_t {
|
|
ut64 vaddr;
|
|
ut64 paddr;
|
|
ut64 haddr;
|
|
};
|
|
|
|
struct rz_bin_pe_section_t {
|
|
ut8 name[PE_IMAGE_SIZEOF_SHORT_NAME * 3];
|
|
ut64 size;
|
|
ut64 vsize;
|
|
ut64 vaddr;
|
|
ut64 paddr;
|
|
ut64 flags;
|
|
ut64 perm;
|
|
int last;
|
|
};
|
|
|
|
struct rz_bin_pe_import_t {
|
|
ut8 name[PE_NAME_LENGTH + 1];
|
|
ut8 libname[PE_NAME_LENGTH + 1];
|
|
ut64 vaddr;
|
|
ut64 paddr;
|
|
ut64 hint;
|
|
ut64 ordinal;
|
|
int last;
|
|
};
|
|
|
|
struct rz_bin_pe_export_t {
|
|
ut8 name[PE_NAME_LENGTH + 1];
|
|
ut8 libname[PE_NAME_LENGTH + 1];
|
|
ut8 forwarder[PE_NAME_LENGTH + 1];
|
|
ut64 vaddr;
|
|
ut64 paddr;
|
|
ut64 ordinal;
|
|
int last;
|
|
};
|
|
|
|
struct rz_bin_pe_string_t {
|
|
char string[PE_STRING_LENGTH];
|
|
ut64 vaddr;
|
|
ut64 paddr;
|
|
ut64 size;
|
|
char type;
|
|
int last;
|
|
};
|
|
|
|
typedef struct _PE_RESOURCE {
|
|
char *timestr;
|
|
char *type;
|
|
char *language;
|
|
char *name;
|
|
Pe_image_resource_data_entry *data;
|
|
} rz_pe_resource;
|
|
|
|
#define GUIDSTR_LEN 41
|
|
#define DBG_FILE_NAME_LEN 255
|
|
|
|
typedef struct SDebugInfo {
|
|
char guidstr[GUIDSTR_LEN];
|
|
char file_name[DBG_FILE_NAME_LEN];
|
|
} SDebugInfo;
|
|
|
|
#endif
|
|
|
|
#define RzBinPEObj struct PE_(rz_bin_pe_obj_t)
|
|
struct PE_(rz_bin_pe_obj_t) {
|
|
// these pointers contain a copy of the headers and sections!
|
|
PE_(image_dos_header) * dos_header;
|
|
PE_(image_nt_headers) * nt_headers;
|
|
PE_(image_optional_header) * optional_header; // not free this just pointer into nt_headers
|
|
PE_(image_data_directory) * data_directory; // not free this just pointer into nt_headers
|
|
PE_(image_section_header) * section_header;
|
|
PE_(image_export_directory) * export_directory;
|
|
PE_(image_import_directory) * import_directory;
|
|
PE_(image_tls_directory) * tls_directory;
|
|
Pe_image_resource_directory *resource_directory;
|
|
PE_(image_delay_import_directory) * delay_import_directory;
|
|
Pe_image_security_directory *security_directory;
|
|
|
|
Pe_image_clr *clr; // dotnet information
|
|
|
|
/* store the section information for future use */
|
|
struct rz_bin_pe_section_t *sections;
|
|
|
|
// these values define the real offset into the untouched binary
|
|
ut64 rich_header_offset;
|
|
ut64 nt_header_offset;
|
|
ut64 section_header_offset;
|
|
ut64 import_directory_offset;
|
|
ut64 export_directory_offset;
|
|
ut64 resource_directory_offset;
|
|
ut64 delay_import_directory_offset;
|
|
|
|
int import_directory_size;
|
|
ut64 size;
|
|
int num_sections;
|
|
bool verbose;
|
|
int big_endian;
|
|
RzList /*<Pe_image_rich_entry *>*/ *rich_entries;
|
|
RzList /*<rz_pe_resource *>*/ *resources;
|
|
RzVector /*<RzBinPeRelocEnt>*/ *relocs;
|
|
const char *file;
|
|
RzBuffer *b;
|
|
Sdb *kv;
|
|
RzCMS *cms;
|
|
RzSpcIndirectDataContent *spcinfo;
|
|
bool has_canary;
|
|
char *authentihash;
|
|
bool is_authhash_valid;
|
|
bool is_signed;
|
|
RzHash *hash;
|
|
};
|
|
|
|
#define MAX_METADATA_STRING_LENGTH 256
|
|
#define COFF_SYMBOL_SIZE 18
|
|
#define PE_READ_STRUCT_FIELD(var, struct_type, field, size) var->field = rz_read_le##size(buf + offsetof(struct_type, field))
|
|
#define PE_READ_STRUCT_FIELD_L(buf, var, struct_type, field, size) var.field = rz_read_le##size(buf + offsetof(struct_type, field))
|
|
|
|
// pe_clr.c
|
|
RZ_OWN RzList /*<RzBinSymbol *>*/ *PE_(rz_bin_pe_get_clr_symbols)(RzBinPEObj *bin);
|
|
ut64 PE_(rz_bin_pe_get_clr_methoddef_offset)(RzBinPEObj *bin, Pe_image_metadata_methoddef *methoddef);
|
|
int PE_(bin_pe_init_clr)(RzBinPEObj *bin);
|
|
|
|
// pe_debug.c
|
|
bool PE_(rz_bin_pe_get_debug_data)(RzBinPEObj *bin, SDebugInfo *res);
|
|
|
|
// pe_exports.c
|
|
int PE_(bin_pe_init_exports)(RzBinPEObj *bin);
|
|
struct rz_bin_pe_export_t *PE_(rz_bin_pe_get_exports)(RzBinPEObj *bin);
|
|
|
|
// pe_hdr.c
|
|
int PE_(bin_pe_init_hdr)(RzBinPEObj *bin);
|
|
|
|
// pe_imports.c
|
|
int PE_(bin_pe_init_imports)(RzBinPEObj *bin);
|
|
int PE_(read_image_import_directory)(RzBuffer *b, ut64 addr, PE_(image_import_directory) * import_dir);
|
|
int PE_(read_image_delay_import_directory)(RzBuffer *b, ut64 addr, PE_(image_delay_import_directory) * directory);
|
|
struct rz_bin_pe_import_t *PE_(rz_bin_pe_get_imports)(RzBinPEObj *bin);
|
|
|
|
// pe_relocs.c
|
|
int PE_(bin_pe_init_relocs)(RZ_NONNULL RzBinPEObj *bin);
|
|
bool PE_(bin_pe_has_base_relocs)(RZ_NONNULL RzBinPEObj *bin);
|
|
|
|
// pe_info.c
|
|
char *PE_(rz_bin_pe_get_arch)(RzBinPEObj *bin);
|
|
char *PE_(rz_bin_pe_get_cc)(RzBinPEObj *bin);
|
|
char *PE_(rz_bin_pe_get_compiler)(RzBinPEObj *bin);
|
|
char *PE_(rz_bin_pe_get_machine)(RzBinPEObj *bin);
|
|
char *PE_(rz_bin_pe_get_cpu)(RzBinPEObj *bin);
|
|
char *PE_(rz_bin_pe_get_os)(RzBinPEObj *bin);
|
|
char *PE_(rz_bin_pe_get_class)(RzBinPEObj *bin);
|
|
int PE_(rz_bin_pe_get_bits)(RzBinPEObj *bin);
|
|
char *PE_(rz_bin_pe_get_subsystem)(RzBinPEObj *bin);
|
|
int PE_(rz_bin_pe_is_dll)(RzBinPEObj *bin);
|
|
int PE_(rz_bin_pe_is_big_endian)(RzBinPEObj *bin);
|
|
int PE_(rz_bin_pe_is_stripped_relocs)(RzBinPEObj *bin);
|
|
int PE_(rz_bin_pe_is_stripped_line_nums)(RzBinPEObj *bin);
|
|
int PE_(rz_bin_pe_is_stripped_local_syms)(RzBinPEObj *bin);
|
|
int PE_(rz_bin_pe_is_stripped_debug)(RzBinPEObj *bin);
|
|
int PE_(bin_pe_get_claimed_checksum)(RzBinPEObj *bin);
|
|
int PE_(bin_pe_get_actual_checksum)(RzBinPEObj *bin);
|
|
bool PE_(rz_bin_pe_has_canary)(const RzBinPEObj *bin);
|
|
struct rz_bin_pe_addr_t *PE_(check_unknow)(RzBinPEObj *bin);
|
|
struct rz_bin_pe_addr_t *PE_(check_msvcseh)(RzBinPEObj *bin);
|
|
struct rz_bin_pe_addr_t *PE_(check_mingw)(RzBinPEObj *bin);
|
|
struct rz_bin_pe_addr_t *PE_(rz_bin_pe_get_entrypoint)(RzBinPEObj *bin);
|
|
struct rz_bin_pe_addr_t *PE_(rz_bin_pe_get_main_vaddr)(RzBinPEObj *bin);
|
|
int PE_(rz_bin_pe_get_image_size)(RzBinPEObj *bin);
|
|
RzPVector /*<char *>*/ *PE_(rz_bin_pe_get_libs)(RzBinPEObj *bin);
|
|
ut64 PE_(rz_bin_pe_get_image_base)(RzBinPEObj *bin);
|
|
|
|
// pe_overlay.c
|
|
int PE_(bin_pe_get_overlay)(RzBinPEObj *bin, ut64 *size);
|
|
int PE_(bin_pe_init_overlay)(RzBinPEObj *bin);
|
|
|
|
// pe_rsrc.c
|
|
RZ_API void PE_(bin_pe_parse_resource)(RzBinPEObj *bin);
|
|
void PE_(bin_pe_init_rich_info)(RzBinPEObj *bin);
|
|
int PE_(bin_pe_init_resource)(RzBinPEObj *bin);
|
|
|
|
// pe_section.c
|
|
int PE_(bin_pe_init_sections)(RzBinPEObj *bin);
|
|
void PE_(rz_bin_pe_check_sections)(RzBinPEObj *bin, struct rz_bin_pe_section_t **sects);
|
|
RzList /*<char *>*/ *PE_(section_flag_to_rzlist)(ut64 flag);
|
|
struct rz_bin_pe_section_t *PE_(rz_bin_pe_get_sections)(RzBinPEObj *bin);
|
|
|
|
// pe_security.c
|
|
int PE_(bin_pe_init_security)(RzBinPEObj *bin);
|
|
const char *PE_(bin_pe_get_authentihash)(RzBinPEObj *bin);
|
|
char *PE_(bin_pe_compute_authentihash)(RzBinPEObj *bin);
|
|
int PE_(bin_pe_is_authhash_valid)(RzBinPEObj *bin);
|
|
void PE_(free_security_directory)(Pe_image_security_directory *security_directory);
|
|
|
|
// pe_tls.c
|
|
int PE_(bin_pe_init_tls)(RzBinPEObj *bin);
|
|
|
|
// pe.c
|
|
PE_DWord PE_(bin_pe_rva_to_paddr)(RzBinPEObj *bin, PE_DWord rva);
|
|
PE_DWord PE_(bin_pe_rva_to_va)(RzBinPEObj *bin, PE_DWord rva);
|
|
PE_DWord PE_(bin_pe_va_to_rva)(RzBinPEObj *bin, PE_DWord va);
|
|
void *PE_(rz_bin_pe_free)(RzBinPEObj *bin);
|
|
RzBinPEObj *PE_(rz_bin_pe_new)(const char *file, bool verbose);
|
|
RzBinPEObj *PE_(rz_bin_pe_new_buf)(RzBuffer *buf, bool verbose);
|