mirror of
https://github.com/zeek/zeek.git
synced 2025-10-15 21:18:20 +00:00
Merge remote-tracking branch 'origin/topic/vladg/file-analysis-exe-analyzer'
* 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
This commit is contained in:
commit
a9979d56a4
30 changed files with 1429 additions and 53 deletions
2
scripts/base/files/pe/__load__.bro
Normal file
2
scripts/base/files/pe/__load__.bro
Normal file
|
@ -0,0 +1,2 @@
|
|||
@load ./consts
|
||||
@load ./main
|
184
scripts/base/files/pe/consts.bro
Normal file
184
scripts/base/files/pe/consts.bro
Normal file
|
@ -0,0 +1,184 @@
|
|||
|
||||
module PE;
|
||||
|
||||
export {
|
||||
const machine_types: table[count] of string = {
|
||||
[0x00] = "UNKNOWN",
|
||||
[0x1d3] = "AM33",
|
||||
[0x8664] = "AMD64",
|
||||
[0x1c0] = "ARM",
|
||||
[0x1c4] = "ARMNT",
|
||||
[0xaa64] = "ARM64",
|
||||
[0xebc] = "EBC",
|
||||
[0x14c] = "I386",
|
||||
[0x200] = "IA64",
|
||||
[0x9041] = "M32R",
|
||||
[0x266] = "MIPS16",
|
||||
[0x366] = "MIPSFPU",
|
||||
[0x466] = "MIPSFPU16",
|
||||
[0x1f0] = "POWERPC",
|
||||
[0x1f1] = "POWERPCFP",
|
||||
[0x166] = "R4000",
|
||||
[0x1a2] = "SH3",
|
||||
[0x1a3] = "SH3DSP",
|
||||
[0x1a6] = "SH4",
|
||||
[0x1a8] = "SH5",
|
||||
[0x1c2] = "THUMB",
|
||||
[0x169] = "WCEMIPSV2"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const file_characteristics: table[count] of string = {
|
||||
[0x1] = "RELOCS_STRIPPED",
|
||||
[0x2] = "EXECUTABLE_IMAGE",
|
||||
[0x4] = "LINE_NUMS_STRIPPED",
|
||||
[0x8] = "LOCAL_SYMS_STRIPPED",
|
||||
[0x10] = "AGGRESSIVE_WS_TRIM",
|
||||
[0x20] = "LARGE_ADDRESS_AWARE",
|
||||
[0x80] = "BYTES_REVERSED_LO",
|
||||
[0x100] = "32BIT_MACHINE",
|
||||
[0x200] = "DEBUG_STRIPPED",
|
||||
[0x400] = "REMOVABLE_RUN_FROM_SWAP",
|
||||
[0x800] = "NET_RUN_FROM_SWAP",
|
||||
[0x1000] = "SYSTEM",
|
||||
[0x2000] = "DLL",
|
||||
[0x4000] = "UP_SYSTEM_ONLY",
|
||||
[0x8000] = "BYTES_REVERSED_HI"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const dll_characteristics: table[count] of string = {
|
||||
[0x40] = "DYNAMIC_BASE",
|
||||
[0x80] = "FORCE_INTEGRITY",
|
||||
[0x100] = "NX_COMPAT",
|
||||
[0x200] = "NO_ISOLATION",
|
||||
[0x400] = "NO_SEH",
|
||||
[0x800] = "NO_BIND",
|
||||
[0x2000] = "WDM_DRIVER",
|
||||
[0x8000] = "TERMINAL_SERVER_AWARE"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const windows_subsystems: table[count] of string = {
|
||||
[0] = "UNKNOWN",
|
||||
[1] = "NATIVE",
|
||||
[2] = "WINDOWS_GUI",
|
||||
[3] = "WINDOWS_CUI",
|
||||
[7] = "POSIX_CUI",
|
||||
[9] = "WINDOWS_CE_GUI",
|
||||
[10] = "EFI_APPLICATION",
|
||||
[11] = "EFI_BOOT_SERVICE_DRIVER",
|
||||
[12] = "EFI_RUNTIME_
DRIVER",
|
||||
[13] = "EFI_ROM",
|
||||
[14] = "XBOX"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const directories: table[count] of string = {
|
||||
[0] = "Export Table",
|
||||
[1] = "Import Table",
|
||||
[2] = "Resource Table",
|
||||
[3] = "Exception Table",
|
||||
[4] = "Certificate Table",
|
||||
[5] = "Base Relocation Table",
|
||||
[6] = "Debug",
|
||||
[7] = "Architecture",
|
||||
[8] = "Global Ptr",
|
||||
[9] = "TLS Table",
|
||||
[10] = "Load Config Table",
|
||||
[11] = "Bound Import",
|
||||
[12] = "IAT",
|
||||
[13] = "Delay Import Descriptor",
|
||||
[14] = "CLR Runtime Header",
|
||||
[15] = "Reserved"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const section_characteristics: table[count] of string = {
|
||||
[0x8] = "TYPE_NO_PAD",
|
||||
[0x20] = "CNT_CODE",
|
||||
[0x40] = "CNT_INITIALIZED_DATA",
|
||||
[0x80] = "CNT_UNINITIALIZED_DATA",
|
||||
[0x100] = "LNK_OTHER",
|
||||
[0x200] = "LNK_INFO",
|
||||
[0x800] = "LNK_REMOVE",
|
||||
[0x1000] = "LNK_COMDAT",
|
||||
[0x8000] = "GPREL",
|
||||
[0x20000] = "MEM_16BIT",
|
||||
[0x40000] = "MEM_LOCKED",
|
||||
[0x80000] = "MEM_PRELOAD",
|
||||
[0x100000] = "ALIGN_1BYTES",
|
||||
[0x200000] = "ALIGN_2BYTES",
|
||||
[0x300000] = "ALIGN_4BYTES",
|
||||
[0x400000] = "ALIGN_8BYTES",
|
||||
[0x500000] = "ALIGN_16BYTES",
|
||||
[0x600000] = "ALIGN_32BYTES",
|
||||
[0x700000] = "ALIGN_64BYTES",
|
||||
[0x800000] = "ALIGN_128BYTES",
|
||||
[0x900000] = "ALIGN_256BYTES",
|
||||
[0xa00000] = "ALIGN_512BYTES",
|
||||
[0xb00000] = "ALIGN_1024BYTES",
|
||||
[0xc00000] = "ALIGN_2048BYTES",
|
||||
[0xd00000] = "ALIGN_4096BYTES",
|
||||
[0xe00000] = "ALIGN_8192BYTES",
|
||||
[0x1000000] = "LNK_NRELOC_OVFL",
|
||||
[0x2000000] = "MEM_DISCARDABLE",
|
||||
[0x4000000] = "MEM_NOT_CACHED",
|
||||
[0x8000000] = "MEM_NOT_PAGED",
|
||||
[0x10000000] = "MEM_SHARED",
|
||||
[0x20000000] = "MEM_EXECUTE",
|
||||
[0x40000000] = "MEM_READ",
|
||||
[0x80000000] = "MEM_WRITE"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const os_versions: table[count, count] of string = {
|
||||
[10,0] = "Windows 10",
|
||||
[6,4] = "Windows 10 Technical Preview",
|
||||
[6,3] = "Windows 8.1 or Server 2012 R2",
|
||||
[6,2] = "Windows 8 or Server 2012",
|
||||
[6,1] = "Windows 7 or Server 2008 R2",
|
||||
[6,0] = "Windows Vista or Server 2008",
|
||||
[5,2] = "Windows XP x64 or Server 2003",
|
||||
[5,1] = "Windows XP",
|
||||
[5,0] = "Windows 2000",
|
||||
[4,90] = "Windows Me",
|
||||
[4,10] = "Windows 98",
|
||||
[4,0] = "Windows 95 or NT 4.0",
|
||||
[3,51] = "Windows NT 3.51",
|
||||
[3,50] = "Windows NT 3.5",
|
||||
[3,2] = "Windows 3.2",
|
||||
[3,11] = "Windows for Workgroups 3.11",
|
||||
[3,10] = "Windows 3.1 or NT 3.1",
|
||||
[3,0] = "Windows 3.0",
|
||||
[2,11] = "Windows 2.11",
|
||||
[2,10] = "Windows 2.10",
|
||||
[2,0] = "Windows 2.0",
|
||||
[1,4] = "Windows 1.04",
|
||||
[1,3] = "Windows 1.03",
|
||||
[1,1] = "Windows 1.01",
|
||||
[1,0] = "Windows 1.0",
|
||||
} &default=function(i: count, j: count):string { return fmt("unknown-%d.%d", i, j); };
|
||||
|
||||
const section_descs: table[string] of string = {
|
||||
[".bss"] = "Uninitialized data",
|
||||
[".cormeta"] = "CLR metadata that indicates that the object file contains managed code",
|
||||
[".data"] = "Initialized data",
|
||||
[".debug$F"] = "Generated FPO debug information",
|
||||
[".debug$P"] = "Precompiled debug types",
|
||||
[".debug$S"] = "Debug symbols",
|
||||
[".debug$T"] = "Debug types",
|
||||
[".drective"] = "Linker options",
|
||||
[".edata"] = "Export tables",
|
||||
[".idata"] = "Import tables",
|
||||
[".idlsym"] = "Includes registered SEH to support IDL attributes",
|
||||
[".pdata"] = "Exception information",
|
||||
[".rdata"] = "Read-only initialized data",
|
||||
[".reloc"] = "Image relocations",
|
||||
[".rsrc"] = "Resource directory",
|
||||
[".sbss"] = "GP-relative uninitialized data",
|
||||
[".sdata"] = "GP-relative initialized data",
|
||||
[".srdata"] = "GP-relative read-only data",
|
||||
[".sxdata"] = "Registered exception handler data",
|
||||
[".text"] = "Executable code",
|
||||
[".tls"] = "Thread-local storage",
|
||||
[".tls$"] = "Thread-local storage",
|
||||
[".vsdata"] = "GP-relative initialized data",
|
||||
[".xdata"] = "Exception information",
|
||||
} &default=function(i: string):string { return fmt("unknown-%s", i); };
|
||||
|
||||
}
|
137
scripts/base/files/pe/main.bro
Normal file
137
scripts/base/files/pe/main.bro
Normal file
|
@ -0,0 +1,137 @@
|
|||
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);
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue