BHIS Wild West Hackin Fest Toolshed: iLEAPP

During WWHF: Deadwood 2021, I gave a presentation (shown above) on the popular tool iLEAPP: iOS Logs, Events, And Plists Parser created by Alexis Brignoni and Yogesh Khatri. You can watch the video on YouTube.

You can find my working code here:

I wanted to expand on a few things talked about in the presentation and some additional information. First on slide 16, I list the following items:

  • Artifact migration to new format
    • Note: Some artifacts such as the Messaging one needs a rework to work properly.
  • Optimizations for calling artifacts
  • Documenting Python code.
  • Python package support

In additional, I am looking at the following (not in the presentation):

  • threading support.
  • Plugin system + split packages
GeoD Application Comparison

New Artifact Format

As noted in the presentation, I reworked the whole artifact systems creating a simplifed process.

First, the removal of reporting, timeline, and directly interacting with artifacts. Reporting is handled automatically by the AbstractArtifact class which all artifacts are required to extend from. I found that nearly every artifact basically performed the same reporting function:

  1. Creat a report object
  2. Add basically information to the report object
  3. Add report headers
  4. Write out report
  5. Close report

(1) The new standard automatically attaching a report object to each artifact which should not need to be modified. (2, 3) Metadata information is added to the __post__init() function which is automatically passed to the report object which includes customizing the report headers. (4, 5) Reports are generated after all artifacts are processed.

Timeline functions are missing still but will probably be attached to each artifact as an object which can accept the timeline information automatically.

Lastly, I realized that most artifacts need between 1 to 5 files which for iOS are plist or sqlite format files. The artifacts do the following:

  1. The "@Search()" function is run which preprocessing the artifact finding each of the files required by artifact
  2. If the list of files is less then 10, then open each file and return the file handles. This can be disabled setting file_names_only=true inside the @Search() function.
  • Returns file handles: @Search('**/')
  • Returns file names only: @Search('**/', files_names_only=True)

In either case, self.found for each artifact holds either a list of file handles, a file list, or a single file handle/file name. Using this option provides a way to open the files yourself incase there is some special way to interact with them.

experimental Also, in the case of SQLite DBs, if the database is < 20 MB, it preloads the database in memory. This does NOT affect how the database is accessed. This may be removed at a later date.


One of the challenges is trying to streamline the processing of each artifact. The above format does lean in that direction where each artifacts is its own object which can be modified and used.

I think here can be used some type of Plugin Manager to control the artifacts better then what I have setup at the moment. This would provide a complete life cycle for each artifact.

Next, I am probably going to look at threading the application to help speed up the processing of artifacts and generally help the overall design. Python already has support for threading. I just need to finish the application re-write then add threading.

Read the Docs search Demo


The above graphic is from the Read the Docs project (See: 1). Documenting is code can be hard but needs to be completed. My original goal with iLEAPP was to do code documentation through Read the Docs; however, I found the program was not setup properly to run sphinx and other tools on the code base to generate the right documentation.

I started with the structure in the docs on my fork. I need to work on documenting the code then swing around and continue to completing this. I my goal is to add more information for project and child projects moving forward.


As noted in the slides, there are several different versions of the base application. The end goal is to create a "xLEAPP" base framework which can be expanded using a plugin framework. The Python Packing User Guide explains three methods (Creating and Discovering Plugins):

  1. Using naming convention.
  2. Using namespace packages.
  3. Using package metadata.

I am considering option #3 for this project. I think this is the easiest direction to take from my point-of-view.

In the end state, there will be the following packages (not final):

  • xleapp: framework + basic application
  • xleapp-ios: support for iOS + MIT licenced artifacts
  • xleapp-ios-non-free: support for non-MIT licenced artifacts
  • xleapp-android: support for Android + MIT licenced artifacts
  • xleapp-android-non-free: support for non-MIT licenced artifacts
  • xleapp-returns: support for Returns + MIT licenced artifacts
  • xleapp-returns-non-free: support for non-MIT licenced artifacts
  • xleapp-vehicle: support for vehicles + MIT licenced artifacts
  • xleapp-vehicle-non-free: support for non-MIT licenced artifacts
  • xleapp-chrome: support for chrome + MIT licenced artifacts
  • xleapp-chrome-non-free: support for non-MIT licenced artifacts

This will even provide a method to extend the software to any other type of hardware/system such as IoT, servers, or others. The reason for the artifact split is due to licenses differences between MIT and other licenses. iLEAPP is distributed with Autopsy and some licences do not permit distributing with this application due to Autopsy's licensing.

Also, the whole suite of packages will be installable directlly through pip and possibly in Python's package directory.

Jesse Spangenberger

Jesse Spangenberger