Working with EnScript and .NET/C#

Ken Mizota

The ability to manipulate and interpret data structures within evidence has long been a strength of EnCase. EnScript—a core EnCase technology—has enabled investigators and incident responders to be efficient, automating the most sophisticated or mind-numbingly rote techniques. For instance, take Simon Key's (@SimonDCKey) recent post on the OS X Quick Look Thumbnail Cache: the ability to mine, extract and work with critical data for your case is available now. This app, courtesy of Guidance Software Training, just happens to be free, enabling the DFIR community to take advantage. If you need to keep pace with the perpetually accelerating gap between data and the investigator’s ability to understand that data, having extensible, flexible tools in your kit is not optional.

In this post, we'll talk about some of the benefits of using EnScript in your investigations while leveraging your expertise and existing code in C#/.NET. If you missed Hector Carmona's CEIC 2014 lab session "Extending EnCase: Beyond EnScript," please read on!

Why go beyond?

First, let's talk about some of the reasons why EnScript is an excellent addition to the kit for many investigators:

  • EnScript is built for investigations. EnScript automates and simplifies many activities in forensics, like iterating through entries, and filtering and searching through data. One would be hard pressed to build a set of libraries as robust as the EnScript API.
  • EnScript enables unparalleled direct access to forensic data and all of the derived facts and data within your case (e.g. tags, bookmarks, artifacts, records, etc.). There's no other API that allows comprehensive, yet structured access to raw forensic data and associated facts.
Of course, we can also point out some circumstances that present obstacles to the use of EnScript:

  • You would like to leverage the logic and implementation of an existing library/source code that is not written in EnScript.
  • You are unfamiliar with EnScript and don't have time to invest in understanding the API. The EnCase IDE is no substitute for Visual Studio.
We get it. Talented investigators are a popular bunch. They're usually busy doing investigations. So, let's get on with it and show how we can address these cons with the latest updates to EnCase.

EnCase and C#

In EnCase 7.09, the EnScript API was enhanced to enable C# developers to easily embed .NET assemblies in EnScript code, instantiate any .NET data type within EnScript, and stream binary data to C# from EnScript and from EnScript to C#.

That last paragraph is a mouthful, so I'll pause for a moment to let that marinate…

You can implement logic in C# and leverage that technology in EnScript. This is likely best explained with a set of basic examples. Here is a link to download code samples referenced below.


For illustration, SampleClass.cs is provided to define a class in C#. We're going to use SampleClass as the basis for a .NET assembly, which we will embed and interact with via EnScript. SampleClass does a few simple things:

It exposes few members of type integer, string, date/time and GUID:
    public int IntProperty { get; set; }
    public string StringProperty { get; set; }
    public DateTime DateTimeProperty { get; set; }
    public Guid GUIDProperty { get; set; }
Implements a method to output the value of the members.
    void Print(Stream outStream) 
      if (outStream.CanWrite)
        var outWriter = new StreamWriter(outStream);
        outWriter.WriteLine("Sample Class");
        outWriter.WriteLine("  IntProperty: {0}", IntProperty);
        outWriter.WriteLine("  StringProperty: {0}", StringProperty);
        outWriter.WriteLine("  DateTimeProperty: {0}", DateTimeProperty);
        outWriter.WriteLine("  GUIDProperty: {0}", GUIDProperty);

...and takes a data stream and outputs the even lines.
public Stream GetEvenLines(Stream input)
  var output = new MemoryStream();
  var reader = new StreamReader(input);
  var writer = new StreamWriter(output);
  int count = 0;
  while (!reader.EndOfStream)
    var line = reader.ReadLine();
    if (++count % 2 == 0)
  return output;

C# in EnScript - Working with Files

Once SampleClass has been compiled into a DLL (e.g. CEIC.dll), we are basically ready to use it in EnScript. We just need to embed the .NET assembly in an EnScript:
assembly embed "Include\CEIC.dll"
The "embed" keyword allows us to embed the DLL itself in an EnPack, so the DLL doesn't have to be distributed independent of the EnPack code.

A file in EnScript can be wrapped in a DotNetStreamClass, and passed to the embedded DLL to be worked with natively in C#. Here we see a local file being opened in EnScript, and wrapped as a DotNetStreamClass.
    LocalFileClass file();
    if (file.Open(SystemClass::ScriptPath(), FileClass::TEXTCRLF)) {
      CEIC::SampleClass sample();
      System::IO::Stream inputStream  = new DotNetStreamClass(file);
This stream may be passed into .NET… here we pass a file to our SampleClass to retrieve the even numbered lines.
System::IO::Stream outputStream = sample.GetEvenLines(inputStream);

The OutputStream must also be wrapped in a DotNetFileClass:
FileClass outputFile = new DotNetFileClass(outputStream);

The function PrintFile simply outputs the contents of a file to the Console.
PrintFile("Original", file);
PrintFile("Even Lines", outputFile);
It should be noted, when the .NET stream is no longer needed it should be explicitly disposed. If you don't explicitly do this, memory leaks may occur.

C# in EnScript - Working with Plain Old Data Types

Now, let's say I don't want to use files to pass between EnScript and C#. Perhaps I'd like to access plain old data types, a.k.a, PODS, directly within EnScript.

After instantiating SampleClass, I can set properties in the .NET class . In this example, we simply set a few variables and output to console:
 CEIC::SampleClass sample();
 // POD Types
 sample.SetStringProperty("This is a string that is being sent to .NET");
 int    intVal    = sample.IntProperty();
 String stringVal = sample.StringProperty();
 Console.WriteLine("POD Values");
 Console.WriteLine("  IntVal    = {0}", intVal);
 Console.WriteLine("  StringVal = {0}", stringVal);

We can also use standard .NET classes (like DateTime and GUID) within EnScript. The sample below shows the assignment operation for two members, and retrieval of the stored data, written to the console:
 System::DateTime dateTime = System::DateTime::Now();
 System::Guid guid = System::Guid::NewGuid();
 Console.WriteLine("  IntProperty      = {0}", sample.IntProperty());
 Console.WriteLine("  StringProperty   = {0}", sample.StringProperty());
 Console.WriteLine("  DateTimeProperty = {0}", sample.DateTimeProperty().ToString());
 Console.WriteLine("  GUIDProperty     = {0}", sample.GUIDProperty().ToString());

Maximum Benefits, Minimum Investment

With this capability, you can invest your time agonizing over how to make your code do what it does best, and less time implementing your algorithm in EnScript. Armed with the concepts illustrated in the examples above, once forensic data is made accessible programmatically to C#, you can not only leverage your own algorithms and libraries built in C#, but also all of the capabilities that C#/.NET provides out of the box. This integration capability enables more code to be re-used, and perhaps most importantly, development effort on your part may be reduced or minimized.

Want to be a Developer?

Before closing, I’d like to point out some resources available if you would like to learn more:

Join the EnCase App Central Developer Network: Get a free 1-year EnCase Forensic SDK and developer support.

Take an EnScript course. There's literally nothing that compares to the hands-on Guidance Software Training course, and I urge you to attend if at all possible. Better yet, sign up for an Annual Training Passport and take a few other classes too. You'll be glad you did.

Have ideas for C# and EnScript projects? Would you have a use for other API level integrations to better leverage your existing code? Post your comments below or tweet us @EnCase or @kenm_encase.

No comments :

Post a Comment