Difference between revisions of "Python Sample Identification ETL"

From truxwiki.com
Jump to navigation Jump to search
Line 12: Line 12:
  
 
=Source Code=
 
=Source Code=
<syntaxhighlight lang="python">
+
<syntaxhighlight line lang="python">
 
import truxton
 
import truxton
  
Line 71: Line 71:
  
 
=Code Walkthrough=
 
=Code Walkthrough=
Lines 5-10 setup the ETL. The message queue name will be "acme", we are an early stage and want to receive <code>[[Type_Unknown]]</code> files.
+
The above code shows how to create an ETL process, register for a particular type of file, receive messages from a message queue, read the contents of a file in Truxton, and send a message to other ETL processes.
  
Line 12 starts the ETL logic and waits until a message arrives on the "acme" queue.
+
Lines 8-20 setup the ETL.
 +
The message queue name will be "acme", we are an early stage and want to receive <code>[[Type_Unknown]]</code> files.
  
Line 15 looks at the data in the message to see if it is even possible for the file we have received to be an Acme file.
+
Line 23 starts the ETL logic and waits until a message arrives on the "acme" queue.
 +
 
 +
Line 30 looks at the data in the message to see if it is even possible for the file we have received to be an Acme file.
 
The <code>signature</code> member contains the first four bytes of the file.
 
The <code>signature</code> member contains the first four bytes of the file.
 
Acme's format has a five byte signature which means we will have to read bytes from the file in order to perform a valid check.
 
Acme's format has a five byte signature which means we will have to read bytes from the file in order to perform a valid check.
Line 81: Line 84:
 
By using <code>signature</code> to check the first four bytes, we can avoid unnecessarily incurring a performance hit by reading from a file we know can't possibly be Acme.
 
By using <code>signature</code> to check the first four bytes, we can avoid unnecessarily incurring a performance hit by reading from a file we know can't possibly be Acme.
  
Line 16 gives you a [https://docs.python.org/3/library/io.html Python file object] so you can read from it.
+
Line 33 gives you a read-only [https://docs.python.org/3/library/io.html Python file object] so you can read from it.
  
Lines 20-21 read the fifth byte in the file and checks it for validity.
+
Lines 36-39 read the fifth byte in the file and checks it for validity.
  
Line 22 changes the file type to our identifier for Acme.
+
Line 41 changes the file type to our identifier for Acme.
 
We talked about [[Add A New File Type#Register a New Type | file type identifiers]] in a previous article.
 
We talked about [[Add A New File Type#Register a New Type | file type identifiers]] in a previous article.
  
Line 23-24 begins the process of sending this newly identified file to any ETL process that has registered for it.
+
Line 46-49 begins the process of sending this newly identified file to any ETL process that has registered for it.
The first step is to overwrite the <code>filetype</code>, which should contain <code>[[Type_Unknown]]</code> with the identifier for our file type.
+
The first step is to overwrite the <code>filetype</code>, which should contain <code>[[Type_Unknown]]</code>, with the identifier for our file type.
 
The last step is to call <code>[[TruxtonMessage#route() | route()]]</code> which tells Truxton to send this message to any ETLs that want it.
 
The last step is to call <code>[[TruxtonMessage#route() | route()]]</code> which tells Truxton to send this message to any ETLs that want it.
 +
 +
Line 52 completes the loop by getting another message from the acme message queue.

Revision as of 11:06, 25 June 2020

This sample shows the steps needed to implement a byte identifier ETL in Python.

Sample File Format

This sample will identify a fake file format we call Acme. Acme Corporation is a known supplier of nefarious devices and explosives. Their file format begins with a five byte magic value followed by eleven bytes in a data structure.

0000h: 88 77 66 55 00 11 22 33 44 55 66 77 88 99 AA BB
0010h: CC

Source Code

 1 import truxton
 2 
 3 # This is a File Identifier ETL
 4 # An Acme File begins with 0x88 0x77 0x66 0x55 0x00 and is at least 16 bytes long
 5 
 6 def main():
 7 
 8   etl = truxton.etl()
 9   etl.name = "Acme Identifier"
10   etl.description = "This ETL identifies files using the Acme method"
11   etl.queue = "acme"
12 
13   # Pick an early stage 
14   etl.stage = 2
15 
16   # We are an identifier, the Loader attempts to identify files first, if it can't it
17   # will give them a type of Type_Unknown
18   # We will grab those files and run them through Acme algorithms
19   # Tell Truxton that we want files of unknown format
20   etl.addtype(truxton.Type_Unknown)
21 
22   # Pause here until a message is received from our "acme" message queue
23   message = etl.getmessage()
24 
25   while message is not None:
26     # We can actually use the message to shortcut the identification process
27     # If our file type begins with a fixed series of bytes we can check the first
28     # four bytes of the contents without having to open the file and read from it.
29     # The "signature" member of the message contains the first four bytes of the file.
30     if message.depotlength >= 16 and message.signature == 0x88776655:
31       # There are enough bytes to attempt identification and the first four bytes match
32       # We will now open the file contents
33       file_in_truxton = message.file()
34 
35       # Since the first four bytes were already checked, let's read the fifth byte
36       file_in_truxton.seek(4)
37       next_byte = file_in_truxton.read(1)
38 
39       if next_byte[0] == 0:
40         # Yes! This is an Acme file. Change the database record
41         file_in_truxton.changetype(11000)
42 
43         # We changed the database, now we need to send this file to any ETL
44         # exploitation processes that registered to receive Acme files
45         # First, change the file type in the message
46         message.filetype = 11000
47 
48         # Now send this message to those ETL processes
49         message.route()
50 
51     # Pause here until we get another message from the "acme" message queue
52     message = etl.getmessage()
53 
54 if __name__ == "__main__":
55     main()

Code Walkthrough

The above code shows how to create an ETL process, register for a particular type of file, receive messages from a message queue, read the contents of a file in Truxton, and send a message to other ETL processes.

Lines 8-20 setup the ETL. The message queue name will be "acme", we are an early stage and want to receive Type_Unknown files.

Line 23 starts the ETL logic and waits until a message arrives on the "acme" queue.

Line 30 looks at the data in the message to see if it is even possible for the file we have received to be an Acme file. The signature member contains the first four bytes of the file. Acme's format has a five byte signature which means we will have to read bytes from the file in order to perform a valid check. Opening a file is rather expensive and we want identification to be as fast as possible. By using signature to check the first four bytes, we can avoid unnecessarily incurring a performance hit by reading from a file we know can't possibly be Acme.

Line 33 gives you a read-only Python file object so you can read from it.

Lines 36-39 read the fifth byte in the file and checks it for validity.

Line 41 changes the file type to our identifier for Acme. We talked about file type identifiers in a previous article.

Line 46-49 begins the process of sending this newly identified file to any ETL process that has registered for it. The first step is to overwrite the filetype, which should contain Type_Unknown, with the identifier for our file type. The last step is to call route() which tells Truxton to send this message to any ETLs that want it.

Line 52 completes the loop by getting another message from the acme message queue.