51
Obfuscator Reloaded Johan Wehrli Rinaldini Julien

Appsec obfuscator reloaded

Embed Size (px)

DESCRIPTION

e

Citation preview

Page 1: Appsec obfuscator reloaded

Obfuscator Reloaded

Johan Wehrli Rinaldini Julien

Page 2: Appsec obfuscator reloaded

Who the **** are we?• Johan Wehrli

• Master of Science HES-SO in Engineering

• Scientific Collaborator

• @jowehrli

• Julien Rinaldini

• Master of Science HES-SO in Engineering

• Research Engineer

• @pyknite / http://rand0m.ch

• IICT, Institute for Information an Communication Technology

Page 3: Appsec obfuscator reloaded

Evil Plan• Obfuscator?

• LLVM?

• Tamper-proofing

• Functions merging

• Tests

• Conclusion

Page 4: Appsec obfuscator reloaded

Obfuscator• Research project in IT security

• Managed by Phd. Pascal Junod

• IICT, HEIG-VD

• Open-source (well, not everything ;) ): http://o-llvm.org

• Important dates

• Born in 2010

• First public release in 2013

• Still in development

• Increase software security

• Substitution, flattening, BCF, …

Page 5: Appsec obfuscator reloaded

LLVM• Open-source project, written in C++

• Compilation framework, several modules

• Support multiple languages:

• C/C++, Obj-C, Haskell, Java,…

• … And multiple architectures:

• x86, ARM, MIPS, PowerPC,…

Page 6: Appsec obfuscator reloaded
Page 7: Appsec obfuscator reloaded

The tamper-proofing is...

• Detecting any modifications

• Making sure that a software is run in the way it was expected to be when it was designed

Page 8: Appsec obfuscator reloaded

The tamper-proofing is not...

• A way of preventing the reverse engineering

Page 9: Appsec obfuscator reloaded

Two-Step• Check

• Verification of the result

• Calculation of execution time

• Hash of a snippet of code

• Respond

• Ending the software

• Restore the initial code

• Tamper the result or the performance

Page 10: Appsec obfuscator reloaded

Typical Attacks• Search for patterns

• Statically

• Dynamically

• Deactivation of the RESPOND

• Modification of the condition

• Pre-processing the new hash value

Page 11: Appsec obfuscator reloaded

Prerequisites - Flattening• Flatten the control flow of a function

• Uses

• External loop

• switch

• One case per basic block

• Basic block -> end -> switch

• Branch variable (SwitchVar)

Page 12: Appsec obfuscator reloaded

int main(int argc, char **argv){

int tab[10] = {5, 9, … , 1};

for(int i = 0; i < 10; ++i){ printf("%d, ",tab[i]); }

return 0;

}

Page 13: Appsec obfuscator reloaded
Page 14: Appsec obfuscator reloaded

Now, let’s do some meth math…

Page 15: Appsec obfuscator reloaded

Prerequisites - CRC 1/10• Linear Code C over a finite field GF(q) of length n

• C is a cyclic code if, for every word in the code

• Notions

• Alphabet :

• Word :

• Cyclic code :

• Generator polynomial :

• Equations

c = (c0, c1, ..., cn � 1) in GF (q)n

⇤ = 0, 1

x = 0b10010 = (1, 0, 0, 1, 0) 2 ⇤5

00000, 00111, 01110, 01001, 11100, 11011, 10010, 101010

g(x) = x

2 + x+ 1

0 · g(x), 1 · g(x), x · g(x), (x+ 1) · g(x), x2 · g(x), (x2 + 1) · g(x),(x2 + x) · g(x), (x2 + x+ 1) · g(x)

Page 16: Appsec obfuscator reloaded
Page 17: Appsec obfuscator reloaded

Prerequisites - CRC• Cyclic Redundancy Check

• To detect errors during transmission

• To calculate the remainder of a polynomial division

• Easy to implement (CRC32)

• How it works

• Cyclic code

• Euclidean division

• Remainder = CRC

Page 18: Appsec obfuscator reloaded

Step One

• ModulePass, IR code, go through all the program

• …

Page 19: Appsec obfuscator reloaded
Page 20: Appsec obfuscator reloaded

Step One• ModulePass, IR code, go through all the

program

• Create multiple check functions

• Pool of functions

• Random names

• ...

Page 21: Appsec obfuscator reloaded

uint32_t normalCRC(uint32_t init, uint32_t* begin, uint32_t* end){

uint32_t crc = init;

while(begin < end){ __asm__ __volatile__( "crc32l %%ecx, %%esi;" :"=S" (crc) :"0" (crc), "c" (*begin) ); ++begin; }

return crc; }

uint32_t inverseCRC(uint32_t init, uint32_t* begin, uint32_t* end){

uint32_t crc = init;

while(begin < end){ __asm__ __volatile__( "crc32l %%ecx, %%esi;" :"=S" (crc) :"0" (crc), "c" (*end) ); --end; }

return crc; }

Page 22: Appsec obfuscator reloaded

Step One• ModulePass, IR code, go through all the program

• Create multiple check functions

• Pool of functions

• Random names

• Place random call to the check

• 1..n per basic block

• Random area of code

• ...

Page 23: Appsec obfuscator reloaded

... store i32 1928457517, i32* %crc, align 4 store i32* inttoptr (i32 4196792 to i32*), i32** %begin, align 8 store i32* inttoptr (i32 4196848 to i32*), i32** %end, align 8 %2 = load i32* %crc, align 4 %3 = load i32** %begin, align 8 %4 = load i32** %end, align 8 %call = call i32 @vHpAKyNAxHgMhPd(i32 %2, i32* %3, i32* %4) store i32 %call, i32* %crc, align 4 ...

Page 24: Appsec obfuscator reloaded

Step One• ModulePass, IR code, go through all the program

• Create multiple check functions

• Pool of functions

• Random names

• Place random call to the check

• 1..n per basic block

• Random area of code

• Get all the call result, calcul the new SwitchVar

SwitchV ar = const� res1 � res2 � ...� resn

Page 25: Appsec obfuscator reloaded

... %14 = load i32* %const1 %15 = load i32* %crc, align 4 %16 = load i32* %crc2, align 4 %xor = xor i32 %15, %16 %xor5 = xor i32 %xor, %14 store i32 %xor5, i32* %switchVar ...

Page 26: Appsec obfuscator reloaded
Page 27: Appsec obfuscator reloaded

Problems• Calculation of the precedence

• One check area is over the xor

• Modify the constant value -> Modify SwitchVar

• The pass occurs in the middle-end

• No addresses

• No machine code

Page 28: Appsec obfuscator reloaded

Solutions• Use static array

• Get the value at a certain address

• Post-process the binary file

• Python script

• PyElfTool

SwitchV ar = tab[0]� res1 � res2 � ...� resn

Page 29: Appsec obfuscator reloaded

Post-Processing• Patch the file once the compilation is over

• Launch manually

• Platform dependent

• Created because the LLVM pass lack informations

• Begin address

• End address

• Hash value

• Static value

Page 30: Appsec obfuscator reloaded

Post-Processing• Read the log file

• Find the data

• Heuristic vs. Search

• Search by function

• Update the data

• Calculate the offset

• Update the addresses

• Calculate the check

• Update the static value

Page 31: Appsec obfuscator reloaded

Conclusion - Tamper• Selection policies

• Area : .Text vs. Function

• CHECK placement

• Control flow modification

• Good combinaison between static and dynamic values

• Future

• Use the Clang driver, detect link phase

• Generic solution, uses the LLVM API

Page 32: Appsec obfuscator reloaded

Functions Merging

What is that?

Page 33: Appsec obfuscator reloaded

// Module test.c int foo(int a) { return a+2; }

float bar(float a) { return a+2.0; }

Page 34: Appsec obfuscator reloaded

// Module test.c void merge(int sw, void *ret, ...) { switch(sw) { case 0:

va_list ap; va_start(ap, 1); int a = va_args(ap, int); va_end(ap);

int *b = (int*)ret; *b = a+2; break; case 1: va_list ap; va_start(ap, 1); float a = va_args(ap, float); va_end(ap);

float *b = (float*)ret; *b = a+2.0; break; } return; }

Page 35: Appsec obfuscator reloaded

input: Module M

begin

fList ;;foreach function f in module M do

if f is not a declaration and f is not main then

fList fList [ {f};

end

end

merge createFunction();foreach function f in fList do

addEntryToSwitch(f,merge);if f has arguments then

loadArgs(f,merge);end

replaceReturn(f,merge);moveContent(f,merge);createWrapper(f,M);

end

end

Page 36: Appsec obfuscator reloaded

input: Module M

begin

fList ;;foreach function f in module M do

if f is not a declaration and f is not main then

fList fList [ {f};

end

end

merge createFunction();foreach function f in fList do

addEntryToSwitch(f,merge);if f has arguments then

loadArgs(f,merge);end

replaceReturn(f,merge);moveContent(f,merge);createWrapper(f,M);

end

end

Page 37: Appsec obfuscator reloaded

• Save all functions, except:

• main()

• Arbitrary choice

• Variadic functions

• Special treatment needed

• No time left to implement it

• fastcall functions

• Try to pass arguments through registers

Page 38: Appsec obfuscator reloaded

input: Module M

begin

fList ;;foreach function f in module M do

if f is not a declaration and f is not main then

fList fList [ {f};

end

end

merge createFunction();foreach function f in fList do

addEntryToSwitch(f,merge);if f has arguments then

loadArgs(f,merge);end

replaceReturn(f,merge);moveContent(f,merge);createWrapper(f,M);

end

end

Page 39: Appsec obfuscator reloaded

• Merge function

• 3 arguments

• int sw

• void *result

• variadic argument (…)

• Uses a switch as a dispatcher

• Random name -> avoid linking problems

define void @merge-1196957890(i128 %sw, i8* %retArg, ...) { entry: %sw.addr = alloca i128 store i128 %sw, i128* %sw.addr %sw1 = load i128* %sw.addr switch i128 %sw1, label %default [ ] default: ; preds = %entry ret void }

Page 40: Appsec obfuscator reloaded

input: Module M

begin

fList ;;foreach function f in module M do

if f is not a declaration and f is not main then

fList fList [ {f};

end

end

merge createFunction();foreach function f in fList do

addEntryToSwitch(f,merge);if f has arguments then

loadArgs(f,merge);end

replaceReturn(f,merge);moveContent(f,merge);createWrapper(f,M);

end

end

Page 41: Appsec obfuscator reloaded

• switch value

• sha256 + salt

• Only use 128 bits

• Avoid online attack

switch i128 %sw1, label %default [ i128 27710209634873760713303062182632130818 , label %0 i128 -6843076191789525760054781676266687358 , label %17 i128 -26221607966511614330399007306620848255 , label %56 ]

Page 42: Appsec obfuscator reloaded

input: Module M

begin

fList ;;foreach function f in module M do

if f is not a declaration and f is not main then

fList fList [ {f};

end

end

merge createFunction();foreach function f in fList do

addEntryToSwitch(f,merge);if f has arguments then

loadArgs(f,merge);end

replaceReturn(f,merge);moveContent(f,merge);createWrapper(f,M);

end

end

Page 43: Appsec obfuscator reloaded

... %ap = alloca i8* %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) %1 = va_arg i8** %ap, i32 call void @llvm.va_end(i8* %ap2) ...

Page 44: Appsec obfuscator reloaded

input: Module M

begin

fList ;;foreach function f in module M do

if f is not a declaration and f is not main then

fList fList [ {f};

end

end

merge createFunction();foreach function f in fList do

addEntryToSwitch(f,merge);if f has arguments then

loadArgs(f,merge);end

replaceReturn(f,merge);moveContent(f,merge);createWrapper(f,M);

end

end

Page 45: Appsec obfuscator reloaded

• Replace all return

• load the return value in the retArg

• ret void

... %14 = alloca i8* store i8* %retArg , i8** %14 %15 = load i8** %14 %16 = bitcast i8* %15 to i32* store i32 3, i32* %16 ret void

Page 46: Appsec obfuscator reloaded

• We still have some problems

• Inter-module calls

• Distribution of an obfuscated library

• API breakage

Page 47: Appsec obfuscator reloaded

• Wrappers! The solution for every problems ;)

; Function Attrs: nounwind ssp uwtable define float @bar(float %a) { entry: %ret = alloca float %retPty = alloca float* store float* %ret, float** %retPty %load = load float** %retPty %bit = bitcast float* %load to i8* call void (i128, i8*, ...)* @merge1806660435(i128 49770522224456207387965548547940082999, i8* %bit, float %a) %0 = load float** %retPty %1 = load float* %0 ret float %1 }

Page 48: Appsec obfuscator reloaded

Conclusion - Function merging

• Use strip!

• Fonctions name give a lot of informations

• Use it with other obfuscations

Page 49: Appsec obfuscator reloaded

Tests• Test suite

• LibTomCrypt

• OpenSSL

• SQLite (+200’000 tests)

• Obfuscation of ALL the code

• Global idea of the consequences

Page 50: Appsec obfuscator reloaded

Conclusion• Both obfuscations works fine

• Debugging is hard

• Promising project

• A lot of others obfuscations

• Flattening V2, debug tricks, tamper V2,…

• Backend obfuscations

• Winner “Bourse Start-Up Heig-VD 2014”

Page 51: Appsec obfuscator reloaded

▄▄▄▄▄▄▄▄▄▄ ▄▄█████████▄▄▄▄▄ ██▄▄▄██████▄▄▄██▄▄ ██▄▄▄██████▄████████ ▄██▄████▄▄▄▄▄▄▄▄▄████ ████████████████▄▄███ ██████▄▄▄▄▄▄█████▄▄▄▄ ▀█████▄▄███████▄▄▄█▄▀ ▄▄▄▄▄▄▄▄▄ ████▄████████▄▄▄▀ ▄▄█████████▄▄ ▄▄██████████▄███ ███████▄▀▀▀▄█▄▄ ▄▄▄█▄▄█▄▄█▄▄▄▄▄▀▀ ████████ ▀▄▄▄▄███▄██▄▄▄███ ████████ ▄▄ ▄▄▄▄▄█▄▄▄▄███████ ████████▄▄██ ██▄▄▄██████████▄▀ ▀▄██████▄▄▄▀ ▀▄█▄██████████▄▀ ▄▄████▄▄██ ▄███▄█▄▄▄▄██▄██ █████████▄▀ █████▄▄▀ ██████ ███▄███▀▀ ███████ ███▄▄▄▄ ▀▄▄▄▀ ████████ ███████ ████████ ████▄▄██▄ ██████▄▄█ ██████▄▄█ █▄▄▄▄█ █▄▄▄▄█

Questions?