This page hosts a formal specification of Microsoft PE (Portable Executable) file format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
use strict;
use warnings;
use IO::KaitaiStruct 0.009_000;
use Encode;
########################################################################
package MicrosoftPe;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
our $PE_FORMAT_ROM_IMAGE = 263;
our $PE_FORMAT_PE32 = 267;
our $PE_FORMAT_PE32_PLUS = 523;
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{mz} = MicrosoftPe::MzPlaceholder->new($self->{_io}, $self, $self->{_root});
}
sub pe {
my ($self) = @_;
return $self->{pe} if ($self->{pe});
my $_pos = $self->{_io}->pos();
$self->{_io}->seek($self->mz()->ofs_pe());
$self->{pe} = MicrosoftPe::PeHeader->new($self->{_io}, $self, $self->{_root});
$self->{_io}->seek($_pos);
return $self->{pe};
}
sub mz {
my ($self) = @_;
return $self->{mz};
}
########################################################################
package MicrosoftPe::CertificateEntry;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
our $CERTIFICATE_REVISION_REVISION_1_0 = 256;
our $CERTIFICATE_REVISION_REVISION_2_0 = 512;
our $CERTIFICATE_TYPE_ENUM_X509 = 1;
our $CERTIFICATE_TYPE_ENUM_PKCS_SIGNED_DATA = 2;
our $CERTIFICATE_TYPE_ENUM_RESERVED_1 = 3;
our $CERTIFICATE_TYPE_ENUM_TS_STACK_SIGNED = 4;
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{length} = $self->{_io}->read_u4le();
$self->{revision} = $self->{_io}->read_u2le();
$self->{certificate_type} = $self->{_io}->read_u2le();
$self->{certificate_bytes} = $self->{_io}->read_bytes(($self->length() - 8));
}
sub length {
my ($self) = @_;
return $self->{length};
}
sub revision {
my ($self) = @_;
return $self->{revision};
}
sub certificate_type {
my ($self) = @_;
return $self->{certificate_type};
}
sub certificate_bytes {
my ($self) = @_;
return $self->{certificate_bytes};
}
########################################################################
package MicrosoftPe::OptionalHeaderWindows;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
our $SUBSYSTEM_ENUM_UNKNOWN = 0;
our $SUBSYSTEM_ENUM_NATIVE = 1;
our $SUBSYSTEM_ENUM_WINDOWS_GUI = 2;
our $SUBSYSTEM_ENUM_WINDOWS_CUI = 3;
our $SUBSYSTEM_ENUM_POSIX_CUI = 7;
our $SUBSYSTEM_ENUM_WINDOWS_CE_GUI = 9;
our $SUBSYSTEM_ENUM_EFI_APPLICATION = 10;
our $SUBSYSTEM_ENUM_EFI_BOOT_SERVICE_DRIVER = 11;
our $SUBSYSTEM_ENUM_EFI_RUNTIME_DRIVER = 12;
our $SUBSYSTEM_ENUM_EFI_ROM = 13;
our $SUBSYSTEM_ENUM_XBOX = 14;
our $SUBSYSTEM_ENUM_WINDOWS_BOOT_APPLICATION = 16;
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32) {
$self->{image_base_32} = $self->{_io}->read_u4le();
}
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32_PLUS) {
$self->{image_base_64} = $self->{_io}->read_u8le();
}
$self->{section_alignment} = $self->{_io}->read_u4le();
$self->{file_alignment} = $self->{_io}->read_u4le();
$self->{major_operating_system_version} = $self->{_io}->read_u2le();
$self->{minor_operating_system_version} = $self->{_io}->read_u2le();
$self->{major_image_version} = $self->{_io}->read_u2le();
$self->{minor_image_version} = $self->{_io}->read_u2le();
$self->{major_subsystem_version} = $self->{_io}->read_u2le();
$self->{minor_subsystem_version} = $self->{_io}->read_u2le();
$self->{win32_version_value} = $self->{_io}->read_u4le();
$self->{size_of_image} = $self->{_io}->read_u4le();
$self->{size_of_headers} = $self->{_io}->read_u4le();
$self->{check_sum} = $self->{_io}->read_u4le();
$self->{subsystem} = $self->{_io}->read_u2le();
$self->{dll_characteristics} = $self->{_io}->read_u2le();
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32) {
$self->{size_of_stack_reserve_32} = $self->{_io}->read_u4le();
}
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32_PLUS) {
$self->{size_of_stack_reserve_64} = $self->{_io}->read_u8le();
}
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32) {
$self->{size_of_stack_commit_32} = $self->{_io}->read_u4le();
}
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32_PLUS) {
$self->{size_of_stack_commit_64} = $self->{_io}->read_u8le();
}
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32) {
$self->{size_of_heap_reserve_32} = $self->{_io}->read_u4le();
}
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32_PLUS) {
$self->{size_of_heap_reserve_64} = $self->{_io}->read_u8le();
}
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32) {
$self->{size_of_heap_commit_32} = $self->{_io}->read_u4le();
}
if ($self->_parent()->std()->format() == $MicrosoftPe::PE_FORMAT_PE32_PLUS) {
$self->{size_of_heap_commit_64} = $self->{_io}->read_u8le();
}
$self->{loader_flags} = $self->{_io}->read_u4le();
$self->{number_of_rva_and_sizes} = $self->{_io}->read_u4le();
}
sub image_base_32 {
my ($self) = @_;
return $self->{image_base_32};
}
sub image_base_64 {
my ($self) = @_;
return $self->{image_base_64};
}
sub section_alignment {
my ($self) = @_;
return $self->{section_alignment};
}
sub file_alignment {
my ($self) = @_;
return $self->{file_alignment};
}
sub major_operating_system_version {
my ($self) = @_;
return $self->{major_operating_system_version};
}
sub minor_operating_system_version {
my ($self) = @_;
return $self->{minor_operating_system_version};
}
sub major_image_version {
my ($self) = @_;
return $self->{major_image_version};
}
sub minor_image_version {
my ($self) = @_;
return $self->{minor_image_version};
}
sub major_subsystem_version {
my ($self) = @_;
return $self->{major_subsystem_version};
}
sub minor_subsystem_version {
my ($self) = @_;
return $self->{minor_subsystem_version};
}
sub win32_version_value {
my ($self) = @_;
return $self->{win32_version_value};
}
sub size_of_image {
my ($self) = @_;
return $self->{size_of_image};
}
sub size_of_headers {
my ($self) = @_;
return $self->{size_of_headers};
}
sub check_sum {
my ($self) = @_;
return $self->{check_sum};
}
sub subsystem {
my ($self) = @_;
return $self->{subsystem};
}
sub dll_characteristics {
my ($self) = @_;
return $self->{dll_characteristics};
}
sub size_of_stack_reserve_32 {
my ($self) = @_;
return $self->{size_of_stack_reserve_32};
}
sub size_of_stack_reserve_64 {
my ($self) = @_;
return $self->{size_of_stack_reserve_64};
}
sub size_of_stack_commit_32 {
my ($self) = @_;
return $self->{size_of_stack_commit_32};
}
sub size_of_stack_commit_64 {
my ($self) = @_;
return $self->{size_of_stack_commit_64};
}
sub size_of_heap_reserve_32 {
my ($self) = @_;
return $self->{size_of_heap_reserve_32};
}
sub size_of_heap_reserve_64 {
my ($self) = @_;
return $self->{size_of_heap_reserve_64};
}
sub size_of_heap_commit_32 {
my ($self) = @_;
return $self->{size_of_heap_commit_32};
}
sub size_of_heap_commit_64 {
my ($self) = @_;
return $self->{size_of_heap_commit_64};
}
sub loader_flags {
my ($self) = @_;
return $self->{loader_flags};
}
sub number_of_rva_and_sizes {
my ($self) = @_;
return $self->{number_of_rva_and_sizes};
}
########################################################################
package MicrosoftPe::OptionalHeaderDataDirs;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{export_table} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{import_table} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{resource_table} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{exception_table} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{certificate_table} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{base_relocation_table} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{debug} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{architecture} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{global_ptr} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{tls_table} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{load_config_table} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{bound_import} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{iat} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{delay_import_descriptor} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
$self->{clr_runtime_header} = MicrosoftPe::DataDir->new($self->{_io}, $self, $self->{_root});
}
sub export_table {
my ($self) = @_;
return $self->{export_table};
}
sub import_table {
my ($self) = @_;
return $self->{import_table};
}
sub resource_table {
my ($self) = @_;
return $self->{resource_table};
}
sub exception_table {
my ($self) = @_;
return $self->{exception_table};
}
sub certificate_table {
my ($self) = @_;
return $self->{certificate_table};
}
sub base_relocation_table {
my ($self) = @_;
return $self->{base_relocation_table};
}
sub debug {
my ($self) = @_;
return $self->{debug};
}
sub architecture {
my ($self) = @_;
return $self->{architecture};
}
sub global_ptr {
my ($self) = @_;
return $self->{global_ptr};
}
sub tls_table {
my ($self) = @_;
return $self->{tls_table};
}
sub load_config_table {
my ($self) = @_;
return $self->{load_config_table};
}
sub bound_import {
my ($self) = @_;
return $self->{bound_import};
}
sub iat {
my ($self) = @_;
return $self->{iat};
}
sub delay_import_descriptor {
my ($self) = @_;
return $self->{delay_import_descriptor};
}
sub clr_runtime_header {
my ($self) = @_;
return $self->{clr_runtime_header};
}
########################################################################
package MicrosoftPe::DataDir;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{virtual_address} = $self->{_io}->read_u4le();
$self->{size} = $self->{_io}->read_u4le();
}
sub virtual_address {
my ($self) = @_;
return $self->{virtual_address};
}
sub size {
my ($self) = @_;
return $self->{size};
}
########################################################################
package MicrosoftPe::CoffSymbol;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{_raw_name_annoying} = $self->{_io}->read_bytes(8);
my $io__raw_name_annoying = IO::KaitaiStruct::Stream->new($self->{_raw_name_annoying});
$self->{name_annoying} = MicrosoftPe::Annoyingstring->new($io__raw_name_annoying, $self, $self->{_root});
$self->{value} = $self->{_io}->read_u4le();
$self->{section_number} = $self->{_io}->read_u2le();
$self->{type} = $self->{_io}->read_u2le();
$self->{storage_class} = $self->{_io}->read_u1();
$self->{number_of_aux_symbols} = $self->{_io}->read_u1();
}
sub section {
my ($self) = @_;
return $self->{section} if ($self->{section});
$self->{section} = @{$self->_root()->pe()->sections()}[($self->section_number() - 1)];
return $self->{section};
}
sub data {
my ($self) = @_;
return $self->{data} if ($self->{data});
my $_pos = $self->{_io}->pos();
$self->{_io}->seek(($self->section()->pointer_to_raw_data() + $self->value()));
$self->{data} = $self->{_io}->read_bytes(1);
$self->{_io}->seek($_pos);
return $self->{data};
}
sub name_annoying {
my ($self) = @_;
return $self->{name_annoying};
}
sub value {
my ($self) = @_;
return $self->{value};
}
sub section_number {
my ($self) = @_;
return $self->{section_number};
}
sub type {
my ($self) = @_;
return $self->{type};
}
sub storage_class {
my ($self) = @_;
return $self->{storage_class};
}
sub number_of_aux_symbols {
my ($self) = @_;
return $self->{number_of_aux_symbols};
}
sub _raw_name_annoying {
my ($self) = @_;
return $self->{_raw_name_annoying};
}
########################################################################
package MicrosoftPe::PeHeader;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{pe_signature} = $self->{_io}->read_bytes(4);
$self->{coff_hdr} = MicrosoftPe::CoffHeader->new($self->{_io}, $self, $self->{_root});
$self->{_raw_optional_hdr} = $self->{_io}->read_bytes($self->coff_hdr()->size_of_optional_header());
my $io__raw_optional_hdr = IO::KaitaiStruct::Stream->new($self->{_raw_optional_hdr});
$self->{optional_hdr} = MicrosoftPe::OptionalHeader->new($io__raw_optional_hdr, $self, $self->{_root});
$self->{sections} = ();
my $n_sections = $self->coff_hdr()->number_of_sections();
for (my $i = 0; $i < $n_sections; $i++) {
push @{$self->{sections}}, MicrosoftPe::Section->new($self->{_io}, $self, $self->{_root});
}
}
sub certificate_table {
my ($self) = @_;
return $self->{certificate_table} if ($self->{certificate_table});
if ($self->optional_hdr()->data_dirs()->certificate_table()->virtual_address() != 0) {
my $_pos = $self->{_io}->pos();
$self->{_io}->seek($self->optional_hdr()->data_dirs()->certificate_table()->virtual_address());
$self->{_raw_certificate_table} = $self->{_io}->read_bytes($self->optional_hdr()->data_dirs()->certificate_table()->size());
my $io__raw_certificate_table = IO::KaitaiStruct::Stream->new($self->{_raw_certificate_table});
$self->{certificate_table} = MicrosoftPe::CertificateTable->new($io__raw_certificate_table, $self, $self->{_root});
$self->{_io}->seek($_pos);
}
return $self->{certificate_table};
}
sub pe_signature {
my ($self) = @_;
return $self->{pe_signature};
}
sub coff_hdr {
my ($self) = @_;
return $self->{coff_hdr};
}
sub optional_hdr {
my ($self) = @_;
return $self->{optional_hdr};
}
sub sections {
my ($self) = @_;
return $self->{sections};
}
sub _raw_optional_hdr {
my ($self) = @_;
return $self->{_raw_optional_hdr};
}
sub _raw_certificate_table {
my ($self) = @_;
return $self->{_raw_certificate_table};
}
########################################################################
package MicrosoftPe::OptionalHeader;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{std} = MicrosoftPe::OptionalHeaderStd->new($self->{_io}, $self, $self->{_root});
$self->{windows} = MicrosoftPe::OptionalHeaderWindows->new($self->{_io}, $self, $self->{_root});
$self->{data_dirs} = MicrosoftPe::OptionalHeaderDataDirs->new($self->{_io}, $self, $self->{_root});
}
sub std {
my ($self) = @_;
return $self->{std};
}
sub windows {
my ($self) = @_;
return $self->{windows};
}
sub data_dirs {
my ($self) = @_;
return $self->{data_dirs};
}
########################################################################
package MicrosoftPe::Section;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{name} = Encode::decode("UTF-8", IO::KaitaiStruct::Stream::bytes_strip_right($self->{_io}->read_bytes(8), 0));
$self->{virtual_size} = $self->{_io}->read_u4le();
$self->{virtual_address} = $self->{_io}->read_u4le();
$self->{size_of_raw_data} = $self->{_io}->read_u4le();
$self->{pointer_to_raw_data} = $self->{_io}->read_u4le();
$self->{pointer_to_relocations} = $self->{_io}->read_u4le();
$self->{pointer_to_linenumbers} = $self->{_io}->read_u4le();
$self->{number_of_relocations} = $self->{_io}->read_u2le();
$self->{number_of_linenumbers} = $self->{_io}->read_u2le();
$self->{characteristics} = $self->{_io}->read_u4le();
}
sub body {
my ($self) = @_;
return $self->{body} if ($self->{body});
my $_pos = $self->{_io}->pos();
$self->{_io}->seek($self->pointer_to_raw_data());
$self->{body} = $self->{_io}->read_bytes($self->size_of_raw_data());
$self->{_io}->seek($_pos);
return $self->{body};
}
sub name {
my ($self) = @_;
return $self->{name};
}
sub virtual_size {
my ($self) = @_;
return $self->{virtual_size};
}
sub virtual_address {
my ($self) = @_;
return $self->{virtual_address};
}
sub size_of_raw_data {
my ($self) = @_;
return $self->{size_of_raw_data};
}
sub pointer_to_raw_data {
my ($self) = @_;
return $self->{pointer_to_raw_data};
}
sub pointer_to_relocations {
my ($self) = @_;
return $self->{pointer_to_relocations};
}
sub pointer_to_linenumbers {
my ($self) = @_;
return $self->{pointer_to_linenumbers};
}
sub number_of_relocations {
my ($self) = @_;
return $self->{number_of_relocations};
}
sub number_of_linenumbers {
my ($self) = @_;
return $self->{number_of_linenumbers};
}
sub characteristics {
my ($self) = @_;
return $self->{characteristics};
}
########################################################################
package MicrosoftPe::CertificateTable;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{items} = ();
while (!$self->{_io}->is_eof()) {
push @{$self->{items}}, MicrosoftPe::CertificateEntry->new($self->{_io}, $self, $self->{_root});
}
}
sub items {
my ($self) = @_;
return $self->{items};
}
########################################################################
package MicrosoftPe::MzPlaceholder;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{magic} = $self->{_io}->read_bytes(2);
$self->{data1} = $self->{_io}->read_bytes(58);
$self->{ofs_pe} = $self->{_io}->read_u4le();
}
sub magic {
my ($self) = @_;
return $self->{magic};
}
sub data1 {
my ($self) = @_;
return $self->{data1};
}
sub ofs_pe {
my ($self) = @_;
return $self->{ofs_pe};
}
########################################################################
package MicrosoftPe::OptionalHeaderStd;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{format} = $self->{_io}->read_u2le();
$self->{major_linker_version} = $self->{_io}->read_u1();
$self->{minor_linker_version} = $self->{_io}->read_u1();
$self->{size_of_code} = $self->{_io}->read_u4le();
$self->{size_of_initialized_data} = $self->{_io}->read_u4le();
$self->{size_of_uninitialized_data} = $self->{_io}->read_u4le();
$self->{address_of_entry_point} = $self->{_io}->read_u4le();
$self->{base_of_code} = $self->{_io}->read_u4le();
if ($self->format() == $MicrosoftPe::PE_FORMAT_PE32) {
$self->{base_of_data} = $self->{_io}->read_u4le();
}
}
sub format {
my ($self) = @_;
return $self->{format};
}
sub major_linker_version {
my ($self) = @_;
return $self->{major_linker_version};
}
sub minor_linker_version {
my ($self) = @_;
return $self->{minor_linker_version};
}
sub size_of_code {
my ($self) = @_;
return $self->{size_of_code};
}
sub size_of_initialized_data {
my ($self) = @_;
return $self->{size_of_initialized_data};
}
sub size_of_uninitialized_data {
my ($self) = @_;
return $self->{size_of_uninitialized_data};
}
sub address_of_entry_point {
my ($self) = @_;
return $self->{address_of_entry_point};
}
sub base_of_code {
my ($self) = @_;
return $self->{base_of_code};
}
sub base_of_data {
my ($self) = @_;
return $self->{base_of_data};
}
########################################################################
package MicrosoftPe::CoffHeader;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
our $MACHINE_TYPE_UNKNOWN = 0;
our $MACHINE_TYPE_I386 = 332;
our $MACHINE_TYPE_R4000 = 358;
our $MACHINE_TYPE_WCE_MIPS_V2 = 361;
our $MACHINE_TYPE_ALPHA = 388;
our $MACHINE_TYPE_SH3 = 418;
our $MACHINE_TYPE_SH3_DSP = 419;
our $MACHINE_TYPE_SH4 = 422;
our $MACHINE_TYPE_SH5 = 424;
our $MACHINE_TYPE_ARM = 448;
our $MACHINE_TYPE_THUMB = 450;
our $MACHINE_TYPE_ARM_NT = 452;
our $MACHINE_TYPE_AM33 = 467;
our $MACHINE_TYPE_POWERPC = 496;
our $MACHINE_TYPE_POWERPC_FP = 497;
our $MACHINE_TYPE_IA64 = 512;
our $MACHINE_TYPE_MIPS16 = 614;
our $MACHINE_TYPE_ALPHA64_OR_AXP64 = 644;
our $MACHINE_TYPE_MIPS_FPU = 870;
our $MACHINE_TYPE_MIPS16_FPU = 1126;
our $MACHINE_TYPE_EBC = 3772;
our $MACHINE_TYPE_RISCV32 = 20530;
our $MACHINE_TYPE_RISCV64 = 20580;
our $MACHINE_TYPE_RISCV128 = 20776;
our $MACHINE_TYPE_LOONGARCH32 = 25138;
our $MACHINE_TYPE_LOONGARCH64 = 25188;
our $MACHINE_TYPE_AMD64 = 34404;
our $MACHINE_TYPE_M32R = 36929;
our $MACHINE_TYPE_ARM64 = 43620;
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
$self->{machine} = $self->{_io}->read_u2le();
$self->{number_of_sections} = $self->{_io}->read_u2le();
$self->{time_date_stamp} = $self->{_io}->read_u4le();
$self->{pointer_to_symbol_table} = $self->{_io}->read_u4le();
$self->{number_of_symbols} = $self->{_io}->read_u4le();
$self->{size_of_optional_header} = $self->{_io}->read_u2le();
$self->{characteristics} = $self->{_io}->read_u2le();
}
sub symbol_table_size {
my ($self) = @_;
return $self->{symbol_table_size} if ($self->{symbol_table_size});
$self->{symbol_table_size} = ($self->number_of_symbols() * 18);
return $self->{symbol_table_size};
}
sub symbol_name_table_offset {
my ($self) = @_;
return $self->{symbol_name_table_offset} if ($self->{symbol_name_table_offset});
$self->{symbol_name_table_offset} = ($self->pointer_to_symbol_table() + $self->symbol_table_size());
return $self->{symbol_name_table_offset};
}
sub symbol_name_table_size {
my ($self) = @_;
return $self->{symbol_name_table_size} if ($self->{symbol_name_table_size});
my $_pos = $self->{_io}->pos();
$self->{_io}->seek($self->symbol_name_table_offset());
$self->{symbol_name_table_size} = $self->{_io}->read_u4le();
$self->{_io}->seek($_pos);
return $self->{symbol_name_table_size};
}
sub symbol_table {
my ($self) = @_;
return $self->{symbol_table} if ($self->{symbol_table});
my $_pos = $self->{_io}->pos();
$self->{_io}->seek($self->pointer_to_symbol_table());
$self->{symbol_table} = ();
my $n_symbol_table = $self->number_of_symbols();
for (my $i = 0; $i < $n_symbol_table; $i++) {
push @{$self->{symbol_table}}, MicrosoftPe::CoffSymbol->new($self->{_io}, $self, $self->{_root});
}
$self->{_io}->seek($_pos);
return $self->{symbol_table};
}
sub machine {
my ($self) = @_;
return $self->{machine};
}
sub number_of_sections {
my ($self) = @_;
return $self->{number_of_sections};
}
sub time_date_stamp {
my ($self) = @_;
return $self->{time_date_stamp};
}
sub pointer_to_symbol_table {
my ($self) = @_;
return $self->{pointer_to_symbol_table};
}
sub number_of_symbols {
my ($self) = @_;
return $self->{number_of_symbols};
}
sub size_of_optional_header {
my ($self) = @_;
return $self->{size_of_optional_header};
}
sub characteristics {
my ($self) = @_;
return $self->{characteristics};
}
########################################################################
package MicrosoftPe::Annoyingstring;
our @ISA = 'IO::KaitaiStruct::Struct';
sub from_file {
my ($class, $filename) = @_;
my $fd;
open($fd, '<', $filename) or return undef;
binmode($fd);
return new($class, IO::KaitaiStruct::Stream->new($fd));
}
sub new {
my ($class, $_io, $_parent, $_root) = @_;
my $self = IO::KaitaiStruct::Struct->new($_io);
bless $self, $class;
$self->{_parent} = $_parent;
$self->{_root} = $_root || $self;;
$self->_read();
return $self;
}
sub _read {
my ($self) = @_;
}
sub name_from_offset {
my ($self) = @_;
return $self->{name_from_offset} if ($self->{name_from_offset});
if ($self->name_zeroes() == 0) {
my $io = $self->_root()->_io();
my $_pos = $io->pos();
$io->seek(($self->name_zeroes() == 0 ? ($self->_parent()->_parent()->symbol_name_table_offset() + $self->name_offset()) : 0));
$self->{name_from_offset} = Encode::decode("ascii", $io->read_bytes_term(0, 0, 1, 0));
$io->seek($_pos);
}
return $self->{name_from_offset};
}
sub name_offset {
my ($self) = @_;
return $self->{name_offset} if ($self->{name_offset});
my $_pos = $self->{_io}->pos();
$self->{_io}->seek(4);
$self->{name_offset} = $self->{_io}->read_u4le();
$self->{_io}->seek($_pos);
return $self->{name_offset};
}
sub name {
my ($self) = @_;
return $self->{name} if ($self->{name});
$self->{name} = ($self->name_zeroes() == 0 ? $self->name_from_offset() : $self->name_from_short());
return $self->{name};
}
sub name_zeroes {
my ($self) = @_;
return $self->{name_zeroes} if ($self->{name_zeroes});
my $_pos = $self->{_io}->pos();
$self->{_io}->seek(0);
$self->{name_zeroes} = $self->{_io}->read_u4le();
$self->{_io}->seek($_pos);
return $self->{name_zeroes};
}
sub name_from_short {
my ($self) = @_;
return $self->{name_from_short} if ($self->{name_from_short});
if ($self->name_zeroes() != 0) {
my $_pos = $self->{_io}->pos();
$self->{_io}->seek(0);
$self->{name_from_short} = Encode::decode("ascii", $self->{_io}->read_bytes_term(0, 0, 1, 0));
$self->{_io}->seek($_pos);
}
return $self->{name_from_short};
}
1;