Checksum

 

This transformation inserts checkers into the program in order to ensure the integrity of the codebytes. A checker computes a hash over a code region and, if the hash is different than expected, issues a response, such as crashing the program. A hash function can be simple (such as computing the xor over the code region) or a highly complex randomly generated function. Responders can be simple (such as exiting the program with an abort() or modifying a global variable) or can be user-specified plugins of arbitrary complexity. Checkers can, of course, be obfuscated with Tigress' other transformations (such as flattening or virtualization), making them harder to detect.

Here is a LigerLabs video that gives a good introduction to the checksum transformation:

And here's another LigerLabs video that describes attacks against checksums:

Checkers can be invoked over a function prior to it being called, ensuring that the function hasn't been tampered with before it is executed. This is illustrated in this figure, where foo is checked by the pink checker, prior to being called. The e1 value is the expected hash value computed over foo.

Checkers can also cover arbitrary levels of overlapping, randomly chosen, code regions. This is the case for the orange and blue checkers. Here, f2 and t2 represent the range of addresses covered by the orange checker.

Unlike other Tigress transformations, the Checksum transform requires a post-processing step. This is performed by the tigress_post program:

The Checksum transformation generates two files: the Tigress-obfuscated output file (here P1.c) into which checkers have been inserted and a file (here hashes.c) that contains information about the generated hash functions. This file needs to be compiled into a dynamically linked .so file. The tigress_post post-processor reads the compiled obfuscated file (P1.exe) and hashes.so and generates a patched executable file (here P2.exe).

Here's an example of how to call Tigress and tigress_post:

> tigress --Seed=0 --Statistics=0 --Verbosity=0 --Environment=x86_64:Darwin:Clang:5.1  \
       --Verbosity=0 \
       --Transform=InitEntropy --Functions=main --InitEntropyKinds=vars \
       --Transform=InitOpaque --Functions=main --InitOpaqueStructs=list,array,env   \
       --Transform=Checksum \
          --ChecksumAddressing=relative \
          --ChecksumInsertSegmentCheckersInTheseFunctions=main \
          --ChecksumDoNotInsertSegmentCheckersInTheseFunctions=fib \
          --ChecksumSegmentCheckersToBeInsertedWhere=randomlyNoLoops \
          --ChecksumRequiredNumberOfSegmentCheckers=10 \
          --ChecksumFunctionsToBeCheckedAtCallSites=fac,fib \
          --ChecksumCallCheckersToBeInsertedWhere='((fac beforeCall) (fib beforeCall))' \
          --ChecksumFunctionPriority="((fac 1.0) (fib 0.5))" \
          --ChecksumHashFunctionsFile=hashes.c \
          --ChecksumHashValueTypes=int64  \
          --ChecksumHashFunctionKinds=add \
            test1.c --out=obf.c 

> gcc -static -fPIC -fno-plt -fcf-protection=none -o obf.exe obf.c     # for Linux
> gcc         -fPIC -fno-plt -o obf.exe obf.c     # for Darwin

> gcc -shared -o hashes.so -fPIC hashes.c

> tigress_post \
           --Action=checksum \
              --HashFunctionsFile=hashes.so \
           obf.exe


Hash Functions

A randomly generated checker looks like this:

/*******************************************************************************/
/* Inline template to be patched by tigress_post.                              */
if (opaque-false) {
    __asm__  volatile   (".align 8,0xf5;\n":);
   L4:  __asm__  volatile   (".long 0xAAAAA001":);         /* Start address */
   L5:  __asm__  volatile   (".long 0xBBBBB001":);         /* End address */
   L6:  __asm__  volatile   (".quad 0xCCCCCCCCCCCCC001":); /* Expected hash value */
}
/*******************************************************************************/
/* Load values from the patched template                                       */
codePtrVar_offset = (int )*((unsigned long *)(&&L4));
codePtrVar_templateAddress = (unsigned long *)(&&L4);
codePtrVar = (unsigned long *)((char *)codePtrVar_templateAddress + codePtrVar_offset);
endPtrVar_offset = (int )*((unsigned long *)(&&L5));
endPtrVar_templateAddress = (unsigned long *)(&&L5);
endPtrVar = (unsigned long *)((char *)endPtrVar_templateAddress + endPtrVar_offset);
/*******************************************************************************/
/* Compute the hash value.                                                     */
hashVar = 0;
while (codePtrVar < endPtrVar) {
  hashVar = ((hashVar + *codePtrVar) + (760749724UL ^ (1 ^ hashVar))) & 
            (*codePtrVar * 5027005UL + 4949079U);
  codePtrVar ++;
}
/*******************************************************************************/
/* Check if the hash value is correct, if not, respond.                        */
expectedHashVar = *((unsigned long *)(&&L6));
if (hashVar != expectedHashVar) {
  abort();
}
/*******************************************************************************/

The word at L4 will (after patching by tigress_post) hold the address of the region that the hash function will check, L5 will hold the address of the end of that region, and L6 will hold the expected hash value.

OptionArgumentsDescription
--Transform Checksum Insert checkers that compute hashes over the code bytes and take action if the hashes return the wrong value
--ChecksumTemplateKinds local, function, string, data Where to insert checker templates. Default=local.
  • local = The text segment, i.e. the code bytes.
  • function = The string segment.
  • string = The constant data segment.
  • data = The data segment. Currently not supported.
--ChecksumHashFunctionKinds add, mul, xor, linear, quadratic, random Kinds of expressions to use in the hash function. Default=xor.
  • add = The body of the hash function performs hash += codeByte.
  • mul = The body of the hash function performs hash *= codeByte.
  • xor = The body of the hash function performs hash ^= codeByte.
  • linear = The body of the hash function performs hash = hash * small_odd_int + codeByte.
  • quadratic = The body of the hash function performs hash = hash * hash * small_odd_int + hash * small_odd_int + codeByte.
  • random = The body of the hash function performs hash += random_function(hash, codeByte).
--ChecksumHashValueTypes int32, int64 Comma-separated list of the kinds of expressions to use in the hash functions. Default=int32,int64.
  • int32 = A 32-bit value.
  • int64 = A 64-bit value.
--ChecksumRandomHashFunctionSize INTSPEC Size of the randomly generated hash function. Default=1.
--ChecksumObfuscateBody BOOLSPEC Obfuscate the body of the hash function. Default=false.

tigress_post --Action=checksum

The purpose of tigress_post --Action=checksum is to patch the checker ``templates'' that were inserted by Tigress:

There are three main steps: first the executable is parsed and the templates are located, then each checker is assigned to a region of the text segment, and finally the hash value is computed and the templates are patched. An option tigress_post ... --OverlapRate=int ... can be set to adjust the number checkers will check each region of the text segment.

tigress_post has the following options:

--Action=checksum 
    Patch the checkers after the 'tigress --Transform=Checksum' transformation.
--Action=parse 
    Parse and print the information collected from the executable input file.

--HashFunctionsFile=file.so 
  The .so-file for the generated hash functions. 
  The file 'hashes'c' is generated by Tigress and 
  should be compiled using the command:
     'gcc -shared -o hashes.so -fPIC hashes.c'

--OverlapRate=int                      
   Amount of overlap in hash function assignment.

--ShowResults                          
   Show a table of final results, i.e. which hashfunctions check which regions.
--Dump=templates   
   Print the checker templates.
--Dump=regions     
   Print the regions that the executable was broken up into.
--Dump=textSegment 
   Print the text segment from the executable.
--Dump=sections    
   Print the sections of the executable.
--Dump=symbols     
   Print the symbol table extracted from the executable.
--Dump=codeBytes   
   Print the code bytes for each function in the executable.
--Trace|-e                             
   Trace the execution of tigress_post.

--Help


tigress_post --Action=kill

To check that the checkers inserted by Tigress actually trigger when the executable is modified, you can use the tigress_post --Action=kill command. It will randomly modify one or more bits in the executable which should cause the responses to trigger.

These are the relevant tigress_post options:

--Action=kill       
   Destroy a function to test that the checkers trigger a response.

--KillFunctions=f1,f2,...
   The functions to be killed by changing random bits.

--KillSize=1|8|16|32
   Number of consecutive bits to be changed when killing a function.

--KillCount= 
   Number of times to kill a function.


Plugin Responders

Tigress has a few simple built-in responders. You can easily add your own by adding a plugin function to your input program:

void responder_1 () {
   for(int i=0; i<10; i++) {
      printf("Hacked %i!\n", i);
   }
   exit(-1);
}

The body of these functions will be inserted in the checkers. These are the relevant options:

tigress ... \
         --Transform=InitPlugins  \
            --InitPluginsResponderPrefix=responder    \
         --Transform=Checksum \
            --ChecksumResponseKinds=plugin \
         ...

You can read more about plugins here.

OptionArgumentsDescription
--ChecksumResponseKinds abort, random, global, plugin Kinds of response to use in in case a checksum computes the wrong hash value Default=abort.
  • abort = Call the abort() function.
  • random = Insert some random codebytes that are likely to make the program crash.
  • global = Modify a global variable.
  • plugin = Call one of the user-provided plugin functions whose name has prefix provided by the --ChecksumPluginResponderPrefix option.

Call Checkers

Tigress has a few options that control where checkers are inserted, and which functions are being checked. Unlike all other Tigress transformations, --Transform=Checksum does not make use of the --Functions=... option. Instead, for call checkers you should use --ChecksumFunctionsToBeCheckedAtCallSitess=... to indicate which functions should be checked before they are called, and --ChecksumCallCheckersToBeInsertedWhere=.. to specify a more exact location (such as after the call, randomly, etc.):

> tigress ... \
          --ChecksumFunctionsToBeCheckedAtCallSites=f1,f2 \
          --ChecksumCallCheckersToBeInsertedWhere='((f1 beforeCall) (f2 beforeCall))' \
          ...

The option --ChecksumCallCheckersToBeInsertedWhere=... describes where in the function the checkers can be inserted. Here, function f6, for example, will be checked by a function that calls it, and the checker will be inserted anywhere in the caller, except within loops (this helps with performance):

tigress ...
          --ChecksumCallCheckersToBeInsertedWhere='((f1 beforeCall) (f2 afterCall) (f3 randomly) (f4 first) (f5 topLevel) (f6 randomlyNoLoops))'

The option --ChecksumFunctionPriority=... can give a priority value for each function, where 0.0 means "never check this function", and 1.0 means "always check this function." This allows you to control how many of the available checkers are assigned to check a particular function:

tigress ...
          --ChecksumFunctionPriority='((fac 1.0) (fib 0.7) (zap 0.2))' \

OptionArgumentsDescription
--ChecksumFunctionPriority S-Expression S-Expression describing which functions are most important to checksum. The syntax is ((function priority) (function priority) ...) where priority is a floating point number in the range [0.0,1.0]. (foo 0.0) means that foo should not be checked. Default=NONE.
--ChecksumFunctionsToBeCheckedAtCallSites String,String,... Comma-separated list of functions that should be checked where they are called. Use --ChecksumCallCheckersToBeInsertedWhere to specify where withing the caller the checker should be inserted. Default=NONE.
--ChecksumCallCheckersToBeInsertedWhere randomly, randomlyNoLoops, topLevel, first, beforeCall, afterCall, annotations S-Expression describing which functions should be checksummed before/after they are called. The syntax is ((function where) (function where) ...) where where is one of "randomly", "first", "beforeCall", "afterCall", "randomlyNoLoops", "topLevel", "annotations". If function bar calls function foo and (foo,randomly) is specified, a checker of foo will be inserted at some random place in bar. If (foo,beforeCall) is specified, the checker will be inserted immediately before the call to foo. If (foo,afterCall) is specified, the checker will be inserted immediately after the call to foo. If (foo,first) is specified, the checker will be inserted at the very beginning of bar. If (foo,randomlyNoLoops) is specified, the checker will be inserted anywhere within bar, but loops will be avoided. If (foo,annotations) is specified, the checker will be inserted where the annotation CHECKSUM_INSERT is specified within bar. Default=first.
  • randomly = Insert checkers anywhere in the caller function.
  • randomlyNoLoops = Insert checkers anywhere in the caller function, except within loops.
  • topLevel = Insert checkers anywhere in the caller function, but do not descend into control strucures (if, loops).
  • first = Insert checkers first in the caller function.
  • beforeCall = Insert checkers before the call to the checked function.
  • afterCall = Insert checkers after a call to the checked function.
  • annotations = Insert checkers where an CHECKER_INSERT annotation occurs in the caller function.

Segment Checkers

For segment checkers, --ChecksumRequiredNumberOfSegmentCheckers=... specifies how many checkers to insert, and --ChecksumInsertCheckersWhere=... describe where in the function to insert them. Here, checkers will be inserted anywhere in the function, except within control structures, or anywhere where the user has added a CHECKSUM_INSERT annotation:

tigress ...
          --ChecksumInsertSegmentCheckersInTheseFunctions='/foo*/' \
          --ChecksumProtectSegments=text \
          --ChecksumRequiredNumberOfSegmentCheckers=10 \
          --ChecksumSegmentCheckersToBeInsertedWhere=topLevel,annotations \

Here's an example of a function with annotations (don't forget to include tigress.h!):


void foo(void) { 
  int x = 10;
  int y = 2;
  if (x < 5) {
     y++;
     CHECKSUM_INSERT;
  } else {
     x++;
     CHECKSUM_INSERT;
  }
  y++;
}

OptionArgumentsDescription
--ChecksumRequiredNumberOfSegmentCheckers INTSPEC Number of segment checkers to insert. Default=0.
--ChecksumProtectSegments text, cstring, const, data Comma-separated list of which segments to protect. Default=text.
  • text = The text segment, i.e. the code bytes.
  • cstring = The string segment.
  • const = The constant data segment.
  • data = The data segment. Currently not supported.
--ChecksumSegmentCheckersToBeInsertedWhere randomly, randomlyNoLoops, topLevel, first, annotations Insert checkers randomly, at top-level, first, or where 'CHECKER'-annotations have been given in the code. Default=first.
  • randomly = Insert checkers anywhere in the function.
  • randomlyNoLoops = Insert checkers anywhere in the function, except within loops.
  • topLevel = Insert checkers anywhere in the function, but do not descend into control strucures (if, loops).
  • first = Insert checkers first in the function.
  • annotations = Insert checkers where an CHECKER_INSERT annotation occurs in the function.
--ChecksumInsertSegmentCheckersInTheseFunctions IDENTSPEC Names of functions into which checkers may be inserted. Default=NONE.
--ChecksumDoNotInsertSegmentCheckersInTheseFunctions String,String,... Comma-separated list of functions in which not to insert checkers. Default=NONE.

Visualizing Results

Calling tigress_post --ShowResults will generate a table like this:

+========+===========================================+===============+=====================================+========+========+========+========+========+========+
| region |    section, priority, address range, size |      function |             template, checker, size |      A |      B |      C |      D |      E |      F |
+========+===========================================+===============+=====================================+========+========+========+========+========+========+
|      0 |    text,0.5,[0x100002d40, 0x100002d4f],16 |     _megaInit |                                     |        |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|      1 |    text,1.0,[0x100002d50, 0x100002d8f],64 |  _loop_switch |                                     | hash_8 |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|      2 |   text,0.5,[0x100002d90, 0x100002e8f],256 |      ___sputc |                                     |        |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|      3 |   text,0.5,[0x100002e90, 0x100003007],376 |         _main |                                     |        |        |        |        |        |        |
|      4 |     text,1.0,[0x100003008, 0x10000300b],4 |               |           start=100002d50,hash_8,64 |        |        |        |        |        |        |
|      5 |     text,1.0,[0x10000300c, 0x10000300f],4 |               |             end=100002d8f,hash_8,64 |        |        |        |        |        |        |
|      6 |     text,1.0,[0x100003010, 0x100003013],4 |               |         expected=5a11fe33,hash_8,64 |        |        |        |        |        |        |
|      7 |   text,0.5,[0x100003014, 0x10000311f],268 |               |                                     |        |        |        |        |        |        |
|      8 |     text,1.0,[0x100003120, 0x100003123],4 |               |           start=100003dc0,hash_0,96 |        |        |        |        |        |        |
|      9 |     text,1.0,[0x100003124, 0x100003127],4 |               |             end=100003e1f,hash_0,96 |        |        |        |        |        |        |
|     10 |     text,1.0,[0x100003128, 0x10000312b],4 |               |         expected=37f9a377,hash_0,96 |        |        |        |        |        |        |
|     11 |   text,0.5,[0x10000312c, 0x1000031ff],212 |               |                                     |        |        |        |        |        |        |
|     12 |     text,1.0,[0x100003200, 0x100003203],4 |               |           start=100003dc0,hash_1,96 |        |        |        |        |        |        |
|     13 |     text,1.0,[0x100003204, 0x100003207],4 |               |             end=100003e1f,hash_1,96 |        |        |        |        |        |        |
|     14 |     text,1.0,[0x100003208, 0x10000320b],4 |               |         expected=37f9a377,hash_1,96 |        |        |        |        |        |        |
|     15 |   text,0.5,[0x10000320c, 0x1000033d7],460 |               |                                     |        |        |        |        |        |        |
|     16 |     text,1.0,[0x1000033d8, 0x1000033db],4 |               |           start=100003dc0,hash_2,96 |        |        |        |        |        |        |
|     17 |     text,1.0,[0x1000033dc, 0x1000033df],4 |               |             end=100003e1f,hash_2,96 |        |        |        |        |        |        |
|     18 |     text,1.0,[0x1000033e0, 0x1000033e3],4 |               |         expected=37f9a377,hash_2,96 |        |        |        |        |        |        |
|     19 |   text,0.5,[0x1000033e4, 0x1000034f7],276 |               |                                     |        |        |        |        |        |        |
|     20 |     text,1.0,[0x1000034f8, 0x1000034fb],4 |               |           start=100003dc0,hash_3,96 |        |        |        |        |        |        |
|     21 |     text,1.0,[0x1000034fc, 0x1000034ff],4 |               |             end=100003e1f,hash_3,96 |        |        |        |        |        |        |
|     22 |     text,1.0,[0x100003500, 0x100003503],4 |               |         expected=37f9a377,hash_3,96 |        |        |        |        |        |        |
|     23 |   text,0.5,[0x100003504, 0x100003617],276 |               |                                     |        |        |        |        |        |        |
|     24 |     text,1.0,[0x100003618, 0x10000361b],4 |               |           start=100003dc0,hash_4,96 |        |        |        |        |        |        |
|     25 |     text,1.0,[0x10000361c, 0x10000361f],4 |               |             end=100003e1f,hash_4,96 |        |        |        |        |        |        |
|     26 |     text,1.0,[0x100003620, 0x100003627],8 |               | expected=a8b3c8039f4a6b74,hash_4,96 |        |        |        |        |        |        |
|     27 |   text,0.5,[0x100003628, 0x100003987],864 |               |                                     |        |        |        |        |        |        |
|     28 |     text,1.0,[0x100003988, 0x10000398b],4 |               |           start=100003dc0,hash_5,96 |        |        |        |        |        |        |
|     29 |     text,1.0,[0x10000398c, 0x10000398f],4 |               |             end=100003e1f,hash_5,96 |        |        |        |        |        |        |
|     30 |     text,1.0,[0x100003990, 0x100003993],4 |               |         expected=37f9a377,hash_5,96 |        |        |        |        |        |        |
|     31 |   text,0.5,[0x100003994, 0x100003aa7],276 |               |                                     |        |        |        |        |        |        |
|     32 |     text,1.0,[0x100003aa8, 0x100003aab],4 |               |          start=100003e20,hash_6,128 |        |        |        |        |        |        |
|     33 |     text,1.0,[0x100003aac, 0x100003aaf],4 |               |            end=100003e9f,hash_6,128 |        |        |        |        |        |        |
|     34 |     text,1.0,[0x100003ab0, 0x100003ab3],4 |               |        expected=2a71a278,hash_6,128 |        |        |        |        |        |        |
|     35 |   text,0.5,[0x100003ab4, 0x100003c1f],364 |               |                                     |        |        |        |        |        |        |
|     36 |     text,1.0,[0x100003c20, 0x100003c23],4 |               |           start=100003ea0,hash_7,96 |        |        |        |        |        |        |
|     37 |     text,1.0,[0x100003c24, 0x100003c27],4 |               |             end=100003eff,hash_7,96 |        |        |        |        |        |        |
|     38 |     text,1.0,[0x100003c28, 0x100003c2f],8 |               | expected=14d8ac0977e8efd8,hash_7,96 |        |        |        |        |        |        |
|     39 |   text,0.5,[0x100003c30, 0x100003d3f],272 |               |                                     |        |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|     40 |    text,0.5,[0x100003d40, 0x100003d9f],96 | _switch_sw... |                                     |        |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|     41 |    text,0.5,[0x100003da0, 0x100003dbf],32 | _tigress_exit |                                     |        |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|     42 |    text,1.0,[0x100003dc0, 0x100003e1f],96 |          _fac |                                     | hash_0 | hash_1 | hash_2 | hash_3 | hash_4 | hash_5 |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|     43 |   text,1.0,[0x100003e20, 0x100003e9f],128 |          _fib |                                     | hash_6 |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|     44 |    text,1.0,[0x100003ea0, 0x100003eff],96 |          _sum |                                     | hash_7 |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|     45 |    text,0.5,[0x100003f00, 0x100003f4f],80 | _tigress_r... |                                     |        |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|     46 |     text,0.5,[0x100003f50, 0x100003f55],6 |          _dbg |                                     |        |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+
|     47 | cstring,1.0,[0x100003f56, 0x100003fb7],98 |               |                                     |        |        |        |        |        |        |
+--------+-------------------------------------------+---------------+-------------------------------------+--------+--------+--------+--------+--------+--------+

The first three columns show that the .text-segment has been broken up into 47 regions. The main function, for example, has been broken up into 37 regions. The fourth column shows that there are 9 checkers, named hash_0 through hash_8. You can learn more about these checkers by inspecting the file generated by Tigress (the --ChecksumHashFunctionsFile=hashes.c options provide the names of the files). The size field shows how many bytes each hash function is checking. The function hash_7, for example, computes a hash over the sum function. Columns A-F, finally, show which regions each hash function is covering. The function hash_7, again, computes a hash over region 44.

Calling tigress_post --ShowResults will also generate tables that provide some statistical information:

Number of bytes checked by each hash function
=============================================
Hash function 'hash_0' checks 96 bytes
Hash function 'hash_1' checks 96 bytes
Hash function 'hash_2' checks 96 bytes
Hash function 'hash_3' checks 96 bytes
Hash function 'hash_4' checks 96 bytes
Hash function 'hash_5' checks 96 bytes
Hash function 'hash_6' checks 128 bytes
Hash function 'hash_7' checks 96 bytes
Hash function 'hash_8' checks 64 bytes
On average, a hash function checks 96.0 bytes

Number of hash function checking each byte
==========================================
4344 bytes are checked by 0 checkers
288 bytes are checked by 1 checkers
96 bytes are checked by 6 checkers
The average byte is checked by 0.2 hash functions

Note that the amount of overlap needs to be controlled with options to both Tigress and tigress_post: for more overlap you need to introduce more checkers (using tigress --ChecksumRequiredNumberOfSegmentCheckers=...) and increase the overlap rate in tigress_post (tigress_post --OverlapRate=...).


Other Options

OptionArgumentsDescription
--Transform Checksum Insert checkers that compute hashes over the code bytes and take action if the hashes return the wrong value
--ChecksumTraceKinds start, stop, step, check List of the information that should be printed at runtime when a checker is executed. Default=NONE.
  • start = Trace the beginning of checksum computation
  • stop = Trace the end of checksum computation
  • step = Trace each intermediate step of the checksum computation
  • check = Trace the correctness check of the checksum computation
--ChecksumHashFunctionsFile String The name of the generated file containing hash functions. It should be compiled into a .so file and becomes input into tigress_post. Default=hashFunctions.c.
--ChecksumAddressing relative, absolute How to load the address of the code region to check. Default=relative.
  • relative = This addressing mode is not allowable on Darwin, and possible on Linux.
  • absolute = This addressing mode is necessary on Darwin, and possible on Linux.
 

Issues

  • The first part of the checkers (containing the address ranges to be checked and the expected hash value) is currently not diversified and are easy to locate.
  • The response should be separated from the check in time and space. It is currently not.
  • On recent versions of gcc/x86 the compiler inserts the instruction endbr64 after branches. In what appears to be a gcc bug, in the code below the compiler inserts the endbr64 instruction after the label, when, presumably, it should go between the test and the label. As a result, we can't correctly calculate the address of the asm instruction:
    if (_2_main_1_opaque_ptr_1 == _2_main_1_opaque_ptr_2) {
       Lab_2000002: 
        __asm__ volatile (".balign 8,0xf9;\n"
                          ".long 0xAAAAA001;\n"
                          ".long 0xBBBBB001;\n"
                          ".quad 0xCCCCCCCCCCCCC001;\n":);
    }
    

    This typically causes a crash. If you notice this issue turn off branch checking by adding -fcf-protection=none to your gcc command line.
 

References