To apply a sequence of transformations, Tigress is invoked like this, where TRANSFORMATION is the name of the obfuscation and IDENTSPEC is one or more functions to which it should be applied:

   tigress --out=OUTFILE.c \
              --Transform=TRANSFORMATION --Functions=IDENTSPEC [EXTRA_OPTS...] \
              --Transform=TRANSFORMATION --Functions=IDENTSPEC [EXTRA_OPTS...] \
                         ....
              --Transform=TRANSFORMATION --Functions=IDENTSPEC [EXTRA_OPTS...] \
           FILE.c
 

A typical invocation looks like this:

    > tigress \
         --Transform=InitOpaque   --Functions=main \                   # First transformation
         --Transform=UpdateOpaque --Functions=f \                      # Second transformation
         --Transform=AddOpaque    --Functions=f --AddOpaqueCount=2 \   # Third transformation
         --out=x.c \                                                   # Output file
         simple1.c                                                     # Input file

Some useful Tigress options:

tigress --help : Show this message
tigress --install : Show how to install Tigress
tigress --options : Show complete list of options to tigress
tigress --license : Display the tigress license
tigress --bibtex : See how to cite us
tigress --apple : How to get past some Darwin issues
tigress --version : Show the current Tigress version
Tigress supports the C99 language. Depending on your compiler, you may have to add a switch (such as -std=c99 for gcc) to indicate this.  

Multiple Input Files

Note that Tigress accepts exactly one C file as input. If your project has multiple files you must first merge them together into one:

$TIGRESS_HOME/cilly --merge -c x1.c -o x1.o
$TIGRESS_HOME/cilly --merge -c x2.c -o x2.o
$TIGRESS_HOME/cilly --merge -c x3.c -o x4.o
$TIGRESS_HOME/cilly --merge  --keepmerged x1.o x2.o x3.o -o merged --mergedout=merged.c 

The first three commands are replacements, essentially, for compiling each of the source file. If, for example, you need to pass different options when compiling the different files, you'd do it here. The merged source file merged.c can subsequently be passed to Tigress for transformation. See CIL's documentation to learn more about the merging process.

Note that options passed through to the compiler have one dash ("-"), while options passed to Tigress start with two ("--").

 

Top-Level Options

OptionArgumentsDescription
--Environment string A string that describes the architecture, operating system, and compiler being used. We currently recognize the following strings: x86_64:Linux:Gcc:4.6, x86_64:Darwin:Clang:5.1, armv7:Linux:Gcc:4.6, armv8:Linux:Gcc:4.6. This is mostly necessary because Clang does not support some features (most notably asm goto) that Gcc does. In the future we will use this to provide better support for 32-bit binaries. Default=0.
--out file.c The file to write to.
--Seed INTSPEC The randomization seed. --Seed=0 makes Tigress generate its own seed.
--FilePrefix AUTO, NONE, string Use this if you intend to run tigress multiple times on each file to avoid name clashes. Only set this option once. Default=NONE.
  • AUTO = generate a prefix to add to all symbols
  • NONE = don't add any prefix
  • string = add this prefix
--Verbosity int Tigress' chattiness level. --Verbosity=0 makes Tigress quiet. --Verbosity=1 prints each transformation as it is being applied. Higher levels also print out all the versions of functions and variables being constructed. Default=0.
--Skip BOOLSPEC Skip a particular transformation. Typically, use like this to skip transformation T1: tigress --Transform=T1 --Skip=true ... --Transform=T2 --Skip=false .... This can be useful when you have a long sequence of transformations and want to experiment with turning certain ones on or off. Default=false.
--Input INPUTSPEC Specify invariants over the command line arguments, such the range of integer values a particular argument may take, the range of lengths of an argument, or the string value of an argument. These are used by the input opaque predicate, which is created by --InitOpaque=input. Default=0.
 

Selecting Transformations

Each transformation is specified, at a minimum, by the --Transform option that selects the type of transformation and the --Functions option that selects the function(s) to which it should be applied.

 

Selecting Targets

To avoid name clashes and to allow you to specify the results of a transformation, prefixes can be added to all new identifiers. For example, after a Split transformation, you may want to perform additional transformations to the newly formed functions, and thus need to know their new names. You can use the --Prefix for this. Also, if you intend to run Tigress multiple times on the same file (rather than applying all transformations in one run), you need to make sure that new names don't clash with old ones. Use --FilePrefix for this.

OptionArgumentsDescription
--Prefix string Add this prefix to each new generated symbol. This is in addition to the --filePrefix. Default is "_number_" where number is the order number of the transformation given on the command line. You can set this for every transformation. Default=_number_.
--Exclude string-list Comma-separated list of the functions to exclude from obfuscation. Useful after an --Functions=* or --Functions=?int option, like this: --Functions=* --Exclude=main
--Functions IDENTSPEC The functions to which the transformation should be applied. See below for how to specify a set of functions.
--GlobalVariables IDENTSPEC The global variables to which the transformation should be applied. Currently only used for the --Transform=EncodeData transformation.
--LocalVariables LOCALSPEC The local variables and formal parameters to which the transformation should be applied. Currently only used for the --Transform=EncodeData transformation.

Thus with the options

   --FilePrefix=AAA_ --Transform=initOpaque --Prefix=BBB

we would generate symbols of the form

   AAA_BBB_opaque_list1

and with the options

   --FilePrefix=AAA_ --Transform=InitOpaque

they would look like this:

   AAA__0__opaque_Node
 

Argument Specifications

For options that take an integer an argument we provide an INTSPEC notation that allows randomized selection of the value. There's a similar BOOLSPEC notation for booleans.

All transformations require you to specify the set of functions to which they should be applied. IDENTSPEC (identifier specifications) allow you to flexibly select all or some of the available functions. Some transformations also use identifier specifications to specify variables, as in --UpdateEntropyVar=* which would select all variables of a function.

OptionArgumentsDescription
INTSPEC ?, int?int, int The INTSPEC notation allows randomized selection of integer valued options.
  • ? = select a 32-bit random number
  • int?int = select a random integer value in the range [int,int]
  • int = select this value
FRACSPEC *, int, int?int, %int The FRACSPEC notation allows the selection of a fraction of a set of elements.
  • * = 100%
  • int = select exactly this number of elements (if they exist)
  • int?int = a?b selects a random number of elements in the rage [a,b] (if they exist)
  • %int = select this fraction of available elements
BOOLSPEC ?, true, false The BOOLSPEC notation allows randomized selection of boolean valued options.
  • ? = select a random boolean value
  • true = select true
  • false = select false
IDENTSPEC *, ?int, %int, /regexp/, string Many transformations require you to specify the set of functions to which they should be applied. Trivally, you can say --Functions=foo to apply the obfuscation only to foo, but frequently you need more flexibility than that. The IDENTSPEC notation provides this functionality. Some transformations also use identifier specifications to specify variables, as in --UpdateEntropyVar=\* which would select all variables of a function.
  • * = select all available identifiers
  • ?int = randomly select int number of identifiers
  • %int = randomly select int percent of available identifiers
  • /regexp/ = select the identifiers that match the regular expression
  • string = select this identifier
LOCALSPEC The LOCALSPEC notation is used to specify a set of local variables and formal parameters. For example, --LocalVariables='main:i,j;foo:\*'=\* would select all variables of foo and i and j of main. The notation is a semicolon-separated list of IDENTSPEC:IDENTSPEC.
INPUTSPEC int, ?int, int?, int?int, +int, -int, "int", "string", "length" The --Input=... switch allows you to specify invariants over the command line arguments. These are used when you set --AddOpaqueStructs=input and --VirtualizeOpaqueStructs=input to create opaque constructs that appear to depend on input. An input specification is a coomma-separated list of 3-tuples: position:kind:value. I.e., --Input=position:kind:value,position:kind:value,.../tt> For example, consider the input specification --InputSpec=+1:int:34?56,-1:length:1? The first tuple specifies that the first command line argument must evaluate to an integer in the range 34-56, and the last argument has a length of exactly 1 character. Specifically, position=/+n|-n/, i.e. the n:th command line argument from the beginning or end of the line. The second part of the 3-tuple, kind is /int|string|length/, specifying that an invariant over a command line argument is a range of integer values, a particular string value, or the length (in characters) of an argument. The last part of the 3-tuple, value, allows you to specify four types of ranges: /[0-9]+/, /?[0-9]+/, /[0-9]+?/, and /[0-9]+?[0-9]+/,/[0-9]*?/, for a specfic value n, a range [n,..], a range [..,n], and a range [n..m]. n (a single integer) specifies a specific value, n? specifies a range starting at n
  • int = range specification: matches a particular integer
  • ?int = range specification: matches any value from int and up
  • int? = range specification: matches any value up to int
  • int?int = range specification: matches values in the range.
  • +int = position specification: argument number int from the left on the command line
  • -int = position specification: argument number int from the right on the command line
  • "int" = invariant specification: match the integer value of a command line argument
  • "string" = invariant specification: match the string value of a command line argument
  • "length" = invariant specification: match the length of a string argument

Examples

Randomly select 3 functions and "foo":

    --Functions=?3,foo   

Add entropy from all variables in function foo:

    --Transform=UpdateEntropy --Functions=foo --UpdateEntropyVar=*

Split 20% of all functions:

    --Transform=split --Functions=%20 

Note that some care needs to be exercised when specifiying identifiers, since some renaming can happen during obfuscation.