mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 16:18:19 +00:00
PE analyzer checkpoint
This commit is contained in:
parent
07b53e9fe2
commit
d1dd4cb688
7 changed files with 224 additions and 70 deletions
|
@ -2489,43 +2489,67 @@ type irc_join_info: record {
|
||||||
## .. bro:see:: irc_join_message
|
## .. bro:see:: irc_join_message
|
||||||
type irc_join_list: set[irc_join_info];
|
type irc_join_list: set[irc_join_info];
|
||||||
|
|
||||||
type PEHeader: record {
|
module PE;
|
||||||
# Machine : count;
|
export {
|
||||||
# TimeDateStamp : time;
|
type PE::DOSHeader: record {
|
||||||
# magic : uint16;
|
signature : string;
|
||||||
# major_linker_version : uint8;
|
used_bytes_in_last_page : count;
|
||||||
# minor_linker_version : uint8;
|
file_in_pages : count;
|
||||||
# size_of_code : uint32;
|
num_reloc_items : count;
|
||||||
# size_of_init_data : uint32;
|
header_in_paragraphs : count;
|
||||||
# size_of_uninit_data : uint32;
|
min_extra_paragraphs : count;
|
||||||
# addr_of_entry_point : uint32;
|
max_extra_paragraphs : count;
|
||||||
# base_of_code : uint32;
|
init_relative_ss : count;
|
||||||
# base_of_data : uint32;
|
init_sp : count;
|
||||||
# image_base : uint32;
|
checksum : count;
|
||||||
# section_alignment : uint32;
|
init_ip : count;
|
||||||
# file_alignment : uint32;
|
init_relative_cs : count;
|
||||||
# os_version_major : uint16;
|
addr_of_reloc_table : count;
|
||||||
# os_version_minor : uint16;
|
overlay_num : count;
|
||||||
# major_image_version : uint16;
|
oem_id : count;
|
||||||
# minor_image_version : uint16;
|
oem_info : count;
|
||||||
# major_subsys_version : uint16;
|
addr_of_new_exe_header : count;
|
||||||
# minor_subsys_version : uint16;
|
};
|
||||||
# win32_version : uint32;
|
|
||||||
# size_of_image : uint32;
|
type PE::FileHeader: record {
|
||||||
# checksum : uint32;
|
machine : count;
|
||||||
# subsystem : uint16;
|
ts : time;
|
||||||
# mem: case magic of {
|
sym_table_ptr : count;
|
||||||
# 0x0b01 -> i32 : MEM_INFO32;
|
num_syms : count;
|
||||||
# 0x0b02 -> i64 : MEM_INFO64;
|
characteristics : set[count];
|
||||||
# default -> InvalidPEFile : empty;
|
};
|
||||||
# };
|
|
||||||
# loader_flags : uint32;
|
type PE::OptionalHeader: record {
|
||||||
# number_of_rva_and_sizes : uint32;
|
magic : count;
|
||||||
#
|
major_linker_version : count;
|
||||||
|
minor_linker_version : count;
|
||||||
|
size_of_code : count;
|
||||||
|
size_of_init_data : count;
|
||||||
|
size_of_uninit_data : count;
|
||||||
|
addr_of_entry_point : count;
|
||||||
|
base_of_code : count;
|
||||||
|
base_of_data : count;
|
||||||
|
image_base : count;
|
||||||
|
section_alignment : count;
|
||||||
|
file_alignment : count;
|
||||||
|
os_version_major : count;
|
||||||
|
os_version_minor : count;
|
||||||
|
major_image_version : count;
|
||||||
|
minor_image_version : count;
|
||||||
|
major_subsys_version : count;
|
||||||
|
minor_subsys_version : count;
|
||||||
|
win32_version : count;
|
||||||
|
size_of_image : count;
|
||||||
|
size_of_headers : count;
|
||||||
|
checksum : count;
|
||||||
|
subsystem : count;
|
||||||
|
dll_characteristics : set[count];
|
||||||
|
loader_flags : count;
|
||||||
|
number_of_rva_and_sizes : count;
|
||||||
};
|
};
|
||||||
|
|
||||||
## Record for Portable Executable (PE) section headers.
|
## Record for Portable Executable (PE) section headers.
|
||||||
type PESectionHeader: record {
|
type PE::SectionHeader: record {
|
||||||
name : string;
|
name : string;
|
||||||
virtual_size : count;
|
virtual_size : count;
|
||||||
virtual_addr : count;
|
virtual_addr : count;
|
||||||
|
@ -2535,8 +2559,10 @@ type PESectionHeader: record {
|
||||||
non_used_ptr_to_line_nums : count;
|
non_used_ptr_to_line_nums : count;
|
||||||
non_used_num_of_relocs : count;
|
non_used_num_of_relocs : count;
|
||||||
non_used_num_of_line_nums : count;
|
non_used_num_of_line_nums : count;
|
||||||
characteristics : count;
|
characteristics : set[count];
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
module GLOBAL;
|
||||||
|
|
||||||
## Deprecated.
|
## Deprecated.
|
||||||
##
|
##
|
||||||
|
|
|
@ -44,4 +44,6 @@
|
||||||
@load base/protocols/ssl
|
@load base/protocols/ssl
|
||||||
@load base/protocols/syslog
|
@load base/protocols/syslog
|
||||||
|
|
||||||
|
@load base/files/pe
|
||||||
|
|
||||||
@load base/misc/find-checksum-offloading
|
@load base/misc/find-checksum-offloading
|
||||||
|
|
|
@ -7059,10 +7059,10 @@ event file_state_remove%(f: fa_file%);
|
||||||
event file_hash%(f: fa_file, kind: string, hash: string%);
|
event file_hash%(f: fa_file, kind: string, hash: string%);
|
||||||
|
|
||||||
|
|
||||||
event file_pe_dosstub%(f: fa_file, checksum: count%);
|
event pe_dos_header%(f: fa_file, h: PE::DOSHeader%);
|
||||||
event file_pe_timestamp%(f: fa_file, ts: time%);
|
event pe_file_header%(f: fa_file, h: PE::FileHeader%);
|
||||||
event file_pe_section_header%(f: fa_file, h: PESectionHeader%);
|
event pe_optional_header%(f: fa_file, h: PE::OptionalHeader%);
|
||||||
|
event pe_section_header%(f: fa_file, h: PE::SectionHeader%);
|
||||||
|
|
||||||
## Deprecated. Will be removed.
|
## Deprecated. Will be removed.
|
||||||
event stp_create_endp%(c: connection, e: int, is_orig: bool%);
|
event stp_create_endp%(c: connection, e: int, is_orig: bool%);
|
||||||
|
|
|
@ -41,7 +41,5 @@ bool PE::DeliverStream(const u_char* data, uint64 len)
|
||||||
|
|
||||||
bool PE::EndOfFile()
|
bool PE::EndOfFile()
|
||||||
{
|
{
|
||||||
printf("end of file!\n");
|
|
||||||
//throw binpac::HaltParser();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,27 +13,142 @@ refine flow File += {
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
function characteristics_to_bro(c: uint32, len: uint8): TableVal
|
||||||
|
%{
|
||||||
|
uint64 mask = (len==16) ? 0xFFFF : 0xFFFFFFFF;
|
||||||
|
TableVal* char_set = new TableVal(internal_type("count_set")->AsTableType());
|
||||||
|
for ( uint16 i=0; i < len; ++i )
|
||||||
|
{
|
||||||
|
if ( ((c >> i) & 0x1) == 1 )
|
||||||
|
{
|
||||||
|
Val *ch = new Val((1<<i)&mask, TYPE_COUNT);
|
||||||
|
char_set->Assign(ch, 0);
|
||||||
|
Unref(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return char_set;
|
||||||
|
%}
|
||||||
|
|
||||||
function proc_dos_header(h: DOS_Header): bool
|
function proc_dos_header(h: DOS_Header): bool
|
||||||
%{
|
%{
|
||||||
BifEvent::generate_file_pe_dosstub((Analyzer *) connection()->bro_analyzer(),
|
if ( pe_dos_header )
|
||||||
|
{
|
||||||
|
RecordVal* dh = new RecordVal(BifType::Record::PE::DOSHeader);
|
||||||
|
dh->Assign(0, new StringVal(${h.signature}.length(), (const char*) ${h.signature}.data()));
|
||||||
|
dh->Assign(1, new Val(${h.UsedBytesInTheLastPage}, TYPE_COUNT));
|
||||||
|
dh->Assign(2, new Val(${h.FileSizeInPages}, TYPE_COUNT));
|
||||||
|
dh->Assign(3, new Val(${h.NumberOfRelocationItems}, TYPE_COUNT));
|
||||||
|
dh->Assign(4, new Val(${h.HeaderSizeInParagraphs}, TYPE_COUNT));
|
||||||
|
dh->Assign(5, new Val(${h.MinimumExtraParagraphs}, TYPE_COUNT));
|
||||||
|
dh->Assign(6, new Val(${h.MaximumExtraParagraphs}, TYPE_COUNT));
|
||||||
|
dh->Assign(7, new Val(${h.InitialRelativeSS}, TYPE_COUNT));
|
||||||
|
dh->Assign(8, new Val(${h.InitialSP}, TYPE_COUNT));
|
||||||
|
dh->Assign(9, new Val(${h.Checksum}, TYPE_COUNT));
|
||||||
|
dh->Assign(10, new Val(${h.InitialIP}, TYPE_COUNT));
|
||||||
|
dh->Assign(11, new Val(${h.InitialRelativeCS}, TYPE_COUNT));
|
||||||
|
dh->Assign(12, new Val(${h.AddressOfRelocationTable}, TYPE_COUNT));
|
||||||
|
dh->Assign(13, new Val(${h.OverlayNumber}, TYPE_COUNT));
|
||||||
|
dh->Assign(14, new Val(${h.OEMid}, TYPE_COUNT));
|
||||||
|
dh->Assign(15, new Val(${h.OEMinfo}, TYPE_COUNT));
|
||||||
|
dh->Assign(16, new Val(${h.AddressOfNewExeHeader}, TYPE_COUNT));
|
||||||
|
|
||||||
|
BifEvent::generate_pe_dos_header((Analyzer *) connection()->bro_analyzer(),
|
||||||
connection()->bro_analyzer()->GetFile()->GetVal()->Ref(),
|
connection()->bro_analyzer()->GetFile()->GetVal()->Ref(),
|
||||||
${h.AddressOfNewExeHeader}-64);
|
dh);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
function proc_pe_header(h: IMAGE_NT_HEADERS): bool
|
function proc_nt_headers(h: IMAGE_NT_HEADERS): bool
|
||||||
%{
|
%{
|
||||||
BifEvent::generate_file_pe_timestamp((Analyzer *) connection()->bro_analyzer(),
|
if ( ${h.PESignature} != 17744 ) // Number is uint32 version of "PE\0\0"
|
||||||
connection()->bro_analyzer()->GetFile()->GetVal()->Ref(),
|
{
|
||||||
${h.file_header.TimeDateStamp});
|
return false;
|
||||||
|
// FileViolation("PE Header signature is incorrect.");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
function proc_file_header(h: IMAGE_FILE_HEADER): bool
|
||||||
|
%{
|
||||||
|
if ( pe_file_header )
|
||||||
|
{
|
||||||
|
RecordVal* fh = new RecordVal(BifType::Record::PE::FileHeader);
|
||||||
|
fh->Assign(0, new Val(${h.Machine}, TYPE_COUNT));
|
||||||
|
fh->Assign(1, new Val(static_cast<double>(${h.TimeDateStamp}), TYPE_TIME));
|
||||||
|
fh->Assign(2, new Val(${h.PointerToSymbolTable}, TYPE_COUNT));
|
||||||
|
fh->Assign(3, new Val(${h.NumberOfSymbols}, TYPE_COUNT));
|
||||||
|
fh->Assign(4, characteristics_to_bro(${h.Characteristics}, 16));
|
||||||
|
BifEvent::generate_pe_file_header((Analyzer *) connection()->bro_analyzer(),
|
||||||
|
connection()->bro_analyzer()->GetFile()->GetVal()->Ref(),
|
||||||
|
fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function proc_optional_header(h: IMAGE_OPTIONAL_HEADER): bool
|
||||||
|
%{
|
||||||
|
if ( ${h.magic} != 0x10b && // normal pe32 executable
|
||||||
|
${h.magic} != 0x107 && // rom image
|
||||||
|
${h.magic} != 0x20b ) // pe32+ executable
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
// FileViolation("PE Optional Header magic is invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pe_optional_header )
|
||||||
|
{
|
||||||
|
RecordVal* oh = new RecordVal(BifType::Record::PE::OptionalHeader);
|
||||||
|
|
||||||
|
oh->Assign(0, new Val(${h.magic}, TYPE_COUNT));
|
||||||
|
oh->Assign(1, new Val(${h.major_linker_version}, TYPE_COUNT));
|
||||||
|
oh->Assign(2, new Val(${h.minor_linker_version}, TYPE_COUNT));
|
||||||
|
oh->Assign(3, new Val(${h.size_of_code}, TYPE_COUNT));
|
||||||
|
oh->Assign(4, new Val(${h.size_of_init_data}, TYPE_COUNT));
|
||||||
|
oh->Assign(5, new Val(${h.size_of_uninit_data}, TYPE_COUNT));
|
||||||
|
oh->Assign(6, new Val(${h.addr_of_entry_point}, TYPE_COUNT));
|
||||||
|
oh->Assign(7, new Val(${h.base_of_code}, TYPE_COUNT));
|
||||||
|
oh->Assign(8, new Val(${h.base_of_data}, TYPE_COUNT));
|
||||||
|
oh->Assign(9, new Val(${h.image_base}, TYPE_COUNT));
|
||||||
|
oh->Assign(10, new Val(${h.section_alignment}, TYPE_COUNT));
|
||||||
|
oh->Assign(11, new Val(${h.file_alignment}, TYPE_COUNT));
|
||||||
|
oh->Assign(12, new Val(${h.os_version_major}, TYPE_COUNT));
|
||||||
|
oh->Assign(13, new Val(${h.os_version_minor}, TYPE_COUNT));
|
||||||
|
oh->Assign(14, new Val(${h.major_image_version}, TYPE_COUNT));
|
||||||
|
oh->Assign(15, new Val(${h.minor_image_version}, TYPE_COUNT));
|
||||||
|
oh->Assign(16, new Val(${h.minor_subsys_version}, TYPE_COUNT));
|
||||||
|
oh->Assign(17, new Val(${h.minor_subsys_version}, TYPE_COUNT));
|
||||||
|
oh->Assign(18, new Val(${h.win32_version}, TYPE_COUNT));
|
||||||
|
oh->Assign(19, new Val(${h.size_of_image}, TYPE_COUNT));
|
||||||
|
oh->Assign(20, new Val(${h.size_of_headers}, TYPE_COUNT));
|
||||||
|
oh->Assign(21, new Val(${h.checksum}, TYPE_COUNT));
|
||||||
|
oh->Assign(22, new Val(${h.subsystem}, TYPE_COUNT));
|
||||||
|
oh->Assign(23, characteristics_to_bro(${h.dll_characteristics}, 16));
|
||||||
|
oh->Assign(24, new Val(${h.loader_flags}, TYPE_COUNT));
|
||||||
|
oh->Assign(25, new Val(${h.number_of_rva_and_sizes}, TYPE_COUNT));
|
||||||
|
BifEvent::generate_pe_optional_header((Analyzer *) connection()->bro_analyzer(),
|
||||||
|
connection()->bro_analyzer()->GetFile()->GetVal()->Ref(),
|
||||||
|
oh);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
function proc_section_header(h: IMAGE_SECTION_HEADER): bool
|
function proc_section_header(h: IMAGE_SECTION_HEADER): bool
|
||||||
%{
|
%{
|
||||||
RecordVal* section_header = new RecordVal(BifType::Record::PESectionHeader);
|
if ( pe_section_header )
|
||||||
section_header->Assign(0, new StringVal(${h.name}.length(), (const char*) ${h.name}.data()));
|
{
|
||||||
|
RecordVal* section_header = new RecordVal(BifType::Record::PE::SectionHeader);
|
||||||
|
|
||||||
|
// Strip null characters from the end of the section name.
|
||||||
|
u_char* first_null = (u_char*) memchr(${h.name}.data(), 0, ${h.name}.length());
|
||||||
|
uint16 name_len;
|
||||||
|
if ( first_null == NULL )
|
||||||
|
name_len = ${h.name}.length();
|
||||||
|
else
|
||||||
|
name_len = first_null - ${h.name}.data();
|
||||||
|
section_header->Assign(0, new StringVal(name_len, (const char*) ${h.name}.data()));
|
||||||
|
|
||||||
section_header->Assign(1, new Val(${h.virtual_size}, TYPE_COUNT));
|
section_header->Assign(1, new Val(${h.virtual_size}, TYPE_COUNT));
|
||||||
section_header->Assign(2, new Val(${h.virtual_addr}, TYPE_COUNT));
|
section_header->Assign(2, new Val(${h.virtual_addr}, TYPE_COUNT));
|
||||||
section_header->Assign(3, new Val(${h.size_of_raw_data}, TYPE_COUNT));
|
section_header->Assign(3, new Val(${h.size_of_raw_data}, TYPE_COUNT));
|
||||||
|
@ -42,11 +157,12 @@ refine flow File += {
|
||||||
section_header->Assign(6, new Val(${h.non_used_ptr_to_line_nums}, TYPE_COUNT));
|
section_header->Assign(6, new Val(${h.non_used_ptr_to_line_nums}, TYPE_COUNT));
|
||||||
section_header->Assign(7, new Val(${h.non_used_num_of_relocs}, TYPE_COUNT));
|
section_header->Assign(7, new Val(${h.non_used_num_of_relocs}, TYPE_COUNT));
|
||||||
section_header->Assign(8, new Val(${h.non_used_num_of_line_nums}, TYPE_COUNT));
|
section_header->Assign(8, new Val(${h.non_used_num_of_line_nums}, TYPE_COUNT));
|
||||||
section_header->Assign(9, new Val(${h.characteristics}, TYPE_COUNT));
|
section_header->Assign(9, characteristics_to_bro(${h.characteristics}, 32));
|
||||||
|
|
||||||
BifEvent::generate_file_pe_section_header((Analyzer *) connection()->bro_analyzer(),
|
BifEvent::generate_pe_section_header((Analyzer *) connection()->bro_analyzer(),
|
||||||
connection()->bro_analyzer()->GetFile()->GetVal()->Ref(),
|
connection()->bro_analyzer()->GetFile()->GetVal()->Ref(),
|
||||||
section_header);
|
section_header);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
@ -56,7 +172,15 @@ refine typeattr DOS_Header += &let {
|
||||||
};
|
};
|
||||||
|
|
||||||
refine typeattr IMAGE_NT_HEADERS += &let {
|
refine typeattr IMAGE_NT_HEADERS += &let {
|
||||||
proc : bool = $context.flow.proc_pe_header(this);
|
proc : bool = $context.flow.proc_nt_headers(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
refine typeattr IMAGE_FILE_HEADER += &let {
|
||||||
|
proc : bool = $context.flow.proc_file_header(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
refine typeattr IMAGE_OPTIONAL_HEADER += &let {
|
||||||
|
proc : bool = $context.flow.proc_optional_header(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
refine typeattr IMAGE_SECTION_HEADER += &let {
|
refine typeattr IMAGE_SECTION_HEADER += &let {
|
||||||
|
|
|
@ -6,8 +6,10 @@ type TheFile = record {
|
||||||
sections_table : IMAGE_SECTION_HEADER[] &length=pe_header.file_header.NumberOfSections*40 &transient;
|
sections_table : IMAGE_SECTION_HEADER[] &length=pe_header.file_header.NumberOfSections*40 &transient;
|
||||||
#pad : bytestring &length=offsetof(pe_header.data_directories + pe_header.data_directories[1].virtual_address);
|
#pad : bytestring &length=offsetof(pe_header.data_directories + pe_header.data_directories[1].virtual_address);
|
||||||
#data_sections : DATA_SECTIONS[pe_header.file_header.NumberOfSections];
|
#data_sections : DATA_SECTIONS[pe_header.file_header.NumberOfSections];
|
||||||
|
data_sections : DATA_SECTIONS[] &length=data_len;
|
||||||
} &let {
|
} &let {
|
||||||
dos_code_len: uint32 = dos_header.AddressOfNewExeHeader - 64;
|
dos_code_len: uint32 = dos_header.AddressOfNewExeHeader - 64;
|
||||||
|
data_len: uint32 = pe_header.optional_header.size_of_init_data;
|
||||||
} &byteorder=littleendian;
|
} &byteorder=littleendian;
|
||||||
|
|
||||||
type DOS_Header = record {
|
type DOS_Header = record {
|
||||||
|
@ -35,8 +37,8 @@ type DOS_Header = record {
|
||||||
type IMAGE_NT_HEADERS = record {
|
type IMAGE_NT_HEADERS = record {
|
||||||
PESignature : uint32;
|
PESignature : uint32;
|
||||||
file_header : IMAGE_FILE_HEADER;
|
file_header : IMAGE_FILE_HEADER;
|
||||||
OptionalHeader : IMAGE_OPTIONAL_HEADER(file_header.SizeOfOptionalHeader);
|
optional_header : IMAGE_OPTIONAL_HEADER(file_header.SizeOfOptionalHeader) &length=file_header.SizeOfOptionalHeader;
|
||||||
} &byteorder=littleendian &length=file_header.SizeOfOptionalHeader+offsetof(OptionalHeader);
|
} &byteorder=littleendian &length=file_header.SizeOfOptionalHeader+offsetof(optional_header);
|
||||||
|
|
||||||
type IMAGE_FILE_HEADER = record {
|
type IMAGE_FILE_HEADER = record {
|
||||||
Machine : uint16;
|
Machine : uint16;
|
||||||
|
@ -124,5 +126,5 @@ type IMAGE_IMPORT_DIRECTORY = record {
|
||||||
};
|
};
|
||||||
|
|
||||||
type DATA_SECTIONS = record {
|
type DATA_SECTIONS = record {
|
||||||
blah: bytestring &length=10;
|
blah: uint8;
|
||||||
};
|
};
|
|
@ -163,8 +163,10 @@ type ModbusHeaders: record;
|
||||||
type ModbusCoils: vector;
|
type ModbusCoils: vector;
|
||||||
type ModbusRegisters: vector;
|
type ModbusRegisters: vector;
|
||||||
|
|
||||||
type PEHeader: record;
|
type PE::DOSHeader: record;
|
||||||
type PESectionHeader: record;
|
type PE::FileHeader: record;
|
||||||
|
type PE::OptionalHeader: record;
|
||||||
|
type PE::SectionHeader: record;
|
||||||
|
|
||||||
module Log;
|
module Log;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue