Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Dump Json and jq Implementation #91

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
106 changes: 71 additions & 35 deletions scripts/evtx_dump_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,16 @@
# - xmltodict >= 0.12.0
import os
import json

import sys
import xmltodict
import argparse

import Evtx.Evtx as evtx


def main():
import argparse

parser = argparse.ArgumentParser(description="Dump a binary EVTX file into XML.")
parser.add_argument("evtx", type=str, action="store", help="Path to the Windows EVTX event log file")
parser.add_argument("-o", "--output", type=str, action="store", help="Path of output JSON file")
args = parser.parse_args()
def main(evtx_file,output):

with evtx.Evtx(args.evtx) as log:
with evtx.Evtx(evtx_file) as log:

# Instantiate the final json object
final_json = []
Expand All @@ -34,32 +29,66 @@ def main():
# Convert the record to a dictionary for ease of parsing
data_dict = xmltodict.parse(record.xml())

# Loop through each key,value pair of the System section of the evtx logs and extract the EventRecordID
for event_system_key, event_system_value in data_dict["Event"]["System"].items():
if event_system_key == "EventRecordID":
json_subline = {}
firstline = {event_system_key: event_system_value}
# Create first line of System Data based on the EventRecordID
json_subline = {}
json_subline.update({'EventRecordID':data_dict['Event']['System']['EventRecordID']})

# Add information to the JSON object for this specific log
json_subline.update(firstline) # add the event ID to JSON subline
# Loop through each key,value pair of the System section of the evtx logs
for event_system_key, event_system_value in data_dict['Event']['System'].items():

# Loop through each key, value pair of the EventData section of the evtx logs
for event_data_key, event_data_value in data_dict["Event"]["EventData"].items():
for values in event_data_value:
if not (event_system_key=="EventRecordID") or not (event_system_key=="Execution"):

# For nested dictionaries, loop through each and extract key information
if isinstance(event_system_value,dict):
for event_system_subkey,event_system_subvalue in event_system_value.items():

# Loop through each subvalue within the EvenData section to extract necessary information
for event_data_subkey, event_data_subvalue in values.items():
if event_data_subkey == "@Name":
data_name = event_data_subvalue
else:
data_value = event_data_subvalue
if event_system_key == "EventID" or event_system_key == "TimeCreated":
json_subline.update({event_system_key: event_system_subvalue})
if event_system_key == "Security":
json_subline.update({event_system_subkey[1:]: event_system_subvalue})

# Add information to the JSON object for this specific log
json_subline.update({data_name: data_value})
else:
# Add information to the JSON object for this specific log
json_subline.update({event_system_key: event_system_value})

# Print the JSON object for the specific log if not requested to output to file
if not args.output:
print(json_subline)
# Loop through each key, value pair of the EventData section of the evtx logs
if "EventData" in data_dict['Event'].keys() and data_dict['Event']['EventData'] != None:
for event_data_key, event_data_value in data_dict['Event']['EventData'].items():

# Check to see if the EventData Data contains a list
if isinstance(event_data_value,list) and event_data_key!="@Name":
for values in event_data_value:

# Loop through each subvalue within the EvenData section to extract necessary information
for event_data_subkey,event_data_subvalue in values.items():
if event_data_subkey == "@Name":
data_name = event_data_subvalue
else:
data_value = event_data_subvalue

# Add information to the JSON object for this specific log
json_subline.update({data_name: data_value})

# Check to see if EventData contains a dictionary
if isinstance(event_data_value,dict) and event_data_key!="@Name":
for event_data_subkey,event_data_subvalue in event_data_value.items():
if event_data_subkey == "@Name":
data_name = event_data_subvalue
else:
data_value = event_data_subvalue

# Add information to the JSON object for this specific log
json_subline.update({data_name: data_value})

# Check to see if EventData contains a string
if isinstance(event_data_value,str) and event_data_key!="@Name":
beautify_event_data_value=event_data_value.replace("<string>","").replace("\n"," ").replace("</string>","")
json_subline.update({event_data_key: beautify_event_data_value})

# Loop through each key, value pair in UserData section, if present
if "UserData" in data_dict["Event"].keys():
for user_data_key,user_data_value in data_dict['Event']['UserData'].items():
json_subline.update({user_data_key: user_data_value})

# Add specific log JSON object to the final JSON object
if not final_json:
Expand All @@ -68,7 +97,7 @@ def main():
final_json.append(json_subline)

# If output is desired
if args.output:
if output:

# Output the JSON data
if os.path.splitext(args.output)[1] == ".json":
Expand All @@ -77,9 +106,16 @@ def main():
json_file = args.output + ".json"

# Write to JSON file
with open(json_file, "w") as outfile:
json.dump(final_json, outfile)

with open(json_file,"w") as outfile:
json.dump(final_json,outfile)
else:
print(json.dumps(final_json))

if __name__ == "__main__":
main()

parser = argparse.ArgumentParser(description="Dump a binary EVTX file into JSON.")
parser.add_argument("evtx",type=str,action="store",help="Path to the Windows EVTX event log file")
parser.add_argument("-o","--output",type=str, action="store",help="Path of output JSON file")
args = parser.parse_args()

main(args.evtx,args.output)
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
# see the following for a discussion:
# https://www.revsys.com/tidbits/pytest-fixtures-are-magic/
# https://lobste.rs/s/j8xgym/pytest_fixtures_are_magic
from fixtures import * # noqa: F403 [unable to detect undefined names]
from fixtures import * # noqa: F403 [unable to detect undefined names]
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ def data_path():
"""
cd = os.path.dirname(__file__)
datadir = os.path.join(cd, "data")
return datadir
return datadir
Loading