
Using the Script Editor
Synalyze It! Pro offers powerful functions for the analysis of binary files. However, there's so much more you
can do when you leverage the functionality with own scripts. Scripts can be stored either globally in the Application Support folder
(e. g. ~/Library/Containers/com.synalyze-it.SynalyzeItPro/Data/Library/Application Support/Synalyze It! Pro/Scripts) or inside grammar files.
There are five different types of scripts:
- Grammar - Automize the modification and usage of grammars
- File - Write scripts that modify binary files
- Generic - Scripts that do tasks not related to grammars or files
- Process results - Interpret the parsing results with a script
- Data type - Interpret the parsing results with a script
- Element - A single scriptable element of a structure in a grammar. These scripts are edited in the grammar editor directly.
Depending on whether a grammar or binary file window are active, grammar or file scripts can be run via the Script menu. The scripts that process parsing results can be chosen in the pop-up menu in the toolbar of a file once a grammar has been applied. Generic scripts are always available in the Script menu.
Grammar scripts
These scripts are intended to work on grammars, be it reading or writing. As an example you could dump the structures of a grammar to some custom format or build the structures from some external source.
File scripts
File scripts work on (binary) files, both reading and writing. The changes can be reversed using undo but better make sure you have a backup, just in case. A sample application for a file script is to apply a patch.
Generic scripts
Since these scripts can always be run when Synalyze It! Pro is active, they can be used for any task that's not related to certain grammars or binary files.
Process results scripts
Displaying the parsing results of binary files is nice but with a script you can process the results tree automatically.
Data type scripts
Data type scripts implement the parsing of custom data types. Additionally they can implement a method to translate changed values back to a file.
- parseByteRange(element, byteView, bitPos, bitLength, results)
This method parses some bits or bytes from a file and add the result to the results tree - fillByteRange(value, byteArray, bitPos, bitLength)
When a user edited a parsing result, this method is called to update the file accordingly.
Annotated Python Example
# DOS date/time structure # 24 16 8 0 # +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ # |Y|Y|Y|Y|Y|Y|Y|M| |M|M|M|D|D|D|D|D| |h|h|h|h|h|m|m|m| |m|m|m|s|s|s|s|s| # +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ # \___________/\________/\_________/ \________/\____________/\_________/ # year month day hour minute second from datetime import datetime def parseByteRange(element, byteView, bitPos, bitLength, results): """parseByteRange method""" # read four bytes into two integer variables highWord = byteView.readUnsignedInt(bitPos/8, 2, ENDIAN_BIG) lowWord = byteView.readUnsignedInt(bitPos/8+2, 2, ENDIAN_BIG) # extract date year = (highWord >> 9) + 1980 month = (highWord >> 5) & 0x1F day = highWord & 0x1F hour = lowWord >> 11 minute = (lowWord >> 5) & 0x3F second = (lowWord & 0x1F) * 2 # create datetime object dt = datetime(year, month, day, hour, minute, second) # create string value with formatted date value = Value() value.setString(dt.isoformat(' ')) # add result to results tree - 4 bytes, iteration 0 # the element needs to be passed here to enable the translation # of changed values back to the file results.addElement(element, 4, 0, value) return 4 def fillByteRange(value, byteArray, bitPos, bitLength): """fillByteRange method""" if (bitLength < 32): print "Not enough space for DOS Date/Time structure, 32 bits needed" # get the string after change by user dateTimeString = value.getString() # parse string dt = datetime.strptime(dateTimeString, "%Y-%m-%d %H:%M:%S") # create values to be written highWord = ((dt.year - 1980) << 9) + (dt.month << 5) + dt.day lowWord = (dt.hour << 11) + (dt.minute << 5) + (dt.second / 2) # update file with modified values byteArray.writeUnsignedInt(highWord, bitPos/8, 2, ENDIAN_BIG) byteArray.writeUnsignedInt(lowWord, bitPos/8+2, 2, ENDIAN_BIG)