Below are some simple recipes that will make it easy for you to get started using Tigress. See them as a starting point for you to explore all of Tigress' features, not as recommendations for particular situations. Before using any kind of software protection technique you must start with a detailed security analysis:
Only when you have answered these questions, and have determined that obfuscation needs to be an integral part of your architecture, can you start putting together Tigress scripts. Over time we will add more recipes here. If you have found a particular combination of Tigress transformations useful, please let us know, and we will add your recipe to the collection!
In the examples below we will be using these programs as input: test.c and test-jit.c.
Here is a simple recipe that should have a relatively low performance impact:
tigress --Seed=42 --Statistics=0 --Verbosity=0 --Environment=x86_64:Darwin:Clang:5.1 \
--Transform=InitEntropy \
--Functions=init_tigress \
--InitEntropyKinds=vars \
--Transform=InitOpaque \
--Functions=init_tigress \
--InitOpaqueStructs=list,array,env \
--Transform=InitBranchFuns \
--InitBranchFunsCount=1 \
--Transform=AddOpaque \
--Functions=fac,fib \
--AddOpaqueStructs=list \
--AddOpaqueKinds=true \
--Transform=AntiBranchAnalysis \
--Functions=fac,fib \
--AntiBranchAnalysisKinds=branchFuns \
--AntiBranchAnalysisObfuscateBranchFunCall=false \
--AntiBranchAnalysisBranchFunFlatten=true \
--Transform=EncodeArithmetic \
--Functions=fac,fib \
test.c --out=output1.c
Here is the resulting code. There are a few things to note here:
Init
-transformations.
In this case we have InitEntropy
, InitOpaque
, and InitBranchFuns
.
This is admittedly annoying, but necessary, so that Tigress can create the types, variables, and functions
necessary to transform the program. For example, InitBranchFuns
creates one or more
branch functions that the AntiBranchAnalysis
transformation can use later on.
init_tigress
function into
which the Init
-transformations can put initialization code. This function can then
also be obfuscated to hide the initializations!
--AntiBranchAnalysisBranchFunFlatten=true
will flatten the code prior to inserting
calls to branch functions. This is because branch functions operate on direct jumps (gotos), and
most codes don't have many of those. After the flattening transformation, however, there are
many jumps to encode.
--Seed=0
(which means the internal random number generator
will be seeded with a new value every time Tigress is run), every time you run this script you
will get a differently obfuscated program.
tigress-merge
.
This transformation shows off a combination of two more powerful transformation, virtualization and self-modifying code, that together is likely to have serious performance impact:
tigress --Seed=42 --Statistics=0 --Verbosity=0 --Environment=x86_64:Darwin:Clang:9.0 \
--Transform=InitEntropy \
--Functions=init_tigress \
--InitEntropyKinds=vars \
--Transform=InitOpaque \
--Functions=init_tigress \
--InitOpaqueStructs=list,array,env \
--Transform=Virtualize \
--Skip=false \
--VirtualizeDispatch=ifnest \
--Functions=fac,fib \
--Transform=SelfModify \
--Skip=false \
--Functions=fac,fib \
--SelfModifySubExpressions=false \
--SelfModifyBogusInstructions=10 \
test.c --out=output2.c
Here is the resulting code. Here are a few things to note:
--Skip-false
option is handy to turn transformations on-and-off to try out
the impact of different transformations.
--VirtualizeDispatch
.
gcc -segprot __TEXT rwx rwx output2.c -o output2.exe
(on Darwin). See the SelfModify page for more information.
In this recipe we first virtualize and then add dynamic obfusction; i.e. the program will decode and re-encode itself as it is running. In this particular case we decode/encode using the XTEA cipher:
tigress --Seed=42 --Statistics=0 --Verbosity=0 --Environment=x86_64:Darwin:Clang:5.1 \
--Transform=InitEntropy \
--Functions=init_tigress \
--InitEntropyKinds=vars \
--Transform=InitOpaque \
--Functions=init_tigress \
--InitOpaqueStructs=list,array,env \
--Transform=Virtualize \
--Skip=false \
--VirtualizeDispatch=direct \
--Functions=fib \
--Transform=JitDynamic \
--Skip=false \
--Functions=fib \
--JitDynamicCodecs=xtea \
--JitDynamicBlockFraction=%100 \
--Transform=Measure \
--Functions=fib \
--MeasureTimes=100 \
test-jit.c --out=output3.c
Here is the resulting code. Here are a few things to note:
Measure
transformation along with differen values of Skip
to
measure the performance impact. On my machine virtualization alone takes 0.000192 seconds,
dynamic obfuscation alone takes 0.077977 seconds, and together, the program slows down to
2.125580 seconds!
--JitDynamicBlockFraction=1
(which means only one basic block will be
encoded) reduces the time to 1.800674 seconds.
In this recipe we first merge all functions together. This includes init_tigress
which has important
secrets in it, in particular the initalization of opaque structures:
tigress --Seed=42 --Statistics=0 --Verbosity=1 --Environment=x86_64:Darwin:Clang:9.0 \
--Transform=InitEntropy \
--Functions=init_tigress \
--InitEntropyKinds=vars \
--Transform=InitOpaque \
--Functions=init_tigress \
--InitOpaqueStructs=list,array,env \
--Transform=Merge \
--MergeFlatten=false \
--MergeName=MERGED \
--Functions=fib,fac,init_tigress \
--Transform=Virtualize \
--VirtualizeDispatch=direct \
--Functions=MERGED \
--Transform=EncodeLiterals \
--Functions=main \
test.c --out=output4.c
Here is the resulting code. Here are a few things to note:
--MergeFlatten=false
to save some on performance.
main
: it now consists of 3 calls to MERGED
rather than calls to
the individual functions.
EncodeLiterals
transformation to add some opaque expressions
to the calls to MERGED
in main
--Transform=RndArgs --Functions=MERGED --RndArgsBogusNo=10
,
which results in this code.