Book Image

Learning Python for Forensics

By : Chapin Bryce
Book Image

Learning Python for Forensics

By: Chapin Bryce

Overview of this book

This book will illustrate how and why you should learn Python to strengthen your analysis skills and efficiency as you creatively solve real-world problems through instruction-based tutorials. The tutorials use an interactive design, giving you experience of the development process so you gain a better understanding of what it means to be a forensic developer. Each chapter walks you through a forensic artifact and one or more methods to analyze the evidence. It also provides reasons why one method may be advantageous over another. We cover common digital forensics and incident response scenarios, with scripts that can be used to tackle case work in the field. Using built-in and community-sourced libraries, you will improve your problem solving skills with the addition of the Python scripting language. In addition, we provide resources for further exploration of each script so you can understand what further purposes Python can serve. With this knowledge, you can rapidly develop and deploy solutions to identify critical information and fine-tune your skill set as an examiner.
Table of Contents (24 chapters)
Learning Python for Forensics
Credits
About the Authors
Acknowledgments
About the Reviewer
www.PacktPub.com
Preface
Index

Understanding scripting flow logic


Flow control logic allows us to create dynamic logic by specifying different routes of program execution based upon a series of circumstances. In any script worth its salt, some manner of flow control needs to be introduced. For example, flow logic would be required to create a dynamic script that returns different results based on options selected by the user. Unaccounted for possibilities are a common cause for error, and are another reason to test your code thoroughly. Creating dynamic code is important in Forensics as we sometimes encounter fragments of data, such as within slack or unallocated space, whose incomplete nature may interfere or cause errors in our scripts. In Python, there are two basic sets of flow logic: conditionals and loops.

Flow operators are frequently accompanied with flow logic. These operators can be strung together to create more complicated logic. The table below represents a "truth table" and illustrates the value of various flow operators based on the "A" or "B" variable Boolean state.

A

B

A and B

A or B

not A

not B

F

F

F

F

T

T

T

F

F

T

F

T

F

T

F

T

T

F

T

T

T

T

F

F

The logical AND and OR operators are the third and fourth columns in the table. Both A and B must be True for the AND operator to return True. Only one of the variables need to be True for the OR operator to be True. The not operator simply switches the Boolean value of the variable to its opposite (for example, True becomes False and vice versa).

Mastering conditionals and loops will take our scripts to another level. At its core, flow logic relies on only two values, True or False. As noted earlier, in Python these are represented by the Boolean True and False data types.

Conditionals

When a script hits a conditional, it's much like standing at a fork in the road. Depending on some factor, say a more promising horizon, you may decide to go East over West. Computer logic is less arbitrary: if something is true the script proceeds one way, if it is false then it will go another. These junctions are critical, if the program decides to go off the path we've developed for it, we'll be in serious trouble. There are three statements used to form a conditional block: if, elif, and else.

The conditional block refers to the conditional statements, their flow logic, and code. A conditional block starts with an if statement followed by flow logic, a colon, and indented line(s) of code. If the flow logic evaluates to True, then the indented code below the if statement will be executed. If it does not evaluate to True the Python Virtual Machine (PVM) will skip those lines of code and go to the next line on the same level of indentation as the if statement. This is usually a corresponding elif (else-if) or else statement.

Indentation is very important in Python. It is used to demarcate code to be executed within a conditional statement or loop. A standard of 4 spaces for indentation is used in this book, though you may encounter code that uses a 2 space indentation or uses tab characters. While all three of these practices are allowed in Python, 4 spaces are preferred and easier to read.

In a conditional block, once one of the statements evaluates to True, the code is executed and the PVM exits the block without evaluating the other statements. Please review Appendix B, Python Technical Details for a description on the Python Virtual Machine.

# Conditional Block Pseudocode
if [logic]:
    # Line(s) of indented code to execute if logic evaluates to True.
elif [logic]:
    # Line(s) of indented code to execute if the 'if' statement is false and this logic is True.
else:
    # Line(s) of code to catch all other possibilities if the if and elif(s) statements are all False.

Until we define functions, we will stick to simple if statement examples.

>>> a = 5
>>> b = 22
>>>
>>> a > 0
True
>>> a > b
False
>>> if a > 0:
...     print str(a) + ' is greater than zero!'
...
5 is greater than zero!
>>> if a > b:
...     print str(a) + ' beats ' + str(b)
...
>>>

Notice how when the flow logic evaluates to True then the code indented below the if statement is executed. When it evaluates to False the code is skipped. Typically, when the if statement is False you will have a secondary statement, such as an elif or else to catch other possibilities, such as when "a" is less than or equal to "b". However, it is important to note that we can just use an if statement without any elif or else statements.

The difference between if and elif is subtle. We can only functionally notice a difference when we use multiple if statements. The elif statement allows for a second condition to be evaluated in the case that the first isn't successful. A second if statement will be evaluated regardless of the outcome of the first if statement.

The else statement does not require any flow logic and can be treated as a catch-all case for any remaining or unaccounted for case. This does not mean, however, errors will not occur when the code in the else statement is executed. Do not rely on else statements to handle errors.

Conditional statements can be made more comprehensive by using the logical and or or operators. These allow for more complex logic in a single conditional statement.

>>> a = 5
>>> b = 22
>>> 
>>> if a > 4 and a < b:
...     print 'Both statements must be true to print this'
...
Both statements must be true to print this
>>> if a > 10 or a < b:
...     print 'One of these statements must be true to print this'
...
One of these statements must be true to print this

The following table can be helpful to understand how common operators work.

Operator

Description

Example

Evaluation

<, >

less than, greater than

8 < 3

False

<=, >=

less than equal or to, greater than or equal to

5 <= 5

True

==, !=

equal to, not equal to

2 != 3

True

not

switches Boolean value

not True

False

Loops

Loops provide another method of flow control and are suited to perform iterative tasks. A loop will repeat inclusive code until the provided condition is no longer True or an exit signal is provided. There are two kinds of loops: for and while. For most iterative tasks a for loop will be the best option to use.

For

For loops are the most common and, in most cases, the preferred method to perform a task over and over again. Imagine a factory line, for each object on the conveyor belt a for loop could be used to perform some task on it, such as placing a label on the object. In this manner, multiple for loops can come together in the form of an assembly line, processing each object, until they are ready to be presented to the user.

Much like the rest of Python, the for loop is very simple syntactically and yet powerful. In some languages a for loop needs to be initialized, have a counter of sorts, and a termination case. Python's for loop is much more dynamic and handles these tasks on its own. These loops contain indented code that is executed line by line. If the object being iterated over still has elements (for example, more items to process) at the end of the indented block, the PVM will position itself at the beginning of the loop and repeat the code again.

The for loop syntax will specify the object to iterate over and what to call each of the elements within the object. Note, the object must be iterable. For example, strings and lists are iterable, but an integer is not. In the example below, we can see how a for loop treats strings and lists and helps us iterate over each element in iterable objects.

>>> for character in 'Python':
...     print character
...
P
y
t
h
o
n
>>> cars = ['Volkswagon', 'Audi', 'BMW']
>>> for car in cars:
...     print car
...
Volkswagon
Audi
BMW

There are additional, more advanced, ways to call a for loop. The enumerate() function can be used to start an index. This comes in handy when you need to keep track of the index of the current object. Indexes are incremented at the beginning of the loop. The first object has an index of 0, the second has an index of 1, and so on. The range() and xrange() functions can execute a loop a certain number of times and provide an index. The difference between range() and xrange() is somewhat subtle, though the xrange() function is quicker and more memory efficient than the range function.

>>> numbers = [5, 25, 35]
>>> for i, x in enumerate(numbers):
...     print 'Item', i, 'from the list is:', x
... 
Item 0 from the list is: 5
Item 1 from the list is: 25
Item 2 from the list is: 35
>>> for x in xrange(0, 100):  # prints 0 to 100 (not shown below in an effort to save trees)
...     print x

While

While loops are not encountered as frequently in Python. A while loop executes as long as a statement is true. The simplest while loop would be a while True statement. This kind of loop would execute forever as the Boolean object True is always True and so the indented code would continually execute.

If you are not careful, you can inadvertently create an infinite loop, which will wreak havoc on your script's intended functionality. It is imperative to utilize conditionals to cover all your bases such as if, elif, and else statements. If you fail to do so, your script can enter an unaccounted situation and crash. This is not to say that while loops are not worth using. They are quite powerful and have their own place in Python.

>>> guess = 0
>>> answer = 42
>>> while True:
...     if guess == answer:
...             print 'You\'ve found the answer to this loop: ' + str(answer) + '.'
...             break
...     else:
...             print guess, 'is not the answer.'
...             guess += 1

The break, continue, and pass statements are used in conjunction with for and while loops to create more dynamic loops. The break escapes from the current loop, while the continue statement causes the PVM to begin executing code at the beginning of the loop, skipping any indented code after the continue. The pass statement literally does nothing and acts as a placeholder. If you're feeling brave or bored, or worse, both, remove the break statement from the previous example and note what happens.