def xml_records(filename): if OPTIONS.alternate: with Evtx(filename) as evtx: try: for xml, record in evtx_file_xml_view(evtx.get_file_header()): try: yield ef.to_lxml(xml), None except etree.XMLSyntaxError as e: yield xml, e except BinaryParser.OverrunBufferException as e: logging.error("Overrun Buffer Exception!") yield None, e except BinaryParser.ParseException as e: logging.error("Parse Exception!") yield None, e except Exception as e: # UnicodeDecodeError, AttributeError logging.error(e) yield None, e else: parser = PyEvtxParser(filename) try: for record in parser.records(): try: yield ef.to_lxml(record['data']), None except etree.XMLSyntaxError as e: yield record['data'], e except Exception as e: # UnicodeDecodeError, AttributeError, RuntimeError logging.error(e) yield None, e
def _read_evt_logs(func, logs_file: str, result_file: str, column_names: List[str]): global_start = time.time() start = time.time() _row_values = dict() if os.path.isfile(result_file): os.remove(result_file) with open(result_file, 'w', encoding='utf-8', newline='') as file: writer = csv.DictWriter(file, column_names) writer.writeheader() log = PyEvtxParser(logs_file) for index, record in enumerate(log.records()): _row_values.clear() _row_values = dict.fromkeys(column_names, 0) log_data = record['data'] func(log_data, _row_values) if IS_DEBUG: if index == 1000: break with open(result_file, 'a', encoding='utf-8', newline='') as file: writer = csv.DictWriter(file, column_names) writer.writerow(_row_values) if index % 10000 == 0: stop = time.time() print(f"{index}: {stop - start} сек.") start = time.time() print(f"затраченно времени: {time.time() - global_start} сек.")
def test_it_fails_nicely_on_close_files(small_sample): with open(small_sample, "rb") as o: parser = PyEvtxParser(o) with pytest.raises(OSError) as e: records = list(parser.records()) assert "closed file" in e.value.args[1]
def test_it_works_with_records(small_sample): parser = PyEvtxParser(small_sample) records = list(parser.records()) assert len(records) == 7 assert records[0]['event_record_id'] == 7 assert records[0]['timestamp'].endswith('UTC') assert '<EventID>4673</EventID>' in records[0]['data']
def test_it_works_on_file_backed_object(small_sample): with open(small_sample, "rb") as o: parser = PyEvtxParser(o) records = list(parser.records()) assert len(records) == 7 assert records[0]['event_record_id'] == 7 assert records[0]['timestamp'].endswith('UTC') assert '<EventID>4673</EventID>' in records[0]['data']
def test_it_works_on_io_object(small_sample): with open(small_sample, "rb") as o: r = o.read() parser = PyEvtxParser(io.BytesIO(r)) records = list(parser.records()) assert len(records) == 7 assert records[0]['event_record_id'] == 7 assert records[0]['timestamp'].endswith('UTC') assert '<EventID>4673</EventID>' in records[0]['data']
def test_it_supports_various_num_threads(small_sample): with open(small_sample, "rb") as o: parser = PyEvtxParser(o, number_of_threads=1) records = list(parser.records()) assert len(records) == 7 assert records[0]['event_record_id'] == 7 assert records[0]['timestamp'].endswith('UTC') assert '<EventID>4673</EventID>' in records[0]['data']
def test_it_supports_various_ascii_codecs(small_sample): with open(small_sample, "rb") as o: parser = PyEvtxParser(o, ansi_codec="ascii") records = list(parser.records()) assert len(records) == 7 assert records[0]['event_record_id'] == 7 assert records[0]['timestamp'].endswith('UTC') assert '<EventID>4673</EventID>' in records[0]['data']
class EvtxViewModel(QAbstractItemModel): def __init__(self, filename): super(QAbstractItemModel, self).__init__() self.__filename = filename self.__chunks = 0 self.__columns = [ ('TimeCreated', lambda r: r.timestamp), ('Provider', lambda r: r.Provider), ('EventID', lambda r: r.EventID), ('EventData', lambda r: r.Level) ] for idx in range(0, len(self.__columns)): self.setHeaderData(idx, Qt.Horizontal, self.__columns[0][0], Qt.DisplayRole) self.__records = dict() self.__record_ids = list() self.load_data() def load_data(self): self.__parser = PyEvtxParser(self.__filename) for record in self.__parser.records(): self.__records[record["event_record_id"]] = EventRecord(record) self.__record_ids.append(record["event_record_id"]) self.__record_ids.sort() def rowCount(self, parent): return len(self.__record_ids) def columnCount(self, parent): return len(self.__columns) def index(self, row: int, column: int, parent: QModelIndex = ...) -> QModelIndex: return self.createIndex(row, column) def data(self, index: QModelIndex, role: int = ...) -> typing.Any: if role == Qt.DisplayRole: row = index.row() record_id = self.__record_ids[row] record = self.__records[record_id] column = self.__columns[index.column()] return column[1](record) else: return QVariant() def flags(self, index: QModelIndex) -> Qt.ItemFlags: return Qt.ItemIsEnabled | Qt.ItemNeverHasChildren def parent(self, qmodelindex=None): return QModelIndex()
def run(self, target_file: TargetFile, result_of_previos_modules: dict) -> dict: events = [] self._filter_ids = self._get_filter_ids_from_params() parser = PyEvtxParser(target_file.get_path()) for record in parser.records(): try: parsed = xmltodict.parse(record["data"]) event = self._get_info(parsed, target_file) if event is not None: events.append(event) except: pass piped = utils.pipe_to_another_output(self._params, events) return {"n_events": len(events)} if piped else {"events": events}
def Evtx_hunt(files, str_regex, input_timzone, output): for file in files: print("Analyzing " + file) try: parser = PyEvtxParser(file) except: print("Issue analyzing " + file + "\nplease check if its not corrupted") continue try: rex = re.compile(str_regex, re.IGNORECASE) for record in parser.records(): EventID = EventID_rex.findall(record['data']) if len(EventID) > 0: Computer = Computer_rex.findall(record['data']) Channel = Channel_rex.findall(record['data']) if len(Channel) > 0: channel = Channel[0] else: channel = " " #print(record['data']) # if record['data'].lower().find(str_regex.lower())>-1: if rex.findall(record['data']): #print("EventID : "+EventID[0]+" , Data : "+record['data']) Hunting_events[0]['timestamp'].append( datetime.timestamp( isoparse( parse(record["timestamp"]).astimezone( input_timzone).isoformat()))) Hunting_events[0]['Date and Time'].append( parse(record["timestamp"]).astimezone( input_timzone).isoformat()) Hunting_events[0]['Channel'].append(channel) Hunting_events[0]['Event ID'].append(EventID[0]) Hunting_events[0]['Computer'].append(Computer[0]) Hunting_events[0]['Original Event Log'].append( str(record['data']).replace("\r", " ").replace( "\n", " ")) except Exception as e: print("issue searching log : " + record['data'] + "\n Error : " + print(e)) hunt_report(output)
def read_evt_logs(func, logs_file: str = 'data/Security.evtx', result_file: str = 'data/column_names_utf_8'): global_start = time.time() start = time.time() stop = 0 log = PyEvtxParser(logs_file) for index, record in enumerate(log.records()): # if index > 0: # break log_data = record['data'] func(log_data) if index % 10000 == 0: stop = time.time() print(f"{index}: {stop - start} сек.") start = time.time() try: with open(result_file, 'w', encoding='utf-8') as file: json.dump(column_names, file) except Exception as ex: print(ex) print(f"затраченно времени: {time.time() - global_start} сек.")
def test_it_returns_error_when_iterating_twice(small_sample): parser = PyEvtxParser(small_sample) _ = list(parser.records()) with pytest.raises(RuntimeError): parser.records()
def auto_detect(path): global input_timezone EventID_rex = re.compile('<EventID.*>(.*)<\/EventID>', re.IGNORECASE) Channel_rex = re.compile('<Channel.*>(.*)<\/Channel>', re.IGNORECASE) Computer_rex = re.compile('<Computer.*>(.*)<\/Computer>', re.IGNORECASE) if os.path.isdir(path): files = glob.glob(path + "*.evtx") elif os.path.isfile(path): files = glob.glob(path) else: print("Issue with the path") return #print("hunting ( %s ) in files ( %s )"%(str_regex,files)) #user_string = input('please enter a string to convert to regex: ') for file in files: print("Analyzing " + file) try: parser = PyEvtxParser(file) except: print("Issue analyzing " + file + "\nplease check if its not corrupted") continue try: for record in parser.records(): Channel = Channel_rex.findall(record['data']) if Channel[0].strip() == "Security": Security_path_list.append(file) break if Channel[0].strip() == "System": system_path_list.append(file) break if Channel[0].strip() == "Windows PowerShell": powershell_path_list.append(file) break if Channel[0].strip( ) == "Microsoft-Windows-PowerShell/Operational": powershellop_path_list.append(file) break if Channel[0].strip( ) == "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational": terminal_path_list.append(file) break if Channel[0].strip( ) == "Microsoft-Windows-TaskScheduler/Operational": scheduledtask_path_list.append(file) break if Channel[0].strip( ) == "Microsoft-Windows-Windows Defender/Operational": defender_path_list.append(file) break if Channel[0].strip() == "Microsoft-Windows-WinRM/Operational": winrm_path_list.append(file) break if Channel[0].strip( ) == "Microsoft-Windows-Sysmon/Operational": sysmon_path_list.append(file) break break except: print("issue assigning path") evtxdetect_auto()