module PE; export { redef enum Log::ID += { LOG }; type Info: record { ts: time &log; fuid: string &log; machine: string &log &optional; compile_ts: time &log &optional; os: string &log &optional; subsystem: string &log &optional; characteristics: set[string] &log &optional; section_names: vector of string &log &optional; }; global set_file: hook(f: fa_file); } redef record fa_file += { pe: Info &optional; }; event bro_init() &priority=5 { Log::create_stream(LOG, [$columns=Info]); } hook set_file(f: fa_file) &priority=5 { if ( ! f?$pe ) { local c: set[string] = set(); f$pe = [$ts=network_time(), $fuid=f$id, $characteristics=c]; } } event pe_dos_header(f: fa_file, h: PE::DOSHeader) &priority=5 { # print "DOS header"; # print h; hook set_file(f); } event pe_file_header(f: fa_file, h: PE::FileHeader) &priority=5 { # print "File header"; # print h; hook set_file(f); f$pe$compile_ts = h$ts; f$pe$machine = machine_types[h$machine]; for ( c in h$characteristics ) add f$pe$characteristics[PE::file_characteristics[c]]; } event pe_optional_header(f: fa_file, h: PE::OptionalHeader) &priority=5 { # print "Optional header"; # print h; hook set_file(f); f$pe$os = os_versions[h$os_version_major, h$os_version_minor]; f$pe$subsystem = windows_subsystems[h$subsystem]; } event pe_section_header(f: fa_file, h: PE::SectionHeader) &priority=5 { # print "Section header"; # print h; hook set_file(f); 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) { if ( f?$pe ) Log::write(LOG, f$pe); } event file_mime_type(f: fa_file, mime_type: string) { if ( mime_type == /application\/x-dosexec.*/ ) { Files::add_analyzer(f, Files::ANALYZER_PE); } }