Encode External

The goal of this transformation is to hide calls to external functions, such as system calls or calls to standard library functions. Our current implementation has two variants:

  • Use dynamic loading ("dlsym()") to load the libary at runtime and make the function call indirect through a pointer.
  • Embed the source of the external library in your program making it amenable to further Tigress obfuscations.

OptionArgumentsDescription
--Transform InitEncodeExternal Replace direct system calls with indirect ones through dlsym.
 

Dynamic Encoding

Here, we simply replace direct calls with indirect ones, and load the address of the functions using dlsym().

OptionArgumentsDescription
--Transform InitEncodeExternal Replace direct system calls with indirect ones through dlsym.
--InitEncodeExternalSymbols Comma-separated list of strings List of of external functions to be encoded.
OptionArgumentsDescription
--Transform EncodeExternal Replace direct system calls with indirect ones through dlsym.
--EncodeExternalObfuscateIndex BOOLSPEC Use opaque expressions to compute function addresses. Default=true.

Consider the following program syscall.c which makes two system calls to getpid and gettimeofday:


void tigress_init() {}

int main () {
   tigress_init();
   int x = getpid(); 
   printf("%i\n", x);
   struct timeval tv;
   int y = gettimeofday(&tv, NULL); 
   printf ("%ld.%06ld\n", tv.tv_sec, tv.tv_usec); 
}

We obfuscate using the following script:

> tigress -ldl \
        --Environment=x86_64:Darwin:Clang:5.1 \
        --Transform=InitEncodeExternal \
           --Functions=tigress_init \
           --InitEncodeExternalSymbols=getpid,gettimeofday  \
        --Transform=EncodeLiterals \
           --Functions=tigress_init \
           --EncodeLiteralsKinds=string \
           --EncodeLiteralsEncoderName=STRINGENCODER \
        --Transform=Virtualize \
           --Functions=STRINGENCODER \
        --Transform=EncodeExternal \
           --Functions=main \
           --EncodeExternalKind=dynamic  \
           --EncodeExternalSymbols=getpid,gettimeofday  \
        --out=syscall_out.c syscall.c
> gcc -o syscall_out syscall_out.c -ldl

The InitEncodeExternal transformation uses dlsym() to load the system calls we want to hide by name, the EncodeLiterals transformation hides these names in a function we call STRINGENCODER, the Virtualize transformation hides what's going on in the STRINGENCODER function, and finally, the EncodeExternal transformation replaces the direct calls to the system calls in main() with indirect ones.

The resulting code will look something like this:

void *_externalFunctionPtrArray[2];

void tigress_init(void) { 
  STRINGENCODER(0, encodeStrings_litStr0);
  _externalFunctionPtrArray[0] = dlsym((void *)-3, encodeStrings_litStr0);
  STRINGENCODER(1, encodeStrings_litStr1);
  _externalFunctionPtrArray[1] = dlsym((void *)-3, encodeStrings_litStr1);
}

void STRINGENCODER(int n , char str[] ) {
  STRINGENCODER_$sp[0] = STRINGENCODER_$stack[0];
  STRINGENCODER_$pc[0] = STRINGENCODER_$array[0];
  while (1) {
    switch (*(STRINGENCODER_$pc[0])) {
    case STRINGENCODER__store_char$left_STA_0$right_STA_1: 
    (STRINGENCODER_$pc[0]) ++;
    *((char *)(STRINGENCODER_$sp[0] + 0)->_void_star) = (STRINGENCODER_$sp[0] + -1)->_char;
    STRINGENCODER_$sp[0] += -2;
    break;
    ...
}

int main( ) { 
  int x,y;
  struct timeval tv ;
  ...
  tigress_init();
  x = ((pid_t (*)(void))_externalFunctionPtrArray[1])();
  printf((char const *)"%i\n", x);
  y = ((int (*)(struct timeval * __restrict   , void * __restrict ))
               _externalFunctionPtrArray[0])((struct timeval *)(& tv),
                (void *)((void *)0));
  printf((char const *)"%ld.%06ld\n", tv.tv_sec, tv.tv_usec);
}

Note how this program no longer has any mention of getpid and gettimeofday. The transformation is purely static, of course; at runtime it is trivial to see that these functions are being called.

 

Function Embedding (From 4.0.7)

IDA Pro's F.L.I.R.T. attempts to identify common library functions by creating a signature from the first 32 bytes of each function. It also provides a tool to identify signatures for third party libraries called idenlib. To thwart such attacks you can embed libraries into your program and then obfuscate them. You can of course do this manually, but Tigress provides functionality to make this simple. Currently we only support the string library.

We obfuscate using the following script:

> tigress -ldl \
        --Environment=x86_64:Darwin:Clang:5.1 \
        --Transform=EncodeExternal \
           --Functions=main \
           --EncodeExternalKind=embed  \
           --EncodeExternalSymbols=strcmp  \
        --Transform=Inline \
           --Functions=string_strcmp \
        --out=embed.c embed.c

Note that, after embedding the string library functions they get prefixed by string__. This is, after embedding, the strcmp function is now called string__strcmp. By further obfuscating the embedded functions (here we're inlining strcmp), you can bypass the F.L.I.R.T. identification.

We currently support embedding the following functions:

memccpy → string___memccpy
memchr → string___memchr
memcmp → string___memcmp
memcpy → string___memcpy
memmem → string___memmem
memmove → string___memmove
memrchr → string___memrchr
stpcpy → string___stpcpy
stpncpy → string___stpncpy
strcasecmp → string___strcasecmp
strncasecmp → string___strncasecmp
strcasestr → string___strcasestr
strcat → string___strcat
strchr → string___strchr
strcmp → string___strcmp
strcoll → string___strcoll
strcspn → string___strcspn
strdup → string___strdup
strlcat → string___strlcat
strlcpy → string___strlcpy
strlen → string___strlen
strncat → string___strncat
strncmp → string___strncmp
strncpy → string___strncpy
strndup → string___strndup
strnlen → string___strnlen
strpbrk → string___strpbrk
strsep → string___strsep
strspn → string___strspn
strstr → string___strstr
strtok → string___strtok
strtok_r → string___strtok_r
strxfrm → string___strxfrm
wcslcpy → string___wcslcpy

 

References

 

Issues

  • On Linux/gcc you need to explicitly add the -ldl option. On MacOS/clang this is not necessary.
  • If you set the --Environment= wrong, your program will fail.
  • We currently only support embedding of the LibC string library. We have, however, developed a tool that makes embedding new libraries into Tigress more-or-less trivial. If you have a library you would like to add to Tigress, let us know: we just require the source to be published under a permissive license.