Generate Challenge Problems

One of the uses of Tigress is as an educational tool. The --Transform=RandomFuns
option will generate a random function that can subsequently be transformed using any
combination of Tigress obfuscations, and then given to students as a cracking target.

You can generate a program for the students to reverse engineer:

or you can generate a program for them to crack:

Depending on the sophistication of your students, you can vary the length of the transformation
sequence, the difficulty of the transformations, the options to the transformations,
the complexity of the generated challenge function, and either give them source to untangle
(a good way to learn about particular transformations), or stripped compiled code (for a more
real-world challenge).

We typically give each student 3 programs, of different levels of difficulty,
to attack. Thanks to the diversity of Tigress-generated programs, each challenge
is unique, making it harder for students to cheat.

Examples

Below is part of the script we use to generate take-home exams for our students.
It contains two assets, a password check and an expired time check,
and it's the students' job to disable these.

Structure of Random Programs

To fulfill our needs, a random program generator must have certain characteristics:

in order to make it easy for reverse engineers to automate attacks, the
generated programs must a have simple I/O behavior;

the generator must be able to produce an "infinite" sequence of different programs;

generated programs should be small, but still have an "interesting" internal structure;

generate programs should always terminate;

an adversary should not be able to guess the internals of a generated
program by examining its input-output behavior;

generated programs should be "minimal," i.e. there should not be a smaller
program that has the same I/O behavior (this is so that it is obvious to
the reverse engineer when he has found the correct program).

Generates excatly the same code whether true or false, except the failure code is rendered impotent. In other words, --RandomFunsDummyFailure=true will have the failure code inserted, but inactive. Default=false.

--RandomFunsActivationCode

int

The code the user has to enter (as the first command line arguments) to be allowed to run the program. Default=42.

--RandomFunsPassword

string

The password the user has to enter (read from standar input) to be allowed to run the program. Default="42".

--RandomFunsTimeCheckCount

int

The number of checks for expired time (gettimeofday() > someTimeInThePast) to be inserted in the program. Default=0.

--RandomFunsActivationCodeCheckCount

int

The number of checks for correct activation code to be inserted in the program. Default=0.

--RandomFunsPasswordCheckCount

int

The number of checks for correct password to be inserted in the program. Probably only 0 and 1 make sense here, since the user will be prompted for a password once for every check. Default=0.

--RandomFunsControlStructures

S-Expression

If set, will define the nested control structures of the generated function. Otherwise, a random structure will be generated. The argument is an S-Expression, where the each subexpression has one of the forms (bb INTSPEC) (for a basic block consisting of a certain number of assignment statements), (for S-expression) (for a a for-loop with a given body), or (if S-expression S-expression) (for an if-statement with a given then and else part). For example, --RandomFunsControlStructures='(for ((bb 4)))' will generate a body consisting of a for-loop with 4 assignment statements in the body. (for ((bb 4) (if ((bb 1)) ((bb 2))))) also puts an if-statement inside the loop. (for ((bb 4) (if ((bb 1)) ((for (bb 2)))))) puts a for-loop inside the else-part of the if-statement. Default=0.

Add if (output[0] == 4242424242U) printf("You win!\n"); after the call to the generated function. The idea is to replace (by hand) 4242424242U with one actual output of the function. This can be used as another reverse engineering challenge: "Find an input for which the program prints "You win!. Default=false.