EnScript Tutorial - Part II
This is the second part of the EnScript tutorial I started in September 4th, 2007. In the first part, we reviewed what the differences are between EnScripts, Filters, Conditions and Queries. In this part, we will begin to learn the EnScript programming language.
First, I want to review the various panes in EnCase and their respective names so when I refer to a particular tab or pane, you understand where I am referring. The EnCase program is generally divided into four panes or sub-windows.
The upper left pane (A) is referred to as the “tree pane”. The upper right pane (B) is referred to as the table pane. The lower left pane (C) is referred to as the view pane and the lower right pane (D) is the EnScripts/Filter pane. The table pane generally shows you all the “objects” or files & folders in a particular piece of evidence. The view pane is used to see the contents of a specific file or folder in various formats (text, hex, doc viewer).
Writing your first EnScript:
What programming tutorial would be complete without the traditional “hello world” programming example? In the EnScript pane (lower right), make sure the EnScript tab is active and then right-click on the root of the EnScript tree that is displayed. Select “New” and then name the EnScript “Hello World”. A new EnScript should be created with the name you provided. The table pane (upper right) should have automatically made the “code” tab active and you should see the minimum EnScript code generated automatically by EnCase.
As I mentioned in the first part of this tutorial, this is the minimum amount of code that must be present in order to be a valid EnScript. This EnScript will run, but will do absolutely nothing. Every EnScript must have a Main Class as well as a function called “Main”. Take a look at the opening curly braces and then the corresponding closing curly brace. The Main function is contained inside the Main class. In this EnScript, line two and three makeup the entire Main Function, while lines one and four are the beginning and ending portions of the Main class. For now, lets focus on the Main function. Absent a constructor, which I will explain later, the first line of the Main function is where this EnScript begins execution. Line two “void Main (CaseClass c)” is where it will start.
When this EnScript begins, the EnCase program is going to hand your EnScript one variable, named “c”. This variable is of the CaseClass type. This means that when you program begins, you will have a reference to the case that is open and active in EnCase at the time the EnScript was executed. CaseClass refers is a type definition describing what type of variable “c” is. With this one variable, you can obtain additional references or pointers to all the other information you may need in your EnScript. This is your starting point. Generally, program execution stops with the corresponding closing curly brace of the Main function (line three).
Here are some basic formatting rules when writing EnScripts:
• White space is generally ignored (the exception is when inside double quotes). So putting extra spaces between lines of code means nothing and it can help to logically separate various pieces of your code .
• To make comments in your code (for future reference or explanation) you can comment one line of code using two forward slashes “//”. Everything after that will turn blue and be ignored at run time. To comment blocks of code, you can use the ANSI C commenting style of a “/*” and then end your commenting block with the opposite “*/”. Anything in-between those markers will turn blue and will be ignored. Those markers can be on the same line, or then can be 100 lines apart and everything in-between will be ignored.
• Get in the habit of indenting your code inside functions, control structures or conditional statements. It makes your code easier to read and helps when debugging for errors
• When writing code inside EnCase, Control-Z is the hot key for undo. So if you delete something or change a piece of code, but then want to undo your change, Control-Z
• Control-F can be used to find specific text in your EnScript. When working with small EnScripts, finding text is not too difficult, but with larger ones, it helps to find variables, functions or specific text.
In the view pane, there is a tab named “Console”. This tab is an output window for when you want your EnScript to write out information. You generally do not want to write important information, but instead use it as a kind of debugging window to write out the status of your EnScript or to debug. The method of writing to this console tab is “Console.WriteLine()”. So to write “hello world” to the console, you would use :
“Console.WriteLine(“hello world”);
Notice that the text you want to appear in the console tab is inside of double quotes and that the line ends with a semi-colon. You will generally end every line with a semicolon. The exception is control statements and other opening statements (such as the first line of a class declaration or function). Your code should look something like this:
class MainClass {
void Main(CaseClass c) { // Execution starts here
Console.WriteLine(“hello world”); // Writes out to the console tab
} // Execution stops here
}
If you now click on the run button at the top of EnCase and then take a look at the console tab, you should see “hello world”. If you run it again, you will see “hello world” twice, once from the first time you ran it and once from the second time. To programmatically clear the console each time you run an EnScript, you could add “SystemClass::ClearConsole();”
class MainClass {
void Main(CaseClass c) { // Execution starts here
SystemClass::ClearConsole(); // Clear the console
Console.WriteLine(“hello world”); // Writes out to the console tab
} // Execution stops here
}
Recursion:
The definition of recursion in the programming world is a piece of code that calls itself. When the EnScript language initially came out, you had to use a recursion routine in order to process or list all the files/folders in the evidence. The current version of EnScript makes it much easier. In order to list or process (do something) all the files/folders in the evidence, you first need to create an object that contains a pointer to the top level of the evidence. Information that is listed in the table pane (upper right) windows are members of the EntryClass.
The previous script did not require a case to be open because it was simply writing to the console. The remainder of this tutorial will require you to have a case open and some evidence loaded.
Remember that EnCase hands you one variable when it starts an EnScript: “CaseClass c”. There is a built-in method that is part of the CaseClass that can give you the top-level entry in the evidence using the method “c.EntryRoot()”. You could use the code:
EntryClass entry = c.EntryRoot();
This would get the first (think of how a hierarchical directory works with a top level root directory) root entry in the evidence. You could then print the name of that object out using the Console.WriteLine() function:
class MainClass {
void Main(CaseClass c) {
SystemClass::ClearConsole();
EntryClass entry = c.EntryRoot().FirstChild();
Console.WriteLine (entry.Name());
}
}
This code would clear the console, then assign the first object (the first physical or logical device in the evidence)in the evidence to the EntryClass variable named “entry”. Then the next line will print the name of that object out in the console pane.
This is a good beginning, but this only gets us the first object in the evidence. What if we want to print out every file/folder name int he evidence? Luckily there is a internal function that makes this *very* simple. If you are familiar with Perl, you should be familiar with "forall" function that goes through a list or array, one object at a time. In EnCase it works the same way by going through every object in the evidence given the top-level object.
class MainClass {
void Main(CaseClass c) {
SystemClass::ClearConsole();
forall (EntryClass entry in c.EntryRoot()){
Console.WriteLine (entry.Name());
}
}
}
This code clears the console (line 3), then receives the top-level object in the case and assigns it to the variable named "entry". It then executes all the code after the forall statement until the closing curly brace (line 5), then goes back to the forall statement and gets the next object in the case and runs the code in between the curly braces again, until all the objects have been processed.
If you look in the console tab, you should see a complete listing of all the file/folder names from all of the loaded evidence. This technique is a foundational technique that will be used to list/process all files in a case.
In the next tutorial, we will begin to identify and process file/folders based on certain criteria.