Matplotlib is an extensive library, and the best way to learn
more about it is through this next demo.
We'll first install matplotlib and dependencies.
Then we'll create a simple bar chart function which will
allow us to aggregate and plot events.
The end goal of this demo is to identify suspicious file share
activity related to a ransomware infection.
Before we start building visualizations, first we need to
install matplotlib, and we'll do this using pip.
Next, we need to import it into our script.
I will create a new function called plotEvents, which receives one parameter.
This should be in the form of a dictionary. Plotting a bar
chart is quite simple by using plt.bar.
The first argument represents the range of elements for the X axis.
The next parameter is the list of the actual values that should be
plotted on the Y axis. And finally, the vertical bar for each element
on the X axis should be aligned centrally. To actually display the
chart, we must use plt.show.
Now it's time to test this.
I will open up a new terminal, start Python, and import the new function.
I will import the sample data, as I have prepared a
sample of events that we can plot.
This contains a dictionary with three elements, and for each of the
three days there is a number of events that occurred during that
day that we want to plot. So now we can use our plotEvents
function, and this returns an error.
This is because there is no graphical user interface engine to
actually display the chart. To fix this,
I will install python3‑tk.
This is the Python tkinter GUI interface module that will be used
behind the scenes to actually display the diagrams.
Next, I will re‑import everything and run the function again.
At first glance, we notice the three bars corresponding to the three values,
but we don't actually see the actual keys of the dictionary.
Let's try to fix this. With plt.xticks, this
defines the tick marks on the X axis.
The first element in the range is the actual tick marks
followed by the list of the event keys.
Now let's try to run this again, and we can notice the days
as well. Now that we have this function,
we can use it to display analyzed log data.
The next goal is to implement the function that calculates how many
file‑related operations are done by each user based on the SMB log.
So I will create a new function called plotSmbActivity, which takes as an
argument the path to the log_file. First I will open the log_file.
Second,
I'll create a Counter dictionary for each user machine
hostname. Then iterate through all of the log entries in
the file and parse each entry, saving the result in the log_data variable.
Finally, I can update the Counter dictionary with the
extracted value for the client_hostname field. Rather than
returning the Counter object,
I will call the plot function and provide the users counter as an argument.
Let's test this out and see how it works. Wow, this is interesting.
From this graph, we notice that win7‑victim machine has a
substantial number of file‑related events generated. While this
provides us some value, it would be really good to also know the
timeframe of these events.
So the next goal is to replicate this,
but for the timestamp field. I will create another Counter object and name it
events. Then extract the timestamp based only on the hours and minutes and
convert this to a string so it can be used as a key, and update the events
Counter with the new timestamp value.
The plot function call needs to be chained so that it plots the
values of the events Counter rather than the users.
Now let's test this out and see how it works. Wow,
this is even more interesting.
Let's make this a bit wider so we can see the timestamp much more clearly.
We notice there is a spike in events at around 8:19 minutes.
While this is very interesting,
we can fine‑tune how the events are grouped by timestamp.
Next, I will create a function that divides the 60 minutes of an hour into
a user‑specified amount of intervals of equal duration.
This function will take in a timestamp and the number of intervals noted
as intervals. One interval will be the integer result of 60 minutes
divided by the number of intervals specified.
Then I will extract the hour and the minute from the timestamp and I
will create a new variable called base_minutes, and this will be the
result of the minutes divided by the interval value, and the integer
value of this multiplied by the interval value again, and return a
string that can be used as a key.
I know that this might seem complex, but let's see this in
action so we can see how it actually works.
I will open a terminal.
I will import date and time as dt, and save the
current date and time into a variable.
The date is not important, only the time. The current time is 13 and 30 minutes.
Let's run this through the function. We specify the datetime
object and we want 4 intervals. Since the minute is 30, this
already marks the start of the third interval.
The first ones start from minute 0 and the second start from minute 15.
Let's use the replace function and alter the minute to 31.
And we notice we get the same base_timestamp. How about 44?
Still we get the same base_timestamp. When we modify to 45, this
is the start of the fourth interval.
Now let's implement this into our code and see how it works. In the
plotSmbActivity function, we only need to modify one line.
Can you guess which it is?
It's the timestamp assignment. Now that we have modified this, let's test it.
I'll open the terminal, run Python, import all required
functions, and call the plot function.
Wow,
this looks much nicer, but now you may wonder, what if we want to view
two diagrams together in order to get more insight.
Well, matplotlib is an extensive toolkit, which certainly allows us to do this.
I will use subplot to create two rows and one
column, and focus on the first row.
This should plot the events. Then use subplot to focus on the
second row, and use this to plot the user activity.
Now that the function takes two arguments, we need to modify
this in the plotSmbActivity function as well.
Finally, we can test this. Nice.