mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 16:18:19 +00:00
Remove the .idata parsing, as it can be more complicated in some cases.
This commit is contained in:
parent
546cbf50c9
commit
ea36686524
5 changed files with 16 additions and 206 deletions
|
@ -29,10 +29,13 @@ export {
|
||||||
section_names: vector of string &log &optional;
|
section_names: vector of string &log &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
global set_file: hook(f: fa_file);
|
global set_file: hook(f: fa_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redef record Info += {
|
||||||
|
confirmed: bool &default=F;
|
||||||
|
};
|
||||||
|
|
||||||
redef record fa_file += {
|
redef record fa_file += {
|
||||||
pe: Info &optional;
|
pe: Info &optional;
|
||||||
};
|
};
|
||||||
|
@ -75,6 +78,12 @@ event pe_file_header(f: fa_file, h: PE::FileHeader) &priority=5
|
||||||
event pe_optional_header(f: fa_file, h: PE::OptionalHeader) &priority=5
|
event pe_optional_header(f: fa_file, h: PE::OptionalHeader) &priority=5
|
||||||
{
|
{
|
||||||
hook set_file(f);
|
hook set_file(f);
|
||||||
|
|
||||||
|
if ( h$magic == 0x10b || h$magic == 0x20b )
|
||||||
|
f$pe$confirmed = T;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
f$pe$os = os_versions[h$os_version_major, h$os_version_minor];
|
f$pe$os = os_versions[h$os_version_major, h$os_version_minor];
|
||||||
f$pe$subsystem = windows_subsystems[h$subsystem];
|
f$pe$subsystem = windows_subsystems[h$subsystem];
|
||||||
for ( c in h$dll_characteristics )
|
for ( c in h$dll_characteristics )
|
||||||
|
@ -99,9 +108,9 @@ event pe_section_header(f: fa_file, h: PE::SectionHeader) &priority=5
|
||||||
f$pe$section_names[|f$pe$section_names|] = h$name;
|
f$pe$section_names[|f$pe$section_names|] = h$name;
|
||||||
}
|
}
|
||||||
|
|
||||||
event file_state_remove(f: fa_file)
|
event file_state_remove(f: fa_file) &priority=-5
|
||||||
{
|
{
|
||||||
if ( f?$pe )
|
if ( f?$pe && f$pe$confirmed )
|
||||||
Log::write(LOG, f$pe);
|
Log::write(LOG, f$pe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,8 @@ refine flow File += {
|
||||||
${h.magic} != 0x107 && // rom image
|
${h.magic} != 0x107 && // rom image
|
||||||
${h.magic} != 0x20b ) // pe32+ executable
|
${h.magic} != 0x20b ) // pe32+ executable
|
||||||
{
|
{
|
||||||
return false;
|
|
||||||
// FileViolation("PE Optional Header magic is invalid.");
|
// FileViolation("PE Optional Header magic is invalid.");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pe_optional_header )
|
if ( pe_optional_header )
|
||||||
|
@ -173,24 +173,6 @@ refine flow File += {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
function proc_import_entry(module_name: bytestring, i: import_entry): bool
|
|
||||||
%{
|
|
||||||
if ( pe_import_entry )
|
|
||||||
{
|
|
||||||
StringVal* name;
|
|
||||||
if ( ${i.name}.length() > 1 )
|
|
||||||
name = new StringVal(${i.name}.length() - 1, (const char*) ${i.name}.begin());
|
|
||||||
else
|
|
||||||
name = new StringVal(0, (const char*) ${i.name}.begin());
|
|
||||||
|
|
||||||
BifEvent::generate_pe_import_entry((analyzer::Analyzer *) connection()->bro_analyzer(),
|
|
||||||
connection()->bro_analyzer()->GetFile()->GetVal()->Ref(),
|
|
||||||
bytestring_to_val(${module_name}),
|
|
||||||
name);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
%}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
refine typeattr DOS_Header += &let {
|
refine typeattr DOS_Header += &let {
|
||||||
|
@ -216,7 +198,3 @@ refine typeattr Optional_Header += &let {
|
||||||
refine typeattr Section_Header += &let {
|
refine typeattr Section_Header += &let {
|
||||||
proc: bool = $context.flow.proc_section_header(this);
|
proc: bool = $context.flow.proc_section_header(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
refine typeattr import_entry += &let {
|
|
||||||
proc: bool = $context.flow.proc_import_entry($context.connection.get_module_name(), this) &if(!is_module);
|
|
||||||
};
|
|
||||||
|
|
|
@ -137,8 +137,6 @@ refine connection MockConnection += {
|
||||||
if ( ${h.size_of_raw_data} + ${h.ptr_to_raw_data} > max_file_location_ )
|
if ( ${h.size_of_raw_data} + ${h.ptr_to_raw_data} > max_file_location_ )
|
||||||
max_file_location_ = ${h.size_of_raw_data} + ${h.ptr_to_raw_data};
|
max_file_location_ = ${h.size_of_raw_data} + ${h.ptr_to_raw_data};
|
||||||
|
|
||||||
if ( ${h.virtual_addr} > 0 && ${h.virtual_addr} <= import_table_rva_ && ( ${h.virtual_addr} + ${h.virtual_size} ) > import_table_rva_ )
|
|
||||||
import_table_va_ = ${h.ptr_to_raw_data} + (import_table_rva_ - ${h.virtual_addr});
|
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -1,171 +0,0 @@
|
||||||
## Support for parsing the .idata section
|
|
||||||
|
|
||||||
type import_directory = record {
|
|
||||||
rva_import_lookup_table : uint32;
|
|
||||||
time_date_stamp : uint32;
|
|
||||||
forwarder_chain : uint32;
|
|
||||||
rva_module_name : uint32;
|
|
||||||
rva_import_addr_table : uint32;
|
|
||||||
} &let {
|
|
||||||
is_null: bool = rva_module_name == 0;
|
|
||||||
proc: bool = $context.connection.proc_image_import_directory(this);
|
|
||||||
} &length=20;
|
|
||||||
|
|
||||||
type import_lookup_attrs(pe32_format: uint8) = record {
|
|
||||||
is_pe32_plus: case pe32_format of {
|
|
||||||
PE32_PLUS -> attrs_64: uint64;
|
|
||||||
default -> attrs_32: uint32;
|
|
||||||
};
|
|
||||||
} &let {
|
|
||||||
attrs: uint64 = (pe32_format == PE32_PLUS) ? attrs_64 : attrs_32;
|
|
||||||
} &length=(pe32_format == PE32_PLUS ? 8 : 4);
|
|
||||||
|
|
||||||
type import_lookup_table = record {
|
|
||||||
attrs: import_lookup_attrs($context.connection.get_pe32_format())[] &until($element.attrs == 0);
|
|
||||||
} &let {
|
|
||||||
proc: bool = $context.connection.proc_import_lookup_table(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
type import_entry(is_module: bool, pad_align: uint8) = record {
|
|
||||||
pad: bytestring &length=pad_align;
|
|
||||||
has_index: case is_module of {
|
|
||||||
true -> null: empty;
|
|
||||||
false -> index: uint16;
|
|
||||||
};
|
|
||||||
name: null_terminated_string;
|
|
||||||
} &let {
|
|
||||||
proc_align: bool = $context.connection.proc_import_hint(name, is_module);
|
|
||||||
};
|
|
||||||
|
|
||||||
type idata = record {
|
|
||||||
directory_table : import_directory[] &until $element.is_null;
|
|
||||||
lookup_tables : import_lookup_table[] &until $context.connection.get_num_imports() <= 0;
|
|
||||||
hint_table : import_entry($context.connection.get_next_hint_type(), $context.connection.get_next_hint_align())[] &until($context.connection.imports_done());
|
|
||||||
};
|
|
||||||
|
|
||||||
refine typeattr RVAS += &let {
|
|
||||||
proc: bool = $context.connection.proc_idata_rva(rvas[1]) &if (num > 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
refine connection MockConnection += {
|
|
||||||
%member{
|
|
||||||
uint8 num_imports_; // How many import tables will we have?
|
|
||||||
|
|
||||||
uint32 import_table_rva_; // Used for finding the right section
|
|
||||||
uint32 import_table_va_;
|
|
||||||
uint32 import_table_len_;
|
|
||||||
|
|
||||||
// We need to track the number of imports for each, to
|
|
||||||
// know when we've parsed them all.
|
|
||||||
vector<uint32> imports_per_module_;
|
|
||||||
|
|
||||||
// These are to determine the alignment of the import hints
|
|
||||||
uint32 next_hint_index_;
|
|
||||||
uint8 next_hint_align_;
|
|
||||||
bool next_hint_is_module_;
|
|
||||||
|
|
||||||
// Track the module name, so we know what each import's for
|
|
||||||
bytestring module_name_;
|
|
||||||
%}
|
|
||||||
|
|
||||||
%init{
|
|
||||||
// It ends with a null import entry, so we'll set it to -1.
|
|
||||||
num_imports_ = -1;
|
|
||||||
|
|
||||||
// First hint is a module name.
|
|
||||||
next_hint_is_module_ = true;
|
|
||||||
next_hint_index_ = 0;
|
|
||||||
next_hint_align_ = 0;
|
|
||||||
|
|
||||||
module_name_ = bytestring();
|
|
||||||
%}
|
|
||||||
|
|
||||||
%cleanup{
|
|
||||||
module_name_.free();
|
|
||||||
%}
|
|
||||||
|
|
||||||
# When we read the section header, store the relative virtual address and
|
|
||||||
# size of the .idata section, so we know when we get there.
|
|
||||||
function proc_idata_rva(r: RVA): bool
|
|
||||||
%{
|
|
||||||
import_table_rva_ = ${r.virtual_address};
|
|
||||||
import_table_len_ = ${r.size};
|
|
||||||
|
|
||||||
return true;
|
|
||||||
%}
|
|
||||||
|
|
||||||
# Each import directory means another module we're importing from.
|
|
||||||
function proc_image_import_directory(i: import_directory): bool
|
|
||||||
%{
|
|
||||||
num_imports_++;
|
|
||||||
return true;
|
|
||||||
%}
|
|
||||||
|
|
||||||
# Store the number of functions imported in each module lookup table.
|
|
||||||
function proc_import_lookup_table(t: import_lookup_table): bool
|
|
||||||
%{
|
|
||||||
--num_imports_;
|
|
||||||
imports_per_module_.push_back(${t.attrs}->size());
|
|
||||||
return true;
|
|
||||||
%}
|
|
||||||
|
|
||||||
# We need to calculate the length of the next padding field
|
|
||||||
function proc_import_hint(hint_name: bytestring, is_module: bool): bool
|
|
||||||
%{
|
|
||||||
next_hint_align_ = ${hint_name}.length() % 2;
|
|
||||||
if ( is_module && ${hint_name}.length() > 1 )
|
|
||||||
{
|
|
||||||
module_name_.clear();
|
|
||||||
module_name_.init(${hint_name}.data(), ${hint_name}.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
%}
|
|
||||||
|
|
||||||
# Functions have an index field, modules don't. Which one is this?
|
|
||||||
function get_next_hint_type(): bool
|
|
||||||
%{
|
|
||||||
if ( next_hint_is_module_ )
|
|
||||||
{
|
|
||||||
next_hint_is_module_ = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ( --imports_per_module_[next_hint_index_] == 0)
|
|
||||||
{
|
|
||||||
++next_hint_index_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
%}
|
|
||||||
|
|
||||||
function imports_done(): bool
|
|
||||||
%{
|
|
||||||
return next_hint_index_ == imports_per_module_.size();
|
|
||||||
%}
|
|
||||||
|
|
||||||
function get_module_name(): bytestring
|
|
||||||
%{
|
|
||||||
return module_name_;
|
|
||||||
%}
|
|
||||||
|
|
||||||
function get_import_table_addr(): uint32
|
|
||||||
%{
|
|
||||||
return import_table_va_ > 0 ? import_table_va_ : 0;
|
|
||||||
%}
|
|
||||||
|
|
||||||
function get_import_table_len(): uint32
|
|
||||||
%{
|
|
||||||
return import_table_va_ > 0 ? import_table_len_ : 0;
|
|
||||||
%}
|
|
||||||
|
|
||||||
function get_num_imports(): uint8
|
|
||||||
%{
|
|
||||||
return num_imports_;
|
|
||||||
%}
|
|
||||||
|
|
||||||
function get_next_hint_align(): uint8
|
|
||||||
%{
|
|
||||||
return next_hint_align_;
|
|
||||||
%}
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,6 +1,5 @@
|
||||||
%include pe-file-types.pac
|
%include pe-file-types.pac
|
||||||
%include pe-file-headers.pac
|
%include pe-file-headers.pac
|
||||||
%include pe-file-idata.pac
|
|
||||||
|
|
||||||
# The base record for a Portable Executable file
|
# The base record for a Portable Executable file
|
||||||
type PE_File = case $context.connection.is_done() of {
|
type PE_File = case $context.connection.is_done() of {
|
||||||
|
@ -10,13 +9,10 @@ type PE_File = case $context.connection.is_done() of {
|
||||||
|
|
||||||
type Portable_Executable = record {
|
type Portable_Executable = record {
|
||||||
headers : Headers;
|
headers : Headers;
|
||||||
pad1 : Padding(iat_loc);
|
pad : Padding(restofdata);
|
||||||
iat : idata &length=$context.connection.get_import_table_len();
|
|
||||||
pad2 : Padding(restofdata);
|
|
||||||
} &let {
|
} &let {
|
||||||
unparsed_hdr_len: uint32 = headers.pe_header.optional_header.size_of_headers - headers.length;
|
unparsed_hdr_len: uint32 = headers.pe_header.optional_header.size_of_headers - headers.length;
|
||||||
iat_loc: uint64 = $context.connection.get_import_table_addr() - headers.pe_header.optional_header.size_of_headers + unparsed_hdr_len;
|
restofdata: uint64 = $context.connection.get_max_file_location() - headers.pe_header.optional_header.size_of_headers + unparsed_hdr_len;
|
||||||
restofdata: uint64 = $context.connection.get_max_file_location() - $context.connection.get_import_table_addr() - $context.connection.get_import_table_len();
|
|
||||||
proc: bool = $context.connection.proc_pe(this);
|
proc: bool = $context.connection.proc_pe(this);
|
||||||
} &byteorder=littleendian;
|
} &byteorder=littleendian;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue