The goal of this transformation is to hide calls to external functions, such as system calls or calls to standard library functions. The current implementation is simplistic: we simply replace direct calls with indirect ones, and load the address of the functions using dlsym().
Option | Arguments | Description |
---|---|---|
--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. |
Option | Arguments | Description |
---|---|---|
--Transform | EncodeExternal | Replace direct system calls with indirect ones through dlsym. |
--EncodeExternalObfuscateIndex | BOOLSPEC | Use opaque expressions to compute function addresses. Default=true. |
--EncodeExternalSymbols | comma-separated list of strings | Set of external functions to be encoded in this function Default=true. |
Consider the following program syscall.c
which makes two system calls to getpid
and gettimeofday
:
#include<stdio.h>
#include<unistd.h>
#include<sys/time.h>
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 \
--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.
ioctl.
dlsym
idea in a
DEFCON
talk.
-ldl
option.
On MacOS/clang this is not necessary.
--Environment=
wrong, your program will fail.