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 |
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
Option | Arguments | Description |
---|---|---|
--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.
|
--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.
Option | Arguments | Description |
---|---|---|
--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.
Option | Arguments | Description |
---|---|---|
INTSPEC | ?, int?int, int | The INTSPEC notation allows randomized selection of integer valued options.
|
FRACSPEC | *, int, int?int, %int | The FRACSPEC notation allows the selection of a fraction of a set of elements.
|
BOOLSPEC | ?, true, false | The BOOLSPEC notation allows randomized selection of boolean valued options.
|
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.
|
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
|
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.