Top-Level Options

Each Tigress 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. The Tigress options described here apply to all transformations. Each transformation additionally has their own set of options, all prefixed by the name of the transformation.

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.
--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. If --LogDir=dirName is set, generated log files will go in dirName. Default=0.
--Version Print the current Tigress version and exit.
--License Print the current Tigress license and exit.
--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 --InitOpaqueStructs=input. Default=0.
 

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
--out file.c The file to write to.
--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
--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,string,... 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.
--outJson string Whether to also save the output as a json file, and which file to save it on. From version 3.3
--DumpConfig bool Print the configuration options in effect, such as sizes of types. From version 4.0.0
--LogDir string --LogDir=dir will create all future log files will go in the dir directory. If dir does not exist, it will be created. From version 3.3.
--TransformVLA alloca, malloc, doNotTransform Describe how Variable Length Arrays (VLAs) should be translated to calls to alloca or malloc. This only applies to transformations that make wholesale changes to the control structures of a function, like flattening or virtualization. Default=alloca.
  • alloca = Use alloca
  • malloc = Use malloc
  • doNotTransform = Do not transform the VLAs. This will likely cause flattened and virtualize code to crash

  • Thus, to generate symbols of the form AAA_BBB_opaque_list1, give the options
    --FilePrefix=AAA_ \
    --Transform=initOpaque \
    --Prefix=BBB
    
  • Or, to generate symbols of the form AAA__0__opaque_Node, give the options
    --FilePrefix=AAA_ \
    --Transform=InitOpaque
    
 

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,... 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

Here are some 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.

 

Function Regions (From version 3.3)

Some transformations allow you to specify a region of a function to transform. In your source program you use the macro TIGRESS_REGION(region-name,code):

#include "tigress.h"

void fib(int n) {
  int a=0;
  int b=1;
  int s=1;

  int i;
  TIGRESS_REGION(region1,
  for (i=1; i<n; i++) {
    s=a+b;
    a=b;
    b=s;
  }
  );
  printf("fib(%i)=%i\n",n,s);
}

Then, in your tigress command, you add :region-name to the --Functions option:

tigress ... --Transform=Virtualize --Functions=fib:region1 ...  

Caveats:

  • Not all transforms currently support this feature..
  • Regions need to be self-contained, i.e. you cannot jump into or out of the region, take the address of a label in the region and use it outside, etc.
  • The current implementation incurs some overhead.
 

Json output (From version 3.3)

Typically, Tigress generates a C file as output, specified by the --out=filename.c option. If you want to process the output further you can also provide --outJson=filename.json option which will produce the output file as an abstract syntax tree. There is no formal definition of this Json AST at this point, but it closely follows the structure of the CIL AST on which it is based. Here's a piece of a function AST:

"GFun": {
    "vname": "TEST",
    "sformals": [],
    "slocals": [
      { "vname": "g", "vtype": { "TInt": "int" }, "vglob": false,
      "vstorage": "NoStorage", "vid": 3252 }
    ],
    "sbody": {
      "bstmts": [
        { "labels": [], "sid": -1, "preds": [], "succs": [],
        "skind": {
          "Instr": [
            {
            "Set": [
              {
              "Var": {
                "vname": "g",
                "vtype": { "TInt": "int" },
                "vglob": false,
                "vstorage": "NoStorage",
                "vid": 3252
              }, "offset": "NoOffset" }, {
              "Const": { "CInt64": [ "42", "int" ] } }
            ] }, {
            "Call": [
              "None", "printf", [
              {
              "CastE": [
                { "TPtr": { "TInt": "char" } }, {
                "Const": { "CStr": "g=%i\n" } }
              ] }, {