mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00

* origin/topic/vladg/file-analysis-exe-analyzer: (31 commits) Tweak the PE OS versions based on real-world traffic. Update pe/main.bro to user register_for_mime_types, ensuring it will also work with the upcoming Files framework changes. A bit of final core-level cleanup. A bit of final script cleanup. Update baselines. Add a btest for the PE analyzer. Add a PE memleak test, and fix a memleak. Documentation and a bit of overall cleanup. Add data about which tables are present. Remove the .idata parsing, as it can be more complicated in some cases. Fix a PE analyzer failure where the IAT isn't aligned with a section boundary. PE: Rehash the log a bit. Make base_of_data optional. Fix support for PE32+ files. PE Analyzer cleanup. Checkpoint - Import Address Table being parsed. Some changes to fix PE analyzer on master. Parse PE section headers. Updated PE analyzer to work with changes in master. In progress checkpoint. Things are starting to work. ... BIT-1369 #merged
137 lines
4 KiB
Text
137 lines
4 KiB
Text
module PE;
|
|
|
|
@load ./consts.bro
|
|
|
|
export {
|
|
redef enum Log::ID += { LOG };
|
|
|
|
type Info: record {
|
|
## Current timestamp.
|
|
ts: time &log;
|
|
## File id of this portable executable file.
|
|
id: string &log;
|
|
## The target machine that the file was compiled for.
|
|
machine: string &log &optional;
|
|
## The time that the file was created at.
|
|
compile_ts: time &log &optional;
|
|
## The required operating system.
|
|
os: string &log &optional;
|
|
## The subsystem that is required to run this file.
|
|
subsystem: string &log &optional;
|
|
## Is the file an executable, or just an object file?
|
|
is_exe: bool &log &default=T;
|
|
## Is the file a 64-bit executable?
|
|
is_64bit: bool &log &default=T;
|
|
## Does the file support Address Space Layout Randomization?
|
|
uses_aslr: bool &log &default=F;
|
|
## Does the file support Data Execution Prevention?
|
|
uses_dep: bool &log &default=F;
|
|
## Does the file enforce code integrity checks?
|
|
uses_code_integrity: bool &log &default=F;
|
|
## Does the file use structured exception handing?
|
|
uses_seh: bool &log &default=T;
|
|
## Does the file have an import table?
|
|
has_import_table: bool &log &optional;
|
|
## Does the file have an export table?
|
|
has_export_table: bool &log &optional;
|
|
## Does the file have an attribute certificate table?
|
|
has_cert_table: bool &log &optional;
|
|
## Does the file have a debug table?
|
|
has_debug_data: bool &log &optional;
|
|
## The names of the sections, in order.
|
|
section_names: vector of string &log &optional;
|
|
};
|
|
|
|
## Event for accessing logged records.
|
|
global log_pe: event(rec: Info);
|
|
|
|
## A hook that gets called when we first see a PE file.
|
|
global set_file: hook(f: fa_file);
|
|
}
|
|
|
|
redef record fa_file += {
|
|
pe: Info &optional;
|
|
};
|
|
|
|
const pe_mime_types = { "application/x-dosexec" };
|
|
|
|
event bro_init() &priority=5
|
|
{
|
|
Files::register_for_mime_types(Files::ANALYZER_PE, pe_mime_types);
|
|
Log::create_stream(LOG, [$columns=Info, $ev=log_pe, $path="pe"]);
|
|
}
|
|
|
|
hook set_file(f: fa_file) &priority=5
|
|
{
|
|
if ( ! f?$pe )
|
|
f$pe = [$ts=network_time(), $id=f$id];
|
|
}
|
|
|
|
event pe_dos_header(f: fa_file, h: PE::DOSHeader) &priority=5
|
|
{
|
|
hook set_file(f);
|
|
}
|
|
|
|
event pe_file_header(f: fa_file, h: PE::FileHeader) &priority=5
|
|
{
|
|
hook set_file(f);
|
|
|
|
f$pe$machine = machine_types[h$machine];
|
|
f$pe$compile_ts = h$ts;
|
|
f$pe$is_exe = ( h$optional_header_size > 0 );
|
|
|
|
for ( c in h$characteristics )
|
|
{
|
|
if ( file_characteristics[c] == "32BIT_MACHINE" )
|
|
f$pe$is_64bit = F;
|
|
}
|
|
}
|
|
|
|
event pe_optional_header(f: fa_file, h: PE::OptionalHeader) &priority=5
|
|
{
|
|
hook set_file(f);
|
|
|
|
# Only EXEs have optional headers
|
|
if ( ! f$pe$is_exe )
|
|
return;
|
|
|
|
f$pe$os = os_versions[h$os_version_major, h$os_version_minor];
|
|
f$pe$subsystem = windows_subsystems[h$subsystem];
|
|
|
|
for ( c in h$dll_characteristics )
|
|
{
|
|
if ( dll_characteristics[c] == "DYNAMIC_BASE" )
|
|
f$pe$uses_aslr = T;
|
|
if ( dll_characteristics[c] == "FORCE_INTEGRITY" )
|
|
f$pe$uses_code_integrity = T;
|
|
if ( dll_characteristics[c] == "NX_COMPAT" )
|
|
f$pe$uses_dep = T;
|
|
if ( dll_characteristics[c] == "NO_SEH" )
|
|
f$pe$uses_seh = F;
|
|
}
|
|
|
|
f$pe$has_export_table = (|h$table_sizes| > 0 && h$table_sizes[0] > 0);
|
|
f$pe$has_import_table = (|h$table_sizes| > 1 && h$table_sizes[1] > 0);
|
|
f$pe$has_cert_table = (|h$table_sizes| > 4 && h$table_sizes[4] > 0);
|
|
f$pe$has_debug_data = (|h$table_sizes| > 6 && h$table_sizes[6] > 0);
|
|
}
|
|
|
|
event pe_section_header(f: fa_file, h: PE::SectionHeader) &priority=5
|
|
{
|
|
hook set_file(f);
|
|
|
|
# Only EXEs have section headers
|
|
if ( ! f$pe$is_exe )
|
|
return;
|
|
|
|
if ( ! f$pe?$section_names )
|
|
f$pe$section_names = vector();
|
|
f$pe$section_names[|f$pe$section_names|] = h$name;
|
|
}
|
|
|
|
event file_state_remove(f: fa_file) &priority=-5
|
|
{
|
|
if ( f?$pe && f$pe?$machine )
|
|
Log::write(LOG, f$pe);
|
|
}
|
|
|